Cherry-pick: Add common GLFence::IsSupported() check

Clean cherry-pick of chromium r278860.

Original description:

Cconsolidate the logic inside gl_fence.cc
to allow checking if a GLFence can be created.

Change-Id: I6e964cca9bfe77c13043ac89e68a84d6b0a1b98a
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 94eb4cc..b3f1b93 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -14,6 +14,7 @@
 #include "base/strings/string_util.h"
 #include "gpu/command_buffer/service/gl_utils.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
+#include "ui/gl/gl_fence.h"
 #include "ui/gl/gl_implementation.h"
 
 namespace gpu {
@@ -789,18 +790,14 @@
     feature_flags_.ext_shader_texture_lod = true;
   }
 
-  bool egl_khr_fence_sync = false;
 #if !defined(OS_MACOSX)
   if (workarounds_.disable_egl_khr_fence_sync) {
     gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync = false;
   }
-  egl_khr_fence_sync = gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync;
 #endif
   if (workarounds_.disable_arb_sync)
     gfx::g_driver_gl.ext.b_GL_ARB_sync = false;
-  bool ui_gl_fence_works = is_es3 || extensions.Contains("GL_NV_fence") ||
-                           gfx::g_driver_gl.ext.b_GL_ARB_sync ||
-                           egl_khr_fence_sync;
+  bool ui_gl_fence_works = gfx::GLFence::IsSupported();
   UMA_HISTOGRAM_BOOLEAN("GPU.FenceSupport", ui_gl_fence_works);
 
   feature_flags_.map_buffer_range =
diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc
index be3e38a..3b32f7a 100644
--- a/gpu/command_buffer/service/feature_info_unittest.cc
+++ b/gpu/command_buffer/service/feature_info_unittest.cc
@@ -13,6 +13,7 @@
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "gpu/config/gpu_driver_bug_workaround_type.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gl/gl_fence.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_mock.h"
 
@@ -46,6 +47,7 @@
 
   void SetupInitExpectationsWithGLVersion(
       const char* extensions, const char* renderer, const char* version) {
+    GpuServiceTest::SetUpWithGLVersion(version, extensions);
     TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
         gl_.get(), extensions, renderer, version);
     info_ = new FeatureInfo();
@@ -53,11 +55,13 @@
   }
 
   void SetupWithCommandLine(const CommandLine& command_line) {
+    GpuServiceTest::SetUp();
     info_ = new FeatureInfo(command_line);
   }
 
   void SetupInitExpectationsWithCommandLine(
       const char* extensions, const CommandLine& command_line) {
+    GpuServiceTest::SetUpWithGLVersion("2.0", extensions);
     TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
         gl_.get(), extensions, "", "");
     info_ = new FeatureInfo(command_line);
@@ -65,11 +69,16 @@
   }
 
   void SetupWithoutInit() {
+    GpuServiceTest::SetUp();
     info_ = new FeatureInfo();
   }
 
  protected:
-  virtual void TearDown() {
+  virtual void SetUp() OVERRIDE {
+    // Do nothing here, since we are using the explicit Setup*() functions.
+  }
+
+  virtual void TearDown() OVERRIDE {
     info_ = NULL;
     GpuServiceTest::TearDown();
   }
@@ -310,6 +319,7 @@
       GL_DEPTH24_STENCIL8_OES));
   EXPECT_FALSE(info_->validators()->equation.IsValid(GL_MIN_EXT));
   EXPECT_FALSE(info_->validators()->equation.IsValid(GL_MAX_EXT));
+  EXPECT_FALSE(info_->feature_flags().chromium_sync_query);
 }
 
 TEST_F(FeatureInfoTest, InitializeWithANGLE) {
@@ -1007,6 +1017,8 @@
   EXPECT_TRUE(
       info_->validators()->texture_internal_format.IsValid(GL_DEPTH_STENCIL));
   EXPECT_TRUE(info_->validators()->texture_format.IsValid(GL_DEPTH_STENCIL));
+  EXPECT_TRUE(info_->feature_flags().chromium_sync_query);
+  EXPECT_TRUE(gfx::GLFence::IsSupported());
 }
 
 TEST_F(FeatureInfoTest, InitializeWithoutSamplers) {
@@ -1014,11 +1026,6 @@
   EXPECT_FALSE(info_->feature_flags().enable_samplers);
 }
 
-TEST_F(FeatureInfoTest, InitializeWithES3AndFences) {
-  SetupInitExpectationsWithGLVersion("EGL_KHR_fence_sync", "", "OpenGL ES 3.0");
-  EXPECT_TRUE(info_->feature_flags().use_async_readpixels);
-}
-
 TEST_F(FeatureInfoTest, ParseDriverBugWorkaroundsSingle) {
   CommandLine command_line(0, NULL);
   command_line.AppendSwitchASCII(
@@ -1043,5 +1050,27 @@
   EXPECT_EQ(4096, info_->workarounds().max_texture_size);
 }
 
+TEST_F(FeatureInfoTest, InitializeWithARBSync) {
+  SetupInitExpectations("GL_ARB_sync");
+  EXPECT_TRUE(info_->feature_flags().chromium_sync_query);
+  EXPECT_TRUE(gfx::GLFence::IsSupported());
+}
+
+TEST_F(FeatureInfoTest, InitializeWithNVFence) {
+  SetupInitExpectations("GL_NV_fence");
+  EXPECT_TRUE(info_->feature_flags().chromium_sync_query);
+  EXPECT_TRUE(gfx::GLFence::IsSupported());
+}
+
+TEST_F(FeatureInfoTest, ARBSyncDisabled) {
+  CommandLine command_line(0, NULL);
+  command_line.AppendSwitchASCII(
+      switches::kGpuDriverBugWorkarounds,
+      base::IntToString(gpu::DISABLE_ARB_SYNC));
+  SetupInitExpectationsWithCommandLine("GL_ARB_sync", command_line);
+  EXPECT_FALSE(info_->feature_flags().chromium_sync_query);
+  EXPECT_FALSE(gfx::GLFence::IsSupported());
+}
+
 }  // namespace gles2
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_service_test.cc b/gpu/command_buffer/service/gpu_service_test.cc
index a51a54c..8d62b5a 100644
--- a/gpu/command_buffer/service/gpu_service_test.cc
+++ b/gpu/command_buffer/service/gpu_service_test.cc
@@ -21,7 +21,8 @@
   DCHECK(ran_teardown_);
 }
 
-void GpuServiceTest::SetUp() {
+void GpuServiceTest::SetUpWithGLVersion(const char* gl_version,
+                                        const char* gl_extensions) {
   testing::Test::SetUp();
 
   gfx::SetGLGetProcAddressProc(gfx::MockGLInterface::GetGLProcAddress);
@@ -30,12 +31,16 @@
   ::gfx::MockGLInterface::SetGLInterface(gl_.get());
 
   context_ = new gfx::GLContextStubWithExtensions;
-  context_->AddExtensionsString(NULL);
-  context_->SetGLVersionString("3.0");
+  context_->AddExtensionsString(gl_extensions);
+  context_->SetGLVersionString(gl_version);
   gfx::GLSurface::InitializeDynamicMockBindingsForTests(context_);
   ran_setup_ = true;
 }
 
+void GpuServiceTest::SetUp() {
+  SetUpWithGLVersion("2.0", NULL);
+}
+
 void GpuServiceTest::TearDown() {
   DCHECK(ran_setup_);
   ::gfx::MockGLInterface::SetGLInterface(NULL);
diff --git a/gpu/command_buffer/service/gpu_service_test.h b/gpu/command_buffer/service/gpu_service_test.h
index f371787..c467c14 100644
--- a/gpu/command_buffer/service/gpu_service_test.h
+++ b/gpu/command_buffer/service/gpu_service_test.h
@@ -25,6 +25,7 @@
   virtual ~GpuServiceTest();
 
  protected:
+  void SetUpWithGLVersion(const char* gl_version, const char* gl_extensions);
   virtual void SetUp() OVERRIDE;
   virtual void TearDown() OVERRIDE;
 
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
index 073e6ee..04c6a48 100644
--- a/ui/gl/gl_fence.cc
+++ b/ui/gl/gl_fence.cc
@@ -7,11 +7,14 @@
 #include "base/compiler_specific.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
+#include "ui/gl/gl_gl_api_implementation.h"
 #include "ui/gl/gl_version_info.h"
 
+namespace gfx {
+
 namespace {
 
-class GLFenceNVFence: public gfx::GLFence {
+class GLFenceNVFence: public GLFence {
  public:
   GLFenceNVFence(bool flush) {
     // What if either of these GL calls fails? TestFenceNV will return true.
@@ -29,7 +32,7 @@
     if (flush) {
       glFlush();
     } else {
-      flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
+      flush_event_ = GLContext::GetCurrent()->SignalFlush();
     }
   }
 
@@ -55,17 +58,17 @@
   }
 
   GLuint fence_;
-  scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
+  scoped_refptr<GLContext::FlushEvent> flush_event_;
 };
 
-class GLFenceARBSync: public gfx::GLFence {
+class GLFenceARBSync: public GLFence {
  public:
   GLFenceARBSync(bool flush) {
     sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
     if (flush) {
       glFlush();
     } else {
-      flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
+      flush_event_ = GLContext::GetCurrent()->SignalFlush();
     }
   }
 
@@ -102,11 +105,11 @@
   }
 
   GLsync sync_;
-  scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
+  scoped_refptr<GLContext::FlushEvent> flush_event_;
 };
 
 #if !defined(OS_MACOSX)
-class EGLFenceSync : public gfx::GLFence {
+class EGLFenceSync : public GLFence {
  public:
   EGLFenceSync(bool flush) {
     display_ = eglGetCurrentDisplay();
@@ -114,7 +117,7 @@
     if (flush) {
       glFlush();
     } else {
-      flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
+      flush_event_ = GLContext::GetCurrent()->SignalFlush();
     }
   }
 
@@ -152,38 +155,49 @@
 
   EGLSyncKHR sync_;
   EGLDisplay display_;
-  scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
+  scoped_refptr<GLContext::FlushEvent> flush_event_;
 };
 #endif // !OS_MACOSX
 
 // static
-gfx::GLFence* CreateFence(bool flush) {
-  DCHECK(gfx::GLContext::GetCurrent())
+GLFence* CreateFence(bool flush) {
+  DCHECK(GLContext::GetCurrent())
       << "Trying to create fence with no context";
 
+  scoped_ptr<GLFence> fence;
   // Prefer ARB_sync which supports server-side wait.
-  if (gfx::g_driver_gl.ext.b_GL_ARB_sync ||
-      gfx::GLContext::GetCurrent()->GetVersionInfo()->is_es3)
-    return new GLFenceARBSync(flush);
+  if (g_driver_gl.ext.b_GL_ARB_sync ||
+      GetGLVersionInfo()->is_es3) {
+    fence.reset(new GLFenceARBSync(flush));
 #if !defined(OS_MACOSX)
-  if (gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync)
-    return new EGLFenceSync(flush);
+  } else if (g_driver_egl.ext.b_EGL_KHR_fence_sync) {
+    fence.reset(new EGLFenceSync(flush));
 #endif
-  if (gfx::g_driver_gl.ext.b_GL_NV_fence)
-    return new GLFenceNVFence(flush);
-  return NULL;
+  } else if (g_driver_gl.ext.b_GL_NV_fence) {
+    fence.reset(new GLFenceNVFence(flush));
+  }
+
+  DCHECK_EQ(!!fence.get(), GLFence::IsSupported());
+  return fence.release();
 }
 
 }  // namespace
 
-namespace gfx {
-
 GLFence::GLFence() {
 }
 
 GLFence::~GLFence() {
 }
 
+bool GLFence::IsSupported() {
+  DCHECK(GetGLVersionInfo());
+  return g_driver_gl.ext.b_GL_ARB_sync || GetGLVersionInfo()->is_es3 ||
+#if !defined(OS_MACOSX)
+         g_driver_egl.ext.b_EGL_KHR_fence_sync ||
+#endif
+         g_driver_gl.ext.b_GL_NV_fence;
+}
+
 GLFence* GLFence::Create() {
   return CreateFence(true);
 }
diff --git a/ui/gl/gl_fence.h b/ui/gl/gl_fence.h
index 021f345..a4f9743 100644
--- a/ui/gl/gl_fence.h
+++ b/ui/gl/gl_fence.h
@@ -15,6 +15,7 @@
   GLFence();
   virtual ~GLFence();
 
+  static bool IsSupported();
   static GLFence* Create();
 
   // Creates a fence that is not guaranteed to signal until the current context
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index 2973388..892b16c 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -288,6 +288,10 @@
   SetGLApi(g_no_context_gl);
 }
 
+const GLVersionInfo* GetGLVersionInfo() {
+  return g_version_info;
+}
+
 void InitializeDynamicGLBindingsGL(GLContext* context) {
   g_driver_gl.InitializeCustomDynamicBindings(context);
   DCHECK(context && context->IsCurrent(NULL) && !g_version_info);
diff --git a/ui/gl/gl_gl_api_implementation.h b/ui/gl/gl_gl_api_implementation.h
index aff5926..6e0f7f1 100644
--- a/ui/gl/gl_gl_api_implementation.h
+++ b/ui/gl/gl_gl_api_implementation.h
@@ -17,6 +17,7 @@
 
 class GLContext;
 class GLSurface;
+struct GLVersionInfo;
 
 void InitializeStaticGLBindingsGL();
 void InitializeDynamicGLBindingsGL(GLContext* context);
@@ -29,6 +30,7 @@
 void SetGLToRealGLApi();
 void SetGLApi(GLApi* api);
 void SetGLApiToNoContext();
+const GLVersionInfo* GetGLVersionInfo();
 
 class GLApiBase : public GLApi {
  public: