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()));
59 return context.Pass();
62 scoped_ptr<gpu::GLInProcessContext> CreateContext(
63 scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
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,
77 NULL /* share_context */,
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));
109 class SynchronousCompositorFactoryImpl::VideoContextProvider
110 : public StreamTextureFactorySynchronousImpl::ContextProvider {
112 VideoContextProvider(
113 scoped_ptr<gpu::GLInProcessContext> gl_in_process_context)
114 : gl_in_process_context_(gl_in_process_context.get()) {
116 context_provider_ = webkit::gpu::ContextProviderInProcess::Create(
117 WrapContext(gl_in_process_context.Pass()),
118 "Video-Offscreen-main-thread");
119 context_provider_->BindToCurrentThread();
122 virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
123 uint32 stream_id) OVERRIDE {
124 return gl_in_process_context_->GetSurfaceTexture(stream_id);
127 virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE {
128 return context_provider_->ContextGL();
131 virtual void AddObserver(StreamTextureFactoryContextObserver* obs) OVERRIDE {
132 observer_list_.AddObserver(obs);
135 virtual void RemoveObserver(
136 StreamTextureFactoryContextObserver* obs) OVERRIDE {
137 observer_list_.RemoveObserver(obs);
140 void RestoreContext() {
141 FOR_EACH_OBSERVER(StreamTextureFactoryContextObserver,
143 ResetStreamTextureProxy());
147 friend class base::RefCountedThreadSafe<VideoContextProvider>;
148 virtual ~VideoContextProvider() {}
150 scoped_refptr<cc::ContextProvider> context_provider_;
151 gpu::GLInProcessContext* gl_in_process_context_;
152 ObserverList<StreamTextureFactoryContextObserver> observer_list_;
154 DISALLOW_COPY_AND_ASSIGN(VideoContextProvider);
157 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
159 SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl()
160 : record_full_layer_(true),
161 num_hardware_compositors_(0) {
162 SynchronousCompositorFactory::SetInstance(this);
165 SynchronousCompositorFactoryImpl::~SynchronousCompositorFactoryImpl() {}
167 scoped_refptr<base::MessageLoopProxy>
168 SynchronousCompositorFactoryImpl::GetCompositorMessageLoop() {
169 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
173 SynchronousCompositorFactoryImpl::RecordFullLayer() {
174 return record_full_layer_;
177 scoped_ptr<cc::OutputSurface>
178 SynchronousCompositorFactoryImpl::CreateOutputSurface(
180 scoped_refptr<content::FrameSwapMessageQueue> frame_swap_message_queue) {
181 scoped_ptr<SynchronousCompositorOutputSurface> output_surface(
182 new SynchronousCompositorOutputSurface(routing_id,
183 frame_swap_message_queue));
184 return output_surface.PassAs<cc::OutputSurface>();
187 InputHandlerManagerClient*
188 SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
189 return synchronous_input_event_filter();
192 scoped_refptr<ContextProviderWebContext>
193 SynchronousCompositorFactoryImpl::CreateOffscreenContextProvider(
194 const blink::WebGraphicsContext3D::Attributes& attributes,
195 const std::string& debug_name) {
196 scoped_ptr<gpu::GLInProcessContext> context =
197 CreateOffscreenContext(attributes);
198 return webkit::gpu::ContextProviderInProcess::Create(
199 WrapContext(context.Pass()), debug_name);
202 scoped_refptr<cc::ContextProvider> SynchronousCompositorFactoryImpl::
203 CreateOnscreenContextProviderForCompositorThread() {
206 gpu::GLInProcessContextSharedMemoryLimits mem_limits;
207 // This is half of what RenderWidget uses because synchronous compositor
208 // pipeline is only one frame deep.
209 mem_limits.mapped_memory_reclaim_limit = 6 * 1024 * 1024;
210 return webkit::gpu::ContextProviderInProcess::Create(
211 WrapContext(CreateContext(service_, mem_limits)),
215 scoped_refptr<StreamTextureFactory>
216 SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int frame_id) {
217 scoped_refptr<StreamTextureFactorySynchronousImpl> factory(
218 StreamTextureFactorySynchronousImpl::Create(
220 &SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory,
221 base::Unretained(this)),
226 webkit::gpu::WebGraphicsContext3DImpl*
227 SynchronousCompositorFactoryImpl::CreateOffscreenGraphicsContext3D(
228 const blink::WebGraphicsContext3D::Attributes& attributes) {
229 return WrapContextWithAttributes(CreateOffscreenContext(attributes),
230 attributes).release();
233 void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw() {
234 base::AutoLock lock(num_hardware_compositor_lock_);
235 num_hardware_compositors_++;
236 if (num_hardware_compositors_ == 1 && main_thread_proxy_) {
237 main_thread_proxy_->PostTask(
240 &SynchronousCompositorFactoryImpl::RestoreContextOnMainThread,
241 base::Unretained(this)));
245 void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() {
246 base::AutoLock lock(num_hardware_compositor_lock_);
247 DCHECK_GT(num_hardware_compositors_, 0u);
248 num_hardware_compositors_--;
251 void SynchronousCompositorFactoryImpl::RestoreContextOnMainThread() {
252 if (CanCreateMainThreadContext() && video_context_provider_ )
253 video_context_provider_->RestoreContext();
256 bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
257 base::AutoLock lock(num_hardware_compositor_lock_);
258 return num_hardware_compositors_ > 0;
261 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
262 SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
264 base::AutoLock lock(num_hardware_compositor_lock_);
265 main_thread_proxy_ = base::MessageLoopProxy::current();
268 // Always fail creation even if |video_context_provider_| is not NULL.
269 // This is to avoid synchronous calls that may deadlock. Setting
270 // |video_context_provider_| to null is also not safe since it makes
271 // synchronous destruction uncontrolled and possibly deadlock.
272 if (!CanCreateMainThreadContext()) {
274 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>();
277 if (!video_context_provider_) {
280 video_context_provider_ = new VideoContextProvider(
281 CreateContext(service_,
282 gpu::GLInProcessContextSharedMemoryLimits()));
284 return video_context_provider_;
287 void SynchronousCompositorFactoryImpl::SetDeferredGpuService(
288 scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
293 void SynchronousCompositorFactoryImpl::SetRecordFullDocument(
294 bool record_full_document) {
295 record_full_layer_ = record_full_document;
298 } // namespace content