summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-09 21:07:00 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-09 21:07:00 +0000
commitefcdd2363d66f110d0e67fcff68e2f8f22bbf7be (patch)
treeaa93312d779f4ecd648ad5ae3fd908316c7abcfe
parent70ec89769238adca7ae8db6df7cdd1c109b64486 (diff)
downloadchromium_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
-rw-r--r--gpu/command_buffer/client/atomicops.h2
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc43
-rw-r--r--gpu/command_buffer/client/gles2_implementation.h7
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest.cc54
-rw-r--r--gpu/command_buffer/client/query_tracker.cc44
-rw-r--r--gpu/command_buffer/client/query_tracker.h13
-rw-r--r--gpu/command_buffer/service/feature_info.cc15
-rw-r--r--gpu/command_buffer/service/gl_utils.h3
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc7
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.h3
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_mock.h1
-rw-r--r--gpu/command_buffer/service/query_manager.cc53
-rw-r--r--gpu/command_buffer/service/query_manager.h12
-rw-r--r--gpu/command_buffer/service/query_manager_unittest.cc57
-rw-r--r--gpu/command_buffer/tests/gl_get_error_query_unittests.cc53
-rw-r--r--gpu/command_buffer_client.gypi2
-rw-r--r--gpu/gpu.gyp2
-rw-r--r--gpu/gpu_common.gypi3
-rw-r--r--third_party/khronos/GLES2/gl2ext.h9
-rw-r--r--third_party/khronos/README.chromium1
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.