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
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 0aa5a47e..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 @@
   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);