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_;