ed5f6fd00d1dc411e212e336b4e92f3c4ff43d5a
[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_compositor_thread_(NULL),
104       num_hardware_compositors_(0) {
105   SynchronousCompositorFactory::SetInstance(this);
106 }
107
108 SynchronousCompositorFactoryImpl::~SynchronousCompositorFactoryImpl() {}
109
110 scoped_refptr<base::MessageLoopProxy>
111 SynchronousCompositorFactoryImpl::GetCompositorMessageLoop() {
112   return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
113 }
114
115 scoped_ptr<cc::OutputSurface>
116 SynchronousCompositorFactoryImpl::CreateOutputSurface(int routing_id) {
117   scoped_ptr<SynchronousCompositorOutputSurface> output_surface(
118       new SynchronousCompositorOutputSurface(routing_id));
119   return output_surface.PassAs<cc::OutputSurface>();
120 }
121
122 InputHandlerManagerClient*
123 SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
124   return synchronous_input_event_filter();
125 }
126
127 scoped_refptr<ContextProviderWebContext>
128 SynchronousCompositorFactoryImpl::GetOffscreenContextProviderForMainThread() {
129   bool failed = false;
130   if ((!offscreen_context_for_main_thread_.get() ||
131        offscreen_context_for_main_thread_->DestroyedOnMainThread())) {
132     scoped_ptr<gpu::GLInProcessContext> context =
133         CreateContext(NULL, NULL, NULL);
134     offscreen_context_for_main_thread_ =
135         webkit::gpu::ContextProviderInProcess::Create(
136             WrapContext(context.Pass()),
137             "Compositor-Offscreen-main-thread");
138     failed = !offscreen_context_for_main_thread_.get() ||
139              !offscreen_context_for_main_thread_->BindToCurrentThread();
140   }
141
142   if (failed) {
143     offscreen_context_for_main_thread_ = NULL;
144   }
145   return offscreen_context_for_main_thread_;
146 }
147
148 // This is called on both renderer main thread (offscreen context creation
149 // path shared between cross-process and in-process platforms) and renderer
150 // compositor impl thread (InitializeHwDraw) in order to support Android
151 // WebView synchronously enable and disable hardware mode multiple times in
152 // the same task. This is ok because in-process WGC3D creation may happen on
153 // any thread and is lightweight.
154 scoped_refptr<cc::ContextProvider> SynchronousCompositorFactoryImpl::
155     GetOffscreenContextProviderForCompositorThread() {
156   base::AutoLock lock(offscreen_context_for_compositor_thread_lock_);
157   DCHECK(service_);
158   bool failed = false;
159   if (!offscreen_context_for_compositor_thread_.get() ||
160       offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) {
161     scoped_ptr<gpu::GLInProcessContext> context =
162         CreateContext(new gfx::GLSurfaceStub, service_, NULL);
163     wrapped_gl_context_for_compositor_thread_ = context.get();
164     offscreen_context_for_compositor_thread_ =
165         webkit::gpu::ContextProviderInProcess::Create(
166             WrapContext(context.Pass()),
167             "Compositor-Offscreen-compositor-thread");
168     failed = !offscreen_context_for_compositor_thread_.get() ||
169              !offscreen_context_for_compositor_thread_->BindToCurrentThread();
170   }
171   if (failed) {
172     offscreen_context_for_compositor_thread_ = NULL;
173     wrapped_gl_context_for_compositor_thread_ = NULL;
174   }
175   return offscreen_context_for_compositor_thread_;
176 }
177
178 scoped_refptr<cc::ContextProvider> SynchronousCompositorFactoryImpl::
179     CreateOnscreenContextProviderForCompositorThread(
180         scoped_refptr<gfx::GLSurface> surface) {
181   DCHECK(surface);
182   DCHECK(service_);
183   DCHECK(wrapped_gl_context_for_compositor_thread_);
184
185   return webkit::gpu::ContextProviderInProcess::Create(
186       WrapContext(CreateContext(
187           surface, service_, wrapped_gl_context_for_compositor_thread_)),
188       "Compositor-Onscreen");
189 }
190
191 scoped_ptr<StreamTextureFactory>
192 SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int view_id) {
193   scoped_ptr<StreamTextureFactorySynchronousImpl> factory(
194       new StreamTextureFactorySynchronousImpl(
195           base::Bind(&SynchronousCompositorFactoryImpl::
196                           TryCreateStreamTextureFactory,
197                      base::Unretained(this)),
198           view_id));
199   return factory.PassAs<StreamTextureFactory>();
200 }
201
202 void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw() {
203   base::AutoLock lock(num_hardware_compositor_lock_);
204   num_hardware_compositors_++;
205 }
206
207 void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() {
208   base::AutoLock lock(num_hardware_compositor_lock_);
209   DCHECK_GT(num_hardware_compositors_, 0u);
210   num_hardware_compositors_--;
211 }
212
213 bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
214   base::AutoLock lock(num_hardware_compositor_lock_);
215   return num_hardware_compositors_ > 0;
216 }
217
218 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
219 SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
220   scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
221       context_provider;
222   // This check only guarantees the main thread context is created after
223   // a compositor did successfully initialize hardware draw in the past.
224   // In particular this does not guarantee that the main thread context
225   // will fail creation when all compositors release hardware draw.
226   if (CanCreateMainThreadContext() && !video_context_provider_) {
227     DCHECK(service_);
228     DCHECK(wrapped_gl_context_for_compositor_thread_);
229
230     video_context_provider_ = new VideoContextProvider(
231         CreateContext(new gfx::GLSurfaceStub,
232                       service_,
233                       wrapped_gl_context_for_compositor_thread_));
234   }
235   return video_context_provider_;
236 }
237
238 void SynchronousCompositorFactoryImpl::SetDeferredGpuService(
239     scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
240   DCHECK(!service_);
241   service_ = service;
242 }
243
244 }  // namespace content