1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/android/in_process/synchronous_compositor_factory_impl.h"
7 #include "content/browser/android/in_process/synchronous_compositor_output_surface.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "gpu/command_buffer/client/gl_in_process_context.h"
10 #include "ui/gl/android/surface_texture.h"
11 #include "ui/gl/gl_surface.h"
12 #include "webkit/common/gpu/context_provider_in_process.h"
13 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
19 class VideoContextProvider
20 : public StreamTextureFactorySynchronousImpl::ContextProvider
{
23 const scoped_refptr
<cc::ContextProvider
>& context_provider
,
24 gpu::GLInProcessContext
* gl_in_process_context
)
25 : context_provider_(context_provider
),
26 gl_in_process_context_(gl_in_process_context
) {}
28 virtual scoped_refptr
<gfx::SurfaceTexture
> GetSurfaceTexture(
29 uint32 stream_id
) OVERRIDE
{
30 return gl_in_process_context_
->GetSurfaceTexture(stream_id
);
33 virtual blink::WebGraphicsContext3D
* Context3d() OVERRIDE
{
34 return context_provider_
->Context3d();
38 friend class base::RefCountedThreadSafe
<VideoContextProvider
>;
39 virtual ~VideoContextProvider() {}
41 scoped_refptr
<cc::ContextProvider
> context_provider_
;
42 gpu::GLInProcessContext
* gl_in_process_context_
;
44 DISALLOW_COPY_AND_ASSIGN(VideoContextProvider
);
49 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl
;
51 SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl()
52 : wrapped_gl_context_for_main_thread_(NULL
),
53 num_hardware_compositors_(0) {
54 SynchronousCompositorFactory::SetInstance(this);
57 SynchronousCompositorFactoryImpl::~SynchronousCompositorFactoryImpl() {}
59 scoped_refptr
<base::MessageLoopProxy
>
60 SynchronousCompositorFactoryImpl::GetCompositorMessageLoop() {
61 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI
);
64 scoped_ptr
<cc::OutputSurface
>
65 SynchronousCompositorFactoryImpl::CreateOutputSurface(int routing_id
) {
66 scoped_ptr
<SynchronousCompositorOutputSurface
> output_surface(
67 new SynchronousCompositorOutputSurface(routing_id
));
68 return output_surface
.PassAs
<cc::OutputSurface
>();
71 InputHandlerManagerClient
*
72 SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
73 return synchronous_input_event_filter();
76 scoped_refptr
<cc::ContextProvider
>
77 SynchronousCompositorFactoryImpl::GetOffscreenContextProviderForMainThread() {
78 // This check only guarantees the main thread context is created after
79 // a compositor did successfully initialize hardware draw in the past.
80 // In particular this does not guarantee that the main thread context
81 // will fail creation when all compositors release hardware draw.
82 bool failed
= !CanCreateMainThreadContext();
84 (!offscreen_context_for_main_thread_
.get() ||
85 offscreen_context_for_main_thread_
->DestroyedOnMainThread())) {
86 offscreen_context_for_main_thread_
=
87 webkit::gpu::ContextProviderInProcess::Create(
88 CreateOffscreenContext(),
89 "Compositor-Offscreen");
90 failed
= !offscreen_context_for_main_thread_
.get() ||
91 !offscreen_context_for_main_thread_
->BindToCurrentThread();
95 offscreen_context_for_main_thread_
= NULL
;
96 wrapped_gl_context_for_main_thread_
= NULL
;
98 return offscreen_context_for_main_thread_
;
101 // This is called on both renderer main thread (offscreen context creation
102 // path shared between cross-process and in-process platforms) and renderer
103 // compositor impl thread (InitializeHwDraw) in order to support Android
104 // WebView synchronously enable and disable hardware mode multiple times in
105 // the same task. This is ok because in-process WGC3D creation may happen on
106 // any thread and is lightweight.
107 scoped_refptr
<cc::ContextProvider
> SynchronousCompositorFactoryImpl::
108 GetOffscreenContextProviderForCompositorThread() {
109 base::AutoLock
lock(offscreen_context_for_compositor_thread_lock_
);
110 if (!offscreen_context_for_compositor_thread_
.get() ||
111 offscreen_context_for_compositor_thread_
->DestroyedOnMainThread()) {
112 offscreen_context_for_compositor_thread_
=
113 webkit::gpu::ContextProviderInProcess::CreateOffscreen();
115 return offscreen_context_for_compositor_thread_
;
118 scoped_ptr
<StreamTextureFactory
>
119 SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int view_id
) {
120 scoped_ptr
<StreamTextureFactorySynchronousImpl
> factory(
121 new StreamTextureFactorySynchronousImpl(
122 base::Bind(&SynchronousCompositorFactoryImpl::
123 TryCreateStreamTextureFactory
,
124 base::Unretained(this)),
126 return factory
.PassAs
<StreamTextureFactory
>();
129 void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw() {
130 base::AutoLock
lock(num_hardware_compositor_lock_
);
131 num_hardware_compositors_
++;
134 void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() {
135 bool should_release_resources
= false;
137 base::AutoLock
lock(num_hardware_compositor_lock_
);
138 DCHECK_GT(num_hardware_compositors_
, 0u);
139 num_hardware_compositors_
--;
140 should_release_resources
= num_hardware_compositors_
== 0u;
142 if (should_release_resources
)
143 ReleaseGlobalHardwareResources();
146 void SynchronousCompositorFactoryImpl::ReleaseGlobalHardwareResources() {
148 base::AutoLock
lock(offscreen_context_for_compositor_thread_lock_
);
149 offscreen_context_for_compositor_thread_
= NULL
;
152 // TODO(boliu): Properly clean up command buffer server of main thread
156 bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
157 base::AutoLock
lock(num_hardware_compositor_lock_
);
158 return num_hardware_compositors_
> 0;
161 scoped_refptr
<StreamTextureFactorySynchronousImpl::ContextProvider
>
162 SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
163 scoped_refptr
<StreamTextureFactorySynchronousImpl::ContextProvider
>
165 if (CanCreateMainThreadContext() &&
166 GetOffscreenContextProviderForMainThread()) {
167 DCHECK(offscreen_context_for_main_thread_
);
168 DCHECK(wrapped_gl_context_for_main_thread_
);
170 new VideoContextProvider(offscreen_context_for_main_thread_
,
171 wrapped_gl_context_for_main_thread_
);
173 return context_provider
;
176 // TODO(boliu): Deduplicate this with synchronous_compositor_output_surface.cc.
177 scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
>
178 SynchronousCompositorFactoryImpl::CreateOffscreenContext() {
179 if (!gfx::GLSurface::InitializeOneOff())
180 return scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
>();
182 const gfx::GpuPreference gpu_preference
= gfx::PreferDiscreteGpu
;
184 blink::WebGraphicsContext3D::Attributes attributes
;
185 attributes
.antialias
= false;
186 attributes
.shareResources
= true;
187 attributes
.noAutomaticFlushes
= true;
189 gpu::GLInProcessContextAttribs in_process_attribs
;
190 WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
191 attributes
, &in_process_attribs
);
192 scoped_ptr
<gpu::GLInProcessContext
> context(
193 gpu::GLInProcessContext::CreateContext(true,
196 attributes
.shareResources
,
200 wrapped_gl_context_for_main_thread_
= context
.get();
202 return scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
>();
204 return scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
>(
205 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
206 context
.Pass(), attributes
));
209 } // namespace content