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