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 "base/command_line.h"
8 #include "base/observer_list.h"
9 #include "content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h"
10 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
11 #include "content/browser/android/in_process/synchronous_compositor_output_surface.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/renderer/gpu/frame_swap_message_queue.h"
14 #include "gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h"
15 #include "gpu/command_buffer/client/gl_in_process_context.h"
16 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
17 #include "gpu/command_buffer/service/gpu_switches.h"
18 #include "ui/gl/android/surface_texture.h"
19 #include "ui/gl/gl_surface.h"
20 #include "ui/gl/gl_surface_stub.h"
21 #include "webkit/common/gpu/context_provider_in_process.h"
23 using cc_blink::ContextProviderWebContext
;
24 using gpu_blink::WebGraphicsContext3DImpl
;
25 using gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl
;
31 struct ContextHolder
{
32 scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
> command_buffer
;
33 gpu::GLInProcessContext
* gl_in_process_context
;
36 blink::WebGraphicsContext3D::Attributes
GetDefaultAttribs() {
37 blink::WebGraphicsContext3D::Attributes attributes
;
38 attributes
.antialias
= false;
39 attributes
.depth
= false;
40 attributes
.stencil
= false;
41 attributes
.shareResources
= true;
42 attributes
.noAutomaticFlushes
= true;
47 ContextHolder
CreateContextHolder(
48 const blink::WebGraphicsContext3D::Attributes
& attributes
,
49 scoped_refptr
<gpu::InProcessCommandBuffer::Service
> service
,
50 const gpu::GLInProcessContextSharedMemoryLimits
& mem_limits
,
52 gpu::gles2::ContextCreationAttribHelper in_process_attribs
;
53 WebGraphicsContext3DImpl::ConvertAttributes(attributes
, &in_process_attribs
);
54 in_process_attribs
.lose_context_when_out_of_memory
= true;
56 scoped_ptr
<gpu::GLInProcessContext
> context(gpu::GLInProcessContext::Create(
60 gfx::kNullAcceleratedWidget
,
62 NULL
/* share_context */,
63 attributes
.shareResources
,
65 gfx::PreferDiscreteGpu
,
70 gpu::GLInProcessContext
* context_ptr
= context
.get();
73 holder
.command_buffer
=
74 scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
>(
75 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
76 context
.Pass(), attributes
));
77 holder
.gl_in_process_context
= context_ptr
;
84 class SynchronousCompositorFactoryImpl::VideoContextProvider
85 : public StreamTextureFactorySynchronousImpl::ContextProvider
{
88 scoped_refptr
<cc::ContextProvider
> context_provider
,
89 gpu::GLInProcessContext
* gl_in_process_context
)
90 : context_provider_(context_provider
),
91 gl_in_process_context_(gl_in_process_context
) {
92 context_provider_
->BindToCurrentThread();
95 scoped_refptr
<gfx::SurfaceTexture
> GetSurfaceTexture(
96 uint32 stream_id
) override
{
97 return gl_in_process_context_
->GetSurfaceTexture(stream_id
);
100 gpu::gles2::GLES2Interface
* ContextGL() override
{
101 return context_provider_
->ContextGL();
104 void AddObserver(StreamTextureFactoryContextObserver
* obs
) override
{
105 observer_list_
.AddObserver(obs
);
108 void RemoveObserver(StreamTextureFactoryContextObserver
* obs
) override
{
109 observer_list_
.RemoveObserver(obs
);
112 void RestoreContext() {
113 FOR_EACH_OBSERVER(StreamTextureFactoryContextObserver
,
115 ResetStreamTextureProxy());
119 friend class base::RefCountedThreadSafe
<VideoContextProvider
>;
120 ~VideoContextProvider() override
{}
122 scoped_refptr
<cc::ContextProvider
> context_provider_
;
123 gpu::GLInProcessContext
* gl_in_process_context_
;
124 ObserverList
<StreamTextureFactoryContextObserver
> observer_list_
;
126 DISALLOW_COPY_AND_ASSIGN(VideoContextProvider
);
130 SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl()
131 : record_full_layer_(true),
132 num_hardware_compositors_(0) {
133 SynchronousCompositorFactory::SetInstance(this);
136 SynchronousCompositorFactoryImpl::~SynchronousCompositorFactoryImpl() {}
138 scoped_refptr
<base::MessageLoopProxy
>
139 SynchronousCompositorFactoryImpl::GetCompositorMessageLoop() {
140 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI
);
144 SynchronousCompositorFactoryImpl::RecordFullLayer() {
145 return record_full_layer_
;
148 scoped_ptr
<cc::OutputSurface
>
149 SynchronousCompositorFactoryImpl::CreateOutputSurface(
151 scoped_refptr
<content::FrameSwapMessageQueue
> frame_swap_message_queue
) {
152 scoped_refptr
<cc::ContextProvider
> onscreen_context
=
153 CreateContextProviderForCompositor();
154 scoped_refptr
<cc::ContextProvider
> worker_context
=
155 CreateContextProviderForCompositor();
157 return make_scoped_ptr(new SynchronousCompositorOutputSurface(
158 onscreen_context
, worker_context
, routing_id
, frame_swap_message_queue
));
161 InputHandlerManagerClient
*
162 SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
163 return synchronous_input_event_filter();
166 scoped_ptr
<cc::BeginFrameSource
>
167 SynchronousCompositorFactoryImpl::CreateExternalBeginFrameSource(
169 return make_scoped_ptr(
170 new SynchronousCompositorExternalBeginFrameSource(routing_id
));
173 scoped_refptr
<ContextProviderWebContext
>
174 SynchronousCompositorFactoryImpl::CreateOffscreenContextProvider(
175 const blink::WebGraphicsContext3D::Attributes
& attributes
,
176 const std::string
& debug_name
) {
177 ContextHolder holder
= CreateContextHolder(
178 attributes
, nullptr, gpu::GLInProcessContextSharedMemoryLimits(), true);
179 return webkit::gpu::ContextProviderInProcess::Create(
180 holder
.command_buffer
.Pass(), debug_name
);
183 scoped_refptr
<cc::ContextProvider
>
184 SynchronousCompositorFactoryImpl::CreateContextProviderForCompositor() {
185 blink::WebGraphicsContext3D::Attributes attributes
= GetDefaultAttribs();
186 gpu::GLInProcessContextSharedMemoryLimits mem_limits
;
187 // This is half of what RenderWidget uses because synchronous compositor
188 // pipeline is only one frame deep.
189 mem_limits
.mapped_memory_reclaim_limit
= 6 * 1024 * 1024;
190 ContextHolder holder
=
191 CreateContextHolder(attributes
, nullptr, mem_limits
, true);
192 return webkit::gpu::ContextProviderInProcess::Create(
193 holder
.command_buffer
.Pass(), "Child-Compositor");
196 scoped_refptr
<StreamTextureFactory
>
197 SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int frame_id
) {
198 scoped_refptr
<StreamTextureFactorySynchronousImpl
> factory(
199 StreamTextureFactorySynchronousImpl::Create(
201 &SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory
,
202 base::Unretained(this)),
207 WebGraphicsContext3DInProcessCommandBufferImpl
*
208 SynchronousCompositorFactoryImpl::CreateOffscreenGraphicsContext3D(
209 const blink::WebGraphicsContext3D::Attributes
& attributes
) {
210 ContextHolder holder
= CreateContextHolder(
212 gpu::GLInProcessContextSharedMemoryLimits(), true);
213 return holder
.command_buffer
.release();
216 void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw() {
217 base::AutoLock
lock(num_hardware_compositor_lock_
);
218 num_hardware_compositors_
++;
219 if (num_hardware_compositors_
== 1 && main_thread_proxy_
.get()) {
220 main_thread_proxy_
->PostTask(
223 &SynchronousCompositorFactoryImpl::RestoreContextOnMainThread
,
224 base::Unretained(this)));
228 void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() {
229 base::AutoLock
lock(num_hardware_compositor_lock_
);
230 DCHECK_GT(num_hardware_compositors_
, 0u);
231 num_hardware_compositors_
--;
234 void SynchronousCompositorFactoryImpl::RestoreContextOnMainThread() {
235 if (CanCreateMainThreadContext() && video_context_provider_
.get())
236 video_context_provider_
->RestoreContext();
239 bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
240 base::AutoLock
lock(num_hardware_compositor_lock_
);
241 return num_hardware_compositors_
> 0;
244 scoped_refptr
<StreamTextureFactorySynchronousImpl::ContextProvider
>
245 SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
247 base::AutoLock
lock(num_hardware_compositor_lock_
);
248 main_thread_proxy_
= base::MessageLoopProxy::current();
251 // Always fail creation even if |video_context_provider_| is not NULL.
252 // This is to avoid synchronous calls that may deadlock. Setting
253 // |video_context_provider_| to null is also not safe since it makes
254 // synchronous destruction uncontrolled and possibly deadlock.
255 if (!CanCreateMainThreadContext()) {
257 scoped_refptr
<StreamTextureFactorySynchronousImpl::ContextProvider
>();
260 if (!video_context_provider_
.get()) {
261 DCHECK(service_
.get());
263 blink::WebGraphicsContext3D::Attributes attributes
= GetDefaultAttribs();
264 attributes
.shareResources
= false;
265 // This needs to run in on-screen |service_| context due to SurfaceTexture
267 ContextHolder holder
=
268 CreateContextHolder(attributes
, service_
,
269 gpu::GLInProcessContextSharedMemoryLimits(), false);
270 video_context_provider_
= new VideoContextProvider(
271 webkit::gpu::ContextProviderInProcess::Create(
272 holder
.command_buffer
.Pass(), "Video-Offscreen-main-thread"),
273 holder
.gl_in_process_context
);
275 return video_context_provider_
;
278 void SynchronousCompositorFactoryImpl::SetDeferredGpuService(
279 scoped_refptr
<gpu::InProcessCommandBuffer::Service
> service
) {
280 DCHECK(!service_
.get());
284 void SynchronousCompositorFactoryImpl::SetRecordFullDocument(
285 bool record_full_document
) {
286 record_full_layer_
= record_full_document
;
289 } // namespace content