Reland 87371 - Support for glSetSurfaceCHROMIUM.

This command allows a previously created GPU surface to be made current for a command buffer. There are no surfaces registered at this point so this command is currently a no-op.
Review URL: http://codereview.chromium.org/7077001
Review URL: http://codereview.chromium.org/7006019

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87408 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 25b66962..dec7c34 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -34,6 +34,7 @@
 #include "gpu/command_buffer/service/renderbuffer_manager.h"
 #include "gpu/command_buffer/service/shader_manager.h"
 #include "gpu/command_buffer/service/shader_translator.h"
+#include "gpu/command_buffer/service/surface_manager.h"
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "gpu/GLES2/gles2_command_buffer.h"
 #include "ui/gfx/gl/gl_context.h"
@@ -661,7 +662,8 @@
 class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
                          public GLES2Decoder {
  public:
-  explicit GLES2DecoderImpl(ContextGroup* group);
+  explicit GLES2DecoderImpl(SurfaceManager* surface_manager,
+                            ContextGroup* group);
 
   // Overridden from AsyncAPIInterface.
   virtual Error DoCommand(unsigned int command,
@@ -672,8 +674,8 @@
   virtual const char* GetCommandName(unsigned int command_id) const;
 
   // Overridden from GLES2Decoder.
-  virtual bool Initialize(gfx::GLSurface* surface,
-                          gfx::GLContext* context,
+  virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
+                          const scoped_refptr<gfx::GLContext>& context,
                           const gfx::Size& size,
                           const DisallowedExtensions& disallowed_extensions,
                           const char* allowed_extensions,
@@ -1229,6 +1231,8 @@
 
   void DoResizeCHROMIUM(GLuint width, GLuint height);
 
+  void DoSetSurfaceCHROMIUM(GLint surface_id);
+
   // Gets the number of values that will be returned by glGetXXX. Returns
   // false if pname is unknown.
   bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
@@ -1339,9 +1343,12 @@
 
   #undef GLES2_CMD_OP
 
+  // Maps surface IDs to GLSurface.
+  gpu::SurfaceManager* surface_manager_;
+
   // The GL context this decoder renders to on behalf of the client.
-  scoped_ptr<gfx::GLSurface> surface_;
-  scoped_ptr<gfx::GLContext> context_;
+  scoped_refptr<gfx::GLSurface> surface_;
+  scoped_refptr<gfx::GLContext> context_;
 
   // The ContextGroup for this decoder uses to track resources.
   ContextGroup::Ref group_;
@@ -1767,12 +1774,15 @@
   return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
 }
 
-GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
-  return new GLES2DecoderImpl(group);
+GLES2Decoder* GLES2Decoder::Create(SurfaceManager* surface_manager,
+                                   ContextGroup* group) {
+  return new GLES2DecoderImpl(surface_manager, group);
 }
 
-GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
+GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
+                                   ContextGroup* group)
     : GLES2Decoder(),
+      surface_manager_(surface_manager),
       group_(ContextGroup::Ref(group ? group : new ContextGroup())),
       error_bits_(0),
       util_(0),  // TODO(gman): Set to actual num compress texture formats.
@@ -1831,8 +1841,8 @@
 }
 
 bool GLES2DecoderImpl::Initialize(
-    gfx::GLSurface* surface,
-    gfx::GLContext* context,
+    const scoped_refptr<gfx::GLSurface>& surface,
+    const scoped_refptr<gfx::GLContext>& context,
     const gfx::Size& size,
     const DisallowedExtensions& disallowed_extensions,
     const char* allowed_extensions,
@@ -1842,13 +1852,15 @@
   DCHECK(context);
   DCHECK(!context_.get());
 
-  // Take ownership of the GLSurface. TODO(apatrick): the decoder should not
-  // own the surface. It should be possible to freely switch the surface the
-  // context renders to.
-  surface_.reset(surface);
+  // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
+  // context is retired, the decoder should not take an initial surface as
+  // an argument to this function.
+  // Maybe create a short lived offscreen GLSurface for the purpose of
+  // initializing the decoder's GLContext.
+  surface_ = surface;
 
   // Take ownership of the GLContext.
-  context_.reset(context);
+  context_ = context;
 
   // Keep only a weak pointer to the parent so we don't unmap its client
   // frame buffer after it has been destroyed.
@@ -2567,7 +2579,7 @@
 
   if (context_.get())
     context_->Destroy();
-  context_.reset();
+  context_ = NULL;
 
   offscreen_target_frame_buffer_.reset();
   offscreen_target_color_texture_.reset();
@@ -2627,6 +2639,14 @@
   }
 }
 
+void GLES2DecoderImpl::DoSetSurfaceCHROMIUM(GLint surface_id) {
+  gfx::GLSurface* surface = surface_manager_->LookupSurface(surface_id);
+  if (!surface)
+    return;
+
+  surface_ = surface;
+}
+
 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
   if (command_id > kStartPoint && command_id < kNumCommands) {
     return gles2::GetCommandName(static_cast<CommandId>(command_id));
@@ -6428,7 +6448,9 @@
   if (!latch) {
     return error::kOutOfBounds;
   }
-  base::subtle::NoBarrier_Store(latch, 1);
+  base::subtle::Atomic32 old =
+      base::subtle::NoBarrier_CompareAndSwap(latch, 0, 1);
+  DCHECK(old == 0);
   if (!latch_callback_.is_null())
     latch_callback_.Run(true);
   return error::kNoError;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 7236cc0..699f85e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -22,6 +22,8 @@
 
 namespace gpu {
 
+class SurfaceManager;
+
 namespace gles2 {
 
 class ContextGroup;
@@ -40,7 +42,8 @@
   typedef error::Error Error;
 
   // Creates a decoder.
-  static GLES2Decoder* Create(ContextGroup* group);
+  static GLES2Decoder* Create(SurfaceManager* surface_manager,
+                              ContextGroup* group);
 
   virtual ~GLES2Decoder();
 
@@ -68,8 +71,8 @@
   //      parent's namespace.
   // Returns:
   //   true if successful.
-  virtual bool Initialize(gfx::GLSurface* surface,
-                          gfx::GLContext* context,
+  virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
+                          const scoped_refptr<gfx::GLContext>& context,
                           const gfx::Size& size,
                           const DisallowedExtensions& disallowed_extensions,
                           const char* allowed_extensions,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 2ae8a034..9f7711a 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -2600,5 +2600,12 @@
   return error::kNoError;
 }
 
+error::Error GLES2DecoderImpl::HandleSetSurfaceCHROMIUM(
+    uint32 immediate_data_size, const gles2::SetSurfaceCHROMIUM& c) {
+  GLint surface_id = static_cast<GLint>(c.surface_id);
+  DoSetSurfaceCHROMIUM(surface_id);
+  return error::kNoError;
+}
+
 #endif  // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_AUTOGEN_H_
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 425fdce7..f775625 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -30,8 +30,8 @@
   virtual ~MockGLES2Decoder();
 
   MOCK_METHOD8(Initialize,
-               bool(gfx::GLSurface* surface,
-                    gfx::GLContext* context,
+               bool(const scoped_refptr<gfx::GLSurface>& surface,
+                    const scoped_refptr<gfx::GLContext>& context,
                     const gfx::Size& size,
                     const DisallowedExtensions& disallowed_extensions,
                     const char* allowed_extensions,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 298640a..274d495 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -16,6 +16,7 @@
 #include "gpu/command_buffer/service/test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/gl/gl_implementation.h"
+#include "ui/gfx/gl/gl_surface_stub.h"
 
 using ::gfx::MockGLInterface;
 using ::testing::_;
@@ -2933,6 +2934,46 @@
   EXPECT_EQ(0, latches[kLastValidLatchId]);
 }
 
+TEST_F(GLES2DecoderTest, SetSurfaceCHROMIUMChangesSurfaceForExistentSurface) {
+  const int kSurfaceId = 1;
+  scoped_refptr<gfx::GLSurfaceStub> surface(new gfx::GLSurfaceStub);
+
+  EXPECT_CALL(*surface_manager_.get(), LookupSurface(kSurfaceId))
+      .WillOnce(Return(surface.get()))
+      .RetiresOnSaturation();
+
+  SetSurfaceCHROMIUM cmd;
+  cmd.Init(kSurfaceId);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+
+  EXPECT_EQ(surface.get(), decoder_->GetGLSurface());
+}
+
+TEST_F(GLES2DecoderTest,
+    SetSurfaceCHROMIUMDoesNotChangeSurfaceWhenSurfaceDoesNotExist) {
+  const int kExistentSurfaceId = 1;
+  const int kNonexistentSurfaceId = 2;
+  scoped_refptr<gfx::GLSurfaceStub> surface(new gfx::GLSurfaceStub);
+
+  EXPECT_CALL(*surface_manager_.get(), LookupSurface(kExistentSurfaceId))
+      .WillOnce(Return(surface.get()))
+      .RetiresOnSaturation();
+
+  EXPECT_CALL(*surface_manager_.get(), LookupSurface(kNonexistentSurfaceId))
+      .WillOnce(Return(static_cast<gfx::GLSurface*>(NULL)))
+      .RetiresOnSaturation();
+
+  SetSurfaceCHROMIUM cmd;
+  cmd.Init(kExistentSurfaceId);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+
+  cmd.Init(kNonexistentSurfaceId);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+
+  EXPECT_EQ(surface.get(), decoder_->GetGLSurface());
+}
+
+
 // TODO(gman): BufferData
 
 // TODO(gman): BufferDataImmediate
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
index 72cd0c39..94c5ffc 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -10,5 +10,6 @@
 
 // TODO(gman): WaitLatchCHROMIUM
 
+// TODO(gman): SetSurfaceCHROMIUM
 #endif  // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_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 a38ab8b..7dbc98c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -55,6 +55,7 @@
     const char* extensions, bool has_alpha_backbuffer) {
   gl_.reset(new StrictMock<MockGLInterface>());
   ::gfx::GLInterface::SetGLInterface(gl_.get());
+  surface_manager_.reset(new StrictMock<MockSurfaceManager>);
   group_ = ContextGroup::Ref(new ContextGroup());
 
   InSequence sequence;
@@ -133,7 +134,7 @@
 
   context_ = new gfx::GLContextStub;
 
-  decoder_.reset(GLES2Decoder::Create(group_.get()));
+  decoder_.reset(GLES2Decoder::Create(surface_manager_.get(), group_.get()));
   decoder_->Initialize(
       surface_, context_, surface_->GetSize(), DisallowedExtensions(),
       NULL, std::vector<int32>(), NULL, 0);
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 dc195c8..d939e4f8 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -16,6 +16,7 @@
 #include "gpu/command_buffer/service/program_manager.h"
 #include "gpu/command_buffer/service/renderbuffer_manager.h"
 #include "gpu/command_buffer/service/shader_manager.h"
+#include "gpu/command_buffer/service/surface_manager_mock.h"
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "gpu/GLES2/gles2_command_buffer.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -256,9 +257,10 @@
 
   // Use StrictMock to make 100% sure we know how GL will be called.
   scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
-  gfx::GLSurfaceStub* surface_;
-  gfx::GLContextStub* context_;
+  scoped_refptr<gfx::GLSurfaceStub> surface_;
+  scoped_refptr<gfx::GLContextStub> context_;
   scoped_ptr<GLES2Decoder> decoder_;
+  scoped_ptr<MockSurfaceManager> surface_manager_;
 
   GLuint client_buffer_id_;
   GLuint client_framebuffer_id_;
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc
index 4c54773..151ff9a 100644
--- a/gpu/command_buffer/service/gpu_scheduler.cc
+++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -19,6 +19,7 @@
 namespace gpu {
 
 GpuScheduler::GpuScheduler(CommandBuffer* command_buffer,
+                           SurfaceManager* surface_manager,
                            gles2::ContextGroup* group)
     : command_buffer_(command_buffer),
       commands_per_update_(100),
@@ -29,7 +30,7 @@
 #endif
       method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
   DCHECK(command_buffer);
-  decoder_.reset(gles2::GLES2Decoder::Create(group));
+  decoder_.reset(gles2::GLES2Decoder::Create(surface_manager, group));
   decoder_->set_engine(this);
 }
 
@@ -55,8 +56,8 @@
 }
 
 bool GpuScheduler::InitializeCommon(
-    gfx::GLSurface* surface,
-    gfx::GLContext* context,
+    const scoped_refptr<gfx::GLSurface>& surface,
+    const scoped_refptr<gfx::GLContext>& context,
     const gfx::Size& size,
     const gles2::DisallowedExtensions& disallowed_extensions,
     const char* allowed_extensions,
diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h
index ebbcc88..d75beae 100644
--- a/gpu/command_buffer/service/gpu_scheduler.h
+++ b/gpu/command_buffer/service/gpu_scheduler.h
@@ -40,7 +40,9 @@
 class GpuScheduler : public CommandBufferEngine {
  public:
   // If a group is not passed in one will be created.
-  GpuScheduler(CommandBuffer* command_buffer, gles2::ContextGroup* group);
+  GpuScheduler(CommandBuffer* command_buffer,
+               SurfaceManager* surface_manager,
+               gles2::ContextGroup* group);
 
   // This constructor is for unit tests.
   GpuScheduler(CommandBuffer* command_buffer,
@@ -139,8 +141,8 @@
  protected:
   // Perform common initialization. Takes ownership of GLSurface and GLContext.
   bool InitializeCommon(
-      gfx::GLSurface* surface,
-      gfx::GLContext* context,
+      const scoped_refptr<gfx::GLSurface>& surface,
+      const scoped_refptr<gfx::GLContext>& context,
       const gfx::Size& size,
       const gles2::DisallowedExtensions& disallowed_extensions,
       const char* allowed_extensions,
diff --git a/gpu/command_buffer/service/gpu_scheduler_linux.cc b/gpu/command_buffer/service/gpu_scheduler_linux.cc
index 3ed89e4..f1d49da 100644
--- a/gpu/command_buffer/service/gpu_scheduler_linux.cc
+++ b/gpu/command_buffer/service/gpu_scheduler_linux.cc
@@ -31,13 +31,13 @@
   }
 
   // Create either a view or pbuffer based GLSurface.
-  scoped_ptr<gfx::GLSurface> surface;
+  scoped_refptr<gfx::GLSurface> surface;
   if (window) {
     DCHECK(!parent_handle);
 
-    surface.reset(gfx::GLSurface::CreateViewGLSurface(window));
+    surface = gfx::GLSurface::CreateViewGLSurface(window);
   } else {
-    surface.reset(gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1)));
+    surface = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1));
   }
 
   if (!surface.get()) {
@@ -47,7 +47,7 @@
   }
 
   // Create a GLContext and attach the surface.
-  scoped_ptr<gfx::GLContext> context(
+  scoped_refptr<gfx::GLContext> context(
       gfx::GLContext::CreateGLContext(parent_context, surface.get()));
   if (!context.get()) {
     LOG(ERROR) << "CreateGLContext failed.\n";
@@ -55,8 +55,8 @@
     return false;
   }
 
-  return InitializeCommon(surface.release(),
-                          context.release(),
+  return InitializeCommon(surface,
+                          context,
                           size,
                           disallowed_extensions,
                           allowed_extensions,
diff --git a/gpu/command_buffer/service/gpu_scheduler_mac.cc b/gpu/command_buffer/service/gpu_scheduler_mac.cc
index 1e323ec..449a90f 100644
--- a/gpu/command_buffer/service/gpu_scheduler_mac.cc
+++ b/gpu/command_buffer/service/gpu_scheduler_mac.cc
@@ -29,7 +29,7 @@
     DCHECK(parent_context);
   }
 
-  scoped_ptr<gfx::GLSurface> surface(
+  scoped_refptr<gfx::GLSurface> surface(
       gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1)));
   if (!surface.get()) {
     LOG(ERROR) << "CreateOffscreenGLSurface failed.\n";
@@ -38,7 +38,7 @@
   }
 
   // Create a GLContext and attach the surface.
-  scoped_ptr<gfx::GLContext> context(
+  scoped_refptr<gfx::GLContext> context(
       gfx::GLContext::CreateGLContext(parent_context, surface.get()));
   if (!context.get()) {
     LOG(ERROR) << "CreateGLContext failed.\n";
@@ -66,8 +66,8 @@
     }
   }
 
-  return InitializeCommon(surface.release(),
-                          context.release(),
+  return InitializeCommon(surface,
+                          context,
                           size,
                           disallowed_extensions,
                           allowed_extensions,
diff --git a/gpu/command_buffer/service/gpu_scheduler_win.cc b/gpu/command_buffer/service/gpu_scheduler_win.cc
index a6dcc73b..81ab10b 100644
--- a/gpu/command_buffer/service/gpu_scheduler_win.cc
+++ b/gpu/command_buffer/service/gpu_scheduler_win.cc
@@ -32,11 +32,11 @@
   }
 
   // Create either a view or pbuffer based GLSurface.
-  scoped_ptr<gfx::GLSurface> surface;
+  scoped_refptr<gfx::GLSurface> surface;
   if (window) {
-    surface.reset(gfx::GLSurface::CreateViewGLSurface(window));
+    surface = gfx::GLSurface::CreateViewGLSurface(window);
   } else {
-    surface.reset(gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1)));
+    surface = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1));
   }
 
   if (!surface.get()) {
@@ -46,7 +46,7 @@
   }
 
   // Create a GLContext and attach the surface.
-  scoped_ptr<gfx::GLContext> context(
+  scoped_refptr<gfx::GLContext> context(
       gfx::GLContext::CreateGLContext(parent_context, surface.get()));
   if (!context.get()) {
     LOG(ERROR) << "CreateGLContext failed.\n";
@@ -54,8 +54,8 @@
     return false;
   }
 
-  return InitializeCommon(surface.release(),
-                          context.release(),
+  return InitializeCommon(surface,
+                          context,
                           size,
                           disallowed_extensions,
                           allowed_extensions,
diff --git a/gpu/command_buffer/service/surface_manager.cc b/gpu/command_buffer/service/surface_manager.cc
new file mode 100644
index 0000000..2fca939
--- /dev/null
+++ b/gpu/command_buffer/service/surface_manager.cc
@@ -0,0 +1,15 @@
+// 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/surface_manager.h"
+
+namespace gpu {
+
+SurfaceManager::SurfaceManager() {
+}
+
+SurfaceManager::~SurfaceManager() {
+}
+
+}  // namespace gpu
diff --git a/gpu/command_buffer/service/surface_manager.h b/gpu/command_buffer/service/surface_manager.h
new file mode 100644
index 0000000..4caa4ac
--- /dev/null
+++ b/gpu/command_buffer/service/surface_manager.h
@@ -0,0 +1,31 @@
+// 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.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_SURFACE_MANAGER_H_
+#define GPU_COMMAND_BUFFER_SERVICE_SURFACE_MANAGER_H_
+
+#include "base/basictypes.h"
+
+namespace gfx {
+class GLSurface;
+}
+
+namespace gpu {
+
+// Interface used to get the GLSurface corresponding to an ID communicated
+// through the command buffer.
+class SurfaceManager {
+ public:
+  SurfaceManager();
+  virtual ~SurfaceManager();
+
+  virtual gfx::GLSurface* LookupSurface(int id) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SurfaceManager);
+};
+
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_SURFACE_MANAGER_H_
diff --git a/gpu/command_buffer/service/surface_manager_mock.h b/gpu/command_buffer/service/surface_manager_mock.h
new file mode 100644
index 0000000..f707ed8
--- /dev/null
+++ b/gpu/command_buffer/service/surface_manager_mock.h
@@ -0,0 +1,23 @@
+// 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.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_SURFACE_MANAGER_MOCK_H_
+#define GPU_COMMAND_BUFFER_SERVICE_SURFACE_MANAGER_MOCK_H_
+
+#include "gpu/command_buffer/service/surface_manager.h"
+
+namespace gpu {
+
+class MockSurfaceManager : public SurfaceManager {
+ public:
+  MockSurfaceManager() {}
+  MOCK_METHOD1(LookupSurface, gfx::GLSurface*(int id));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockSurfaceManager);
+};
+
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_SURFACE_MANAGER_MOCK_H_