summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorbajones@chromium.org <bajones@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-15 21:38:07 +0000
committerbajones@chromium.org <bajones@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-15 21:38:07 +0000
commit84624fc5c237fc8528b62faff2b80339bd6b9482 (patch)
treea4dabe9942f6e5c6a740af9f1dde47c3910aca78 /gpu
parentfbe03618e02d5152ef405fbffbae3649fa36796f (diff)
downloadchromium_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.cc74
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest.cc116
-rw-r--r--gpu/command_buffer/service/feature_info.cc8
-rw-r--r--gpu/command_buffer/service/feature_info_unittest.cc8
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);