diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-09 21:07:00 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-09 21:07:00 +0000 |
commit | efcdd2363d66f110d0e67fcff68e2f8f22bbf7be (patch) | |
tree | aa93312d779f4ecd648ad5ae3fd908316c7abcfe | |
parent | 70ec89769238adca7ae8db6df7cdd1c109b64486 (diff) | |
download | chromium_src-efcdd2363d66f110d0e67fcff68e2f8f22bbf7be.zip chromium_src-efcdd2363d66f110d0e67fcff68e2f8f22bbf7be.tar.gz chromium_src-efcdd2363d66f110d0e67fcff68e2f8f22bbf7be.tar.bz2 |
Add GL_CHROMIUM_get_error_query
Makes it possible to asynchronously query GL errors.
TEST=unit tests
BUG=133630
Review URL: https://chromiumcodereview.appspot.com/10577037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@145739 0039d316-1c4b-4281-b951-d872f2087c98
20 files changed, 324 insertions, 60 deletions
diff --git a/gpu/command_buffer/client/atomicops.h b/gpu/command_buffer/client/atomicops.h index 7fa68bd..517ef07 100644 --- a/gpu/command_buffer/client/atomicops.h +++ b/gpu/command_buffer/client/atomicops.h @@ -11,7 +11,7 @@ namespace gpu { -void MemoryBarrier(); +GPU_EXPORT void MemoryBarrier(); class LockImpl; class GPU_EXPORT Lock { diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index ca3a9e7..d6f7723 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -503,6 +503,10 @@ GLES2Implementation::~GLES2Implementation() { Finish(); } +GLES2CmdHelper* GLES2Implementation::helper() const { + return helper_; +} + GLuint GLES2Implementation::MakeTextureId() { GLuint id; GetIdHandler(id_namespaces::kTextures)->MakeIds(this, 0, 1, &id); @@ -592,11 +596,28 @@ GLenum GLES2Implementation::GetError() { return err; } +GLenum GLES2Implementation::GetClientSideGLError() { + if (error_bits_ == 0) { + return GL_NO_ERROR; + } + + GLenum error = GL_NO_ERROR; + for (uint32 mask = 1; mask != 0; mask = mask << 1) { + if ((error_bits_ & mask) != 0) { + error = GLES2Util::GLErrorBitToGLError(mask); + break; + } + } + error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error); + return error; +} + GLenum GLES2Implementation::GetGLError() { TRACE_EVENT0("gpu", "GLES2::GetGLError"); // Check the GL error first, then our wrapped error. typedef gles2::GetError::Result Result; Result* result = GetResultAs<Result*>(); + // If we couldn't allocate a result the context is lost. if (!result) { return GL_NO_ERROR; } @@ -604,16 +625,9 @@ GLenum GLES2Implementation::GetGLError() { helper_->GetError(GetResultShmId(), GetResultShmOffset()); WaitForCmd(); GLenum error = *result; - if (error == GL_NO_ERROR && error_bits_ != 0) { - for (uint32 mask = 1; mask != 0; mask = mask << 1) { - if ((error_bits_ & mask) != 0) { - error = GLES2Util::GLErrorBitToGLError(mask); - break; - } - } - } - - if (error != GL_NO_ERROR) { + if (error == GL_NO_ERROR) { + error = GetClientSideGLError(); + } else { // There was an error, clear the corresponding wrapped error. error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error); } @@ -3085,11 +3099,7 @@ void GLES2Implementation::BeginQueryEXT(GLenum target, GLuint id) { current_query_ = query; - // init memory, inc count - query->MarkAsActive(); - - // tell service about id, shared memory and count - helper_->BeginQueryEXT(target, id, query->shm_id(), query->shm_offset()); + query->Begin(this); } void GLES2Implementation::EndQueryEXT(GLenum target) { @@ -3108,8 +3118,7 @@ void GLES2Implementation::EndQueryEXT(GLenum target) { return; } - helper_->EndQueryEXT(target, current_query_->submit_count()); - current_query_->MarkAsPending(helper_->InsertToken()); + current_query_->End(this); current_query_ = NULL; } diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index bf68273..9b07a32 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -198,9 +198,10 @@ class GLES2_IMPL_EXPORT GLES2Implementation { // The GLES2CmdHelper being used by this GLES2Implementation. You can use // this to issue cmds at a lower level for certain kinds of optimization. - GLES2CmdHelper* helper() const { - return helper_; - } + GLES2CmdHelper* helper() const; + + // Gets client side generated errors. + GLenum GetClientSideGLError(); // Include the auto-generated part of this class. We split this because // it means we can easily edit the non-auto generated parts right here in diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index b7f599b4..c64696f 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -2564,6 +2564,60 @@ TEST_F(GLES2ImplementationTest, BeginEndQueryEXT) { EXPECT_EQ(0u, available); } +TEST_F(GLES2ImplementationTest, ErrorQuery) { + GLuint id = 0; + gl_->GenQueriesEXT(1, &id); + ClearCommands(); + + // Test BeginQueryEXT does NOT insert commands. + gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id); + EXPECT_TRUE(NoCommandsWritten()); + QueryTracker::Query* query = GetQuery(id); + ASSERT_TRUE(query != NULL); + + // Test EndQueryEXT sends both begin and end command + struct EndCmds { + BeginQueryEXT begin_query; + EndQueryEXT end_query; + }; + EndCmds expected_end_cmds; + expected_end_cmds.begin_query.Init( + GL_GET_ERROR_QUERY_CHROMIUM, id, query->shm_id(), query->shm_offset()); + expected_end_cmds.end_query.Init( + GL_GET_ERROR_QUERY_CHROMIUM, query->submit_count()); + const void* commands = GetPut(); + gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM); + EXPECT_EQ(0, memcmp( + &expected_end_cmds, commands, sizeof(expected_end_cmds))); + ClearCommands(); + + // Check result is not yet available. + GLuint available = 0xBDu; + gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available); + EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(0u, available); + + // Test no commands are sent if there is a client side error. + + // Generate a client side error + gl_->ActiveTexture(GL_TEXTURE0 - 1); + + gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id); + gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM); + EXPECT_TRUE(NoCommandsWritten()); + + // Check result is available. + gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available); + EXPECT_TRUE(NoCommandsWritten()); + EXPECT_NE(0u, available); + + // Check result. + GLuint result = 0xBDu; + gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_EXT, &result); + EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(static_cast<GLuint>(GL_INVALID_ENUM), result); +} + #include "gpu/command_buffer/client/gles2_implementation_unittest_autogen.h" } // namespace gles2 diff --git a/gpu/command_buffer/client/query_tracker.cc b/gpu/command_buffer/client/query_tracker.cc index 5d08f2e..e1e150f 100644 --- a/gpu/command_buffer/client/query_tracker.cc +++ b/gpu/command_buffer/client/query_tracker.cc @@ -2,10 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + #include "../client/query_tracker.h" #include "../client/atomicops.h" -#include "../client/cmd_buffer_helper.h" +#include "../client/gles2_cmd_helper.h" +#include "../client/gles2_implementation.h" #include "../client/mapped_memory.h" namespace gpu { @@ -51,6 +55,44 @@ void QuerySyncManager::Free(const QuerySyncManager::QueryInfo& info) { free_queries_.push(info); } +void QueryTracker::Query::Begin(GLES2Implementation* gl) { + // init memory, inc count + MarkAsActive(); + + switch (target()) { + case GL_GET_ERROR_QUERY_CHROMIUM: + // To nothing on begin for error queries. + break; + default: + // tell service about id, shared memory and count + gl->helper()->BeginQueryEXT(target(), id(), shm_id(), shm_offset()); + break; + } +} + +void QueryTracker::Query::End(GLES2Implementation* gl) { + switch (target()) { + case GL_GET_ERROR_QUERY_CHROMIUM: { + GLenum error = gl->GetClientSideGLError(); + if (error == GL_NO_ERROR) { + // There was no error so start the query on the serivce. + // it will end immediately. + gl->helper()->BeginQueryEXT(target(), id(), shm_id(), shm_offset()); + } else { + // There's an error on the client, no need to bother the service. just + // set the query as completed and return the error. + if (error != GL_NO_ERROR) { + state_ = kComplete; + result_ = error; + return; + } + } + } + } + gl->helper()->EndQueryEXT(target(), submit_count()); + MarkAsPending(gl->helper()->InsertToken()); +} + bool QueryTracker::Query::CheckResultsAvailable( CommandBufferHelper* helper) { if (Pending()) { diff --git a/gpu/command_buffer/client/query_tracker.h b/gpu/command_buffer/client/query_tracker.h index 9746497..adaba82 100644 --- a/gpu/command_buffer/client/query_tracker.h +++ b/gpu/command_buffer/client/query_tracker.h @@ -8,9 +8,9 @@ #include <GLES2/gl2.h> #include <queue> -#include "../../gpu_export.h" #include "../client/hash_tables.h" #include "../common/gles2_cmd_format.h" +#include "gles2_impl_export.h" namespace gpu { @@ -19,8 +19,10 @@ class MappedMemoryManager; namespace gles2 { +class GLES2Implementation; + // Manages buckets of QuerySync instances in mapped memory. -class GPU_EXPORT QuerySyncManager { +class GLES2_IMPL_EXPORT QuerySyncManager { public: static const size_t kSyncsPerBucket = 4096; @@ -57,9 +59,9 @@ class GPU_EXPORT QuerySyncManager { }; // Tracks queries for client side of command buffer. -class GPU_EXPORT QueryTracker { +class GLES2_IMPL_EXPORT QueryTracker { public: - class GPU_EXPORT Query { + class GLES2_IMPL_EXPORT Query { public: enum State { kUninitialized, // never used @@ -126,6 +128,9 @@ class GPU_EXPORT QueryTracker { uint32 GetResult() const; + void Begin(GLES2Implementation* gl); + void End(GLES2Implementation* gl); + private: friend class QueryTracker; friend class QueryTrackerTest; diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 7983ffd..c7dce24 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -176,17 +176,18 @@ void FeatureInfo::AddFeatures(const char* desired_features) { bool npot_ok = false; + AddExtensionString("GL_ANGLE_translated_shader_source"); AddExtensionString("GL_CHROMIUM_bind_uniform_location"); - AddExtensionString("GL_CHROMIUM_resource_safe"); - AddExtensionString("GL_CHROMIUM_resize"); - AddExtensionString("GL_CHROMIUM_strict_attribs"); - AddExtensionString("GL_CHROMIUM_rate_limit_offscreen_context"); - AddExtensionString("GL_CHROMIUM_set_visibility"); - AddExtensionString("GL_CHROMIUM_discard_framebuffer"); AddExtensionString("GL_CHROMIUM_command_buffer_query"); AddExtensionString("GL_CHROMIUM_copy_texture"); + AddExtensionString("GL_CHROMIUM_discard_framebuffer"); + AddExtensionString("GL_CHROMIUM_get_error_query"); + AddExtensionString("GL_CHROMIUM_rate_limit_offscreen_context"); + AddExtensionString("GL_CHROMIUM_resize"); + AddExtensionString("GL_CHROMIUM_resource_safe"); + AddExtensionString("GL_CHROMIUM_set_visibility"); + AddExtensionString("GL_CHROMIUM_strict_attribs"); AddExtensionString("GL_CHROMIUM_texture_mailbox"); - AddExtensionString("GL_ANGLE_translated_shader_source"); if (!disallowed_features_.gpu_memory_manager) AddExtensionString("GL_CHROMIUM_gpu_memory_manager"); diff --git a/gpu/command_buffer/service/gl_utils.h b/gpu/command_buffer/service/gl_utils.h index 316c3bb..5788670 100644 --- a/gpu/command_buffer/service/gl_utils.h +++ b/gpu/command_buffer/service/gl_utils.h @@ -86,6 +86,9 @@ // GL_CHROMIUM_command_buffer_query #define GL_COMMANDS_ISSUED_CHROMIUM 0x84F2 +/* GL_CHROMIUM_get_error_query */ +#define GL_GET_ERROR_QUERY_CHROMIUM 0x84F3 + // GL_OES_texure_3D #define GL_SAMPLER_3D_OES 0x8B5F diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 7510160..81ecee4 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -514,6 +514,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, virtual bool GetServiceTextureId(uint32 client_texture_id, uint32* service_texture_id); + virtual uint32 GetGLError() OVERRIDE; + // Restores the current state to the user's settings. void RestoreCurrentFramebufferBindings(); void RestoreCurrentRenderbufferBindings(); @@ -1176,9 +1178,6 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // false if pname is unknown. bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values); - // Gets the GLError through our wrapper. - GLenum GetGLError(); - // Gets the GLError and stores it in our wrapper. Effectively // this lets us peek at the error without losing it. GLenum PeekGLError(); @@ -5046,7 +5045,7 @@ void GLES2DecoderImpl::DoUseProgram(GLuint program) { } } -GLenum GLES2DecoderImpl::GetGLError() { +uint32 GLES2DecoderImpl::GetGLError() { // Check the GL error first, then our wrapped error. GLenum error = glGetError(); if (error == GL_NO_ERROR && error_bits_ != 0) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index a5d00d9..cc604fc 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -167,6 +167,9 @@ class GPU_EXPORT GLES2Decoder : public CommonDecoder { int height, bool is_texture_immutable) = 0; + // Gets the GL error for this context. + virtual uint32 GetGLError() = 0; + // A callback for messages from the decoder. virtual void SetMsgCallback(const MsgCallback& callback) = 0; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index e5bdf30..073b0c1 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h @@ -72,6 +72,7 @@ class MockGLES2Decoder : public GLES2Decoder { int width, int height, bool is_texture_immutable)); + MOCK_METHOD0(GetGLError, uint32()); MOCK_METHOD1(SetMsgCallback, void(const MsgCallback& callback)); DISALLOW_COPY_AND_ASSIGN(MockGLES2Decoder); diff --git a/gpu/command_buffer/service/query_manager.cc b/gpu/command_buffer/service/query_manager.cc index 14a4ab4..0f94d46 100644 --- a/gpu/command_buffer/service/query_manager.cc +++ b/gpu/command_buffer/service/query_manager.cc @@ -7,7 +7,7 @@ #include "base/logging.h" #include "base/time.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" -#include "gpu/command_buffer/service/common_decoder.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/feature_info.h" namespace gpu { @@ -120,8 +120,52 @@ void CommandsIssuedQuery::Destroy(bool /* have_context */) { CommandsIssuedQuery::~CommandsIssuedQuery() { } +class GetErrorQuery : public QueryManager::Query { + public: + GetErrorQuery( + QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); + + virtual bool Begin() OVERRIDE; + virtual bool End(uint32 submit_count) OVERRIDE; + virtual bool Process() OVERRIDE; + virtual void Destroy(bool have_context) OVERRIDE; + + protected: + virtual ~GetErrorQuery(); + + private: +}; + +GetErrorQuery::GetErrorQuery( + QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset) + : Query(manager, target, shm_id, shm_offset) { +} + +bool GetErrorQuery::Begin() { + return true; +} + +bool GetErrorQuery::End(uint32 submit_count) { + MarkAsPending(submit_count); + return MarkAsCompleted(manager()->decoder()->GetGLError()); +} + +bool GetErrorQuery::Process() { + NOTREACHED(); + return true; +} + +void GetErrorQuery::Destroy(bool /* have_context */) { + if (!IsDeleted()) { + MarkAsDeleted(); + } +} + +GetErrorQuery::~GetErrorQuery() { +} + QueryManager::QueryManager( - CommonDecoder* decoder, + GLES2Decoder* decoder, FeatureInfo* feature_info) : decoder_(decoder), use_arb_occlusion_query2_for_occlusion_query_boolean_( @@ -159,6 +203,9 @@ QueryManager::Query* QueryManager::CreateQuery( case GL_COMMANDS_ISSUED_CHROMIUM: query = new CommandsIssuedQuery(this, target, shm_id, shm_offset); break; + case GL_GET_ERROR_QUERY_CHROMIUM: + query = new GetErrorQuery(this, target, shm_id, shm_offset); + break; default: { GLuint service_id = 0; glGenQueriesARB(1, &service_id); @@ -253,7 +300,7 @@ QueryManager::Query::~Query() { bool QueryManager::Query::MarkAsCompleted(GLuint result) { DCHECK(pending_); QuerySync* sync = manager_->decoder_->GetSharedMemoryAs<QuerySync*>( - shm_id_, shm_offset_, sizeof(*sync)); + shm_id_, shm_offset_, sizeof(*sync)); if (!sync) { return false; } diff --git a/gpu/command_buffer/service/query_manager.h b/gpu/command_buffer/service/query_manager.h index 7e3f38d..f6d3942 100644 --- a/gpu/command_buffer/service/query_manager.h +++ b/gpu/command_buffer/service/query_manager.h @@ -17,7 +17,7 @@ namespace gpu { -class CommonDecoder; +class GLES2Decoder; namespace gles2 { @@ -132,7 +132,7 @@ class GPU_EXPORT QueryManager { }; QueryManager( - CommonDecoder* decoder, + GLES2Decoder* decoder, FeatureInfo* feature_info); ~QueryManager(); @@ -162,6 +162,10 @@ class GPU_EXPORT QueryManager { // True if there are pending queries. bool HavePendingQueries(); + GLES2Decoder* decoder() const { + return decoder_; + } + private: void StartTracking(Query* query); void StopTracking(Query* query); @@ -183,8 +187,8 @@ class GPU_EXPORT QueryManager { // used to emulate a query. GLenum AdjustTargetForEmulation(GLenum target); - // Used to validate shared memory. - CommonDecoder* decoder_; + // Used to validate shared memory and get GL errors. + GLES2Decoder* decoder_; bool use_arb_occlusion_query2_for_occlusion_query_boolean_; bool use_arb_occlusion_query_for_occlusion_query_boolean_; diff --git a/gpu/command_buffer/service/query_manager_unittest.cc b/gpu/command_buffer/service/query_manager_unittest.cc index bd2b84f..941b2e8 100644 --- a/gpu/command_buffer/service/query_manager_unittest.cc +++ b/gpu/command_buffer/service/query_manager_unittest.cc @@ -6,28 +6,20 @@ #include "gpu/command_buffer/common/gl_mock.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" -#include "gpu/command_buffer/service/common_decoder.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::_; using ::testing::InSequence; +using ::testing::Return; using ::testing::SetArgumentPointee; namespace gpu { namespace gles2 { -class MockDecoder : public CommonDecoder { - public: - virtual ~MockDecoder() { } - MOCK_METHOD3(DoCommand, error::Error( - unsigned int command, - unsigned int arg_count, - const void* cmd_data)); - MOCK_CONST_METHOD1(GetCommandName, const char* (unsigned int command_id)); -}; - class QueryManagerTest : public testing::Test { public: static const int32 kSharedMemoryId = 401; @@ -48,7 +40,7 @@ class QueryManagerTest : public testing::Test { gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); engine_.reset(new MockCommandBufferEngine()); - decoder_.reset(new MockDecoder()); + decoder_.reset(new MockGLES2Decoder()); decoder_->set_engine(engine_.get()); TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), @@ -90,7 +82,7 @@ class QueryManagerTest : public testing::Test { // Use StrictMock to make 100% sure we know how GL will be called. scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; - scoped_ptr<MockDecoder> decoder_; + scoped_ptr<MockGLES2Decoder> decoder_; scoped_ptr<QueryManager> manager_; private: @@ -469,6 +461,8 @@ TEST_F(QueryManagerTest, ExitWithPendingQuery) { QueueQuery(query.get(), kService1Id, kSubmitCount); } +// Test that when based on ARB_occlusion_query2 we use GL_ANY_SAMPLES_PASSED_ARB +// for GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT TEST_F(QueryManagerTest, ARBOcclusionQuery2) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; @@ -501,6 +495,8 @@ TEST_F(QueryManagerTest, ARBOcclusionQuery2) { manager->Destroy(false); } +// Test that when based on ARB_occlusion_query we use GL_SAMPLES_PASSED_ARB +// for GL_ANY_SAMPLES_PASSED_EXT TEST_F(QueryManagerTest, ARBOcclusionQuery) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; @@ -533,6 +529,41 @@ TEST_F(QueryManagerTest, ARBOcclusionQuery) { manager->Destroy(false); } +TEST_F(QueryManagerTest, GetErrorQuery) { + const GLuint kClient1Id = 1; + const GLenum kTarget = GL_GET_ERROR_QUERY_CHROMIUM; + const uint32 kSubmitCount = 123; + + TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), ""); + FeatureInfo::Ref feature_info(new FeatureInfo()); + feature_info->Initialize("*"); + scoped_ptr<QueryManager> manager( + new QueryManager(decoder_.get(), feature_info.get())); + + QueryManager::Query* query = manager->CreateQuery( + kTarget, kClient1Id, kSharedMemoryId, kSharedMemoryOffset); + ASSERT_TRUE(query != NULL); + + // Setup shared memory like client would. + QuerySync* sync = decoder_->GetSharedMemoryAs<QuerySync*>( + kSharedMemoryId, kSharedMemoryOffset, sizeof(*sync)); + ASSERT_TRUE(sync != NULL); + sync->Reset(); + + EXPECT_TRUE(manager->BeginQuery(query)); + + EXPECT_CALL(*decoder_.get(), GetGLError()) + .WillOnce(Return(GL_INVALID_ENUM)) + .RetiresOnSaturation(); + + EXPECT_TRUE(manager->EndQuery(query, kSubmitCount)); + EXPECT_FALSE(query->pending()); + + EXPECT_EQ(static_cast<GLuint>(GL_INVALID_ENUM), sync->result); + + manager->Destroy(false); +} + } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/tests/gl_get_error_query_unittests.cc b/gpu/command_buffer/tests/gl_get_error_query_unittests.cc new file mode 100644 index 0000000..a177044 --- /dev/null +++ b/gpu/command_buffer/tests/gl_get_error_query_unittests.cc @@ -0,0 +1,53 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include "gpu/command_buffer/tests/gl_manager.h" +#include "gpu/command_buffer/tests/gl_test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace gpu { + +class GetErrorQueryTest : public testing::Test { + protected: + virtual void SetUp() { + gl_.Initialize(gfx::Size(2, 2)); + } + + virtual void TearDown() { + gl_.Destroy(); + } + + GLManager gl_; +}; + +TEST_F(GetErrorQueryTest, Basic) { + EXPECT_TRUE(GLTestHelper::HasExtension("GL_CHROMIUM_get_error_query")); + + GLuint query = 0; + glGenQueriesEXT(1, &query); + + GLuint query_status = 0; + GLuint result = 0; + + glBeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, query); + glEnable(GL_TEXTURE_2D); // Generates an INVALID_ENUM error + glEndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM); + + glFinish(); + + query_status = 0; + result = 0; + glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &result); + EXPECT_TRUE(result); + glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &query_status); + EXPECT_EQ(static_cast<uint32>(GL_INVALID_ENUM), query_status); +} + +} // namespace gpu + + diff --git a/gpu/command_buffer_client.gypi b/gpu/command_buffer_client.gypi index f007f97..97484f6 100644 --- a/gpu/command_buffer_client.gypi +++ b/gpu/command_buffer_client.gypi @@ -23,8 +23,6 @@ 'command_buffer/client/hash_tables.h', 'command_buffer/client/mapped_memory.cc', 'command_buffer/client/mapped_memory.h', - 'command_buffer/client/query_tracker.cc', - 'command_buffer/client/query_tracker.h', 'command_buffer/client/ring_buffer.cc', 'command_buffer/client/ring_buffer.h', 'command_buffer/client/transfer_buffer.cc', diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index e87daae..1b8d54d 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp @@ -25,6 +25,8 @@ 'command_buffer/client/gles2_implementation.h', 'command_buffer/client/program_info_manager.cc', 'command_buffer/client/program_info_manager.h', + 'command_buffer/client/query_tracker.cc', + 'command_buffer/client/query_tracker.h', 'command_buffer/client/share_group.cc', 'command_buffer/client/share_group.h', ] diff --git a/gpu/gpu_common.gypi b/gpu/gpu_common.gypi index 6fa68294..d117fc0 100644 --- a/gpu/gpu_common.gypi +++ b/gpu/gpu_common.gypi @@ -231,10 +231,10 @@ ], 'sources': [ '<@(gles2_c_lib_source_files)', - 'command_buffer/tests/occlusion_query_unittests.cc', 'command_buffer/tests/gl_bind_uniform_location_unittest.cc', 'command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc', 'command_buffer/tests/gl_depth_texture_unittest.cc', + 'command_buffer/tests/gl_get_error_query_unittests.cc', 'command_buffer/tests/gl_manager.cc', 'command_buffer/tests/gl_manager.h', 'command_buffer/tests/gl_pointcoord_unittest.cc', @@ -243,6 +243,7 @@ 'command_buffer/tests/gl_test_utils.h', 'command_buffer/tests/gl_texture_mailbox_unittests.cc', 'command_buffer/tests/gl_unittests.cc', + 'command_buffer/tests/occlusion_query_unittests.cc', ], }, { diff --git a/third_party/khronos/GLES2/gl2ext.h b/third_party/khronos/GLES2/gl2ext.h index c604c12..ee0da03 100644 --- a/third_party/khronos/GLES2/gl2ext.h +++ b/third_party/khronos/GLES2/gl2ext.h @@ -1985,6 +1985,15 @@ typedef void (GL_APIENTRYP PFNGLCOPYTEXTURECHROMIUM) (GLenum target, GLenum sour #define GL_COMMANDS_ISSUED_CHROMIUM 0x84F2 #endif +/* GL_CHROMIUM_get_error_query */ +/* Exposes GL_CHROMIUM_get_error_query. + */ +#ifndef GL_CHROMIUM_get_error_query +#define GL_CHROMIUM_get_error_query 1 +// TODO(gman): Get official numbers for these constants. +#define GL_GET_ERROR_QUERY_CHROMIUM 0x84F3 +#endif + /* GL_CHROMIUM_texture_mailbox */ #ifndef GL_CHROMIUM_texture_mailbox #define GL_CHROMIUM_texture_mailbox 1 diff --git a/third_party/khronos/README.chromium b/third_party/khronos/README.chromium index 1fa97c6..bbdba9c 100644 --- a/third_party/khronos/README.chromium +++ b/third_party/khronos/README.chromium @@ -23,5 +23,6 @@ GLES2/gl2ext.h - Added GL_CHROMIUM_command_buffer_query - Added GL_CHROMIUM_copy_texture - Added GL_CHROMIUM_bind_uniform_location + - Added GL_CHROMIUM_get_error_query EGL/eglplatform.h - Added EGLNative*Type for Mac. |