summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-24 00:00:40 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-24 00:00:40 +0000
commit1e6f58db132a6e641299f7cb2502dbf88a06b454 (patch)
tree75020e23a3df5fa5162494850e93c0af8a3ffa00 /gpu/command_buffer
parent5aea18697928ef225433a2c0a334f192fc4eb8e1 (diff)
downloadchromium_src-1e6f58db132a6e641299f7cb2502dbf88a06b454.zip
chromium_src-1e6f58db132a6e641299f7cb2502dbf88a06b454.tar.gz
chromium_src-1e6f58db132a6e641299f7cb2502dbf88a06b454.tar.bz2
Implement latch system to help with GPU compositing flow control.
TEST=unit tests BUG=none Review URL: http://codereview.chromium.org/6719014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79218 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py10
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h10
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h10
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h8
-rw-r--r--gpu/command_buffer/common/constants.h7
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h76
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h30
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h2
-rw-r--r--gpu/command_buffer/service/cmd_parser.cc8
-rw-r--r--gpu/command_buffer/service/cmd_parser.h2
-rw-r--r--gpu/command_buffer/service/cmd_parser_test.cc26
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc39
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc61
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc3
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h3
-rw-r--r--gpu/command_buffer/service/gpu_processor.cc3
17 files changed, 291 insertions, 9 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index c050afe..d827b82 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -211,6 +211,8 @@ GL_APICALL void GL_APIENTRY glCopyTextureToParentTextureCHROMIUM (GLidBi
GL_APICALL void GL_APIENTRY glResizeCHROMIUM (GLuint width, GLuint height);
GL_APICALL const GLchar* GL_APIENTRY glGetRequestableExtensionsCHROMIUM (void);
GL_APICALL void GL_APIENTRY glRequestExtensionCHROMIUM (const char* extension);
+GL_APICALL void GL_APIENTRY glSetLatchCHROMIUM (GLint shm_id, GLuint latch_id);
+GL_APICALL void GL_APIENTRY glWaitLatchCHROMIUM (GLint shm_id, GLuint latch_id);
"""
# This is the list of all commmands that will be generated and their Id.
@@ -414,6 +416,8 @@ _CMD_ID_TABLE = {
'ResizeCHROMIUM': 448,
'GetRequestableExtensionsCHROMIUM': 449,
'RequestExtensionCHROMIUM': 450,
+ 'SetLatchCHROMIUM': 451,
+ 'WaitLatchCHROMIUM': 452,
}
# This is a list of enum names and their valid values. It is used to map
@@ -1611,6 +1615,12 @@ _FUNCTION_INFO = {
'extension': True,
'chromium': True,
},
+ 'SetLatchCHROMIUM': {
+ 'type': 'Custom',
+ },
+ 'WaitLatchCHROMIUM': {
+ 'type': 'Custom',
+ },
}
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 953b22d..bbc0faa 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -877,6 +877,16 @@ void GLES2RequestExtensionCHROMIUM(const char* extension) {
GPU_CLIENT_LOG("RequestExtensionCHROMIUM" << "(" << extension << ")");
gles2::GetGLContext()->RequestExtensionCHROMIUM(extension);
}
+void GLES2SetLatchCHROMIUM(GLint shm_id, GLuint latch_id) {
+ GPU_CLIENT_LOG(
+ "SetLatchCHROMIUM" << "(" << shm_id << ", " << latch_id << ")");
+ gles2::GetGLContext()->SetLatchCHROMIUM(shm_id, latch_id);
+}
+void GLES2WaitLatchCHROMIUM(GLint shm_id, GLuint latch_id) {
+ GPU_CLIENT_LOG(
+ "WaitLatchCHROMIUM" << "(" << shm_id << ", " << latch_id << ")");
+ gles2::GetGLContext()->WaitLatchCHROMIUM(shm_id, latch_id);
+}
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_C_LIB_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index 2dc0687..dc50582 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -1215,5 +1215,15 @@
c.Init(bucket_id);
}
+ void SetLatchCHROMIUM(GLint shm_id, GLuint latch_id) {
+ gles2::SetLatchCHROMIUM& c = GetCmdSpace<gles2::SetLatchCHROMIUM>();
+ c.Init(shm_id, latch_id);
+ }
+
+ void WaitLatchCHROMIUM(GLint shm_id, GLuint latch_id) {
+ gles2::WaitLatchCHROMIUM& c = GetCmdSpace<gles2::WaitLatchCHROMIUM>();
+ c.Init(shm_id, latch_id);
+ }
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index a8fcfa0..5e05132 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -889,5 +889,13 @@ const GLchar* GetRequestableExtensionsCHROMIUM();
void RequestExtensionCHROMIUM(const char* extension);
+void SetLatchCHROMIUM(GLint shm_id, GLuint latch_id) {
+ helper_->SetLatchCHROMIUM(shm_id, latch_id);
+}
+
+void WaitLatchCHROMIUM(GLint shm_id, GLuint latch_id) {
+ helper_->WaitLatchCHROMIUM(shm_id, latch_id);
+}
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/constants.h b/gpu/command_buffer/common/constants.h
index 79b0048..c028fc9 100644
--- a/gpu/command_buffer/common/constants.h
+++ b/gpu/command_buffer/common/constants.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -23,6 +23,11 @@ namespace error {
kLostContext,
kGenericError,
+ // This is not an error. It is returned by commands that want to
+ // be called again until they return a different error. For
+ // example: WaitLatch.
+ kWaiting,
+
// This is not an error. It is returned by commands to mark a position
// in the command buffer that should not be issued to the the GL backend
// until no more than a fixed number of such positions have already been
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 8a37edb..4e97bc5 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -8901,6 +8901,82 @@ COMPILE_ASSERT(offsetof(RequestExtensionCHROMIUM, header) == 0,
COMPILE_ASSERT(offsetof(RequestExtensionCHROMIUM, bucket_id) == 4,
OffsetOf_RequestExtensionCHROMIUM_bucket_id_not_4);
+struct SetLatchCHROMIUM {
+ typedef SetLatchCHROMIUM ValueType;
+ static const CommandId kCmdId = kSetLatchCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+ static uint32 ComputeSize() {
+ return static_cast<uint32>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() {
+ header.SetCmd<ValueType>();
+ }
+
+ void Init(GLint _shm_id, GLuint _latch_id) {
+ SetHeader();
+ shm_id = _shm_id;
+ latch_id = _latch_id;
+ }
+
+ void* Set(void* cmd, GLint _shm_id, GLuint _latch_id) {
+ static_cast<ValueType*>(cmd)->Init(_shm_id, _latch_id);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ int32 shm_id;
+ uint32 latch_id;
+};
+
+COMPILE_ASSERT(sizeof(SetLatchCHROMIUM) == 12,
+ Sizeof_SetLatchCHROMIUM_is_not_12);
+COMPILE_ASSERT(offsetof(SetLatchCHROMIUM, header) == 0,
+ OffsetOf_SetLatchCHROMIUM_header_not_0);
+COMPILE_ASSERT(offsetof(SetLatchCHROMIUM, shm_id) == 4,
+ OffsetOf_SetLatchCHROMIUM_shm_id_not_4);
+COMPILE_ASSERT(offsetof(SetLatchCHROMIUM, latch_id) == 8,
+ OffsetOf_SetLatchCHROMIUM_latch_id_not_8);
+
+struct WaitLatchCHROMIUM {
+ typedef WaitLatchCHROMIUM ValueType;
+ static const CommandId kCmdId = kWaitLatchCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+
+ static uint32 ComputeSize() {
+ return static_cast<uint32>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() {
+ header.SetCmd<ValueType>();
+ }
+
+ void Init(GLint _shm_id, GLuint _latch_id) {
+ SetHeader();
+ shm_id = _shm_id;
+ latch_id = _latch_id;
+ }
+
+ void* Set(void* cmd, GLint _shm_id, GLuint _latch_id) {
+ static_cast<ValueType*>(cmd)->Init(_shm_id, _latch_id);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ int32 shm_id;
+ uint32 latch_id;
+};
+
+COMPILE_ASSERT(sizeof(WaitLatchCHROMIUM) == 12,
+ Sizeof_WaitLatchCHROMIUM_is_not_12);
+COMPILE_ASSERT(offsetof(WaitLatchCHROMIUM, header) == 0,
+ OffsetOf_WaitLatchCHROMIUM_header_not_0);
+COMPILE_ASSERT(offsetof(WaitLatchCHROMIUM, shm_id) == 4,
+ OffsetOf_WaitLatchCHROMIUM_shm_id_not_4);
+COMPILE_ASSERT(offsetof(WaitLatchCHROMIUM, latch_id) == 8,
+ OffsetOf_WaitLatchCHROMIUM_latch_id_not_8);
+
#endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index fcada01..603b71e 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -3506,5 +3506,35 @@ TEST(GLES2FormatTest, RequestExtensionCHROMIUM) {
EXPECT_EQ(static_cast<uint32>(11), cmd.bucket_id);
}
+TEST(GLES2FormatTest, SetLatchCHROMIUM) {
+ SetLatchCHROMIUM cmd = { { 0 } };
+ void* next_cmd = cmd.Set(
+ &cmd,
+ static_cast<GLint>(11),
+ static_cast<GLuint>(12));
+ EXPECT_EQ(static_cast<uint32>(SetLatchCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<char*>(next_cmd),
+ reinterpret_cast<char*>(&cmd) + sizeof(cmd));
+ EXPECT_EQ(static_cast<GLint>(11), cmd.shm_id);
+ EXPECT_EQ(static_cast<GLuint>(12), cmd.latch_id);
+}
+
+TEST(GLES2FormatTest, WaitLatchCHROMIUM) {
+ WaitLatchCHROMIUM cmd = { { 0 } };
+ void* next_cmd = cmd.Set(
+ &cmd,
+ static_cast<GLint>(11),
+ static_cast<GLuint>(12));
+ EXPECT_EQ(static_cast<uint32>(WaitLatchCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<char*>(next_cmd),
+ reinterpret_cast<char*>(&cmd) + sizeof(cmd));
+ EXPECT_EQ(static_cast<GLint>(11), cmd.shm_id);
+ EXPECT_EQ(static_cast<GLuint>(12), cmd.latch_id);
+}
+
#endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index f4e0e9e..7566beb 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -203,6 +203,8 @@
OP(ResizeCHROMIUM) /* 448 */ \
OP(GetRequestableExtensionsCHROMIUM) /* 449 */ \
OP(RequestExtensionCHROMIUM) /* 450 */ \
+ OP(SetLatchCHROMIUM) /* 451 */ \
+ OP(WaitLatchCHROMIUM) /* 452 */ \
enum CommandId {
kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/service/cmd_parser.cc b/gpu/command_buffer/service/cmd_parser.cc
index 47a2b5a..199eb05 100644
--- a/gpu/command_buffer/service/cmd_parser.cc
+++ b/gpu/command_buffer/service/cmd_parser.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -59,12 +59,14 @@ error::Error CommandParser::ProcessCommand() {
// TODO(gman): If you want to log errors this is the best place to catch them.
// It seems like we need an official way to turn on a debug mode and
// get these errors.
- if (result != error::kNoError && result != error::kThrottle) {
+ if (result != error::kNoError &&
+ result != error::kThrottle &&
+ result != error::kWaiting) {
ReportError(header.command, result);
}
// If get was not set somewhere else advance it.
- if (get == get_)
+ if (result != error::kWaiting && get == get_)
get_ = (get + header.size) % entry_count_;
return result;
}
diff --git a/gpu/command_buffer/service/cmd_parser.h b/gpu/command_buffer/service/cmd_parser.h
index 663ea48..fe3eb12 100644
--- a/gpu/command_buffer/service/cmd_parser.h
+++ b/gpu/command_buffer/service/cmd_parser.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
diff --git a/gpu/command_buffer/service/cmd_parser_test.cc b/gpu/command_buffer/service/cmd_parser_test.cc
index 7917eee..06249cc 100644
--- a/gpu/command_buffer/service/cmd_parser_test.cc
+++ b/gpu/command_buffer/service/cmd_parser_test.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -288,4 +288,28 @@ TEST_F(CommandParserTest, TestError) {
Mock::VerifyAndClearExpectations(api_mock());
}
+TEST_F(CommandParserTest, TestWaiting) {
+ const unsigned int kNumEntries = 5;
+ scoped_ptr<CommandParser> parser(MakeParser(kNumEntries));
+ CommandBufferOffset put = parser->put();
+ CommandHeader header;
+
+ // Generate a command with size 1.
+ header.size = 1;
+ header.command = 3;
+ buffer()[put++].value_header = header;
+
+ parser->set_put(put);
+ // A command that returns kWaiting should not advance the get pointer.
+ AddDoCommandExpect(error::kWaiting, 3, 0, NULL);
+ EXPECT_EQ(error::kWaiting, parser->ProcessAllCommands());
+ EXPECT_EQ(0, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+ // Not waiting should advance the get pointer.
+ AddDoCommandExpect(error::kNoError, 3, 0, NULL);
+ EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
+ EXPECT_EQ(put, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 0aa5a47..57df63c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -14,6 +14,7 @@
#include "app/gfx/gl/gl_context.h"
#include "app/gfx/gl/gl_implementation.h"
+#include "base/atomicops.h"
#include "base/at_exit.h"
#include "base/callback.h"
#include "base/scoped_ptr.h"
@@ -6173,6 +6174,44 @@ error::Error GLES2DecoderImpl::HandleSwapBuffers(
return IsAngle() ? error::kThrottle : error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleSetLatchCHROMIUM(
+ uint32 immediate_data_size, const gles2::SetLatchCHROMIUM& c) {
+ int32 shm_id = c.shm_id;
+ uint32 latch_id = c.latch_id;
+ uint32 shm_offset = 0;
+ base::subtle::Atomic32* latch;
+ if (!SafeMultiplyUint32(latch_id, sizeof(*latch), &shm_offset)) {
+ return error::kOutOfBounds;
+ }
+ latch = GetSharedMemoryAs<base::subtle::Atomic32*>(
+ shm_id, shm_offset, sizeof(*latch));
+ if (!latch) {
+ return error::kOutOfBounds;
+ }
+ *latch = 1;
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleWaitLatchCHROMIUM(
+ uint32 immediate_data_size, const gles2::WaitLatchCHROMIUM& c) {
+ int32 shm_id = c.shm_id;
+ uint32 latch_id = c.latch_id;
+ uint32 shm_offset = 0;
+ base::subtle::Atomic32* latch;
+ if (!SafeMultiplyUint32(latch_id, sizeof(*latch), &shm_offset)) {
+ return error::kOutOfBounds;
+ }
+ latch = GetSharedMemoryAs<base::subtle::Atomic32*>(
+ shm_id, shm_offset, sizeof(*latch));
+ if (!latch) {
+ return error::kOutOfBounds;
+ }
+
+ base::subtle::Atomic32 old =
+ base::subtle::NoBarrier_CompareAndSwap(latch, 1, 0);
+ return (old == 0) ? error::kWaiting : error::kNoError;
+}
+
error::Error GLES2DecoderImpl::HandleCommandBufferEnableCHROMIUM(
uint32 immediate_data_size, const gles2::CommandBufferEnableCHROMIUM& c) {
Bucket* bucket = GetBucket(c.bucket_id);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 2363d2f..5e4370e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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 "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "base/atomicops.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/common/gl_mock.h"
@@ -2859,6 +2860,64 @@ TEST_F(GLES2DecoderWithShaderTest, VertexAttribPointer) {
}
}
+TEST_F(GLES2DecoderTest, SetLatch) {
+ const uint32 kLatchId = 1;
+ base::subtle::Atomic32* latches = static_cast<base::subtle::Atomic32*>(
+ shared_memory_base_);
+ const uint32 kInvalidLatchId = kSharedBufferSize / sizeof(*latches);
+ const uint32 kLastValidLatchId = kInvalidLatchId - 1;
+ latches[kLatchId] = 0;
+ latches[kLastValidLatchId] = 0;
+ SetLatchCHROMIUM cmd;
+ // Check bad shared memory id.
+ cmd.Init(kInvalidSharedMemoryId, kLatchId);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ // Check out of range latch id.
+ cmd.Init(shared_memory_id_, kInvalidLatchId);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ cmd.Init(shared_memory_id_, kLatchId);
+ // Check valid latch.
+ EXPECT_EQ(0, latches[kLatchId]);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(1, latches[kLatchId]);
+ // Check last valid latch.
+ EXPECT_EQ(0, latches[kLastValidLatchId]);
+ cmd.Init(shared_memory_id_, kLastValidLatchId);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(1, latches[kLastValidLatchId]);
+}
+
+TEST_F(GLES2DecoderTest, WaitLatch) {
+ const uint32 kLatchId = 1;
+ base::subtle::Atomic32* latches = static_cast<base::subtle::Atomic32*>(
+ shared_memory_base_);
+ const uint32 kInvalidLatchId = kSharedBufferSize / sizeof(*latches);
+ const uint32 kLastValidLatchId = kInvalidLatchId - 1;
+ latches[kLatchId] = 0;
+ latches[kLastValidLatchId] = 0;
+ WaitLatchCHROMIUM cmd;
+ // Check bad shared memory id.
+ cmd.Init(kInvalidSharedMemoryId, kLatchId);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ // Check out of range latch id.
+ cmd.Init(shared_memory_id_, kInvalidLatchId);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ // Check valid latch.
+ cmd.Init(shared_memory_id_, kLatchId);
+ EXPECT_EQ(0, latches[kLatchId]);
+ EXPECT_EQ(error::kWaiting, ExecuteCmd(cmd));
+ latches[kLatchId] = 1;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, latches[kLatchId]);
+ // Check last valid latch.
+ cmd.Init(shared_memory_id_, kLastValidLatchId);
+ EXPECT_EQ(0, latches[kLastValidLatchId]);
+ EXPECT_EQ(error::kWaiting, ExecuteCmd(cmd));
+ latches[kLastValidLatchId] = 1;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, latches[kLastValidLatchId]);
+}
+
// TODO(gman): BufferData
// TODO(gman): BufferDataImmediate
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
index 50715df..18ebb1b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
@@ -1573,5 +1573,7 @@ TEST_F(GLES2DecoderTest2, ViewportInvalidArgs3_0) {
// TODO(gman): RequestExtensionCHROMIUM
+// TODO(gman): SetLatchCHROMIUM
+
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
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 0699e3b..ebab9ba 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -124,6 +124,7 @@ void GLES2DecoderTestBase::InitDecoder(
shared_memory_address_ = reinterpret_cast<int8*>(buffer.ptr) +
shared_memory_offset_;
shared_memory_id_ = kSharedMemoryId;
+ shared_memory_base_ = buffer.ptr;
context_ = new gfx::StubGLContext;
context_->SetSize(gfx::Size(kBackBufferWidth, kBackBufferHeight));
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 c184f17..6496c3f 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -269,6 +269,7 @@ class GLES2DecoderTestBase : public testing::Test {
uint32 shared_memory_id_;
uint32 shared_memory_offset_;
void* shared_memory_address_;
+ void* shared_memory_base_;
int8 immediate_buffer_[256];
diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc
index e94c870..b43b98e 100644
--- a/gpu/command_buffer/service/gpu_processor.cc
+++ b/gpu/command_buffer/service/gpu_processor.cc
@@ -169,6 +169,9 @@ void GPUProcessor::ProcessCommands() {
int commands_processed = 0;
while (commands_processed < commands_per_update_ && !parser_->IsEmpty()) {
error::Error error = parser_->ProcessCommand();
+ if (error == error::kWaiting) {
+ break;
+ }
// If the command indicated it should be throttled, insert a new fence into
// the fence queue.