Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / android / in_process / synchronous_compositor_factory_impl.cc
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.
4
5 #include "content/browser/android/in_process/synchronous_compositor_factory_impl.h"
6
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 "ui/gl/gl_surface_stub.h"
13 #include "webkit/common/gpu/context_provider_in_process.h"
14 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
15
16 using webkit::gpu::ContextProviderWebContext;
17
18 namespace content {
19
20 namespace {
21
22 blink::WebGraphicsContext3D::Attributes GetDefaultAttribs() {
23   blink::WebGraphicsContext3D::Attributes attributes;
24   attributes.antialias = false;
25   attributes.depth = false;
26   attributes.stencil = false;
27   attributes.shareResources = true;
28   attributes.noAutomaticFlushes = true;
29
30   return attributes;
31 }
32
33 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
34
35 scoped_ptr<gpu::GLInProcessContext> CreateContext(
36     scoped_refptr<gfx::GLSurface> surface,
37     scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
38     gpu::GLInProcessContext* share_context) {
39   const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
40
41   if (!surface)
42     surface = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1));
43
44   gpu::GLInProcessContextAttribs in_process_attribs;
45   WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
46       GetDefaultAttribs(), &in_process_attribs);
47   scoped_ptr<gpu::GLInProcessContext> context(
48       gpu::GLInProcessContext::CreateWithSurface(surface,
49                                                  service,
50                                                  share_context,
51                                                  in_process_attribs,
52                                                  gpu_preference));
53   return context.Pass();
54 }
55
56 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> WrapContext(
57     scoped_ptr<gpu::GLInProcessContext> context) {
58   if (!context.get())
59     return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();
60
61   return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(
62       WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
63           context.Pass(), GetDefaultAttribs()));
64 }
65
66 class VideoContextProvider
67     : public StreamTextureFactorySynchronousImpl::ContextProvider {
68  public:
69   VideoContextProvider(
70       scoped_ptr<gpu::GLInProcessContext> gl_in_process_context)
71       : gl_in_process_context_(gl_in_process_context.get()) {
72
73     context_provider_ = webkit::gpu::ContextProviderInProcess::Create(
74         WrapContext(gl_in_process_context.Pass()),
75         "Video-Offscreen-main-thread");
76     context_provider_->BindToCurrentThread();
77   }
78
79   virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
80       uint32 stream_id) OVERRIDE {
81     return gl_in_process_context_->GetSurfaceTexture(stream_id);
82   }
83
84   virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE {
85     return context_provider_->ContextGL();
86   }
87
88  private:
89   friend class base::RefCountedThreadSafe<VideoContextProvider>;
90   virtual ~VideoContextProvider() {}
91
92   scoped_refptr<cc::ContextProvider> context_provider_;
93   gpu::GLInProcessContext* gl_in_process_context_;
94
95   DISALLOW_COPY_AND_ASSIGN(VideoContextProvider);
96 };
97
98 }  // namespace
99
100 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
101
102 SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl()
103     : wrapped_gl_context_for_main_thread_(NULL),
104       wrapped_gl_context_for_compositor_thread_(NULL),
105       num_hardware_compositors_(0) {
106   SynchronousCompositorFactory::SetInstance(this);
107 }
108
109 SynchronousCompositorFactoryImpl::~SynchronousCompositorFactoryImpl() {}
110
111 scoped_refptr<base::MessageLoopProxy>
112 SynchronousCompositorFactoryImpl::GetCompositorMessageLoop() {
113   return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
114 }
115
116 scoped_ptr<cc::OutputSurface>
117 SynchronousCompositorFactoryImpl::CreateOutputSurface(int routing_id) {
118   scoped_ptr<SynchronousCompositorOutputSurface> output_surface(
119       new SynchronousCompositorOutputSurface(routing_id));
120   return output_surface.PassAs<cc::OutputSurface>();
121 }
122
123 InputHandlerManagerClient*
124 SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
125   return synchronous_input_event_filter();
126 }
127
128 scoped_refptr<ContextProviderWebContext>
129 SynchronousCompositorFactoryImpl::GetOffscreenContextProviderForMainThread() {
130   bool failed = false;
131   if ((!offscreen_context_for_main_thread_.get() ||
132        offscreen_context_for_main_thread_->DestroyedOnMainThread())) {
133     scoped_ptr<gpu::GLInProcessContext> context =
134         CreateContext(NULL, NULL, NULL);
135     wrapped_gl_context_for_main_thread_ = context.get();
136     offscreen_context_for_main_thread_ =
137         webkit::gpu::ContextProviderInProcess::Create(
138             WrapContext(context.Pass()),
139             "Compositor-Offscreen-main-thread");
140     failed = !offscreen_context_for_main_thread_.get() ||
141              !offscreen_context_for_main_thread_->BindToCurrentThread();
142   }
143
144   if (failed) {
145     offscreen_context_for_main_thread_ = NULL;
146     wrapped_gl_context_for_main_thread_ = NULL;
147   }
148   return offscreen_context_for_main_thread_;
149 }
150
151 // This is called on both renderer main thread (offscreen context creation
152 // path shared between cross-process and in-process platforms) and renderer
153 // compositor impl thread (InitializeHwDraw) in order to support Android
154 // WebView synchronously enable and disable hardware mode multiple times in
155 // the same task. This is ok because in-process WGC3D creation may happen on
156 // any thread and is lightweight.
157 scoped_refptr<cc::ContextProvider> SynchronousCompositorFactoryImpl::
158     GetOffscreenContextProviderForCompositorThread() {
159   base::AutoLock lock(offscreen_context_for_compositor_thread_lock_);
160   DCHECK(service_);
161   bool failed = false;
162   if (!offscreen_context_for_compositor_thread_.get() ||
163       offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) {
164     scoped_ptr<gpu::GLInProcessContext> context =
165         CreateContext(new gfx::GLSurfaceStub, service_, NULL);
166     wrapped_gl_context_for_compositor_thread_ = context.get();
167     offscreen_context_for_compositor_thread_ =
168         webkit::gpu::ContextProviderInProcess::Create(
169             WrapContext(context.Pass()),
170             "Compositor-Offscreen-compositor-thread");
171     failed = !offscreen_context_for_compositor_thread_.get() ||
172              !offscreen_context_for_compositor_thread_->BindToCurrentThread();
173   }
174   if (failed) {
175     offscreen_context_for_compositor_thread_ = NULL;
176     wrapped_gl_context_for_compositor_thread_ = NULL;
177   }
178   return offscreen_context_for_compositor_thread_;
179 }
180
181 scoped_refptr<cc::ContextProvider> SynchronousCompositorFactoryImpl::
182     CreateOnscreenContextProviderForCompositorThread(
183         scoped_refptr<gfx::GLSurface> surface) {
184   DCHECK(surface);
185   DCHECK(service_);
186   DCHECK(wrapped_gl_context_for_compositor_thread_);
187
188   return webkit::gpu::ContextProviderInProcess::Create(
189       WrapContext(CreateContext(
190           surface, service_, wrapped_gl_context_for_compositor_thread_)),
191       "Compositor-Onscreen");
192 }
193
194 scoped_ptr<StreamTextureFactory>
195 SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int view_id) {
196   scoped_ptr<StreamTextureFactorySynchronousImpl> factory(
197       new StreamTextureFactorySynchronousImpl(
198           base::Bind(&SynchronousCompositorFactoryImpl::
199                           TryCreateStreamTextureFactory,
200                      base::Unretained(this)),
201           view_id));
202   return factory.PassAs<StreamTextureFactory>();
203 }
204
205 void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw() {
206   base::AutoLock lock(num_hardware_compositor_lock_);
207   num_hardware_compositors_++;
208 }
209
210 void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() {
211   base::AutoLock lock(num_hardware_compositor_lock_);
212   DCHECK_GT(num_hardware_compositors_, 0u);
213   num_hardware_compositors_--;
214 }
215
216 bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
217   base::AutoLock lock(num_hardware_compositor_lock_);
218   return num_hardware_compositors_ > 0;
219 }
220
221 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
222 SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
223   scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
224       context_provider;
225   // This check only guarantees the main thread context is created after
226   // a compositor did successfully initialize hardware draw in the past.
227   // In particular this does not guarantee that the main thread context
228   // will fail creation when all compositors release hardware draw.
229   if (CanCreateMainThreadContext() && !video_context_provider_) {
230     DCHECK(service_);
231     DCHECK(wrapped_gl_context_for_compositor_thread_);
232
233     video_context_provider_ = new VideoContextProvider(
234         CreateContext(new gfx::GLSurfaceStub,
235                       service_,
236                       wrapped_gl_context_for_compositor_thread_));
237   }
238   return video_context_provider_;
239 }
240
241 void SynchronousCompositorFactoryImpl::SetDeferredGpuService(
242     scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
243   DCHECK(!service_);
244   service_ = service;
245 }
246
247 }  // namespace content