Cherry-pick: gpu: Expose GLFence impls

Clean cherry-pick of chromium r279621

Original description:

Move implementations to their own header+source files.

Then specifically use EGL_KHR_fence_sync implementation for
mailbox synchronizing because it's the only one working across
contexts and share groups.

Change-Id: I49b2d17acd2af3980351239c04143b1d50e6e296
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index f97a6dc..15eb0ea 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -721,6 +721,11 @@
     EXPECT_CALL(*gl, FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0))
         .WillOnce(Return(kGlSync))
         .RetiresOnSaturation();
+#if DCHECK_IS_ON
+    EXPECT_CALL(*gl, IsSync(kGlSync))
+        .WillOnce(Return(GL_TRUE))
+        .RetiresOnSaturation();
+#endif
   }
 
   EndQueryEXT end_cmd;
@@ -737,6 +742,11 @@
         .RetiresOnSaturation();
   }
   if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM) {
+#if DCHECK_IS_ON
+    EXPECT_CALL(*gl, IsSync(kGlSync))
+        .WillOnce(Return(GL_TRUE))
+        .RetiresOnSaturation();
+#endif
     EXPECT_CALL(*gl, ClientWaitSync(kGlSync, _, _))
         .WillOnce(Return(GL_ALREADY_SIGNALED))
         .RetiresOnSaturation();
@@ -752,8 +762,14 @@
   if (query_type.is_gl) {
     EXPECT_CALL(*gl, DeleteQueriesARB(1, _)).Times(1).RetiresOnSaturation();
   }
-  if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM)
+  if (query_type.type == GL_COMMANDS_COMPLETED_CHROMIUM) {
+#if DCHECK_IS_ON
+    EXPECT_CALL(*gl, IsSync(kGlSync))
+        .WillOnce(Return(GL_TRUE))
+        .RetiresOnSaturation();
+#endif
     EXPECT_CALL(*gl, DeleteSync(kGlSync)).Times(1).RetiresOnSaturation();
+  }
   test->ResetDecoder();
 }
 
@@ -879,6 +895,11 @@
   EXPECT_CALL(*gl_, FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0))
       .WillOnce(Return(kGlSync))
       .RetiresOnSaturation();
+#if DCHECK_IS_ON
+  EXPECT_CALL(*gl_, IsSync(kGlSync))
+      .WillOnce(Return(GL_TRUE))
+      .RetiresOnSaturation();
+#endif
 
   EndQueryEXT end_cmd;
   end_cmd.Init(GL_COMMANDS_COMPLETED_CHROMIUM, 1);
@@ -886,6 +907,11 @@
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
   EXPECT_TRUE(query->pending());
 
+#if DCHECK_IS_ON
+  EXPECT_CALL(*gl_, IsSync(kGlSync))
+      .WillOnce(Return(GL_TRUE))
+      .RetiresOnSaturation();
+#endif
   EXPECT_CALL(*gl_, ClientWaitSync(kGlSync, _, _))
       .WillOnce(Return(GL_TIMEOUT_EXPIRED))
       .RetiresOnSaturation();
@@ -894,6 +920,11 @@
   EXPECT_TRUE(process_success);
   EXPECT_TRUE(query->pending());
 
+#if DCHECK_IS_ON
+  EXPECT_CALL(*gl_, IsSync(kGlSync))
+      .WillOnce(Return(GL_TRUE))
+      .RetiresOnSaturation();
+#endif
   EXPECT_CALL(*gl_, ClientWaitSync(kGlSync, _, _))
       .WillOnce(Return(GL_ALREADY_SIGNALED))
       .RetiresOnSaturation();
@@ -904,6 +935,11 @@
   QuerySync* sync = static_cast<QuerySync*>(shared_memory_address_);
   EXPECT_EQ(static_cast<GLenum>(0), static_cast<GLenum>(sync->result));
 
+#if DCHECK_IS_ON
+  EXPECT_CALL(*gl_, IsSync(kGlSync))
+      .WillOnce(Return(GL_TRUE))
+      .RetiresOnSaturation();
+#endif
   EXPECT_CALL(*gl_, DeleteSync(kGlSync)).Times(1).RetiresOnSaturation();
   ResetDecoder();
 }
diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc
index 3703f14..7028a5a 100644
--- a/gpu/command_buffer/service/texture_definition.cc
+++ b/gpu/command_buffer/service/texture_definition.cc
@@ -106,11 +106,32 @@
                        EGLDisplay display,
                        EGLImageKHR image);
   virtual ~NativeImageBufferEGL();
+  virtual void AddClient(gfx::GLImage* client) OVERRIDE;
+  virtual void RemoveClient(gfx::GLImage* client) OVERRIDE;
+  virtual bool IsClient(gfx::GLImage* client) OVERRIDE;
   virtual void BindToTexture(GLenum target) OVERRIDE;
+  virtual void WillRead(gfx::GLImage* client) OVERRIDE;
+  virtual void WillWrite(gfx::GLImage* client) OVERRIDE;
+  virtual void DidRead(gfx::GLImage* client) OVERRIDE;
+  virtual void DidWrite(gfx::GLImage* client) OVERRIDE;
 
   EGLDisplay egl_display_;
   EGLImageKHR egl_image_;
 
+  base::Lock lock_;
+
+  struct ClientInfo {
+    ClientInfo(gfx::GLImage* client);
+    ~ClientInfo();
+
+    gfx::GLImage* client;
+    bool needs_wait_before_read;
+    linked_ptr<gfx::GLFence> read_fence;
+  };
+  std::list<ClientInfo> client_infos_;
+  scoped_ptr<gfx::GLFence> write_fence_;
+  gfx::GLImage* write_client_;
+
   DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL);
 };
 
@@ -143,76 +164,35 @@
       make_scoped_ptr(gfx::GLFence::Create()), egl_display, egl_image);
 }
 
+NativeImageBufferEGL::ClientInfo::ClientInfo(gfx::GLImage* client)
+    : client(client), needs_wait_before_read(true) {}
+
+NativeImageBufferEGL::ClientInfo::~ClientInfo() {}
+
 NativeImageBufferEGL::NativeImageBufferEGL(scoped_ptr<gfx::GLFence> write_fence,
                                            EGLDisplay display,
                                            EGLImageKHR image)
-    : NativeImageBuffer(write_fence.Pass()),
+    : NativeImageBuffer(),
       egl_display_(display),
-      egl_image_(image) {
+      egl_image_(image),
+      write_fence_(write_fence.Pass()),
+      write_client_(NULL) {
   DCHECK(egl_display_ != EGL_NO_DISPLAY);
   DCHECK(egl_image_ != EGL_NO_IMAGE_KHR);
 }
 
 NativeImageBufferEGL::~NativeImageBufferEGL() {
+  DCHECK(client_infos_.empty());
   if (egl_image_ != EGL_NO_IMAGE_KHR)
     eglDestroyImageKHR(egl_display_, egl_image_);
 }
 
-void NativeImageBufferEGL::BindToTexture(GLenum target) {
-  DCHECK(egl_image_ != EGL_NO_IMAGE_KHR);
-  glEGLImageTargetTexture2DOES(target, egl_image_);
-  DCHECK_EQ(static_cast<EGLint>(EGL_SUCCESS), eglGetError());
-  DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
-}
-#endif
-
-class NativeImageBufferStub : public NativeImageBuffer {
- public:
-  NativeImageBufferStub() : NativeImageBuffer(scoped_ptr<gfx::GLFence>()) {}
-
- private:
-  virtual ~NativeImageBufferStub() {}
-  virtual void BindToTexture(GLenum target) OVERRIDE {}
-
-  DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub);
-};
-
-}  // anonymous namespace
-
-// static
-scoped_refptr<NativeImageBuffer> NativeImageBuffer::Create(GLuint texture_id) {
-  switch (gfx::GetGLImplementation()) {
-#if !defined(OS_MACOSX)
-    case gfx::kGLImplementationEGLGLES2:
-      return NativeImageBufferEGL::Create(texture_id);
-#endif
-    case gfx::kGLImplementationMockGL:
-      return new NativeImageBufferStub;
-    default:
-      NOTREACHED();
-      return NULL;
-  }
-}
-
-NativeImageBuffer::ClientInfo::ClientInfo(gfx::GLImage* client)
-    : client(client), needs_wait_before_read(true) {}
-
-NativeImageBuffer::ClientInfo::~ClientInfo() {}
-
-NativeImageBuffer::NativeImageBuffer(scoped_ptr<gfx::GLFence> write_fence)
-    : write_fence_(write_fence.Pass()), write_client_(NULL) {
-}
-
-NativeImageBuffer::~NativeImageBuffer() {
-  DCHECK(client_infos_.empty());
-}
-
-void NativeImageBuffer::AddClient(gfx::GLImage* client) {
+void NativeImageBufferEGL::AddClient(gfx::GLImage* client) {
   base::AutoLock lock(lock_);
   client_infos_.push_back(ClientInfo(client));
 }
 
-void NativeImageBuffer::RemoveClient(gfx::GLImage* client) {
+void NativeImageBufferEGL::RemoveClient(gfx::GLImage* client) {
   base::AutoLock lock(lock_);
   if (write_client_ == client)
     write_client_ = NULL;
@@ -227,7 +207,7 @@
   NOTREACHED();
 }
 
-bool NativeImageBuffer::IsClient(gfx::GLImage* client) {
+bool NativeImageBufferEGL::IsClient(gfx::GLImage* client) {
   base::AutoLock lock(lock_);
   for (std::list<ClientInfo>::iterator it = client_infos_.begin();
        it != client_infos_.end();
@@ -238,7 +218,14 @@
   return false;
 }
 
-void NativeImageBuffer::WillRead(gfx::GLImage* client) {
+void NativeImageBufferEGL::BindToTexture(GLenum target) {
+  DCHECK(egl_image_ != EGL_NO_IMAGE_KHR);
+  glEGLImageTargetTexture2DOES(target, egl_image_);
+  DCHECK_EQ(static_cast<EGLint>(EGL_SUCCESS), eglGetError());
+  DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+void NativeImageBufferEGL::WillRead(gfx::GLImage* client) {
   base::AutoLock lock(lock_);
   if (!write_fence_.get() || write_client_ == client)
     return;
@@ -257,7 +244,7 @@
   NOTREACHED();
 }
 
-void NativeImageBuffer::WillWrite(gfx::GLImage* client) {
+void NativeImageBufferEGL::WillWrite(gfx::GLImage* client) {
   base::AutoLock lock(lock_);
   if (write_client_ != client)
     write_fence_->ServerWait();
@@ -270,7 +257,7 @@
   }
 }
 
-void NativeImageBuffer::DidRead(gfx::GLImage* client) {
+void NativeImageBufferEGL::DidRead(gfx::GLImage* client) {
   base::AutoLock lock(lock_);
   for (std::list<ClientInfo>::iterator it = client_infos_.begin();
        it != client_infos_.end();
@@ -283,7 +270,7 @@
   NOTREACHED();
 }
 
-void NativeImageBuffer::DidWrite(gfx::GLImage* client) {
+void NativeImageBufferEGL::DidWrite(gfx::GLImage* client) {
   base::AutoLock lock(lock_);
   // Sharing semantics require the client to flush in order to make changes
   // visible to other clients.
@@ -296,6 +283,43 @@
   }
 }
 
+#endif
+
+class NativeImageBufferStub : public NativeImageBuffer {
+ public:
+  NativeImageBufferStub() : NativeImageBuffer() {}
+
+ private:
+  virtual ~NativeImageBufferStub() {}
+  virtual void AddClient(gfx::GLImage* client) OVERRIDE {}
+  virtual void RemoveClient(gfx::GLImage* client) OVERRIDE {}
+  virtual bool IsClient(gfx::GLImage* client) OVERRIDE { return true; }
+  virtual void BindToTexture(GLenum target) OVERRIDE {}
+  virtual void WillRead(gfx::GLImage* client) OVERRIDE {}
+  virtual void WillWrite(gfx::GLImage* client) OVERRIDE {}
+  virtual void DidRead(gfx::GLImage* client) OVERRIDE {}
+  virtual void DidWrite(gfx::GLImage* client) OVERRIDE {}
+
+  DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub);
+};
+
+}  // anonymous namespace
+
+// static
+scoped_refptr<NativeImageBuffer> NativeImageBuffer::Create(GLuint texture_id) {
+  switch (gfx::GetGLImplementation()) {
+#if !defined(OS_MACOSX)
+    case gfx::kGLImplementationEGLGLES2:
+      return NativeImageBufferEGL::Create(texture_id);
+#endif
+    case gfx::kGLImplementationMockGL:
+      return new NativeImageBufferStub;
+    default:
+      NOTREACHED();
+      return NULL;
+  }
+}
+
 TextureDefinition::LevelInfo::LevelInfo(GLenum target,
                                         GLenum internal_format,
                                         GLsizei width,
diff --git a/gpu/command_buffer/service/texture_definition.h b/gpu/command_buffer/service/texture_definition.h
index 7708902..0b4816a 100644
--- a/gpu/command_buffer/service/texture_definition.h
+++ b/gpu/command_buffer/service/texture_definition.h
@@ -29,35 +29,20 @@
 class NativeImageBuffer : public base::RefCountedThreadSafe<NativeImageBuffer> {
  public:
   static scoped_refptr<NativeImageBuffer> Create(GLuint texture_id);
+
+  virtual void AddClient(gfx::GLImage* client) = 0;
+  virtual void RemoveClient(gfx::GLImage* client) = 0;
+  virtual bool IsClient(gfx::GLImage* client) = 0;
   virtual void BindToTexture(GLenum target) = 0;
-
-  void AddClient(gfx::GLImage* client);
-  void RemoveClient(gfx::GLImage* client);
-  bool IsClient(gfx::GLImage* client);
-
-  void WillRead(gfx::GLImage* client);
-  void WillWrite(gfx::GLImage* client);
-  void DidRead(gfx::GLImage* client);
-  void DidWrite(gfx::GLImage* client);
+  virtual void WillRead(gfx::GLImage* client) = 0;
+  virtual void WillWrite(gfx::GLImage* client) = 0;
+  virtual void DidRead(gfx::GLImage* client) = 0;
+  virtual void DidWrite(gfx::GLImage* client) = 0;
 
  protected:
   friend class base::RefCountedThreadSafe<NativeImageBuffer>;
-  explicit NativeImageBuffer(scoped_ptr<gfx::GLFence> write_fence);
-  virtual ~NativeImageBuffer();
-
-  base::Lock lock_;
-
-  struct ClientInfo {
-    ClientInfo(gfx::GLImage* client);
-    ~ClientInfo();
-
-    gfx::GLImage* client;
-    bool needs_wait_before_read;
-    linked_ptr<gfx::GLFence> read_fence;
-  };
-  std::list<ClientInfo> client_infos_;
-  scoped_ptr<gfx::GLFence> write_fence_;
-  gfx::GLImage* write_client_;
+  NativeImageBuffer() {}
+  virtual ~NativeImageBuffer() {}
 
   DISALLOW_COPY_AND_ASSIGN(NativeImageBuffer);
 };
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index f63d580..8a904ab 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -50,6 +50,10 @@
     "gl_export.h",
     "gl_fence.cc",
     "gl_fence.h",
+    "gl_fence_arb.cc",
+    "gl_fence_arb.h",
+    "gl_fence_nv.cc",
+    "gl_fence_nv.h",
     "gl_gl_api_implementation.cc",
     "gl_gl_api_implementation.h",
     "gl_image.cc",
@@ -131,6 +135,8 @@
       "egl_util.h",
       "gl_context_egl.cc",
       "gl_context_egl.h",
+      "gl_fence_egl.cc",
+      "gl_fence_egl.h",
       "gl_image_egl.cc",
       "gl_image_egl.h",
       "gl_surface_egl.cc",
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index 248e4ff..2ff3de9 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -754,6 +754,9 @@
 { 'return_type': 'GLsync',
   'names': ['glFenceSync'],
   'arguments': 'GLenum condition, GLbitfield flags', },
+{ 'return_type': 'GLboolean',
+  'names': ['glIsSync'],
+  'arguments': 'GLsync sync', },
 { 'return_type': 'void',
   'names': ['glDeleteSync'],
   'arguments': 'GLsync sync', },
diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp
index 59e82a6..ddd361a 100644
--- a/ui/gl/gl.gyp
+++ b/ui/gl/gl.gyp
@@ -71,6 +71,10 @@
         'gl_export.h',
         'gl_fence.cc',
         'gl_fence.h',
+        'gl_fence_arb.cc',
+        'gl_fence_arb.h',
+        'gl_fence_nv.cc',
+        'gl_fence_nv.h',
         'gl_gl_api_implementation.cc',
         'gl_gl_api_implementation.h',
         'gl_image.cc',
@@ -177,6 +181,8 @@
             'egl_util.h',
             'gl_context_egl.cc',
             'gl_context_egl.h',
+            'gl_fence_egl.cc',
+            'gl_fence_egl.h',
             'gl_image_egl.cc',
             'gl_image_egl.h',
             'gl_surface_egl.cc',
diff --git a/ui/gl/gl.target.darwin-arm.mk b/ui/gl/gl.target.darwin-arm.mk
index 2bda780..006d278 100644
--- a/ui/gl/gl.target.darwin-arm.mk
+++ b/ui/gl/gl.target.darwin-arm.mk
@@ -97,6 +97,8 @@
 	ui/gl/gl_context_stub.cc \
 	ui/gl/gl_context_stub_with_extensions.cc \
 	ui/gl/gl_fence.cc \
+	ui/gl/gl_fence_arb.cc \
+	ui/gl/gl_fence_nv.cc \
 	ui/gl/gl_gl_api_implementation.cc \
 	ui/gl/gl_image.cc \
 	ui/gl/gl_image_android.cc \
@@ -119,6 +121,7 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_fence_egl.cc \
 	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
diff --git a/ui/gl/gl.target.darwin-arm64.mk b/ui/gl/gl.target.darwin-arm64.mk
index 84157fb..596f90c 100644
--- a/ui/gl/gl.target.darwin-arm64.mk
+++ b/ui/gl/gl.target.darwin-arm64.mk
@@ -97,6 +97,8 @@
 	ui/gl/gl_context_stub.cc \
 	ui/gl/gl_context_stub_with_extensions.cc \
 	ui/gl/gl_fence.cc \
+	ui/gl/gl_fence_arb.cc \
+	ui/gl/gl_fence_nv.cc \
 	ui/gl/gl_gl_api_implementation.cc \
 	ui/gl/gl_image.cc \
 	ui/gl/gl_image_android.cc \
@@ -119,6 +121,7 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_fence_egl.cc \
 	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
diff --git a/ui/gl/gl.target.darwin-mips.mk b/ui/gl/gl.target.darwin-mips.mk
index 90112a4..e88d594 100644
--- a/ui/gl/gl.target.darwin-mips.mk
+++ b/ui/gl/gl.target.darwin-mips.mk
@@ -97,6 +97,8 @@
 	ui/gl/gl_context_stub.cc \
 	ui/gl/gl_context_stub_with_extensions.cc \
 	ui/gl/gl_fence.cc \
+	ui/gl/gl_fence_arb.cc \
+	ui/gl/gl_fence_nv.cc \
 	ui/gl/gl_gl_api_implementation.cc \
 	ui/gl/gl_image.cc \
 	ui/gl/gl_image_android.cc \
@@ -119,6 +121,7 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_fence_egl.cc \
 	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
diff --git a/ui/gl/gl.target.darwin-x86.mk b/ui/gl/gl.target.darwin-x86.mk
index 32118f9..8abced9 100644
--- a/ui/gl/gl.target.darwin-x86.mk
+++ b/ui/gl/gl.target.darwin-x86.mk
@@ -97,6 +97,8 @@
 	ui/gl/gl_context_stub.cc \
 	ui/gl/gl_context_stub_with_extensions.cc \
 	ui/gl/gl_fence.cc \
+	ui/gl/gl_fence_arb.cc \
+	ui/gl/gl_fence_nv.cc \
 	ui/gl/gl_gl_api_implementation.cc \
 	ui/gl/gl_image.cc \
 	ui/gl/gl_image_android.cc \
@@ -119,6 +121,7 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_fence_egl.cc \
 	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
diff --git a/ui/gl/gl.target.darwin-x86_64.mk b/ui/gl/gl.target.darwin-x86_64.mk
index 9440fb9..aadbb3b 100644
--- a/ui/gl/gl.target.darwin-x86_64.mk
+++ b/ui/gl/gl.target.darwin-x86_64.mk
@@ -97,6 +97,8 @@
 	ui/gl/gl_context_stub.cc \
 	ui/gl/gl_context_stub_with_extensions.cc \
 	ui/gl/gl_fence.cc \
+	ui/gl/gl_fence_arb.cc \
+	ui/gl/gl_fence_nv.cc \
 	ui/gl/gl_gl_api_implementation.cc \
 	ui/gl/gl_image.cc \
 	ui/gl/gl_image_android.cc \
@@ -119,6 +121,7 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_fence_egl.cc \
 	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
diff --git a/ui/gl/gl.target.linux-arm.mk b/ui/gl/gl.target.linux-arm.mk
index 2bda780..006d278 100644
--- a/ui/gl/gl.target.linux-arm.mk
+++ b/ui/gl/gl.target.linux-arm.mk
@@ -97,6 +97,8 @@
 	ui/gl/gl_context_stub.cc \
 	ui/gl/gl_context_stub_with_extensions.cc \
 	ui/gl/gl_fence.cc \
+	ui/gl/gl_fence_arb.cc \
+	ui/gl/gl_fence_nv.cc \
 	ui/gl/gl_gl_api_implementation.cc \
 	ui/gl/gl_image.cc \
 	ui/gl/gl_image_android.cc \
@@ -119,6 +121,7 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_fence_egl.cc \
 	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
diff --git a/ui/gl/gl.target.linux-arm64.mk b/ui/gl/gl.target.linux-arm64.mk
index 84157fb..596f90c 100644
--- a/ui/gl/gl.target.linux-arm64.mk
+++ b/ui/gl/gl.target.linux-arm64.mk
@@ -97,6 +97,8 @@
 	ui/gl/gl_context_stub.cc \
 	ui/gl/gl_context_stub_with_extensions.cc \
 	ui/gl/gl_fence.cc \
+	ui/gl/gl_fence_arb.cc \
+	ui/gl/gl_fence_nv.cc \
 	ui/gl/gl_gl_api_implementation.cc \
 	ui/gl/gl_image.cc \
 	ui/gl/gl_image_android.cc \
@@ -119,6 +121,7 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_fence_egl.cc \
 	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
diff --git a/ui/gl/gl.target.linux-mips.mk b/ui/gl/gl.target.linux-mips.mk
index 90112a4..e88d594 100644
--- a/ui/gl/gl.target.linux-mips.mk
+++ b/ui/gl/gl.target.linux-mips.mk
@@ -97,6 +97,8 @@
 	ui/gl/gl_context_stub.cc \
 	ui/gl/gl_context_stub_with_extensions.cc \
 	ui/gl/gl_fence.cc \
+	ui/gl/gl_fence_arb.cc \
+	ui/gl/gl_fence_nv.cc \
 	ui/gl/gl_gl_api_implementation.cc \
 	ui/gl/gl_image.cc \
 	ui/gl/gl_image_android.cc \
@@ -119,6 +121,7 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_fence_egl.cc \
 	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
diff --git a/ui/gl/gl.target.linux-x86.mk b/ui/gl/gl.target.linux-x86.mk
index 32118f9..8abced9 100644
--- a/ui/gl/gl.target.linux-x86.mk
+++ b/ui/gl/gl.target.linux-x86.mk
@@ -97,6 +97,8 @@
 	ui/gl/gl_context_stub.cc \
 	ui/gl/gl_context_stub_with_extensions.cc \
 	ui/gl/gl_fence.cc \
+	ui/gl/gl_fence_arb.cc \
+	ui/gl/gl_fence_nv.cc \
 	ui/gl/gl_gl_api_implementation.cc \
 	ui/gl/gl_image.cc \
 	ui/gl/gl_image_android.cc \
@@ -119,6 +121,7 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_fence_egl.cc \
 	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
diff --git a/ui/gl/gl.target.linux-x86_64.mk b/ui/gl/gl.target.linux-x86_64.mk
index 9440fb9..aadbb3b 100644
--- a/ui/gl/gl.target.linux-x86_64.mk
+++ b/ui/gl/gl.target.linux-x86_64.mk
@@ -97,6 +97,8 @@
 	ui/gl/gl_context_stub.cc \
 	ui/gl/gl_context_stub_with_extensions.cc \
 	ui/gl/gl_fence.cc \
+	ui/gl/gl_fence_arb.cc \
+	ui/gl/gl_fence_nv.cc \
 	ui/gl/gl_gl_api_implementation.cc \
 	ui/gl/gl_image.cc \
 	ui/gl/gl_image_android.cc \
@@ -119,6 +121,7 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_fence_egl.cc \
 	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
index 04c6a48..5186f23 100644
--- a/ui/gl/gl_fence.cc
+++ b/ui/gl/gl_fence.cc
@@ -7,6 +7,9 @@
 #include "base/compiler_specific.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
+#include "ui/gl/gl_fence_arb.h"
+#include "ui/gl/gl_fence_egl.h"
+#include "ui/gl/gl_fence_nv.h"
 #include "ui/gl/gl_gl_api_implementation.h"
 #include "ui/gl/gl_version_info.h"
 
@@ -14,151 +17,6 @@
 
 namespace {
 
-class GLFenceNVFence: public GLFence {
- public:
-  GLFenceNVFence(bool flush) {
-    // What if either of these GL calls fails? TestFenceNV will return true.
-    // See spec:
-    // http://www.opengl.org/registry/specs/NV/fence.txt
-    //
-    // What should happen if TestFenceNV is called for a name before SetFenceNV
-    // is called?
-    //     We generate an INVALID_OPERATION error, and return TRUE.
-    //     This follows the semantics for texture object names before
-    //     they are bound, in that they acquire their state upon binding.
-    //     We will arbitrarily return TRUE for consistency.
-    glGenFencesNV(1, &fence_);
-    glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
-    if (flush) {
-      glFlush();
-    } else {
-      flush_event_ = GLContext::GetCurrent()->SignalFlush();
-    }
-  }
-
-  virtual bool HasCompleted() OVERRIDE {
-    return !!glTestFenceNV(fence_);
-  }
-
-  virtual void ClientWait() OVERRIDE {
-    if (!flush_event_ || flush_event_->IsSignaled()) {
-      glFinishFenceNV(fence_);
-    } else {
-      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-    }
-  }
-
-  virtual void ServerWait() OVERRIDE {
-    ClientWait();
-  }
-
- private:
-  virtual ~GLFenceNVFence() {
-    glDeleteFencesNV(1, &fence_);
-  }
-
-  GLuint fence_;
-  scoped_refptr<GLContext::FlushEvent> flush_event_;
-};
-
-class GLFenceARBSync: public GLFence {
- public:
-  GLFenceARBSync(bool flush) {
-    sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-    if (flush) {
-      glFlush();
-    } else {
-      flush_event_ = GLContext::GetCurrent()->SignalFlush();
-    }
-  }
-
-  virtual bool HasCompleted() OVERRIDE {
-    // Handle the case where FenceSync failed.
-    if (!sync_)
-      return true;
-
-    // We could potentially use glGetSynciv here, but it doesn't work
-    // on OSX 10.7 (always says the fence is not signaled yet).
-    // glClientWaitSync works better, so let's use that instead.
-    return  glClientWaitSync(sync_, 0, 0) != GL_TIMEOUT_EXPIRED;
-  }
-
-  virtual void ClientWait() OVERRIDE {
-    if (!flush_event_ || flush_event_->IsSignaled()) {
-      glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
-    } else {
-      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-    }
-  }
-
-  virtual void ServerWait() OVERRIDE {
-    if (!flush_event_ || flush_event_->IsSignaled()) {
-      glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
-    } else {
-      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-    }
-  }
-
- private:
-  virtual ~GLFenceARBSync() {
-    glDeleteSync(sync_);
-  }
-
-  GLsync sync_;
-  scoped_refptr<GLContext::FlushEvent> flush_event_;
-};
-
-#if !defined(OS_MACOSX)
-class EGLFenceSync : public GLFence {
- public:
-  EGLFenceSync(bool flush) {
-    display_ = eglGetCurrentDisplay();
-    sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL);
-    if (flush) {
-      glFlush();
-    } else {
-      flush_event_ = GLContext::GetCurrent()->SignalFlush();
-    }
-  }
-
-  virtual bool HasCompleted() OVERRIDE {
-    EGLint value = 0;
-    eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value);
-    DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR);
-    return !value || value == EGL_SIGNALED_KHR;
-  }
-
-  virtual void ClientWait() OVERRIDE {
-    if (!flush_event_ || flush_event_->IsSignaled()) {
-      EGLint flags = 0;
-      EGLTimeKHR time = EGL_FOREVER_KHR;
-      eglClientWaitSyncKHR(display_, sync_, flags, time);
-    } else {
-      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-    }
-  }
-
-  virtual void ServerWait() OVERRIDE {
-    if (!flush_event_ || flush_event_->IsSignaled()) {
-      EGLint flags = 0;
-      eglWaitSyncKHR(display_, sync_, flags);
-    } else {
-      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-    }
-  }
-
-
- private:
-  virtual ~EGLFenceSync() {
-    eglDestroySyncKHR(display_, sync_);
-  }
-
-  EGLSyncKHR sync_;
-  EGLDisplay display_;
-  scoped_refptr<GLContext::FlushEvent> flush_event_;
-};
-#endif // !OS_MACOSX
-
 // static
 GLFence* CreateFence(bool flush) {
   DCHECK(GLContext::GetCurrent())
@@ -168,13 +26,13 @@
   // Prefer ARB_sync which supports server-side wait.
   if (g_driver_gl.ext.b_GL_ARB_sync ||
       GetGLVersionInfo()->is_es3) {
-    fence.reset(new GLFenceARBSync(flush));
+    fence.reset(new GLFenceARB(flush));
 #if !defined(OS_MACOSX)
   } else if (g_driver_egl.ext.b_EGL_KHR_fence_sync) {
-    fence.reset(new EGLFenceSync(flush));
+    fence.reset(new GLFenceEGL(flush));
 #endif
   } else if (g_driver_gl.ext.b_GL_NV_fence) {
-    fence.reset(new GLFenceNVFence(flush));
+    fence.reset(new GLFenceNV(flush));
   }
 
   DCHECK_EQ(!!fence.get(), GLFence::IsSupported());
diff --git a/ui/gl/gl_fence.h b/ui/gl/gl_fence.h
index a4f9743..5af253d 100644
--- a/ui/gl/gl_fence.h
+++ b/ui/gl/gl_fence.h
@@ -31,9 +31,6 @@
   // client.
   virtual void ServerWait() = 0;
 
- protected:
-  static bool IsContextLost();
-
  private:
   DISALLOW_COPY_AND_ASSIGN(GLFence);
 };
diff --git a/ui/gl/gl_fence_arb.cc b/ui/gl/gl_fence_arb.cc
new file mode 100644
index 0000000..b854346
--- /dev/null
+++ b/ui/gl/gl_fence_arb.cc
@@ -0,0 +1,57 @@
+// Copyright 2014 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 "ui/gl/gl_fence_arb.h"
+
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+
+namespace gfx {
+
+GLFenceARB::GLFenceARB(bool flush) {
+  sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+  DCHECK_EQ(GL_TRUE, glIsSync(sync_));
+  if (flush) {
+    glFlush();
+  } else {
+    flush_event_ = GLContext::GetCurrent()->SignalFlush();
+  }
+}
+
+bool GLFenceARB::HasCompleted() {
+  // Handle the case where FenceSync failed.
+  if (!sync_)
+    return true;
+
+  DCHECK_EQ(GL_TRUE, glIsSync(sync_));
+  // We could potentially use glGetSynciv here, but it doesn't work
+  // on OSX 10.7 (always says the fence is not signaled yet).
+  // glClientWaitSync works better, so let's use that instead.
+  return glClientWaitSync(sync_, 0, 0) != GL_TIMEOUT_EXPIRED;
+}
+
+void GLFenceARB::ClientWait() {
+  DCHECK_EQ(GL_TRUE, glIsSync(sync_));
+  if (!flush_event_ || flush_event_->IsSignaled()) {
+    glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
+  } else {
+    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+  }
+}
+
+void GLFenceARB::ServerWait() {
+  DCHECK_EQ(GL_TRUE, glIsSync(sync_));
+  if (!flush_event_ || flush_event_->IsSignaled()) {
+    glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
+  } else {
+    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+  }
+}
+
+GLFenceARB::~GLFenceARB() {
+  DCHECK_EQ(GL_TRUE, glIsSync(sync_));
+  glDeleteSync(sync_);
+}
+
+}  // namespace gfx
diff --git a/ui/gl/gl_fence_arb.h b/ui/gl/gl_fence_arb.h
new file mode 100644
index 0000000..db29675
--- /dev/null
+++ b/ui/gl/gl_fence_arb.h
@@ -0,0 +1,34 @@
+// Copyright 2014 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 UI_GL_GL_FENCE_ARB_H_
+#define UI_GL_GL_FENCE_ARB_H_
+
+#include "base/macros.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_fence.h"
+
+namespace gfx {
+
+class GL_EXPORT GLFenceARB : public GLFence {
+ public:
+  GLFenceARB(bool flush);
+  virtual ~GLFenceARB();
+
+  // GLFence implementation:
+  virtual bool HasCompleted() OVERRIDE;
+  virtual void ClientWait() OVERRIDE;
+  virtual void ServerWait() OVERRIDE;
+
+ private:
+  GLsync sync_;
+  scoped_refptr<GLContext::FlushEvent> flush_event_;
+
+  DISALLOW_COPY_AND_ASSIGN(GLFenceARB);
+};
+
+}  // namespace gfx
+
+#endif  // UI_GL_GL_FENCE_ARB_H_
diff --git a/ui/gl/gl_fence_egl.cc b/ui/gl/gl_fence_egl.cc
new file mode 100644
index 0000000..71d3103
--- /dev/null
+++ b/ui/gl/gl_fence_egl.cc
@@ -0,0 +1,53 @@
+// Copyright 2014 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 "ui/gl/gl_fence_egl.h"
+
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+
+namespace gfx {
+
+GLFenceEGL::GLFenceEGL(bool flush) {
+  display_ = eglGetCurrentDisplay();
+  sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL);
+  DCHECK(sync_ != EGL_NO_SYNC_KHR);
+  if (flush) {
+    glFlush();
+  } else {
+    flush_event_ = GLContext::GetCurrent()->SignalFlush();
+  }
+}
+
+bool GLFenceEGL::HasCompleted() {
+  EGLint value = 0;
+  eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value);
+  DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR);
+  return !value || value == EGL_SIGNALED_KHR;
+}
+
+void GLFenceEGL::ClientWait() {
+  if (!flush_event_ || flush_event_->IsSignaled()) {
+    EGLint flags = 0;
+    EGLTimeKHR time = EGL_FOREVER_KHR;
+    eglClientWaitSyncKHR(display_, sync_, flags, time);
+  } else {
+    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+  }
+}
+
+void GLFenceEGL::ServerWait() {
+  if (!flush_event_ || flush_event_->IsSignaled()) {
+    EGLint flags = 0;
+    eglWaitSyncKHR(display_, sync_, flags);
+  } else {
+    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+  }
+}
+
+GLFenceEGL::~GLFenceEGL() {
+  eglDestroySyncKHR(display_, sync_);
+}
+
+}  // namespace gfx
diff --git a/ui/gl/gl_fence_egl.h b/ui/gl/gl_fence_egl.h
new file mode 100644
index 0000000..531b3dc
--- /dev/null
+++ b/ui/gl/gl_fence_egl.h
@@ -0,0 +1,35 @@
+// Copyright 2014 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 UI_GL_GL_FENCE_EGL_H_
+#define UI_GL_GL_FENCE_EGL_H_
+
+#include "base/macros.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_fence.h"
+
+namespace gfx {
+
+class GL_EXPORT GLFenceEGL : public GLFence {
+ public:
+  GLFenceEGL(bool flush);
+  virtual ~GLFenceEGL();
+
+  // GLFence implementation:
+  virtual bool HasCompleted() OVERRIDE;
+  virtual void ClientWait() OVERRIDE;
+  virtual void ServerWait() OVERRIDE;
+
+ private:
+  EGLSyncKHR sync_;
+  EGLDisplay display_;
+  scoped_refptr<GLContext::FlushEvent> flush_event_;
+
+  DISALLOW_COPY_AND_ASSIGN(GLFenceEGL);
+};
+
+}  // namespace gfx
+
+#endif  // UI_GL_GL_FENCE_EGL_H_
diff --git a/ui/gl/gl_fence_nv.cc b/ui/gl/gl_fence_nv.cc
new file mode 100644
index 0000000..9dbc47d
--- /dev/null
+++ b/ui/gl/gl_fence_nv.cc
@@ -0,0 +1,57 @@
+// Copyright 2014 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 "ui/gl/gl_fence_nv.h"
+
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+
+namespace gfx {
+
+GLFenceNV::GLFenceNV(bool flush) {
+  // What if either of these GL calls fails? TestFenceNV will return true.
+  // See spec:
+  // http://www.opengl.org/registry/specs/NV/fence.txt
+  //
+  // What should happen if TestFenceNV is called for a name before SetFenceNV
+  // is called?
+  //     We generate an INVALID_OPERATION error, and return TRUE.
+  //     This follows the semantics for texture object names before
+  //     they are bound, in that they acquire their state upon binding.
+  //     We will arbitrarily return TRUE for consistency.
+  glGenFencesNV(1, &fence_);
+  glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
+  DCHECK(glIsFenceNV(fence_));
+  if (flush) {
+    glFlush();
+  } else {
+    flush_event_ = GLContext::GetCurrent()->SignalFlush();
+  }
+}
+
+bool GLFenceNV::HasCompleted() {
+  DCHECK(glIsFenceNV(fence_));
+  return !!glTestFenceNV(fence_);
+}
+
+void GLFenceNV::ClientWait() {
+  DCHECK(glIsFenceNV(fence_));
+  if (!flush_event_ || flush_event_->IsSignaled()) {
+    glFinishFenceNV(fence_);
+  } else {
+    LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+  }
+}
+
+void GLFenceNV::ServerWait() {
+  DCHECK(glIsFenceNV(fence_));
+  ClientWait();
+}
+
+GLFenceNV::~GLFenceNV() {
+  DCHECK(glIsFenceNV(fence_));
+  glDeleteFencesNV(1, &fence_);
+}
+
+}  // namespace gfx
diff --git a/ui/gl/gl_fence_nv.h b/ui/gl/gl_fence_nv.h
new file mode 100644
index 0000000..fee9eff
--- /dev/null
+++ b/ui/gl/gl_fence_nv.h
@@ -0,0 +1,34 @@
+// Copyright 2014 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 UI_GL_GL_FENCE_NV_H_
+#define UI_GL_GL_FENCE_NV_H_
+
+#include "base/macros.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_fence.h"
+
+namespace gfx {
+
+class GL_EXPORT GLFenceNV : public GLFence {
+ public:
+  GLFenceNV(bool flush);
+  virtual ~GLFenceNV();
+
+  // GLFence implementation:
+  virtual bool HasCompleted() OVERRIDE;
+  virtual void ClientWait() OVERRIDE;
+  virtual void ServerWait() OVERRIDE;
+
+ private:
+  GLuint fence_;
+  scoped_refptr<GLContext::FlushEvent> flush_event_;
+
+  DISALLOW_COPY_AND_ASSIGN(GLFenceNV);
+};
+
+}  // namespace gfx
+
+#endif  // UI_GL_GL_FENCE_NV_H_