diff options
author | bajones@chromium.org <bajones@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-12 16:25:57 +0000 |
---|---|---|
committer | bajones@chromium.org <bajones@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-12 16:25:57 +0000 |
commit | ab4fd728dca3d8d59564dd5fb552eea244929363 (patch) | |
tree | e46ae4f2fefcb282c0212f96ec6d254739c66319 /gpu | |
parent | e9ec622093449d24d4f5182eb6c60f0266308eb3 (diff) | |
download | chromium_src-ab4fd728dca3d8d59564dd5fb552eea244929363.zip chromium_src-ab4fd728dca3d8d59564dd5fb552eea244929363.tar.gz chromium_src-ab4fd728dca3d8d59564dd5fb552eea244929363.tar.bz2 |
Added emulation of the OES_vertex_array_object WebGL extension for devices that
do not support it natively, such as those using ANGLE.
TEST=Visit https://www.khronos.org/registry/webgl/sdk/tests/conformance/extensions/oes-vertex-array-object.html
on an ANGLE device. All tests should pass.
Review URL: https://chromiumcodereview.appspot.com/10983072
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@161589 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
8 files changed, 393 insertions, 192 deletions
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 7f15dbf..606db90 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -84,7 +84,8 @@ FeatureInfo::FeatureFlags::FeatureFlags() disable_workarounds(false), is_intel(false), is_nvidia(false), - is_amd(false) { + is_amd(false), + is_mesa(false) { } FeatureInfo::FeatureInfo() { @@ -207,6 +208,7 @@ void FeatureInfo::AddFeatures(const char* desired_features) { feature_flags_.is_nvidia |= string_set.Contains("nvidia"); feature_flags_.is_amd |= string_set.Contains("amd") || string_set.Contains("ati"); + feature_flags_.is_mesa |= string_set.Contains("mesa"); } } @@ -344,11 +346,15 @@ void FeatureInfo::AddFeatures(const char* desired_features) { validators_.render_buffer_format.AddValue(GL_DEPTH24_STENCIL8); } - if (ext.Desire("GL_OES_vertex_array_object") && - (ext.Have("GL_OES_vertex_array_object") || - ext.Have("GL_ARB_vertex_array_object") || - ext.Have("GL_APPLE_vertex_array_object"))) { - feature_flags_.native_vertex_array_object_ = true; + if (ext.Desire("GL_OES_vertex_array_object")) { + if (ext.Have("GL_OES_vertex_array_object") || + ext.Have("GL_ARB_vertex_array_object") || + ext.Have("GL_APPLE_vertex_array_object")) { + feature_flags_.native_vertex_array_object_ = true; + } + + // OES_vertex_array_object is emulated if not present natively, + // so the extension string is always exposed. AddExtensionString("GL_OES_vertex_array_object"); } diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index 5f3fbe0..2f3268d 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h @@ -43,6 +43,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool is_intel; bool is_nvidia; bool is_amd; + bool is_mesa; }; FeatureInfo(); diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc index f08d4ce..3d14e7c 100644 --- a/gpu/command_buffer/service/feature_info_unittest.cc +++ b/gpu/command_buffer/service/feature_info_unittest.cc @@ -9,6 +9,7 @@ #include "gpu/command_buffer/service/test_helper.h" #include "gpu/command_buffer/service/texture_manager.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_implementation.h" using ::gfx::MockGLInterface; using ::testing::_; @@ -88,9 +89,11 @@ TEST_F(FeatureInfoTest, Basic) { ).use_arb_occlusion_query2_for_occlusion_query_boolean); EXPECT_FALSE(info_->feature_flags( ).use_arb_occlusion_query_for_occlusion_query_boolean); + EXPECT_FALSE(info_->feature_flags().native_vertex_array_object_); EXPECT_FALSE(info_->feature_flags().is_intel); EXPECT_FALSE(info_->feature_flags().is_nvidia); EXPECT_FALSE(info_->feature_flags().is_amd); + EXPECT_FALSE(info_->feature_flags().is_mesa); // Test good types. { @@ -765,7 +768,7 @@ TEST_F(FeatureInfoTest, InitializeOES_vertex_array_object) { SetupInitExpectations("GL_OES_vertex_array_object"); info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), - HasSubstr("GL_OES_vertex_array_object")); + HasSubstr("GL_OES_vertex_array_object")); EXPECT_TRUE(info_->feature_flags().native_vertex_array_object_); } @@ -773,7 +776,7 @@ TEST_F(FeatureInfoTest, InitializeARB_vertex_array_object) { SetupInitExpectations("GL_ARB_vertex_array_object"); info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), - HasSubstr("GL_OES_vertex_array_object")); + HasSubstr("GL_OES_vertex_array_object")); EXPECT_TRUE(info_->feature_flags().native_vertex_array_object_); } @@ -781,7 +784,7 @@ TEST_F(FeatureInfoTest, InitializeAPPLE_vertex_array_object) { SetupInitExpectations("GL_APPLE_vertex_array_object"); info_->Initialize(NULL); EXPECT_THAT(info_->extensions(), - HasSubstr("GL_OES_vertex_array_object")); + HasSubstr("GL_OES_vertex_array_object")); EXPECT_TRUE(info_->feature_flags().native_vertex_array_object_); } @@ -791,6 +794,8 @@ TEST_F(FeatureInfoTest, InitializeNo_vertex_array_object) { // Even if the native extensions are not available the implementation // may still emulate the GL_OES_vertex_array_object functionality. In this // scenario native_vertex_array_object must be false. + EXPECT_THAT(info_->extensions(), + HasSubstr("GL_OES_vertex_array_object")); EXPECT_FALSE(info_->feature_flags().native_vertex_array_object_); } @@ -800,6 +805,7 @@ TEST_F(FeatureInfoTest, IsIntel) { EXPECT_TRUE(info_->feature_flags().is_intel); EXPECT_FALSE(info_->feature_flags().is_nvidia); EXPECT_FALSE(info_->feature_flags().is_amd); + EXPECT_FALSE(info_->feature_flags().is_mesa); SetupInitExpectationsWithVendor("", "", "IntEl"); FeatureInfo::Ref feature_info(new FeatureInfo()); @@ -807,6 +813,7 @@ TEST_F(FeatureInfoTest, IsIntel) { EXPECT_TRUE(feature_info->feature_flags().is_intel); EXPECT_FALSE(feature_info->feature_flags().is_nvidia); EXPECT_FALSE(feature_info->feature_flags().is_amd); + EXPECT_FALSE(info_->feature_flags().is_mesa); } TEST_F(FeatureInfoTest, IsNvidia) { @@ -815,6 +822,7 @@ TEST_F(FeatureInfoTest, IsNvidia) { EXPECT_FALSE(info_->feature_flags().is_intel); EXPECT_TRUE(info_->feature_flags().is_nvidia); EXPECT_FALSE(info_->feature_flags().is_amd); + EXPECT_FALSE(info_->feature_flags().is_mesa); SetupInitExpectationsWithVendor("", "", "NViDiA"); { @@ -823,6 +831,7 @@ TEST_F(FeatureInfoTest, IsNvidia) { EXPECT_FALSE(feature_info->feature_flags().is_intel); EXPECT_TRUE(feature_info->feature_flags().is_nvidia); EXPECT_FALSE(feature_info->feature_flags().is_amd); + EXPECT_FALSE(feature_info->feature_flags().is_mesa); } SetupInitExpectationsWithVendor("", "NVIDIA Corporation", ""); @@ -832,6 +841,7 @@ TEST_F(FeatureInfoTest, IsNvidia) { EXPECT_FALSE(feature_info->feature_flags().is_intel); EXPECT_TRUE(feature_info->feature_flags().is_nvidia); EXPECT_FALSE(feature_info->feature_flags().is_amd); + EXPECT_FALSE(feature_info->feature_flags().is_mesa); } } @@ -841,6 +851,7 @@ TEST_F(FeatureInfoTest, IsAMD) { EXPECT_FALSE(info_->feature_flags().is_intel); EXPECT_FALSE(info_->feature_flags().is_nvidia); EXPECT_TRUE(info_->feature_flags().is_amd); + EXPECT_FALSE(info_->feature_flags().is_mesa); SetupInitExpectationsWithVendor("", "", "AmD"); FeatureInfo::Ref feature_info(new FeatureInfo()); @@ -848,6 +859,7 @@ TEST_F(FeatureInfoTest, IsAMD) { EXPECT_FALSE(feature_info->feature_flags().is_intel); EXPECT_FALSE(feature_info->feature_flags().is_nvidia); EXPECT_TRUE(feature_info->feature_flags().is_amd); + EXPECT_FALSE(feature_info->feature_flags().is_mesa); } TEST_F(FeatureInfoTest, IsAMDATI) { @@ -856,6 +868,7 @@ TEST_F(FeatureInfoTest, IsAMDATI) { EXPECT_FALSE(info_->feature_flags().is_intel); EXPECT_FALSE(info_->feature_flags().is_nvidia); EXPECT_TRUE(info_->feature_flags().is_amd); + EXPECT_FALSE(info_->feature_flags().is_mesa); SetupInitExpectationsWithVendor("", "", "AtI"); FeatureInfo::Ref feature_info(new FeatureInfo()); @@ -863,6 +876,24 @@ TEST_F(FeatureInfoTest, IsAMDATI) { EXPECT_FALSE(feature_info->feature_flags().is_intel); EXPECT_FALSE(feature_info->feature_flags().is_nvidia); EXPECT_TRUE(feature_info->feature_flags().is_amd); + EXPECT_FALSE(feature_info->feature_flags().is_mesa); +} + +TEST_F(FeatureInfoTest, IsMesa) { + SetupInitExpectationsWithVendor("", "MesA", ""); + info_->Initialize(NULL); + EXPECT_FALSE(info_->feature_flags().is_intel); + EXPECT_FALSE(info_->feature_flags().is_nvidia); + EXPECT_FALSE(info_->feature_flags().is_amd); + EXPECT_TRUE(info_->feature_flags().is_mesa); + + SetupInitExpectationsWithVendor("", "", "meSa"); + FeatureInfo::Ref feature_info(new FeatureInfo()); + feature_info->Initialize(NULL); + EXPECT_FALSE(feature_info->feature_flags().is_intel); + EXPECT_FALSE(feature_info->feature_flags().is_nvidia); + EXPECT_FALSE(feature_info->feature_flags().is_amd); + EXPECT_TRUE(feature_info->feature_flags().is_mesa); } } // namespace gles2 diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index f5d455c..1159ba4 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1037,6 +1037,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Wrapper for glBindVertexArrayOES void DoBindVertexArrayOES(GLuint array); + void EmulateVertexArrayState(); // Wrapper for glBlitFramebufferEXT. void DoBlitFramebufferEXT( @@ -2130,7 +2131,8 @@ bool GLES2DecoderImpl::Initialize( default_vertex_attrib_manager_ = new VertexAttribManager(); default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs()); - vertex_attrib_manager_ = default_vertex_attrib_manager_; + // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call + DoBindVertexArrayOES(0); query_manager_.reset(new QueryManager(this, feature_info_)); vertex_array_manager_.reset(new VertexArrayManager()); @@ -2394,10 +2396,6 @@ bool GLES2DecoderImpl::Initialize( DoBindFramebuffer(GL_FRAMEBUFFER, 0); DoBindRenderbuffer(GL_RENDERBUFFER, 0); - if (feature_info_->feature_flags().native_vertex_array_object_) { - DoBindVertexArrayOES(0); - } - // AMD and Intel drivers on Mac OS apparently get gl_PointCoord // backward from the spec and this setting makes them work // correctly. rdar://problem/11883495 @@ -8820,33 +8818,31 @@ error::Error GLES2DecoderImpl::HandleEndQueryEXT( bool GLES2DecoderImpl::GenVertexArraysOESHelper( GLsizei n, const GLuint* client_ids) { - - if (!feature_info_->feature_flags().native_vertex_array_object_) { - // TODO(bajones): Emulate if not present - SetGLError(GL_INVALID_OPERATION, "glGenVertexArraysOES", "not supported."); - } - for (GLsizei ii = 0; ii < n; ++ii) { if (GetVertexAttribManager(client_ids[ii])) { return false; } } - scoped_array<GLuint> service_ids(new GLuint[n]); - glGenVertexArraysOES(n, service_ids.get()); - for (GLsizei ii = 0; ii < n; ++ii) { - CreateVertexAttribManager(client_ids[ii], service_ids[ii]); + + if (!feature_info_->feature_flags().native_vertex_array_object_) { + // Emulated VAO + for (GLsizei ii = 0; ii < n; ++ii) { + CreateVertexAttribManager(client_ids[ii], 0); + } + } else { + scoped_array<GLuint> service_ids(new GLuint[n]); + + glGenVertexArraysOES(n, service_ids.get()); + for (GLsizei ii = 0; ii < n; ++ii) { + CreateVertexAttribManager(client_ids[ii], service_ids[ii]); + } } + return true; } void GLES2DecoderImpl::DeleteVertexArraysOESHelper( GLsizei n, const GLuint* client_ids) { - if (!feature_info_->feature_flags().native_vertex_array_object_) { - // TODO(bajones): Emulate if not present - SetGLError(GL_INVALID_OPERATION, - "glDeleteVertexArraysOES", "not supported."); - } - for (GLsizei ii = 0; ii < n; ++ii) { VertexAttribManager* vao = GetVertexAttribManager(client_ids[ii]); @@ -8860,11 +8856,6 @@ void GLES2DecoderImpl::DeleteVertexArraysOESHelper( } void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) { - if (!feature_info_->feature_flags().native_vertex_array_object_) { - // TODO(bajones): Emulate if not present - SetGLError(GL_INVALID_OPERATION, "glBindVertexArrayOES", "not supported."); - } - VertexAttribManager* vao = NULL; GLuint service_id = 0; if (client_id != 0) { @@ -8881,21 +8872,36 @@ void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) { } else { service_id = vao->service_id(); } - - vertex_attrib_manager_ = vao; } else { - vertex_attrib_manager_ = default_vertex_attrib_manager_; + vao = default_vertex_attrib_manager_; } - glBindVertexArrayOES(service_id); + // Only set the VAO state if it's changed + if (vertex_attrib_manager_ != vao) { + vertex_attrib_manager_ = vao; + if (!feature_info_->feature_flags().native_vertex_array_object_) { + EmulateVertexArrayState(); + } else { + glBindVertexArrayOES(service_id); + } + } } -bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) { - if (!feature_info_->feature_flags().native_vertex_array_object_) { - // TODO(bajones): Emulate if not present - SetGLError(GL_INVALID_OPERATION, "glIsVertexArrayOES", "not supported."); +// Used when OES_vertex_array_object isn't natively supported +void GLES2DecoderImpl::EmulateVertexArrayState() { + // Setup the Vertex attribute state + for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) { + RestoreStateForAttrib(vv); } + // Setup the element buffer + BufferManager::BufferInfo* element_array_buffer = + vertex_attrib_manager_->element_array_buffer(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, + element_array_buffer ? element_array_buffer->service_id() : 0); +} + +bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) { const VertexAttribManager* vao = GetVertexAttribManager(client_id); return vao && vao->IsValid() && !vao->IsDeleted(); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index 3a1f4c5..59e82c9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -130,47 +130,6 @@ class GLES2DecoderANGLEManualInitTest : public GLES2DecoderANGLETest { } }; -class GLES2DecoderVertexArraysOESTest : public GLES2DecoderWithShaderTest { - public: - GLES2DecoderVertexArraysOESTest() { } - - bool vertex_array_deleted_manually_; - - virtual void SetUp() { - InitDecoder( - "GL_OES_vertex_array_object", // extensions - false, // has alpha - false, // has depth - false, // has stencil - false, // request alpha - false, // request depth - false, // request stencil - true); // bind generates resource - SetupDefaultProgram(); - - EXPECT_CALL(*gl_, GenVertexArraysOES(_, _)) - .WillOnce(SetArgumentPointee<1>(kServiceVertexArrayId)) - .RetiresOnSaturation(); - GenHelper<GenVertexArraysOESImmediate>(client_vertexarray_id_); - - vertex_array_deleted_manually_ = false; - } - - virtual void TearDown() { - // This should only be set if the test handled deletion of the vertex array - // itself. Necessary because vertex_array_objects are not sharable, and thus - // not managed in the ContextGroup, meaning they will be destroyed during - // test tear down - if (!vertex_array_deleted_manually_) { - EXPECT_CALL(*gl_, DeleteVertexArraysOES(1, _)) - .Times(1) - .RetiresOnSaturation(); - } - - GLES2DecoderWithShaderTest::TearDown(); - } -}; - TEST_F(GLES2DecoderWithShaderTest, DrawArraysNoAttributesSucceeds) { SetupTexture(); AddExpectationsForSimulatedAttrib0(kNumVertices, 0); @@ -7576,144 +7535,276 @@ TEST_F(GLES2DecoderWithShaderTest, BindUniformLocationCHROMIUM) { EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } +class GLES2DecoderVertexArraysOESTest : public GLES2DecoderWithShaderTest { + public: + GLES2DecoderVertexArraysOESTest() { } + + bool vertex_array_deleted_manually_; + + virtual void SetUp() { + InitDecoder( + "GL_OES_vertex_array_object", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + true); // bind generates resource + SetupDefaultProgram(); + + AddExpectationsForGenVertexArraysOES(); + GenHelper<GenVertexArraysOESImmediate>(client_vertexarray_id_); + + vertex_array_deleted_manually_ = false; + } + + virtual void TearDown() { + // This should only be set if the test handled deletion of the vertex array + // itself. Necessary because vertex_array_objects are not sharable, and thus + // not managed in the ContextGroup, meaning they will be destroyed during + // test tear down + if (!vertex_array_deleted_manually_) { + AddExpectationsForDeleteVertexArraysOES(); + } + + GLES2DecoderWithShaderTest::TearDown(); + } + + void GenVertexArraysOESValidArgs() { + AddExpectationsForGenVertexArraysOES(); + GetSharedMemoryAs<GLuint*>()[0] = kNewClientId; + GenVertexArraysOES cmd; + cmd.Init(1, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetVertexArrayInfo(kNewClientId) != NULL); + AddExpectationsForDeleteVertexArraysOES(); + } + + void GenVertexArraysOESInvalidArgs() { + EXPECT_CALL(*gl_, GenVertexArraysOES(_, _)).Times(0); + GetSharedMemoryAs<GLuint*>()[0] = client_vertexarray_id_; + GenVertexArraysOES cmd; + cmd.Init(1, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); + } + + void GenVertexArraysOESImmediateValidArgs() { + AddExpectationsForGenVertexArraysOES(); + GenVertexArraysOESImmediate* cmd = + GetImmediateAs<GenVertexArraysOESImmediate>(); + GLuint temp = kNewClientId; + cmd->Init(1, &temp); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(*cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(GetVertexArrayInfo(kNewClientId) != NULL); + AddExpectationsForDeleteVertexArraysOES(); + } + + void GenVertexArraysOESImmediateInvalidArgs() { + EXPECT_CALL(*gl_, GenVertexArraysOES(_, _)).Times(0); + GenVertexArraysOESImmediate* cmd = + GetImmediateAs<GenVertexArraysOESImmediate>(); + cmd->Init(1, &client_vertexarray_id_); + EXPECT_EQ(error::kInvalidArguments, + ExecuteImmediateCmd(*cmd, sizeof(&client_vertexarray_id_))); + } + + void DeleteVertexArraysOESValidArgs() { + AddExpectationsForDeleteVertexArraysOES(); + GetSharedMemoryAs<GLuint*>()[0] = client_vertexarray_id_; + DeleteVertexArraysOES cmd; + cmd.Init(1, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE( + GetVertexArrayInfo(client_vertexarray_id_) == NULL); + vertex_array_deleted_manually_ = true; + } + + void DeleteVertexArraysOESInvalidArgs() { + GetSharedMemoryAs<GLuint*>()[0] = kInvalidClientId; + DeleteVertexArraysOES cmd; + cmd.Init(1, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + + void DeleteVertexArraysOESImmediateValidArgs() { + AddExpectationsForDeleteVertexArraysOES(); + DeleteVertexArraysOESImmediate& cmd = + *GetImmediateAs<DeleteVertexArraysOESImmediate>(); + cmd.Init(1, &client_vertexarray_id_); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(cmd, sizeof(client_vertexarray_id_))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE( + GetVertexArrayInfo(client_vertexarray_id_) == NULL); + vertex_array_deleted_manually_ = true; + } + + void DeleteVertexArraysOESImmediateInvalidArgs() { + DeleteVertexArraysOESImmediate& cmd = + *GetImmediateAs<DeleteVertexArraysOESImmediate>(); + GLuint temp = kInvalidClientId; + cmd.Init(1, &temp); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(cmd, sizeof(temp))); + } + + void IsVertexArrayOESValidArgs() { + IsVertexArrayOES cmd; + cmd.Init(client_vertexarray_id_, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + + void IsVertexArrayOESInvalidArgsBadSharedMemoryId() { + IsVertexArrayOES cmd; + cmd.Init( + client_vertexarray_id_, kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init( + client_vertexarray_id_, shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + } + + void BindVertexArrayOESValidArgs() { + AddExpectationsForBindVertexArrayOES(); + BindVertexArrayOES cmd; + cmd.Init(client_vertexarray_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + + void BindVertexArrayOESValidArgsNewId() { + BindVertexArrayOES cmd; + cmd.Init(kNewClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + } +}; + +class GLES2DecoderEmulatedVertexArraysOESTest + : public GLES2DecoderVertexArraysOESTest { + public: + GLES2DecoderEmulatedVertexArraysOESTest() { } + + virtual void SetUp() { + InitDecoder( + "", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + true); // bind generates resource + SetupDefaultProgram(); + + AddExpectationsForGenVertexArraysOES(); + GenHelper<GenVertexArraysOESImmediate>(client_vertexarray_id_); + + vertex_array_deleted_manually_ = false; + } +}; + +// Test vertex array objects with native support TEST_F(GLES2DecoderVertexArraysOESTest, GenVertexArraysOESValidArgs) { - EXPECT_CALL(*gl_, GenVertexArraysOES(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - GetSharedMemoryAs<GLuint*>()[0] = kNewClientId; - SpecializedSetup<GenVertexArraysOES, 0>(true); - GenVertexArraysOES cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(GetVertexArrayInfo(kNewClientId) != NULL); - EXPECT_CALL(*gl_, DeleteVertexArraysOES(1, _)) - .Times(1); + GenVertexArraysOESValidArgs(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, GenVertexArraysOESValidArgs) { + GenVertexArraysOESValidArgs(); } TEST_F(GLES2DecoderVertexArraysOESTest, GenVertexArraysOESInvalidArgs) { - EXPECT_CALL(*gl_, GenVertexArraysOES(_, _)).Times(0); - GetSharedMemoryAs<GLuint*>()[0] = client_vertexarray_id_; - SpecializedSetup<GenVertexArraysOES, 0>(false); - GenVertexArraysOES cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); + GenVertexArraysOESInvalidArgs(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, ) { + GenVertexArraysOESInvalidArgs(); } TEST_F(GLES2DecoderVertexArraysOESTest, GenVertexArraysOESImmediateValidArgs) { - EXPECT_CALL(*gl_, GenVertexArraysOES(1, _)) - .WillOnce(SetArgumentPointee<1>(kNewServiceId)); - GenVertexArraysOESImmediate* cmd = - GetImmediateAs<GenVertexArraysOESImmediate>(); - GLuint temp = kNewClientId; - SpecializedSetup<GenVertexArraysOESImmediate, 0>(true); - cmd->Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(*cmd, sizeof(temp))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(GetVertexArrayInfo(kNewClientId) != NULL); - EXPECT_CALL(*gl_, DeleteVertexArraysOES(1, _)) - .Times(1); + GenVertexArraysOESImmediateValidArgs(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, + GenVertexArraysOESImmediateValidArgs) { + GenVertexArraysOESImmediateValidArgs(); } TEST_F(GLES2DecoderVertexArraysOESTest, GenVertexArraysOESImmediateInvalidArgs) { - EXPECT_CALL(*gl_, GenVertexArraysOES(_, _)).Times(0); - GenVertexArraysOESImmediate* cmd = - GetImmediateAs<GenVertexArraysOESImmediate>(); - SpecializedSetup<GenVertexArraysOESImmediate, 0>(false); - cmd->Init(1, &client_vertexarray_id_); - EXPECT_EQ(error::kInvalidArguments, - ExecuteImmediateCmd(*cmd, sizeof(&client_vertexarray_id_))); + GenVertexArraysOESImmediateInvalidArgs(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, + GenVertexArraysOESImmediateInvalidArgs) { + GenVertexArraysOESImmediateInvalidArgs(); } TEST_F(GLES2DecoderVertexArraysOESTest, DeleteVertexArraysOESValidArgs) { - EXPECT_CALL( - *gl_, - DeleteVertexArraysOES(1, Pointee(kServiceVertexArrayId))) - .Times(1); - GetSharedMemoryAs<GLuint*>()[0] = client_vertexarray_id_; - SpecializedSetup<DeleteVertexArraysOES, 0>(true); - DeleteVertexArraysOES cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetVertexArrayInfo(client_vertexarray_id_) == NULL); - vertex_array_deleted_manually_ = true; + DeleteVertexArraysOESValidArgs(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, + DeleteVertexArraysOESValidArgs) { + DeleteVertexArraysOESValidArgs(); } TEST_F(GLES2DecoderVertexArraysOESTest, DeleteVertexArraysOESInvalidArgs) { - GetSharedMemoryAs<GLuint*>()[0] = kInvalidClientId; - SpecializedSetup<DeleteVertexArraysOES, 0>(false); - DeleteVertexArraysOES cmd; - cmd.Init(1, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + DeleteVertexArraysOESInvalidArgs(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, + DeleteVertexArraysOESInvalidArgs) { + DeleteVertexArraysOESInvalidArgs(); } TEST_F(GLES2DecoderVertexArraysOESTest, DeleteVertexArraysOESImmediateValidArgs) { - EXPECT_CALL( - *gl_, - DeleteVertexArraysOES(1, Pointee(kServiceVertexArrayId))) - .Times(1); - DeleteVertexArraysOESImmediate& cmd = - *GetImmediateAs<DeleteVertexArraysOESImmediate>(); - SpecializedSetup<DeleteVertexArraysOESImmediate, 0>(true); - cmd.Init(1, &client_vertexarray_id_); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(client_vertexarray_id_))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE( - GetVertexArrayInfo(client_vertexarray_id_) == NULL); - vertex_array_deleted_manually_ = true; + DeleteVertexArraysOESImmediateValidArgs(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, + DeleteVertexArraysOESImmediateValidArgs) { + DeleteVertexArraysOESImmediateValidArgs(); } TEST_F(GLES2DecoderVertexArraysOESTest, DeleteVertexArraysOESImmediateInvalidArgs) { - DeleteVertexArraysOESImmediate& cmd = - *GetImmediateAs<DeleteVertexArraysOESImmediate>(); - SpecializedSetup<DeleteVertexArraysOESImmediate, 0>(false); - GLuint temp = kInvalidClientId; - cmd.Init(1, &temp); - EXPECT_EQ(error::kNoError, - ExecuteImmediateCmd(cmd, sizeof(temp))); + DeleteVertexArraysOESImmediateInvalidArgs(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, + DeleteVertexArraysOESImmediateInvalidArgs) { + DeleteVertexArraysOESImmediateInvalidArgs(); } TEST_F(GLES2DecoderVertexArraysOESTest, IsVertexArrayOESValidArgs) { - SpecializedSetup<IsVertexArrayOES, 0>(true); - IsVertexArrayOES cmd; - cmd.Init(client_vertexarray_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); + IsVertexArrayOESValidArgs(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, IsVertexArrayOESValidArgs) { + IsVertexArrayOESValidArgs(); } TEST_F(GLES2DecoderVertexArraysOESTest, IsVertexArrayOESInvalidArgsBadSharedMemoryId) { - SpecializedSetup<IsVertexArrayOES, 0>(false); - IsVertexArrayOES cmd; - cmd.Init( - client_vertexarray_id_, kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init( - client_vertexarray_id_, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + IsVertexArrayOESInvalidArgsBadSharedMemoryId(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, + IsVertexArrayOESInvalidArgsBadSharedMemoryId) { + IsVertexArrayOESInvalidArgsBadSharedMemoryId(); } TEST_F(GLES2DecoderVertexArraysOESTest, BindVertexArrayOESValidArgs) { - EXPECT_CALL(*gl_, BindVertexArrayOES(kServiceVertexArrayId)); - SpecializedSetup<BindVertexArrayOES, 0>(true); - BindVertexArrayOES cmd; - cmd.Init(client_vertexarray_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); + BindVertexArrayOESValidArgs(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, BindVertexArrayOESValidArgs) { + BindVertexArrayOESValidArgs(); } TEST_F(GLES2DecoderVertexArraysOESTest, BindVertexArrayOESValidArgsNewId) { - SpecializedSetup<BindVertexArrayOES, 0>(true); - BindVertexArrayOES cmd; - cmd.Init(kNewClientId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + BindVertexArrayOESValidArgsNewId(); +} +TEST_F(GLES2DecoderEmulatedVertexArraysOESTest, + BindVertexArrayOESValidArgsNewId) { + BindVertexArrayOESValidArgsNewId(); } // TODO(gman): Complete this test. diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 0350fd7..b51aa55 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -15,6 +15,7 @@ #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/program_manager.h" +#include "gpu/command_buffer/service/vertex_attrib_manager.h" #include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_implementation.h" @@ -98,6 +99,8 @@ void GLES2DecoderTestBase::InitDecoder( AddExpectationsForVertexAttribManager(); + AddExpectationsForBindVertexArrayOES(); + EXPECT_CALL(*gl_, EnableVertexAttribArray(0)) .Times(1) .RetiresOnSaturation(); @@ -305,12 +308,6 @@ void GLES2DecoderTestBase::InitDecoder( .Times(1) .RetiresOnSaturation(); - if (group_->feature_info()->feature_flags().native_vertex_array_object_) { - EXPECT_CALL(*gl_, BindVertexArrayOES(0)) - .Times(1) - .RetiresOnSaturation(); - } - engine_.reset(new StrictMock<MockCommandBufferEngine>()); Buffer buffer = engine_->GetSharedMemoryBuffer(kSharedMemoryId); shared_memory_offset_ = kSharedMemoryOffset; @@ -987,6 +984,69 @@ void GLES2DecoderTestBase::DoVertexAttribDivisorANGLE( EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } +void GLES2DecoderTestBase::AddExpectationsForGenVertexArraysOES(){ + if (group_->feature_info()->feature_flags().native_vertex_array_object_) { + EXPECT_CALL(*gl_, GenVertexArraysOES(1, _)) + .WillOnce(SetArgumentPointee<1>(kServiceVertexArrayId)) + .RetiresOnSaturation(); + } +} + +void GLES2DecoderTestBase::AddExpectationsForDeleteVertexArraysOES(){ + if (group_->feature_info()->feature_flags().native_vertex_array_object_) { + EXPECT_CALL(*gl_, DeleteVertexArraysOES(1, _)) + .Times(1) + .RetiresOnSaturation(); + } +} + +void GLES2DecoderTestBase::AddExpectationsForBindVertexArrayOES() { + if (group_->feature_info()->feature_flags().native_vertex_array_object_) { + EXPECT_CALL(*gl_, BindVertexArrayOES(_)) + .Times(1) + .RetiresOnSaturation(); + } else { + for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) { + AddExpectationsForRestoreAttribState(vv); + } + + EXPECT_CALL(*gl_, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _)) + .Times(1) + .RetiresOnSaturation(); + } +} + +void GLES2DecoderTestBase::AddExpectationsForRestoreAttribState(GLuint attrib) { + EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, _)) + .Times(1) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, VertexAttribPointer(attrib, _, _, _, _, _)) + .Times(1) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(attrib, _)) + .Times(testing::AtMost(1)) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, _)) + .Times(1) + .RetiresOnSaturation(); + + if (attrib != 0 || + gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { + + // TODO(bajones): Not sure if I can tell which of these will be called + EXPECT_CALL(*gl_, EnableVertexAttribArray(attrib)) + .Times(testing::AtMost(1)) + .RetiresOnSaturation(); + + EXPECT_CALL(*gl_, DisableVertexAttribArray(attrib)) + .Times(testing::AtMost(1)) + .RetiresOnSaturation(); + } +} + // GCC requires these declarations, but MSVC requires they not be present #ifndef COMPILER_MSVC const int GLES2DecoderTestBase::kBackBufferWidth; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index a5294f1..f2fd38b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -196,6 +196,7 @@ class GLES2DecoderTestBase : public testing::Test { void DoBindFramebuffer(GLenum target, GLuint client_id, GLuint service_id); void DoBindRenderbuffer(GLenum target, GLuint client_id, GLuint service_id); void DoBindTexture(GLenum target, GLuint client_id, GLuint service_id); + void DoBindVertexArrayOES(GLuint client_id, GLuint service_id); bool DoIsBuffer(GLuint client_id); bool DoIsFramebuffer(GLuint client_id); @@ -328,6 +329,11 @@ class GLES2DecoderTestBase : public testing::Test { void AddExpectationsForSimulatedAttrib0( GLsizei num_vertices, GLuint buffer_id); + void AddExpectationsForGenVertexArraysOES(); + void AddExpectationsForDeleteVertexArraysOES(); + void AddExpectationsForBindVertexArrayOES(); + void AddExpectationsForRestoreAttribState(GLuint attrib); + GLvoid* BufferOffset(unsigned i) { return static_cast<int8 *>(NULL)+(i); } diff --git a/gpu/command_buffer/service/vertex_attrib_manager.cc b/gpu/command_buffer/service/vertex_attrib_manager.cc index 7d15938..f8bc061 100644 --- a/gpu/command_buffer/service/vertex_attrib_manager.cc +++ b/gpu/command_buffer/service/vertex_attrib_manager.cc @@ -86,8 +86,8 @@ VertexAttribManager::VertexAttribManager( VertexAttribManager::~VertexAttribManager() { if (manager_) { if (manager_->have_context_) { - GLuint id = service_id(); - glDeleteVertexArraysOES(1, &id); + if (service_id_ != 0) // 0 indicates an emulated VAO + glDeleteVertexArraysOES(1, &service_id_); } manager_->StopTracking(this); manager_ = NULL; |