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/observer_list.h"
8 #include "content/browser/android/in_process/synchronous_compositor_output_surface.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "content/renderer/gpu/frame_swap_message_queue.h"
11 #include "gpu/command_buffer/client/gl_in_process_context.h"
12 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
13 #include "ui/gl/android/surface_texture.h"
14 #include "ui/gl/gl_surface.h"
15 #include "ui/gl/gl_surface_stub.h"
16 #include "webkit/common/gpu/context_provider_in_process.h"
17 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
19 using webkit::gpu::ContextProviderWebContext;
25 blink::WebGraphicsContext3D::Attributes GetDefaultAttribs() {
26 blink::WebGraphicsContext3D::Attributes attributes;
27 attributes.antialias = false;
28 attributes.depth = false;
29 attributes.stencil = false;
30 attributes.shareResources = true;
31 attributes.noAutomaticFlushes = true;
36 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
37 using webkit::gpu::WebGraphicsContext3DImpl;
39 scoped_ptr<gpu::GLInProcessContext> CreateOffscreenContext(
40 const blink::WebGraphicsContext3D::Attributes& attributes) {
41 const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
43 gpu::gles2::ContextCreationAttribHelper in_process_attribs;
44 WebGraphicsContext3DImpl::ConvertAttributes(
45 attributes, &in_process_attribs);
46 in_process_attribs.lose_context_when_out_of_memory = true;
48 scoped_ptr<gpu::GLInProcessContext> context(gpu::GLInProcessContext::Create(
51 true /* is_offscreen */,
52 gfx::kNullAcceleratedWidget,
54 NULL /* share_context */,
55 false /* share_resources */,
58 gpu::GLInProcessContextSharedMemoryLimits(),
61 return context.Pass();
64 scoped_ptr<gpu::GLInProcessContext> CreateContext(
65 scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
66 const gpu::GLInProcessContextSharedMemoryLimits& mem_limits) {
67 const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
68 gpu::gles2::ContextCreationAttribHelper in_process_attribs;
69 WebGraphicsContext3DImpl::ConvertAttributes(
70 GetDefaultAttribs(), &in_process_attribs);
71 in_process_attribs.lose_context_when_out_of_memory = true;
73 scoped_ptr<gpu::GLInProcessContext> context(gpu::GLInProcessContext::Create(
76 false /* is_offscreen */,
77 gfx::kNullAcceleratedWidget,
79 NULL /* share_context */,
80 false /* share_resources */,
86 return context.Pass();
89 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> WrapContext(
90 scoped_ptr<gpu::GLInProcessContext> context) {
92 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
94 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(
95 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
96 context.Pass(), GetDefaultAttribs()));
99 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
100 WrapContextWithAttributes(
101 scoped_ptr<gpu::GLInProcessContext> context,
102 const blink::WebGraphicsContext3D::Attributes& attributes) {
104 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
106 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(
107 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
108 context.Pass(), attributes));
113 class SynchronousCompositorFactoryImpl::VideoContextProvider
114 : public StreamTextureFactorySynchronousImpl::ContextProvider {
116 VideoContextProvider(
117 scoped_ptr<gpu::GLInProcessContext> gl_in_process_context)
118 : gl_in_process_context_(gl_in_process_context.get()) {
120 context_provider_ = webkit::gpu::ContextProviderInProcess::Create(
121 WrapContext(gl_in_process_context.Pass()),
122 "Video-Offscreen-main-thread");
123 context_provider_->BindToCurrentThread();
126 virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
127 uint32 stream_id) override {
128 return gl_in_process_context_->GetSurfaceTexture(stream_id);
131 virtual gpu::gles2::GLES2Interface* ContextGL() override {
132 return context_provider_->ContextGL();
135 virtual void AddObserver(StreamTextureFactoryContextObserver* obs) override {
136 observer_list_.AddObserver(obs);
139 virtual void RemoveObserver(
140 StreamTextureFactoryContextObserver* obs) override {
141 observer_list_.RemoveObserver(obs);
144 void RestoreContext() {
145 FOR_EACH_OBSERVER(StreamTextureFactoryContextObserver,
147 ResetStreamTextureProxy());
151 friend class base::RefCountedThreadSafe<VideoContextProvider>;
152 virtual ~VideoContextProvider() {}
154 scoped_refptr<cc::ContextProvider> context_provider_;
155 gpu::GLInProcessContext* gl_in_process_context_;
156 ObserverList<StreamTextureFactoryContextObserver> observer_list_;
158 DISALLOW_COPY_AND_ASSIGN(VideoContextProvider);
161 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
163 SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl()
164 : record_full_layer_(true),
165 num_hardware_compositors_(0) {
166 SynchronousCompositorFactory::SetInstance(this);
169 SynchronousCompositorFactoryImpl::~SynchronousCompositorFactoryImpl() {}
171 scoped_refptr<base::MessageLoopProxy>
172 SynchronousCompositorFactoryImpl::GetCompositorMessageLoop() {
173 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
177 SynchronousCompositorFactoryImpl::RecordFullLayer() {
178 return record_full_layer_;
181 scoped_ptr<cc::OutputSurface>
182 SynchronousCompositorFactoryImpl::CreateOutputSurface(
184 scoped_refptr<content::FrameSwapMessageQueue> frame_swap_message_queue) {
185 scoped_ptr<SynchronousCompositorOutputSurface> output_surface(
186 new SynchronousCompositorOutputSurface(routing_id,
187 frame_swap_message_queue));
188 return output_surface.Pass();
191 InputHandlerManagerClient*
192 SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
193 return synchronous_input_event_filter();
196 scoped_refptr<ContextProviderWebContext>
197 SynchronousCompositorFactoryImpl::CreateOffscreenContextProvider(
198 const blink::WebGraphicsContext3D::Attributes& attributes,
199 const std::string& debug_name) {
200 scoped_ptr<gpu::GLInProcessContext> context =
201 CreateOffscreenContext(attributes);
202 return webkit::gpu::ContextProviderInProcess::Create(
203 WrapContext(context.Pass()), debug_name);
206 scoped_refptr<cc::ContextProvider> SynchronousCompositorFactoryImpl::
207 CreateOnscreenContextProviderForCompositorThread() {
208 DCHECK(service_.get());
210 gpu::GLInProcessContextSharedMemoryLimits mem_limits;
211 // This is half of what RenderWidget uses because synchronous compositor
212 // pipeline is only one frame deep.
213 mem_limits.mapped_memory_reclaim_limit = 6 * 1024 * 1024;
214 return webkit::gpu::ContextProviderInProcess::Create(
215 WrapContext(CreateContext(service_, mem_limits)),
219 scoped_refptr<StreamTextureFactory>
220 SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int frame_id) {
221 scoped_refptr<StreamTextureFactorySynchronousImpl> factory(
222 StreamTextureFactorySynchronousImpl::Create(
224 &SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory,
225 base::Unretained(this)),
230 webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl*
231 SynchronousCompositorFactoryImpl::CreateOffscreenGraphicsContext3D(
232 const blink::WebGraphicsContext3D::Attributes& attributes) {
233 return WrapContextWithAttributes(CreateOffscreenContext(attributes),
234 attributes).release();
237 void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw() {
238 base::AutoLock lock(num_hardware_compositor_lock_);
239 num_hardware_compositors_++;
240 if (num_hardware_compositors_ == 1 && main_thread_proxy_.get()) {
241 main_thread_proxy_->PostTask(
244 &SynchronousCompositorFactoryImpl::RestoreContextOnMainThread,
245 base::Unretained(this)));
249 void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() {
250 base::AutoLock lock(num_hardware_compositor_lock_);
251 DCHECK_GT(num_hardware_compositors_, 0u);
252 num_hardware_compositors_--;
255 void SynchronousCompositorFactoryImpl::RestoreContextOnMainThread() {
256 if (CanCreateMainThreadContext() && video_context_provider_.get())
257 video_context_provider_->RestoreContext();
260 bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
261 base::AutoLock lock(num_hardware_compositor_lock_);
262 return num_hardware_compositors_ > 0;
265 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
266 SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
268 base::AutoLock lock(num_hardware_compositor_lock_);
269 main_thread_proxy_ = base::MessageLoopProxy::current();
272 // Always fail creation even if |video_context_provider_| is not NULL.
273 // This is to avoid synchronous calls that may deadlock. Setting
274 // |video_context_provider_| to null is also not safe since it makes
275 // synchronous destruction uncontrolled and possibly deadlock.
276 if (!CanCreateMainThreadContext()) {
278 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>();
281 if (!video_context_provider_.get()) {
282 DCHECK(service_.get());
284 video_context_provider_ = new VideoContextProvider(
285 CreateContext(service_,
286 gpu::GLInProcessContextSharedMemoryLimits()));
288 return video_context_provider_;
291 void SynchronousCompositorFactoryImpl::SetDeferredGpuService(
292 scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
293 DCHECK(!service_.get());
297 void SynchronousCompositorFactoryImpl::SetRecordFullDocument(
298 bool record_full_document) {
299 record_full_layer_ = record_full_document;
302 } // namespace content