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 "content/renderer/gpu/frame_swap_message_queue.h"
10 #include "gpu/command_buffer/client/gl_in_process_context.h"
11 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
12 #include "ui/gl/android/surface_texture.h"
13 #include "ui/gl/gl_surface.h"
14 #include "ui/gl/gl_surface_stub.h"
15 #include "webkit/common/gpu/context_provider_in_process.h"
16 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
18 using webkit::gpu::ContextProviderWebContext
;
24 blink::WebGraphicsContext3D::Attributes
GetDefaultAttribs() {
25 blink::WebGraphicsContext3D::Attributes attributes
;
26 attributes
.antialias
= false;
27 attributes
.depth
= false;
28 attributes
.stencil
= false;
29 attributes
.shareResources
= true;
30 attributes
.noAutomaticFlushes
= true;
35 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl
;
36 using webkit::gpu::WebGraphicsContext3DImpl
;
38 scoped_ptr
<gpu::GLInProcessContext
> CreateOffscreenContext(
39 const blink::WebGraphicsContext3D::Attributes
& attributes
) {
40 const gfx::GpuPreference gpu_preference
= gfx::PreferDiscreteGpu
;
42 gpu::gles2::ContextCreationAttribHelper in_process_attribs
;
43 WebGraphicsContext3DImpl::ConvertAttributes(
44 attributes
, &in_process_attribs
);
45 in_process_attribs
.lose_context_when_out_of_memory
= true;
47 scoped_ptr
<gpu::GLInProcessContext
> context(gpu::GLInProcessContext::Create(
50 true /* is_offscreen */,
51 gfx::kNullAcceleratedWidget
,
53 NULL
/* share_context */,
54 false /* share_resources */,
57 gpu::GLInProcessContextSharedMemoryLimits()));
58 return context
.Pass();
61 scoped_ptr
<gpu::GLInProcessContext
> CreateContext(
62 scoped_refptr
<gpu::InProcessCommandBuffer::Service
> service
,
63 gpu::GLInProcessContext
* share_context
,
64 const gpu::GLInProcessContextSharedMemoryLimits
& mem_limits
) {
65 const gfx::GpuPreference gpu_preference
= gfx::PreferDiscreteGpu
;
66 gpu::gles2::ContextCreationAttribHelper in_process_attribs
;
67 WebGraphicsContext3DImpl::ConvertAttributes(
68 GetDefaultAttribs(), &in_process_attribs
);
69 in_process_attribs
.lose_context_when_out_of_memory
= true;
71 scoped_ptr
<gpu::GLInProcessContext
> context(gpu::GLInProcessContext::Create(
74 false /* is_offscreen */,
75 gfx::kNullAcceleratedWidget
,
78 false /* share_resources */,
82 return context
.Pass();
85 scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
> WrapContext(
86 scoped_ptr
<gpu::GLInProcessContext
> context
) {
88 return scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
>();
90 return scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
>(
91 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
92 context
.Pass(), GetDefaultAttribs()));
95 scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
>
96 WrapContextWithAttributes(
97 scoped_ptr
<gpu::GLInProcessContext
> context
,
98 const blink::WebGraphicsContext3D::Attributes
& attributes
) {
100 return scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
>();
102 return scoped_ptr
<WebGraphicsContext3DInProcessCommandBufferImpl
>(
103 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
104 context
.Pass(), attributes
));
107 class VideoContextProvider
108 : public StreamTextureFactorySynchronousImpl::ContextProvider
{
110 VideoContextProvider(
111 scoped_ptr
<gpu::GLInProcessContext
> gl_in_process_context
)
112 : gl_in_process_context_(gl_in_process_context
.get()) {
114 context_provider_
= webkit::gpu::ContextProviderInProcess::Create(
115 WrapContext(gl_in_process_context
.Pass()),
116 "Video-Offscreen-main-thread");
117 context_provider_
->BindToCurrentThread();
120 virtual scoped_refptr
<gfx::SurfaceTexture
> GetSurfaceTexture(
121 uint32 stream_id
) OVERRIDE
{
122 return gl_in_process_context_
->GetSurfaceTexture(stream_id
);
125 virtual gpu::gles2::GLES2Interface
* ContextGL() OVERRIDE
{
126 return context_provider_
->ContextGL();
130 friend class base::RefCountedThreadSafe
<VideoContextProvider
>;
131 virtual ~VideoContextProvider() {}
133 scoped_refptr
<cc::ContextProvider
> context_provider_
;
134 gpu::GLInProcessContext
* gl_in_process_context_
;
136 DISALLOW_COPY_AND_ASSIGN(VideoContextProvider
);
141 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl
;
143 SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl()
144 : record_full_layer_(true),
145 num_hardware_compositors_(0) {
146 SynchronousCompositorFactory::SetInstance(this);
149 SynchronousCompositorFactoryImpl::~SynchronousCompositorFactoryImpl() {}
151 scoped_refptr
<base::MessageLoopProxy
>
152 SynchronousCompositorFactoryImpl::GetCompositorMessageLoop() {
153 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI
);
157 SynchronousCompositorFactoryImpl::RecordFullLayer() {
158 return record_full_layer_
;
161 scoped_ptr
<cc::OutputSurface
>
162 SynchronousCompositorFactoryImpl::CreateOutputSurface(
164 scoped_refptr
<content::FrameSwapMessageQueue
> frame_swap_message_queue
) {
165 scoped_ptr
<SynchronousCompositorOutputSurface
> output_surface(
166 new SynchronousCompositorOutputSurface(routing_id
,
167 frame_swap_message_queue
));
168 return output_surface
.PassAs
<cc::OutputSurface
>();
171 InputHandlerManagerClient
*
172 SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
173 return synchronous_input_event_filter();
176 scoped_refptr
<ContextProviderWebContext
>
177 SynchronousCompositorFactoryImpl::CreateOffscreenContextProvider(
178 const blink::WebGraphicsContext3D::Attributes
& attributes
,
179 const std::string
& debug_name
) {
180 scoped_ptr
<gpu::GLInProcessContext
> context
=
181 CreateOffscreenContext(attributes
);
182 return webkit::gpu::ContextProviderInProcess::Create(
183 WrapContext(context
.Pass()), debug_name
);
186 scoped_refptr
<cc::ContextProvider
> SynchronousCompositorFactoryImpl::
187 CreateOnscreenContextProviderForCompositorThread() {
190 if (!share_context_
.get()) {
191 share_context_
= CreateContext(
192 service_
, NULL
, gpu::GLInProcessContextSharedMemoryLimits());
194 gpu::GLInProcessContextSharedMemoryLimits mem_limits
;
195 // This is half of what RenderWidget uses because synchronous compositor
196 // pipeline is only one frame deep.
197 mem_limits
.mapped_memory_reclaim_limit
= 6 * 1024 * 1024;
198 return webkit::gpu::ContextProviderInProcess::Create(
199 WrapContext(CreateContext(service_
, share_context_
.get(), mem_limits
)),
203 gpu::GLInProcessContext
* SynchronousCompositorFactoryImpl::GetShareContext() {
204 DCHECK(share_context_
.get());
205 return share_context_
.get();
208 scoped_refptr
<StreamTextureFactory
>
209 SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int frame_id
) {
210 scoped_refptr
<StreamTextureFactorySynchronousImpl
> factory(
211 StreamTextureFactorySynchronousImpl::Create(
213 &SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory
,
214 base::Unretained(this)),
219 blink::WebGraphicsContext3D
*
220 SynchronousCompositorFactoryImpl::CreateOffscreenGraphicsContext3D(
221 const blink::WebGraphicsContext3D::Attributes
& attributes
) {
222 return WrapContextWithAttributes(CreateOffscreenContext(attributes
),
223 attributes
).release();
226 void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw() {
227 base::AutoLock
lock(num_hardware_compositor_lock_
);
228 num_hardware_compositors_
++;
231 void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() {
232 base::AutoLock
lock(num_hardware_compositor_lock_
);
233 DCHECK_GT(num_hardware_compositors_
, 0u);
234 num_hardware_compositors_
--;
237 bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
238 base::AutoLock
lock(num_hardware_compositor_lock_
);
239 return num_hardware_compositors_
> 0;
242 scoped_refptr
<StreamTextureFactorySynchronousImpl::ContextProvider
>
243 SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
244 // Always fail creation even if |video_context_provider_| is not NULL.
245 // This is to avoid synchronous calls that may deadlock. Setting
246 // |video_context_provider_| to null is also not safe since it makes
247 // synchronous destruction uncontrolled and possibly deadlock.
248 if (!CanCreateMainThreadContext()) {
250 scoped_refptr
<StreamTextureFactorySynchronousImpl::ContextProvider
>();
253 if (!video_context_provider_
) {
255 DCHECK(share_context_
.get());
257 video_context_provider_
= new VideoContextProvider(
258 CreateContext(service_
,
259 share_context_
.get(),
260 gpu::GLInProcessContextSharedMemoryLimits()));
262 return video_context_provider_
;
265 void SynchronousCompositorFactoryImpl::SetDeferredGpuService(
266 scoped_refptr
<gpu::InProcessCommandBuffer::Service
> service
) {
271 void SynchronousCompositorFactoryImpl::SetRecordFullDocument(
272 bool record_full_document
) {
273 record_full_layer_
= record_full_document
;
276 } // namespace content