diff options
author | bajones@chromium.org <bajones@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-15 21:38:07 +0000 |
---|---|---|
committer | bajones@chromium.org <bajones@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-15 21:38:07 +0000 |
commit | 84624fc5c237fc8528b62faff2b80339bd6b9482 (patch) | |
tree | a4dabe9942f6e5c6a740af9f1dde47c3910aca78 /gpu | |
parent | fbe03618e02d5152ef405fbffbae3649fa36796f (diff) | |
download | chromium_src-84624fc5c237fc8528b62faff2b80339bd6b9482.zip chromium_src-84624fc5c237fc8528b62faff2b80339bd6b9482.tar.gz chromium_src-84624fc5c237fc8528b62faff2b80339bd6b9482.tar.bz2 |
Implemented OES_element_index_uint in the Chrome GPU command buffer
(Will be non-accessible until associated WebKit code is landed: http://webkit.org/b/97400)
Review URL: https://chromiumcodereview.appspot.com/11053015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@161971 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.cc | 74 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_unittest.cc | 116 | ||||
-rw-r--r-- | gpu/command_buffer/service/feature_info.cc | 8 | ||||
-rw-r--r-- | gpu/command_buffer/service/feature_info_unittest.cc | 8 |
4 files changed, 187 insertions, 19 deletions
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 41ec8c1..da37582 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -10,6 +10,7 @@ #include <map> #include <queue> #include <set> +#include <limits> #include <stdio.h> #include <string.h> #include <GLES2/gl2ext.h> @@ -305,23 +306,13 @@ class ClientSideBufferHelper { } // Copies in indices to the service and returns the highest index accessed + 1 - GLsizei SetupSimulatedIndexBuffer( + bool SetupSimulatedIndexBuffer( GLES2Implementation* gl, GLES2CmdHelper* gl_helper, GLsizei count, GLenum type, - const void* indices) { - gl_helper->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_array_buffer_id_); - GLsizei bytes_per_element = - GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type); - GLsizei bytes_needed = bytes_per_element * count; - if (bytes_needed > element_array_buffer_size_) { - element_array_buffer_size_ = bytes_needed; - gl->BufferDataHelper( - GL_ELEMENT_ARRAY_BUFFER, bytes_needed, NULL, GL_DYNAMIC_DRAW); - } - gl->BufferSubDataHelper( - GL_ELEMENT_ARRAY_BUFFER, 0, bytes_needed, indices); + const void* indices, + GLsizei* max_index_out) { GLsizei max_index = -1; switch (type) { case GL_UNSIGNED_BYTE: { @@ -342,10 +333,42 @@ class ClientSideBufferHelper { } break; } + case GL_UNSIGNED_INT: { + uint32 max_glsizei = static_cast<uint32>( + std::numeric_limits<GLsizei>::max()); + const uint32* src = static_cast<const uint32*>(indices); + for (GLsizei ii = 0; ii < count; ++ii) { + // Other parts of the API use GLsizei (signed) to store limits. + // As such, if we encounter a index that cannot be represented with + // an unsigned int we need to flag it as an error here. + + if(src[ii] > max_glsizei) { + return false; + } + GLsizei signed_index = static_cast<GLsizei>(src[ii]); + if (signed_index > max_index) { + max_index = signed_index; + } + } + break; + } default: break; } - return max_index + 1; + gl_helper->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_array_buffer_id_); + GLsizei bytes_per_element = + GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type); + GLsizei bytes_needed = bytes_per_element * count; + if (bytes_needed > element_array_buffer_size_) { + element_array_buffer_size_ = bytes_needed; + gl->BufferDataHelper( + GL_ELEMENT_ARRAY_BUFFER, bytes_needed, NULL, GL_DYNAMIC_DRAW); + } + gl->BufferSubDataHelper( + GL_ELEMENT_ARRAY_BUFFER, 0, bytes_needed, indices); + + *max_index_out = max_index + 1; + return true; } private: @@ -1046,11 +1069,18 @@ void GLES2Implementation::DrawElements( client_side_buffer_helper_->HaveEnabledClientSideBuffers(); GLsizei num_elements = 0; GLuint offset = ToGLuint(indices); + bool success; if (bound_element_array_buffer_id_ == 0) { // Index buffer is client side array. // Copy to buffer, scan for highest index. - num_elements = client_side_buffer_helper_->SetupSimulatedIndexBuffer( - this, helper_, count, type, indices); + success = client_side_buffer_helper_->SetupSimulatedIndexBuffer( + this, helper_, count, type, indices, &num_elements); + + if(!success) { + SetGLError(GL_INVALID_OPERATION, "glDrawElements", "index too large."); + return; + } + offset = 0; } else { // Index buffer is GL buffer. Ask the service for the highest vertex @@ -3340,11 +3370,19 @@ void GLES2Implementation::DrawElementsInstancedANGLE( client_side_buffer_helper_->HaveEnabledClientSideBuffers(); GLsizei num_elements = 0; GLuint offset = ToGLuint(indices); + bool success; if (bound_element_array_buffer_id_ == 0) { // Index buffer is client side array. // Copy to buffer, scan for highest index. - num_elements = client_side_buffer_helper_->SetupSimulatedIndexBuffer( - this, helper_, count, type, indices); + success = client_side_buffer_helper_->SetupSimulatedIndexBuffer( + this, helper_, count, type, indices, &num_elements); + + if(!success) { + SetGLError(GL_INVALID_OPERATION, "glDrawElementsInstancedANGLE", + "index too large."); + return; + } + offset = 0; } else { // Index buffer is GL buffer. Ask the service for the highest vertex diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 28fdbd3..8844fb4 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -896,6 +896,122 @@ TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffers) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersIndexUint) { + static const float verts[][4] = { + { 12.0f, 23.0f, 34.0f, 45.0f, }, + { 56.0f, 67.0f, 78.0f, 89.0f, }, + { 13.0f, 24.0f, 35.0f, 46.0f, }, + }; + static const uint32 indices[] = { + 1, 2, + }; + struct Cmds { + EnableVertexAttribArray enable1; + EnableVertexAttribArray enable2; + BindBuffer bind_to_index_emu; + BufferData set_index_size; + BufferSubData copy_data0; + cmd::SetToken set_token0; + BindBuffer bind_to_emu; + BufferData set_size; + BufferSubData copy_data1; + cmd::SetToken set_token1; + VertexAttribPointer set_pointer1; + BufferSubData copy_data2; + cmd::SetToken set_token2; + VertexAttribPointer set_pointer2; + DrawElements draw; + BindBuffer restore; + BindBuffer restore_element; + }; + const GLsizei kIndexSize = sizeof(indices); + const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; + const GLuint kEmuIndexBufferId = + GLES2Implementation::kClientSideElementArrayId; + const GLuint kAttribIndex1 = 1; + const GLuint kAttribIndex2 = 3; + const GLint kNumComponents1 = 3; + const GLint kNumComponents2 = 2; + const GLsizei kClientStride = sizeof(verts[0]); + const GLsizei kCount = 2; + const GLsizei kSize1 = + arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); + const GLsizei kSize2 = + arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); + const GLsizei kEmuOffset1 = 0; + const GLsizei kEmuOffset2 = kSize1; + const GLsizei kTotalSize = kSize1 + kSize2; + + ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize); + ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1); + ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2); + + Cmds expected; + expected.enable1.Init(kAttribIndex1); + expected.enable2.Init(kAttribIndex2); + expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId); + expected.set_index_size.Init( + GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW); + expected.copy_data0.Init( + GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset); + expected.set_token0.Init(GetNextToken()); + expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); + expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); + expected.copy_data1.Init( + GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset); + expected.set_token1.Init(GetNextToken()); + expected.set_pointer1.Init( + kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); + expected.copy_data2.Init( + GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset); + expected.set_token2.Init(GetNextToken()); + expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, 0, kEmuOffset2); + expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_INT, 0); + expected.restore.Init(GL_ARRAY_BUFFER, 0); + expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0); + gl_->EnableVertexAttribArray(kAttribIndex1); + gl_->EnableVertexAttribArray(kAttribIndex2); + gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, + GL_FLOAT, GL_FALSE, kClientStride, verts); + gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, kClientStride, verts); + gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersInvalidIndexUint) { + static const float verts[][4] = { + { 12.0f, 23.0f, 34.0f, 45.0f, }, + { 56.0f, 67.0f, 78.0f, 89.0f, }, + { 13.0f, 24.0f, 35.0f, 46.0f, }, + }; + static const uint32 indices[] = { + 1, 0x90000000 + }; + + const GLuint kAttribIndex1 = 1; + const GLuint kAttribIndex2 = 3; + const GLint kNumComponents1 = 3; + const GLint kNumComponents2 = 2; + const GLsizei kClientStride = sizeof(verts[0]); + const GLsizei kCount = 2; + + EXPECT_CALL(*command_buffer(), OnFlush()) + .Times(1) + .RetiresOnSaturation(); + + gl_->EnableVertexAttribArray(kAttribIndex1); + gl_->EnableVertexAttribArray(kAttribIndex2); + gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, + GL_FLOAT, GL_FALSE, kClientStride, verts); + gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, kClientStride, verts); + gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices); + + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError()); +} + TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersServiceSideIndices) { static const float verts[][4] = { diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 606db90..14d421f 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -358,6 +358,13 @@ void FeatureInfo::AddFeatures(const char* desired_features) { AddExtensionString("GL_OES_vertex_array_object"); } + if (ext.Desire("GL_OES_element_index_uint")) { + if (ext.Have("GL_OES_element_index_uint") || gfx::HasDesktopGLFeatures()) { + AddExtensionString("GL_OES_element_index_uint"); + validators_.index_type.AddValue(GL_UNSIGNED_INT); + } + } + bool enable_texture_format_bgra8888 = false; bool enable_read_format_bgra = false; // Check if we should allow GL_EXT_texture_format_BGRA8888 @@ -546,7 +553,6 @@ void FeatureInfo::AddFeatures(const char* desired_features) { // TODO(gman): Add support for these extensions. // GL_OES_depth32 - // GL_OES_element_index_uint feature_flags_.enable_texture_float_linear |= enable_texture_float_linear; feature_flags_.enable_texture_half_float_linear |= diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc index 3d14e7c..3510c70 100644 --- a/gpu/command_buffer/service/feature_info_unittest.cc +++ b/gpu/command_buffer/service/feature_info_unittest.cc @@ -799,6 +799,14 @@ TEST_F(FeatureInfoTest, InitializeNo_vertex_array_object) { EXPECT_FALSE(info_->feature_flags().native_vertex_array_object_); } +TEST_F(FeatureInfoTest, InitializeOES_element_index_uint) { + SetupInitExpectations("GL_OES_element_index_uint"); + info_->Initialize(NULL); + EXPECT_THAT(info_->extensions(), + HasSubstr("GL_OES_element_index_uint")); + EXPECT_TRUE(info_->validators()->index_type.IsValid(GL_UNSIGNED_INT)); +} + TEST_F(FeatureInfoTest, IsIntel) { SetupInitExpectationsWithVendor("", "iNTel", ""); info_->Initialize(NULL); |