Cherry-pick: Support multiple service instances with GLInProcessContext

Cherry-pick with conflict of crrev.com/r250984

Conflicts:
	content/browser/android/in_process/synchronous_compositor_factory_impl.cc
	content/browser/android/in_process/synchronous_compositor_factory_impl.h
	content/browser/android/in_process/synchronous_compositor_output_surface.cc

Conflicts are due to not having crrev.com/r249099 and crrev.com/r244697.
Moved had to fix some includes and add gfx::GLSurface::InitializeOneOff to
SynchronousCompositorFactoryImpl::SetDeferredGpuService.

Original description:

For example, it supports running two GPU threads.

This simplifies the scheduling/queuing logic in InProcessCommandBuffer
a bit and moves the non-thread/queue implementation out to WebView by
allowing for passing in a InProcessCommandBuffer::Service instance
when creating a context.

BUG: 13328348

Change-Id: Ia0c108cdf0275dfbfedb3cf0b27500d3f57fcf49
diff --git a/android_webview/browser/in_process_view_renderer.cc b/android_webview/browser/in_process_view_renderer.cc
index 4496f2b..2e4d846 100644
--- a/android_webview/browser/in_process_view_renderer.cc
+++ b/android_webview/browser/in_process_view_renderer.cc
@@ -173,7 +173,8 @@
 
 bool ScopedAllowGL::allow_gl = false;
 
-base::LazyInstance<GLViewRendererManager>::Leaky g_view_renderer_manager;
+base::LazyInstance<GLViewRendererManager>::Leaky g_view_renderer_manager =
+    LAZY_INSTANCE_INITIALIZER;
 
 void RequestProcessGLOnUIThread() {
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
@@ -190,23 +191,94 @@
   }
 }
 
-}  // namespace
+class DeferredGpuCommandService
+    : public gpu::InProcessCommandBuffer::Service,
+      public base::RefCountedThreadSafe<DeferredGpuCommandService> {
+ public:
+  DeferredGpuCommandService();
+
+  virtual void ScheduleTask(const base::Closure& task) OVERRIDE;
+  virtual void ScheduleIdleWork(const base::Closure& task) OVERRIDE;
+  virtual bool UseVirtualizedGLContexts() OVERRIDE;
+
+  void RunTasks();
+
+  virtual void AddRef() const OVERRIDE {
+    base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef();
+  }
+  virtual void Release() const OVERRIDE {
+    base::RefCountedThreadSafe<DeferredGpuCommandService>::Release();
+  }
+
+ protected:
+  virtual ~DeferredGpuCommandService();
+  friend class base::RefCountedThreadSafe<DeferredGpuCommandService>;
+
+ private:
+  base::Lock tasks_lock_;
+  std::queue<base::Closure> tasks_;
+  DISALLOW_COPY_AND_ASSIGN(DeferredGpuCommandService);
+};
+
+DeferredGpuCommandService::DeferredGpuCommandService() {}
+
+DeferredGpuCommandService::~DeferredGpuCommandService() {
+  base::AutoLock lock(tasks_lock_);
+  DCHECK(tasks_.empty());
+}
 
 // Called from different threads!
-static void ScheduleGpuWork() {
+void DeferredGpuCommandService::ScheduleTask(const base::Closure& task) {
+  {
+    base::AutoLock lock(tasks_lock_);
+    tasks_.push(task);
+  }
   if (ScopedAllowGL::IsAllowed()) {
-    gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread();
+    RunTasks();
   } else {
     RequestProcessGLOnUIThread();
   }
 }
 
+void DeferredGpuCommandService::ScheduleIdleWork(
+    const base::Closure& callback) {
+  // TODO(sievers): Should this do anything?
+}
+
+bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
+
+void DeferredGpuCommandService::RunTasks() {
+  bool has_more_tasks;
+  {
+    base::AutoLock lock(tasks_lock_);
+    has_more_tasks = tasks_.size() > 0;
+  }
+
+  while (has_more_tasks) {
+    base::Closure task;
+    {
+      base::AutoLock lock(tasks_lock_);
+      task = tasks_.front();
+      tasks_.pop();
+    }
+    task.Run();
+    {
+      base::AutoLock lock(tasks_lock_);
+      has_more_tasks = tasks_.size() > 0;
+    }
+
+  }
+}
+
+base::LazyInstance<scoped_refptr<DeferredGpuCommandService> > g_service =
+    LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
 // static
 void BrowserViewRenderer::SetAwDrawSWFunctionTable(
     AwDrawSWFunctionTable* table) {
   g_sw_draw_functions = table;
-  gpu::InProcessCommandBuffer::SetScheduleCallback(
-      base::Bind(&ScheduleGpuWork));
 }
 
 // static
@@ -350,7 +422,7 @@
   TRACE_EVENT0("android_webview", "InProcessViewRenderer::TrimMemory");
   ScopedAppGLStateRestore state_restore(
       ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
-  gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread();
+  g_service.Get()->RunTasks();
   ScopedAllowGL allow_gl;
 
   SetMemoryPolicy(policy);
@@ -388,7 +460,11 @@
 bool InProcessViewRenderer::InitializeHwDraw() {
   TRACE_EVENT0("android_webview", "InitializeHwDraw");
   DCHECK(!gl_surface_);
-  gl_surface_  = new AwGLSurface;
+  gl_surface_ = new AwGLSurface;
+  if (!g_service.Get()) {
+    g_service.Get() = new DeferredGpuCommandService;
+    content::SynchronousCompositor::SetGpuService(g_service.Get());
+  }
   hardware_failed_ = !compositor_->InitializeHwDraw(gl_surface_);
   hardware_initialized_ = true;
 
@@ -413,7 +489,8 @@
   }
 
   ScopedAppGLStateRestore state_restore(ScopedAppGLStateRestore::MODE_DRAW);
-  gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread();
+  if (g_service.Get())
+    g_service.Get()->RunTasks();
   ScopedAllowGL allow_gl;
 
   if (!attached_to_window_) {
@@ -690,7 +767,7 @@
 
     ScopedAppGLStateRestore state_restore(
         ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT);
-    gpu::InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread();
+    g_service.Get()->RunTasks();
     ScopedAllowGL allow_gl;
     compositor_->ReleaseHwDraw();
     hardware_initialized_ = false;
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc
index a172b86..c3186ae 100644
--- a/android_webview/lib/main/aw_main_delegate.cc
+++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -51,7 +51,6 @@
 
   gpu::InProcessCommandBuffer::SetGpuMemoryBufferFactory(
       gpu_memory_buffer_factory_.get());
-  gpu::InProcessCommandBuffer::EnableVirtualizedContext();
 
   InProcessViewRenderer::CalculateTileMemoryPolicy();
 
diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
index b0856b1..754180f 100644
--- a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
+++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
@@ -9,6 +9,7 @@
 #include "gpu/command_buffer/client/gl_in_process_context.h"
 #include "ui/gl/android/surface_texture.h"
 #include "ui/gl/gl_surface.h"
+#include "ui/gl/gl_surface_stub.h"
 #include "webkit/common/gpu/context_provider_in_process.h"
 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
 
@@ -16,14 +17,62 @@
 
 namespace {
 
+blink::WebGraphicsContext3D::Attributes GetDefaultAttribs() {
+  blink::WebGraphicsContext3D::Attributes attributes;
+  attributes.antialias = false;
+  attributes.depth = false;
+  attributes.stencil = false;
+  attributes.shareResources = true;
+  attributes.noAutomaticFlushes = true;
+
+  return attributes;
+}
+
+using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
+
+scoped_ptr<gpu::GLInProcessContext> CreateContext(
+    scoped_refptr<gfx::GLSurface> surface,
+    scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
+    gpu::GLInProcessContext* share_context) {
+  const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
+
+  if (!surface)
+    surface = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1));
+
+  gpu::GLInProcessContextAttribs in_process_attribs;
+  WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
+      GetDefaultAttribs(), &in_process_attribs);
+  scoped_ptr<gpu::GLInProcessContext> context(
+      gpu::GLInProcessContext::CreateWithSurface(surface,
+                                                 service,
+                                                 share_context,
+                                                 in_process_attribs,
+                                                 gpu_preference));
+  return context.Pass();
+}
+
+scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> WrapContext(
+    scoped_ptr<gpu::GLInProcessContext> context) {
+  if (!context.get())
+    return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
+
+  return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(
+      WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
+          context.Pass(), GetDefaultAttribs()));
+}
+
 class VideoContextProvider
     : public StreamTextureFactorySynchronousImpl::ContextProvider {
  public:
   VideoContextProvider(
-      const scoped_refptr<cc::ContextProvider>& context_provider,
-      gpu::GLInProcessContext* gl_in_process_context)
-      : context_provider_(context_provider),
-        gl_in_process_context_(gl_in_process_context) {}
+      scoped_ptr<gpu::GLInProcessContext> gl_in_process_context)
+      : gl_in_process_context_(gl_in_process_context.get()) {
+
+    context_provider_ = webkit::gpu::ContextProviderInProcess::Create(
+        WrapContext(gl_in_process_context.Pass()),
+        "Video-Offscreen-main-thread");
+    context_provider_->BindToCurrentThread();
+  }
 
   virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
       uint32 stream_id) OVERRIDE {
@@ -50,6 +99,7 @@
 
 SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl()
     : wrapped_gl_context_for_main_thread_(NULL),
+      wrapped_gl_context_for_compositor_thread_(NULL),
       num_hardware_compositors_(0) {
   SynchronousCompositorFactory::SetInstance(this);
 }
@@ -75,17 +125,16 @@
 
 scoped_refptr<cc::ContextProvider>
 SynchronousCompositorFactoryImpl::GetOffscreenContextProviderForMainThread() {
-  // This check only guarantees the main thread context is created after
-  // a compositor did successfully initialize hardware draw in the past.
-  // In particular this does not guarantee that the main thread context
-  // will fail creation when all compositors release hardware draw.
   bool failed = false;
   if ((!offscreen_context_for_main_thread_.get() ||
        offscreen_context_for_main_thread_->DestroyedOnMainThread())) {
+    scoped_ptr<gpu::GLInProcessContext> context =
+        CreateContext(NULL, NULL, NULL);
+    wrapped_gl_context_for_main_thread_ = context.get();
     offscreen_context_for_main_thread_ =
         webkit::gpu::ContextProviderInProcess::Create(
-            CreateOffscreenContext(),
-            "Compositor-Offscreen");
+            WrapContext(context.Pass()),
+            "Compositor-Offscreen-main-thread");
     failed = !offscreen_context_for_main_thread_.get() ||
              !offscreen_context_for_main_thread_->BindToCurrentThread();
   }
@@ -106,14 +155,40 @@
 scoped_refptr<cc::ContextProvider> SynchronousCompositorFactoryImpl::
     GetOffscreenContextProviderForCompositorThread() {
   base::AutoLock lock(offscreen_context_for_compositor_thread_lock_);
+  DCHECK(service_);
+  bool failed = false;
   if (!offscreen_context_for_compositor_thread_.get() ||
       offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) {
+    scoped_ptr<gpu::GLInProcessContext> context =
+        CreateContext(new gfx::GLSurfaceStub, service_, NULL);
+    wrapped_gl_context_for_compositor_thread_ = context.get();
     offscreen_context_for_compositor_thread_ =
-        webkit::gpu::ContextProviderInProcess::CreateOffscreen();
+        webkit::gpu::ContextProviderInProcess::Create(
+            WrapContext(context.Pass()),
+            "Compositor-Offscreen-compositor-thread");
+    failed = !offscreen_context_for_compositor_thread_.get() ||
+             !offscreen_context_for_compositor_thread_->BindToCurrentThread();
+  }
+  if (failed) {
+    offscreen_context_for_compositor_thread_ = NULL;
+    wrapped_gl_context_for_compositor_thread_ = NULL;
   }
   return offscreen_context_for_compositor_thread_;
 }
 
+scoped_refptr<cc::ContextProvider> SynchronousCompositorFactoryImpl::
+    CreateOnscreenContextProviderForCompositorThread(
+        scoped_refptr<gfx::GLSurface> surface) {
+  DCHECK(surface);
+  DCHECK(service_);
+  DCHECK(wrapped_gl_context_for_compositor_thread_);
+
+  return webkit::gpu::ContextProviderInProcess::Create(
+      WrapContext(CreateContext(
+          surface, service_, wrapped_gl_context_for_compositor_thread_)),
+      "Compositor-Onscreen");
+}
+
 scoped_ptr<StreamTextureFactory>
 SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int view_id) {
   scoped_ptr<StreamTextureFactorySynchronousImpl> factory(
@@ -161,48 +236,27 @@
 SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
   scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
       context_provider;
-  if (CanCreateMainThreadContext() &&
-      GetOffscreenContextProviderForMainThread()) {
-    DCHECK(offscreen_context_for_main_thread_);
-    DCHECK(wrapped_gl_context_for_main_thread_);
-    context_provider =
-        new VideoContextProvider(offscreen_context_for_main_thread_,
-                                 wrapped_gl_context_for_main_thread_);
+  // This check only guarantees the main thread context is created after
+  // a compositor did successfully initialize hardware draw in the past.
+  // In particular this does not guarantee that the main thread context
+  // will fail creation when all compositors release hardware draw.
+  if (CanCreateMainThreadContext() && !video_context_provider_) {
+    DCHECK(service_);
+    DCHECK(wrapped_gl_context_for_compositor_thread_);
+
+    video_context_provider_ = new VideoContextProvider(
+        CreateContext(new gfx::GLSurfaceStub,
+                      service_,
+                      wrapped_gl_context_for_compositor_thread_));
   }
-  return context_provider;
+  return video_context_provider_;
 }
 
-// TODO(boliu): Deduplicate this with synchronous_compositor_output_surface.cc.
-scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
-SynchronousCompositorFactoryImpl::CreateOffscreenContext() {
-  if (!gfx::GLSurface::InitializeOneOff())
-    return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
-
-  const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
-
-  blink::WebGraphicsContext3D::Attributes attributes;
-  attributes.antialias = false;
-  attributes.shareResources = true;
-  attributes.noAutomaticFlushes = true;
-
-  gpu::GLInProcessContextAttribs in_process_attribs;
-  WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
-      attributes, &in_process_attribs);
-  scoped_ptr<gpu::GLInProcessContext> context(
-      gpu::GLInProcessContext::CreateContext(true,
-                                             NULL,
-                                             gfx::Size(1, 1),
-                                             attributes.shareResources,
-                                             in_process_attribs,
-                                             gpu_preference));
-
-  wrapped_gl_context_for_main_thread_ = context.get();
-  if (!context.get())
-    return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
-
-  return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(
-      WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
-          context.Pass(), attributes));
+void SynchronousCompositorFactoryImpl::SetDeferredGpuService(
+    scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
+  DCHECK(!service_);
+  gfx::GLSurface::InitializeOneOff();
+  service_ = service;
 }
 
 }  // namespace content
diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.h b/content/browser/android/in_process/synchronous_compositor_factory_impl.h
index 40bcbac..90e3e79 100644
--- a/content/browser/android/in_process/synchronous_compositor_factory_impl.h
+++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.h
@@ -9,6 +9,11 @@
 #include "content/browser/android/in_process/synchronous_input_event_filter.h"
 #include "content/renderer/android/synchronous_compositor_factory.h"
 #include "content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h"
+#include "gpu/command_buffer/service/in_process_command_buffer.h"
+
+namespace gfx {
+class GLSurface;
+}
 
 namespace gpu {
 class GLInProcessContext;
@@ -50,16 +55,20 @@
     return &synchronous_input_event_filter_;
   }
 
+  void SetDeferredGpuService(
+      scoped_refptr<gpu::InProcessCommandBuffer::Service> service);
   void CompositorInitializedHardwareDraw();
   void CompositorReleasedHardwareDraw();
 
+  scoped_refptr<cc::ContextProvider>
+      CreateOnscreenContextProviderForCompositorThread(
+          scoped_refptr<gfx::GLSurface> surface);
+
  private:
   void ReleaseGlobalHardwareResources();
   bool CanCreateMainThreadContext();
   scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
       TryCreateStreamTextureFactory();
-  scoped_ptr<webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl>
-      CreateOffscreenContext();
 
   SynchronousInputEventFilter synchronous_input_event_filter_;
 
@@ -70,8 +79,13 @@
   // This is a pointer to the context owned by
   // |offscreen_context_for_main_thread_|.
   gpu::GLInProcessContext* wrapped_gl_context_for_main_thread_;
+  gpu::GLInProcessContext* wrapped_gl_context_for_compositor_thread_;
   scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_;
 
+  scoped_refptr<gpu::InProcessCommandBuffer::Service> service_;
+  scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
+      video_context_provider_;
+
   // |num_hardware_compositor_lock_| is updated on UI thread only but can be
   // read on renderer main thread.
   base::Lock num_hardware_compositor_lock_;
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc
index f9fda92..2df695f 100644
--- a/content/browser/android/in_process/synchronous_compositor_impl.cc
+++ b/content/browser/android/in_process/synchronous_compositor_impl.cc
@@ -82,13 +82,27 @@
   compositor_client_ = compositor_client;
 }
 
+// static
+void SynchronousCompositor::SetGpuService(
+    scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
+  g_factory.Get().SetDeferredGpuService(service);
+}
+
 bool SynchronousCompositorImpl::InitializeHwDraw(
     scoped_refptr<gfx::GLSurface> surface) {
   DCHECK(CalledOnValidThread());
   DCHECK(output_surface_);
-  bool success = output_surface_->InitializeHwDraw(
-      surface,
-      g_factory.Get().GetOffscreenContextProviderForCompositorThread());
+
+  // Create contexts in this order so that the share group gets passed
+  // along correctly.
+  scoped_refptr<cc::ContextProvider> offscreen_context =
+      g_factory.Get().GetOffscreenContextProviderForCompositorThread();
+  scoped_refptr<cc::ContextProvider> onscreen_context =
+  g_factory.Get().CreateOnscreenContextProviderForCompositorThread(surface);
+
+  bool success =
+      output_surface_->InitializeHwDraw(onscreen_context, offscreen_context);
+
   if (success)
     g_factory.Get().CompositorInitializedHardwareDraw();
   return success;
diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
index 2d37659..6d08d95 100644
--- a/content/browser/android/in_process/synchronous_compositor_output_surface.cc
+++ b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
@@ -20,7 +20,6 @@
 #include "ui/gfx/rect_conversions.h"
 #include "ui/gfx/skia_util.h"
 #include "ui/gfx/transform.h"
-#include "ui/gl/gl_surface.h"
 #include "webkit/common/gpu/context_provider_in_process.h"
 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
 
@@ -28,35 +27,6 @@
 
 namespace {
 
-scoped_ptr<webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl>
-CreateWebGraphicsContext3D(scoped_refptr<gfx::GLSurface> surface) {
-  using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
-  if (!gfx::GLSurface::InitializeOneOff())
-    return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
-
-  const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
-
-  blink::WebGraphicsContext3D::Attributes attributes;
-  attributes.antialias = false;
-  attributes.shareResources = true;
-  attributes.noAutomaticFlushes = true;
-
-  gpu::GLInProcessContextAttribs in_process_attribs;
-  WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
-      attributes, &in_process_attribs);
-  scoped_ptr<gpu::GLInProcessContext> context(
-      gpu::GLInProcessContext::CreateWithSurface(surface,
-                                                 attributes.shareResources,
-                                                 in_process_attribs,
-                                                 gpu_preference));
-
-  if (!context.get())
-    return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
-
-  return WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
-      context.Pass(), attributes).Pass();
-}
-
 void DidActivatePendingTree(int routing_id) {
   SynchronousCompositorOutputSurfaceDelegate* delegate =
       SynchronousCompositorImpl::FromRoutingID(routing_id);
@@ -192,16 +162,12 @@
 } // namespace
 
 bool SynchronousCompositorOutputSurface::InitializeHwDraw(
-    scoped_refptr<gfx::GLSurface> surface,
+    scoped_refptr<cc::ContextProvider> onscreen_context_provider,
     scoped_refptr<cc::ContextProvider> offscreen_context_provider) {
   DCHECK(CalledOnValidThread());
   DCHECK(HasClient());
   DCHECK(!context_provider_);
-  DCHECK(surface);
 
-  scoped_refptr<cc::ContextProvider> onscreen_context_provider =
-      webkit::gpu::ContextProviderInProcess::Create(
-          CreateWebGraphicsContext3D(surface), "SynchronousCompositor");
   return InitializeAndSetContext3d(onscreen_context_provider,
                                    offscreen_context_provider);
 }
diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.h b/content/browser/android/in_process/synchronous_compositor_output_surface.h
index 2879de0..c97f230 100644
--- a/content/browser/android/in_process/synchronous_compositor_output_surface.h
+++ b/content/browser/android/in_process/synchronous_compositor_output_surface.h
@@ -64,7 +64,7 @@
 
   // Partial SynchronousCompositor API implementation.
   bool InitializeHwDraw(
-      scoped_refptr<gfx::GLSurface> surface,
+      scoped_refptr<cc::ContextProvider> onscreen_context_provider,
       scoped_refptr<cc::ContextProvider> offscreen_context_provider);
   void ReleaseHwDraw();
   bool DemandDrawHw(gfx::Size surface_size,
diff --git a/content/public/browser/android/synchronous_compositor.h b/content/public/browser/android/synchronous_compositor.h
index c77d2a8..1d03278 100644
--- a/content/public/browser/android/synchronous_compositor.h
+++ b/content/public/browser/android/synchronous_compositor.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "content/common/content_export.h"
+#include "gpu/command_buffer/service/in_process_command_buffer.h"
 #include "ui/gfx/rect.h"
 #include "ui/gfx/size.h"
 
@@ -52,6 +53,9 @@
   // the caller.
   virtual void SetClient(SynchronousCompositorClient* client) = 0;
 
+  static void SetGpuService(
+      scoped_refptr<gpu::InProcessCommandBuffer::Service> service);
+
   // Synchronously initialize compositor for hardware draw. Can only be called
   // while compositor is in software only mode, either after compositor is
   // first created or after ReleaseHwDraw is called. It is invalid to
diff --git a/gpu/command_buffer/client/gl_in_process_context.cc b/gpu/command_buffer/client/gl_in_process_context.cc
index 3c19c4d..d9a258e 100644
--- a/gpu/command_buffer/client/gl_in_process_context.cc
+++ b/gpu/command_buffer/client/gl_in_process_context.cc
@@ -26,7 +26,6 @@
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/common/command_buffer.h"
 #include "gpu/command_buffer/common/constants.h"
-#include "gpu/command_buffer/service/in_process_command_buffer.h"
 #include "ui/gfx/size.h"
 #include "ui/gl/gl_image.h"
 
@@ -52,13 +51,16 @@
   explicit GLInProcessContextImpl();
   virtual ~GLInProcessContextImpl();
 
-  bool Initialize(scoped_refptr<gfx::GLSurface> surface,
-                  bool is_offscreen,
-                  bool share_resources,
-                  gfx::AcceleratedWidget window,
-                  const gfx::Size& size,
-                  const GLInProcessContextAttribs& attribs,
-                  gfx::GpuPreference gpu_preference);
+  bool Initialize(
+      scoped_refptr<gfx::GLSurface> surface,
+      bool is_offscreen,
+      bool use_global_share_group,
+      GLInProcessContext* share_context,
+      gfx::AcceleratedWidget window,
+      const gfx::Size& size,
+      const GLInProcessContextAttribs& attribs,
+      gfx::GpuPreference gpu_preference,
+      const scoped_refptr<InProcessCommandBuffer::Service>& service);
 
   // GLInProcessContext implementation:
   virtual void SetContextLostCallback(const base::Closure& callback) OVERRIDE;
@@ -120,11 +122,14 @@
 bool GLInProcessContextImpl::Initialize(
     scoped_refptr<gfx::GLSurface> surface,
     bool is_offscreen,
-    bool share_resources,
+    bool use_global_share_group,
+    GLInProcessContext* share_context,
     gfx::AcceleratedWidget window,
     const gfx::Size& size,
     const GLInProcessContextAttribs& attribs,
-    gfx::GpuPreference gpu_preference) {
+    gfx::GpuPreference gpu_preference,
+    const scoped_refptr<InProcessCommandBuffer::Service>& service) {
+  DCHECK(!use_global_share_group || !share_context);
   DCHECK(size.width() >= 0 && size.height() >= 0);
 
   // Changes to these values should also be copied to
@@ -184,12 +189,12 @@
 
   base::Closure wrapped_callback =
       base::Bind(&GLInProcessContextImpl::OnContextLost, AsWeakPtr());
-  command_buffer_.reset(new InProcessCommandBuffer());
+  command_buffer_.reset(new InProcessCommandBuffer(service));
 
   scoped_ptr<base::AutoLock> scoped_shared_context_lock;
   scoped_refptr<gles2::ShareGroup> share_group;
   InProcessCommandBuffer* share_command_buffer = NULL;
-  if (share_resources) {
+  if (use_global_share_group) {
     scoped_shared_context_lock.reset(
         new base::AutoLock(g_all_shared_contexts_lock.Get()));
     for (std::set<GLInProcessContextImpl*>::const_iterator it =
@@ -205,7 +210,15 @@
         break;
       }
     }
+  } else if (share_context) {
+    GLInProcessContextImpl* impl =
+        static_cast<GLInProcessContextImpl*>(share_context);
+    share_group = impl->gles2_implementation_->share_group();
+    share_command_buffer = impl->command_buffer_.get();
+    DCHECK(share_group);
+    DCHECK(share_command_buffer);
   }
+
   if (!command_buffer_->Initialize(surface,
                                    is_offscreen,
                                    window,
@@ -241,7 +254,7 @@
       free_everything_when_invisible,
       command_buffer_.get()));
 
-  if (share_resources) {
+  if (use_global_share_group) {
     g_all_shared_contexts.Get().insert(this);
     scoped_shared_context_lock.reset();
   }
@@ -307,10 +320,12 @@
       NULL /* surface */,
       is_offscreen,
       share_resources,
+      NULL,
       window,
       size,
       attribs,
-      gpu_preference))
+      gpu_preference,
+      scoped_refptr<InProcessCommandBuffer::Service>()))
     return NULL;
 
   return context.release();
@@ -319,7 +334,8 @@
 // static
 GLInProcessContext* GLInProcessContext::CreateWithSurface(
     scoped_refptr<gfx::GLSurface> surface,
-    bool share_resources,
+    scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
+    GLInProcessContext* share_context,
     const GLInProcessContextAttribs& attribs,
     gfx::GpuPreference gpu_preference) {
   scoped_ptr<GLInProcessContextImpl> context(
@@ -327,11 +343,13 @@
   if (!context->Initialize(
       surface,
       surface->IsOffscreen(),
-      share_resources,
+      false,
+      share_context,
       gfx::kNullAcceleratedWidget,
       surface->GetSize(),
       attribs,
-      gpu_preference))
+      gpu_preference,
+      service))
     return NULL;
 
   return context.release();
diff --git a/gpu/command_buffer/client/gl_in_process_context.h b/gpu/command_buffer/client/gl_in_process_context.h
index 6d96f13..188ed34 100644
--- a/gpu/command_buffer/client/gl_in_process_context.h
+++ b/gpu/command_buffer/client/gl_in_process_context.h
@@ -8,6 +8,7 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "gles2_impl_export.h"
+#include "gpu/command_buffer/service/in_process_command_buffer.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/gpu_preference.h"
@@ -64,7 +65,8 @@
   // thread safe.
   static GLInProcessContext* CreateWithSurface(
       scoped_refptr<gfx::GLSurface> surface,
-      bool share_resources,
+      scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
+      GLInProcessContext* share_context,
       const GLInProcessContextAttribs& attribs,
       gfx::GpuPreference gpu_preference);
 
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc
index 365e261..990824a 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.cc
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -43,8 +43,6 @@
 
 namespace {
 
-static bool g_use_virtualized_gl_context = false;
-static bool g_uses_explicit_scheduling = false;
 static GpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL;
 
 template <typename T>
@@ -57,13 +55,25 @@
 
 class GpuInProcessThread
     : public base::Thread,
+      public InProcessCommandBuffer::Service,
       public base::RefCountedThreadSafe<GpuInProcessThread> {
  public:
   GpuInProcessThread();
 
+  virtual void AddRef() const OVERRIDE {
+    base::RefCountedThreadSafe<GpuInProcessThread>::AddRef();
+  }
+  virtual void Release() const OVERRIDE {
+    base::RefCountedThreadSafe<GpuInProcessThread>::Release();
+  }
+
+  virtual void ScheduleTask(const base::Closure& task) OVERRIDE;
+  virtual void ScheduleIdleWork(const base::Closure& callback) OVERRIDE;
+  virtual bool UseVirtualizedGLContexts() OVERRIDE { return false; }
+
  private:
-  friend class base::RefCountedThreadSafe<GpuInProcessThread>;
   virtual ~GpuInProcessThread();
+  friend class base::RefCountedThreadSafe<GpuInProcessThread>;
 
   DISALLOW_COPY_AND_ASSIGN(GpuInProcessThread);
 };
@@ -76,164 +86,19 @@
   Stop();
 }
 
-// Used with explicit scheduling when there is no dedicated GPU thread.
-class GpuCommandQueue {
- public:
-  GpuCommandQueue();
-  ~GpuCommandQueue();
-
-  void QueueTask(const base::Closure& task);
-  void RunTasks();
-  void SetScheduleCallback(const base::Closure& callback);
-
- private:
-  base::Lock tasks_lock_;
-  std::queue<base::Closure> tasks_;
-  base::Closure schedule_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuCommandQueue);
-};
-
-GpuCommandQueue::GpuCommandQueue() {}
-
-GpuCommandQueue::~GpuCommandQueue() {
-  base::AutoLock lock(tasks_lock_);
-  DCHECK(tasks_.empty());
+void GpuInProcessThread::ScheduleTask(const base::Closure& task) {
+  message_loop()->PostTask(FROM_HERE, task);
 }
 
-void GpuCommandQueue::QueueTask(const base::Closure& task) {
-  {
-    base::AutoLock lock(tasks_lock_);
-    tasks_.push(task);
-  }
-
-  DCHECK(!schedule_callback_.is_null());
-  schedule_callback_.Run();
-}
-
-void GpuCommandQueue::RunTasks() {
-  size_t num_tasks;
-  {
-    base::AutoLock lock(tasks_lock_);
-    num_tasks = tasks_.size();
-  }
-
-  while (num_tasks) {
-    base::Closure task;
-    {
-      base::AutoLock lock(tasks_lock_);
-      task = tasks_.front();
-      tasks_.pop();
-      num_tasks = tasks_.size();
-    }
-
-    task.Run();
-  }
-}
-
-void GpuCommandQueue::SetScheduleCallback(const base::Closure& callback) {
-  DCHECK(schedule_callback_.is_null());
-  schedule_callback_ = callback;
-}
-
-static base::LazyInstance<GpuCommandQueue> g_gpu_queue =
-    LAZY_INSTANCE_INITIALIZER;
-
-class SchedulerClientBase : public InProcessCommandBuffer::SchedulerClient {
- public:
-  explicit SchedulerClientBase(bool need_thread);
-  virtual ~SchedulerClientBase();
-
-  static bool HasClients();
-
- protected:
-  scoped_refptr<GpuInProcessThread> thread_;
-
- private:
-  static base::LazyInstance<std::set<SchedulerClientBase*> > all_clients_;
-  static base::LazyInstance<base::Lock> all_clients_lock_;
-};
-
-base::LazyInstance<std::set<SchedulerClientBase*> >
-    SchedulerClientBase::all_clients_ = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<base::Lock> SchedulerClientBase::all_clients_lock_ =
-    LAZY_INSTANCE_INITIALIZER;
-
-SchedulerClientBase::SchedulerClientBase(bool need_thread) {
-  base::AutoLock lock(all_clients_lock_.Get());
-  if (need_thread) {
-    if (!all_clients_.Get().empty()) {
-      SchedulerClientBase* other = *all_clients_.Get().begin();
-      thread_ = other->thread_;
-      DCHECK(thread_.get());
-    } else {
-      thread_ = new GpuInProcessThread;
-    }
-  }
-  all_clients_.Get().insert(this);
-}
-
-SchedulerClientBase::~SchedulerClientBase() {
-  base::AutoLock lock(all_clients_lock_.Get());
-  all_clients_.Get().erase(this);
-}
-
-bool SchedulerClientBase::HasClients() {
-  base::AutoLock lock(all_clients_lock_.Get());
-  return !all_clients_.Get().empty();
-}
-
-// A client that talks to the GPU thread
-class ThreadClient : public SchedulerClientBase {
- public:
-  ThreadClient();
-  virtual void QueueTask(const base::Closure& task) OVERRIDE;
-  virtual void ScheduleIdleWork(const base::Closure& callback) OVERRIDE;
-};
-
-ThreadClient::ThreadClient() : SchedulerClientBase(true) {
-  DCHECK(thread_.get());
-}
-
-void ThreadClient::QueueTask(const base::Closure& task) {
-  thread_->message_loop()->PostTask(FROM_HERE, task);
-}
-
-void ThreadClient::ScheduleIdleWork(const base::Closure& callback) {
-  thread_->message_loop()->PostDelayedTask(
+void GpuInProcessThread::ScheduleIdleWork(const base::Closure& callback) {
+  message_loop()->PostDelayedTask(
       FROM_HERE, callback, base::TimeDelta::FromMilliseconds(5));
 }
 
-// A client that talks to the GpuCommandQueue
-class QueueClient : public SchedulerClientBase {
- public:
-  QueueClient();
-  virtual void QueueTask(const base::Closure& task) OVERRIDE;
-  virtual void ScheduleIdleWork(const base::Closure& callback) OVERRIDE;
-};
-
-QueueClient::QueueClient() : SchedulerClientBase(false) {
-  DCHECK(!thread_.get());
-}
-
-void QueueClient::QueueTask(const base::Closure& task) {
-  g_gpu_queue.Get().QueueTask(task);
-}
-
-void QueueClient::ScheduleIdleWork(const base::Closure& callback) {
-  // TODO(sievers): Should this do anything?
-}
-
-static scoped_ptr<InProcessCommandBuffer::SchedulerClient>
-CreateSchedulerClient() {
-  scoped_ptr<InProcessCommandBuffer::SchedulerClient> client;
-  if (g_uses_explicit_scheduling)
-    client.reset(new QueueClient);
-  else
-    client.reset(new ThreadClient);
-
-  return client.Pass();
-}
+base::LazyInstance<std::set<InProcessCommandBuffer*> > default_thread_clients_ =
+    LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::Lock> default_thread_clients_lock_ =
+    LAZY_INSTANCE_INITIALIZER;
 
 class ScopedEvent {
  public:
@@ -246,15 +111,41 @@
 
 }  // anonyous namespace
 
-InProcessCommandBuffer::InProcessCommandBuffer()
+InProcessCommandBuffer::Service::Service() {}
+
+InProcessCommandBuffer::Service::~Service() {}
+
+scoped_refptr<InProcessCommandBuffer::Service>
+InProcessCommandBuffer::GetDefaultService() {
+  base::AutoLock lock(default_thread_clients_lock_.Get());
+  scoped_refptr<Service> service;
+  if (!default_thread_clients_.Get().empty()) {
+    InProcessCommandBuffer* other = *default_thread_clients_.Get().begin();
+    service = other->service_;
+    DCHECK(service.get());
+  } else {
+    service = new GpuInProcessThread;
+  }
+  return service;
+}
+
+InProcessCommandBuffer::InProcessCommandBuffer(
+    const scoped_refptr<Service>& service)
     : context_lost_(false),
       last_put_offset_(-1),
       flush_event_(false, false),
-      queue_(CreateSchedulerClient()),
-      gpu_thread_weak_ptr_factory_(this) {}
+      service_(service.get() ? service : GetDefaultService()),
+      gpu_thread_weak_ptr_factory_(this) {
+  if (!service) {
+    base::AutoLock lock(default_thread_clients_lock_.Get());
+    default_thread_clients_.Get().insert(this);
+  }
+}
 
 InProcessCommandBuffer::~InProcessCommandBuffer() {
   Destroy();
+  base::AutoLock lock(default_thread_clients_lock_.Get());
+  default_thread_clients_.Get().erase(this);
 }
 
 void InProcessCommandBuffer::OnResizeView(gfx::Size size, float scale_factor) {
@@ -301,7 +192,7 @@
     gfx::GpuPreference gpu_preference,
     const base::Closure& context_lost_callback,
     InProcessCommandBuffer* share_group) {
-
+  DCHECK(!share_group || service_ == share_group->service_);
   context_lost_callback_ = WrapCallback(context_lost_callback);
 
   if (surface) {
@@ -402,7 +293,7 @@
     return false;
   }
 
-  if (g_use_virtualized_gl_context) {
+  if (service_->UseVirtualizedGLContexts()) {
     context_ = gl_share_group_->GetSharedContext();
     if (!context_.get()) {
       context_ = gfx::GLContext::CreateGLContext(
@@ -549,7 +440,7 @@
   // pump idle work until the query is passed.
   if (put_offset == state_after_last_flush_.get_offset &&
       gpu_scheduler_->HasMoreWork()) {
-    queue_->ScheduleIdleWork(
+    service_->ScheduleIdleWork(
         base::Bind(&InProcessCommandBuffer::ScheduleMoreIdleWork,
                    gpu_thread_weak_ptr_));
   }
@@ -560,7 +451,7 @@
   base::AutoLock lock(command_buffer_lock_);
   if (gpu_scheduler_->HasMoreWork()) {
     gpu_scheduler_->PerformIdleWork();
-    queue_->ScheduleIdleWork(
+    service_->ScheduleIdleWork(
         base::Bind(&InProcessCommandBuffer::ScheduleMoreIdleWork,
                    gpu_thread_weak_ptr_));
   }
@@ -760,25 +651,6 @@
 #endif
 
 // static
-void InProcessCommandBuffer::EnableVirtualizedContext() {
-  g_use_virtualized_gl_context = true;
-}
-
-// static
-void InProcessCommandBuffer::SetScheduleCallback(
-    const base::Closure& callback) {
-  DCHECK(!g_uses_explicit_scheduling);
-  DCHECK(!SchedulerClientBase::HasClients());
-  g_uses_explicit_scheduling = true;
-  g_gpu_queue.Get().SetScheduleCallback(callback);
-}
-
-// static
-void InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread() {
-  g_gpu_queue.Get().RunTasks();
-}
-
-// static
 void InProcessCommandBuffer::SetGpuMemoryBufferFactory(
     GpuMemoryBufferFactory* factory) {
   g_gpu_memory_buffer_factory = factory;
diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h
index bc0ac1a..1afb628 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.h
+++ b/gpu/command_buffer/service/in_process_command_buffer.h
@@ -59,21 +59,10 @@
 class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer,
                                           public GpuControl {
  public:
-  InProcessCommandBuffer();
+  class Service;
+  explicit InProcessCommandBuffer(const scoped_refptr<Service>& service);
   virtual ~InProcessCommandBuffer();
 
-  // Used to override the GPU thread with explicit scheduling.
-  // (By default an internal GPU thread will be spawned to handle all GL work
-  // and the two functions are unused.)
-  // The callback will be called from different client threads. After the
-  // callback is issued, the client is expected to eventually call
-  // ProcessGpuWorkOnCurrentThread(). The latter cannot be called from different
-  // threads.
-  // The callback needs to be set before any context is created.
-  static void SetScheduleCallback(const base::Closure& callback);
-  static void ProcessGpuWorkOnCurrentThread();
-
-  static void EnableVirtualizedContext();
   static void SetGpuMemoryBufferFactory(GpuMemoryBufferFactory* factory);
 
   // If |surface| is not NULL, use it directly; in this case, the command
@@ -128,16 +117,22 @@
   virtual void Echo(const base::Closure& callback) OVERRIDE;
 
   // The serializer interface to the GPU service (i.e. thread).
-  class SchedulerClient {
+  class Service {
    public:
-     virtual ~SchedulerClient() {}
+    Service();
+    virtual ~Service();
 
-     // Queues a task to run as soon as possible.
-     virtual void QueueTask(const base::Closure& task) = 0;
+    virtual void AddRef() const = 0;
+    virtual void Release() const = 0;
 
-     // Schedules |callback| to run at an appropriate time for performing idle
-     // work.
-     virtual void ScheduleIdleWork(const base::Closure& task) = 0;
+    // Queues a task to run as soon as possible.
+    virtual void ScheduleTask(const base::Closure& task) = 0;
+
+    // Schedules |callback| to run at an appropriate time for performing idle
+    // work.
+    virtual void ScheduleIdleWork(const base::Closure& task) = 0;
+
+    virtual bool UseVirtualizedGLContexts() = 0;
   };
 
 #if defined(OS_ANDROID)
@@ -177,7 +172,7 @@
   bool MakeCurrent();
   base::Closure WrapCallback(const base::Closure& callback);
   State GetStateFast();
-  void QueueTask(const base::Closure& task) { queue_->QueueTask(task); }
+  void QueueTask(const base::Closure& task) { service_->ScheduleTask(task); }
   void CheckSequencedThread();
 
   // Callbacks:
@@ -187,6 +182,8 @@
   void PumpCommands();
   void ScheduleMoreIdleWork();
 
+  static scoped_refptr<Service> GetDefaultService();
+
   // Members accessed on the gpu thread (possibly with the exception of
   // creation):
   bool context_lost_;
@@ -206,7 +203,7 @@
   scoped_ptr<CommandBuffer> command_buffer_;
   base::Lock command_buffer_lock_;
   base::WaitableEvent flush_event_;
-  scoped_ptr<SchedulerClient> queue_;
+  scoped_refptr<Service> service_;
   State state_after_last_flush_;
   base::Lock state_after_last_flush_lock_;
   scoped_ptr<GpuControl> gpu_control_;