| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/android/in_process/synchronous_compositor_impl.h" | 5 #include "content/browser/android/in_process/synchronous_compositor_impl.h" |
| 6 | 6 |
| 7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/synchronization/lock.h" | |
| 10 #include "cc/input/input_handler.h" | 9 #include "cc/input/input_handler.h" |
| 11 #include "cc/input/layer_scroll_offset_delegate.h" | 10 #include "cc/input/layer_scroll_offset_delegate.h" |
| 11 #include "content/browser/android/in_process/synchronous_compositor_factory_impl
.h" |
| 12 #include "content/browser/android/in_process/synchronous_input_event_filter.h" | 12 #include "content/browser/android/in_process/synchronous_input_event_filter.h" |
| 13 #include "content/browser/renderer_host/render_widget_host_view_android.h" | 13 #include "content/browser/renderer_host/render_widget_host_view_android.h" |
| 14 #include "content/public/browser/android/synchronous_compositor_client.h" | 14 #include "content/public/browser/android/synchronous_compositor_client.h" |
| 15 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
| 16 #include "content/public/browser/render_process_host.h" | 16 #include "content/public/browser/render_process_host.h" |
| 17 #include "content/public/browser/render_view_host.h" | 17 #include "content/public/browser/render_view_host.h" |
| 18 #include "content/renderer/android/synchronous_compositor_factory.h" | |
| 19 #include "content/renderer/media/android/stream_texture_factory_android_synchron
ous_impl.h" | |
| 20 #include "gpu/command_buffer/client/gl_in_process_context.h" | |
| 21 #include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h
" | |
| 22 #include "ui/gl/android/surface_texture.h" | |
| 23 #include "ui/gl/gl_surface.h" | 18 #include "ui/gl/gl_surface.h" |
| 24 #include "webkit/common/gpu/context_provider_in_process.h" | |
| 25 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.
h" | |
| 26 | 19 |
| 27 namespace content { | 20 namespace content { |
| 28 | 21 |
| 29 namespace { | 22 namespace { |
| 30 | 23 |
| 31 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; | |
| 32 | |
| 33 int GetInProcessRendererId() { | 24 int GetInProcessRendererId() { |
| 34 content::RenderProcessHost::iterator it = | 25 content::RenderProcessHost::iterator it = |
| 35 content::RenderProcessHost::AllHostsIterator(); | 26 content::RenderProcessHost::AllHostsIterator(); |
| 36 if (it.IsAtEnd()) { | 27 if (it.IsAtEnd()) { |
| 37 // There should always be one RPH in single process mode. | 28 // There should always be one RPH in single process mode. |
| 38 NOTREACHED(); | 29 NOTREACHED(); |
| 39 return 0; | 30 return 0; |
| 40 } | 31 } |
| 41 | 32 |
| 42 int id = it.GetCurrentValue()->GetID(); | 33 int id = it.GetCurrentValue()->GetID(); |
| 43 it.Advance(); | 34 it.Advance(); |
| 44 DCHECK(it.IsAtEnd()); // Not multiprocess compatible. | 35 DCHECK(it.IsAtEnd()); // Not multiprocess compatible. |
| 45 return id; | 36 return id; |
| 46 } | 37 } |
| 47 | 38 |
| 48 class VideoContextProvider | |
| 49 : public StreamTextureFactorySynchronousImpl::ContextProvider { | |
| 50 public: | |
| 51 VideoContextProvider( | |
| 52 const scoped_refptr<cc::ContextProvider>& context_provider, | |
| 53 gpu::GLInProcessContext* gl_in_process_context) | |
| 54 : context_provider_(context_provider), | |
| 55 gl_in_process_context_(gl_in_process_context) {} | |
| 56 | |
| 57 virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture( | |
| 58 uint32 stream_id) OVERRIDE { | |
| 59 return gl_in_process_context_->GetSurfaceTexture(stream_id); | |
| 60 } | |
| 61 | |
| 62 virtual blink::WebGraphicsContext3D* Context3d() OVERRIDE { | |
| 63 return context_provider_->Context3d(); | |
| 64 } | |
| 65 | |
| 66 private: | |
| 67 friend class base::RefCountedThreadSafe<VideoContextProvider>; | |
| 68 virtual ~VideoContextProvider() {} | |
| 69 | |
| 70 scoped_refptr<cc::ContextProvider> context_provider_; | |
| 71 gpu::GLInProcessContext* gl_in_process_context_; | |
| 72 | |
| 73 DISALLOW_COPY_AND_ASSIGN(VideoContextProvider); | |
| 74 }; | |
| 75 | |
| 76 class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { | |
| 77 public: | |
| 78 SynchronousCompositorFactoryImpl() | |
| 79 : wrapped_gl_context_for_main_thread_(NULL), | |
| 80 num_hardware_compositors_(0) { | |
| 81 SynchronousCompositorFactory::SetInstance(this); | |
| 82 } | |
| 83 | |
| 84 // SynchronousCompositorFactory | |
| 85 virtual scoped_refptr<base::MessageLoopProxy> | |
| 86 GetCompositorMessageLoop() OVERRIDE { | |
| 87 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); | |
| 88 } | |
| 89 | |
| 90 virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface( | |
| 91 int routing_id) OVERRIDE { | |
| 92 scoped_ptr<SynchronousCompositorOutputSurface> output_surface( | |
| 93 new SynchronousCompositorOutputSurface(routing_id)); | |
| 94 return output_surface.PassAs<cc::OutputSurface>(); | |
| 95 } | |
| 96 | |
| 97 virtual InputHandlerManagerClient* GetInputHandlerManagerClient() OVERRIDE { | |
| 98 return synchronous_input_event_filter(); | |
| 99 } | |
| 100 | |
| 101 SynchronousInputEventFilter* synchronous_input_event_filter() { | |
| 102 return &synchronous_input_event_filter_; | |
| 103 } | |
| 104 | |
| 105 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> | |
| 106 CreateOffscreenContext() { | |
| 107 if (!gfx::GLSurface::InitializeOneOff()) | |
| 108 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(); | |
| 109 | |
| 110 const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; | |
| 111 | |
| 112 blink::WebGraphicsContext3D::Attributes attributes; | |
| 113 attributes.antialias = false; | |
| 114 attributes.shareResources = true; | |
| 115 attributes.noAutomaticFlushes = true; | |
| 116 | |
| 117 gpu::GLInProcessContextAttribs in_process_attribs; | |
| 118 WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes( | |
| 119 attributes, &in_process_attribs); | |
| 120 scoped_ptr<gpu::GLInProcessContext> context( | |
| 121 gpu::GLInProcessContext::CreateContext(true, | |
| 122 NULL, | |
| 123 gfx::Size(1, 1), | |
| 124 attributes.shareResources, | |
| 125 in_process_attribs, | |
| 126 gpu_preference)); | |
| 127 | |
| 128 wrapped_gl_context_for_main_thread_ = context.get(); | |
| 129 if (!context.get()) | |
| 130 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(); | |
| 131 | |
| 132 return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>( | |
| 133 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext( | |
| 134 context.Pass(), attributes)); | |
| 135 } | |
| 136 | |
| 137 virtual scoped_refptr<cc::ContextProvider> | |
| 138 GetOffscreenContextProviderForMainThread() OVERRIDE { | |
| 139 // This check only guarantees the main thread context is created after | |
| 140 // a compositor did successfully initialize hardware draw in the past. | |
| 141 // In particular this does not guarantee that the main thread context | |
| 142 // will fail creation when all compositors release hardware draw. | |
| 143 bool failed = !CanCreateMainThreadContext(); | |
| 144 if (!failed && | |
| 145 (!offscreen_context_for_main_thread_.get() || | |
| 146 offscreen_context_for_main_thread_->DestroyedOnMainThread())) { | |
| 147 offscreen_context_for_main_thread_ = | |
| 148 webkit::gpu::ContextProviderInProcess::Create( | |
| 149 CreateOffscreenContext(), | |
| 150 "Compositor-Offscreen"); | |
| 151 failed = !offscreen_context_for_main_thread_.get() || | |
| 152 !offscreen_context_for_main_thread_->BindToCurrentThread(); | |
| 153 } | |
| 154 | |
| 155 if (failed) { | |
| 156 offscreen_context_for_main_thread_ = NULL; | |
| 157 wrapped_gl_context_for_main_thread_ = NULL; | |
| 158 } | |
| 159 return offscreen_context_for_main_thread_; | |
| 160 } | |
| 161 | |
| 162 // This is called on both renderer main thread (offscreen context creation | |
| 163 // path shared between cross-process and in-process platforms) and renderer | |
| 164 // compositor impl thread (InitializeHwDraw) in order to support Android | |
| 165 // WebView synchronously enable and disable hardware mode multiple times in | |
| 166 // the same task. This is ok because in-process WGC3D creation may happen on | |
| 167 // any thread and is lightweight. | |
| 168 virtual scoped_refptr<cc::ContextProvider> | |
| 169 GetOffscreenContextProviderForCompositorThread() OVERRIDE { | |
| 170 base::AutoLock lock(offscreen_context_for_compositor_thread_lock_); | |
| 171 if (!offscreen_context_for_compositor_thread_.get() || | |
| 172 offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) { | |
| 173 offscreen_context_for_compositor_thread_ = | |
| 174 webkit::gpu::ContextProviderInProcess::CreateOffscreen(); | |
| 175 } | |
| 176 return offscreen_context_for_compositor_thread_; | |
| 177 } | |
| 178 | |
| 179 virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory( | |
| 180 int view_id) OVERRIDE { | |
| 181 scoped_ptr<StreamTextureFactorySynchronousImpl> factory( | |
| 182 new StreamTextureFactorySynchronousImpl( | |
| 183 base::Bind(&SynchronousCompositorFactoryImpl:: | |
| 184 TryCreateStreamTextureFactory, | |
| 185 base::Unretained(this)), | |
| 186 view_id)); | |
| 187 return factory.PassAs<StreamTextureFactory>(); | |
| 188 } | |
| 189 | |
| 190 void CompositorInitializedHardwareDraw(SynchronousCompositorImpl* compositor); | |
| 191 void CompositorReleasedHardwareDraw(SynchronousCompositorImpl* compositor); | |
| 192 | |
| 193 private: | |
| 194 void ReleaseGlobalHardwareResources(); | |
| 195 bool CanCreateMainThreadContext(); | |
| 196 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider> | |
| 197 TryCreateStreamTextureFactory(); | |
| 198 | |
| 199 SynchronousInputEventFilter synchronous_input_event_filter_; | |
| 200 | |
| 201 // Only guards construction and destruction of | |
| 202 // |offscreen_context_for_compositor_thread_|, not usage. | |
| 203 base::Lock offscreen_context_for_compositor_thread_lock_; | |
| 204 scoped_refptr<cc::ContextProvider> offscreen_context_for_main_thread_; | |
| 205 // This is a pointer to the context owned by | |
| 206 // |offscreen_context_for_main_thread_|. | |
| 207 gpu::GLInProcessContext* wrapped_gl_context_for_main_thread_; | |
| 208 scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_; | |
| 209 | |
| 210 // |num_hardware_compositor_lock_| is updated on UI thread only but can be | |
| 211 // read on renderer main thread. | |
| 212 base::Lock num_hardware_compositor_lock_; | |
| 213 unsigned int num_hardware_compositors_; | |
| 214 }; | |
| 215 | |
| 216 void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw( | |
| 217 SynchronousCompositorImpl* compositor) { | |
| 218 base::AutoLock lock(num_hardware_compositor_lock_); | |
| 219 num_hardware_compositors_++; | |
| 220 } | |
| 221 | |
| 222 void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw( | |
| 223 SynchronousCompositorImpl* compositor) { | |
| 224 bool should_release_resources = false; | |
| 225 { | |
| 226 base::AutoLock lock(num_hardware_compositor_lock_); | |
| 227 DCHECK_GT(num_hardware_compositors_, 0u); | |
| 228 num_hardware_compositors_--; | |
| 229 should_release_resources = num_hardware_compositors_ == 0u; | |
| 230 } | |
| 231 if (should_release_resources) | |
| 232 ReleaseGlobalHardwareResources(); | |
| 233 } | |
| 234 | |
| 235 void SynchronousCompositorFactoryImpl::ReleaseGlobalHardwareResources() { | |
| 236 { | |
| 237 base::AutoLock lock(offscreen_context_for_compositor_thread_lock_); | |
| 238 offscreen_context_for_compositor_thread_ = NULL; | |
| 239 } | |
| 240 | |
| 241 // TODO(boliu): Properly clean up command buffer server of main thread | |
| 242 // context here. | |
| 243 } | |
| 244 | |
| 245 bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() { | |
| 246 base::AutoLock lock(num_hardware_compositor_lock_); | |
| 247 return num_hardware_compositors_ > 0; | |
| 248 } | |
| 249 | |
| 250 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider> | |
| 251 SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() { | |
| 252 scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider> | |
| 253 context_provider; | |
| 254 if (CanCreateMainThreadContext() && | |
| 255 GetOffscreenContextProviderForMainThread()) { | |
| 256 DCHECK(offscreen_context_for_main_thread_); | |
| 257 DCHECK(wrapped_gl_context_for_main_thread_); | |
| 258 context_provider = | |
| 259 new VideoContextProvider(offscreen_context_for_main_thread_, | |
| 260 wrapped_gl_context_for_main_thread_); | |
| 261 } | |
| 262 return context_provider; | |
| 263 } | |
| 264 | |
| 265 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory = | 39 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory = |
| 266 LAZY_INSTANCE_INITIALIZER; | 40 LAZY_INSTANCE_INITIALIZER; |
| 267 | 41 |
| 268 } // namespace | 42 } // namespace |
| 269 | 43 |
| 270 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl); | 44 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl); |
| 271 | 45 |
| 272 // static | 46 // static |
| 273 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id, | 47 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id, |
| 274 int routing_id) { | 48 int routing_id) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 } | 83 } |
| 310 | 84 |
| 311 bool SynchronousCompositorImpl::InitializeHwDraw( | 85 bool SynchronousCompositorImpl::InitializeHwDraw( |
| 312 scoped_refptr<gfx::GLSurface> surface) { | 86 scoped_refptr<gfx::GLSurface> surface) { |
| 313 DCHECK(CalledOnValidThread()); | 87 DCHECK(CalledOnValidThread()); |
| 314 DCHECK(output_surface_); | 88 DCHECK(output_surface_); |
| 315 bool success = output_surface_->InitializeHwDraw( | 89 bool success = output_surface_->InitializeHwDraw( |
| 316 surface, | 90 surface, |
| 317 g_factory.Get().GetOffscreenContextProviderForCompositorThread()); | 91 g_factory.Get().GetOffscreenContextProviderForCompositorThread()); |
| 318 if (success) | 92 if (success) |
| 319 g_factory.Get().CompositorInitializedHardwareDraw(this); | 93 g_factory.Get().CompositorInitializedHardwareDraw(); |
| 320 return success; | 94 return success; |
| 321 } | 95 } |
| 322 | 96 |
| 323 void SynchronousCompositorImpl::ReleaseHwDraw() { | 97 void SynchronousCompositorImpl::ReleaseHwDraw() { |
| 324 DCHECK(CalledOnValidThread()); | 98 DCHECK(CalledOnValidThread()); |
| 325 DCHECK(output_surface_); | 99 DCHECK(output_surface_); |
| 326 output_surface_->ReleaseHwDraw(); | 100 output_surface_->ReleaseHwDraw(); |
| 327 g_factory.Get().CompositorReleasedHardwareDraw(this); | 101 g_factory.Get().CompositorReleasedHardwareDraw(); |
| 328 } | 102 } |
| 329 | 103 |
| 330 bool SynchronousCompositorImpl::DemandDrawHw( | 104 bool SynchronousCompositorImpl::DemandDrawHw( |
| 331 gfx::Size surface_size, | 105 gfx::Size surface_size, |
| 332 const gfx::Transform& transform, | 106 const gfx::Transform& transform, |
| 333 gfx::Rect viewport, | 107 gfx::Rect viewport, |
| 334 gfx::Rect clip, | 108 gfx::Rect clip, |
| 335 bool stencil_enabled) { | 109 bool stencil_enabled) { |
| 336 DCHECK(CalledOnValidThread()); | 110 DCHECK(CalledOnValidThread()); |
| 337 DCHECK(output_surface_); | 111 DCHECK(output_surface_); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 g_factory.Get(); // Ensure it's initialized. | 259 g_factory.Get(); // Ensure it's initialized. |
| 486 SynchronousCompositorImpl::CreateForWebContents(contents); | 260 SynchronousCompositorImpl::CreateForWebContents(contents); |
| 487 } | 261 } |
| 488 if (SynchronousCompositorImpl* instance = | 262 if (SynchronousCompositorImpl* instance = |
| 489 SynchronousCompositorImpl::FromWebContents(contents)) { | 263 SynchronousCompositorImpl::FromWebContents(contents)) { |
| 490 instance->SetClient(client); | 264 instance->SetClient(client); |
| 491 } | 265 } |
| 492 } | 266 } |
| 493 | 267 |
| 494 } // namespace content | 268 } // namespace content |
| OLD | NEW |