1 // Copyright (c) 2012 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/renderer_host/image_transport_factory.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/observer_list.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/threading/non_thread_safe.h"
17 #include "cc/output/compositor_frame.h"
18 #include "cc/output/output_surface.h"
19 #include "cc/output/output_surface_client.h"
20 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
21 #include "content/browser/gpu/gpu_data_manager_impl.h"
22 #include "content/browser/gpu/gpu_process_host.h"
23 #include "content/browser/gpu/gpu_surface_tracker.h"
24 #include "content/browser/renderer_host/render_widget_host_impl.h"
25 #include "content/common/gpu/client/context_provider_command_buffer.h"
26 #include "content/common/gpu/client/gl_helper.h"
27 #include "content/common/gpu/client/gpu_channel_host.h"
28 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
29 #include "content/common/gpu/gpu_messages.h"
30 #include "content/common/gpu/gpu_process_launch_causes.h"
31 #include "content/public/common/content_switches.h"
32 #include "gpu/GLES2/gl2extchromium.h"
33 #include "gpu/ipc/command_buffer_proxy.h"
34 #include "third_party/khronos/GLES2/gl2.h"
35 #include "third_party/khronos/GLES2/gl2ext.h"
36 #include "ui/compositor/compositor.h"
37 #include "ui/compositor/compositor_setup.h"
38 #include "ui/compositor/compositor_switches.h"
39 #include "ui/compositor/layer.h"
40 #include "ui/compositor/test_web_graphics_context_3d.h"
41 #include "ui/gfx/native_widget_types.h"
42 #include "ui/gfx/size.h"
45 #include "content/browser/renderer_host/software_output_device_win.h"
46 #include "ui/surface/accelerated_surface_win.h"
47 #elif defined(USE_X11)
48 #include "content/browser/renderer_host/software_output_device_x11.h"
54 ImageTransportFactory
* g_factory
;
56 // An ImageTransportFactory that disables transport.
57 class NoTransportFactory
: public ImageTransportFactory
{
59 explicit NoTransportFactory(ui::ContextFactory
* context_factory
)
60 : context_factory_(context_factory
) {
63 virtual ui::ContextFactory
* AsContextFactory() OVERRIDE
{
64 return context_factory_
.get();
67 virtual gfx::GLSurfaceHandle
CreateSharedSurfaceHandle() OVERRIDE
{
68 return gfx::GLSurfaceHandle();
71 virtual void DestroySharedSurfaceHandle(
72 gfx::GLSurfaceHandle surface
) OVERRIDE
{
75 virtual scoped_refptr
<ui::Texture
> CreateTransportClient(
76 float device_scale_factor
) OVERRIDE
{
80 virtual scoped_refptr
<ui::Texture
> CreateOwnedTexture(
81 const gfx::Size
& size
,
82 float device_scale_factor
,
83 unsigned int texture_id
) OVERRIDE
{
87 virtual GLHelper
* GetGLHelper() OVERRIDE
{
91 virtual uint32
InsertSyncPoint() OVERRIDE
{
95 virtual void WaitSyncPoint(uint32 sync_point
) OVERRIDE
{
98 // We don't generate lost context events, so we don't need to keep track of
100 virtual void AddObserver(ImageTransportFactoryObserver
* observer
) OVERRIDE
{
103 virtual void RemoveObserver(
104 ImageTransportFactoryObserver
* observer
) OVERRIDE
{
108 scoped_ptr
<ui::ContextFactory
> context_factory_
;
109 DISALLOW_COPY_AND_ASSIGN(NoTransportFactory
);
112 class OwnedTexture
: public ui::Texture
, ImageTransportFactoryObserver
{
114 OwnedTexture(WebKit::WebGraphicsContext3D
* host_context
,
115 const gfx::Size
& size
,
116 float device_scale_factor
,
117 unsigned int texture_id
)
118 : ui::Texture(true, size
, device_scale_factor
),
119 host_context_(host_context
),
120 texture_id_(texture_id
) {
121 ImageTransportFactory::GetInstance()->AddObserver(this);
124 // ui::Texture overrides:
125 virtual unsigned int PrepareTexture() OVERRIDE
{
129 virtual WebKit::WebGraphicsContext3D
* HostContext3D() OVERRIDE
{
130 return host_context_
;
133 // ImageTransportFactory overrides:
134 virtual void OnLostResources() OVERRIDE
{
139 virtual ~OwnedTexture() {
140 ImageTransportFactory::GetInstance()->RemoveObserver(this);
145 void DeleteTexture() {
147 host_context_
->deleteTexture(texture_id_
);
152 // A raw pointer. This |ImageTransportClientTexture| will be destroyed
153 // before the |host_context_| via
154 // |ImageTransportFactoryObserver::OnLostContext()| handlers.
155 WebKit::WebGraphicsContext3D
* host_context_
;
156 unsigned texture_id_
;
158 DISALLOW_COPY_AND_ASSIGN(OwnedTexture
);
161 class ImageTransportClientTexture
: public OwnedTexture
{
163 ImageTransportClientTexture(
164 WebKit::WebGraphicsContext3D
* host_context
,
165 float device_scale_factor
)
166 : OwnedTexture(host_context
,
169 host_context
->createTexture()) {
172 virtual void Consume(const std::string
& mailbox_name
,
173 const gfx::Size
& new_size
) OVERRIDE
{
174 DCHECK(mailbox_name
.size() == GL_MAILBOX_SIZE_CHROMIUM
);
175 mailbox_name_
= mailbox_name
;
176 if (mailbox_name
.empty())
179 DCHECK(host_context_
&& texture_id_
);
180 host_context_
->bindTexture(GL_TEXTURE_2D
, texture_id_
);
181 host_context_
->consumeTextureCHROMIUM(
183 reinterpret_cast<const signed char*>(mailbox_name
.c_str()));
185 host_context_
->shallowFlushCHROMIUM();
188 virtual std::string
Produce() OVERRIDE
{
189 return mailbox_name_
;
193 virtual ~ImageTransportClientTexture() {}
196 std::string mailbox_name_
;
197 DISALLOW_COPY_AND_ASSIGN(ImageTransportClientTexture
);
200 class GpuProcessTransportFactory
;
202 class CompositorSwapClient
203 : public base::SupportsWeakPtr
<CompositorSwapClient
>,
204 public WebGraphicsContext3DSwapBuffersClient
{
206 CompositorSwapClient(ui::Compositor
* compositor
,
207 GpuProcessTransportFactory
* factory
)
208 : compositor_(compositor
),
212 virtual ~CompositorSwapClient() {
215 virtual void OnViewContextSwapBuffersPosted() OVERRIDE
{
216 compositor_
->OnSwapBuffersPosted();
219 virtual void OnViewContextSwapBuffersComplete() OVERRIDE
{
220 compositor_
->OnSwapBuffersComplete();
223 virtual void OnViewContextSwapBuffersAborted() OVERRIDE
{
224 // Recreating contexts directly from here causes issues, so post a task
226 // TODO(piman): Fix the underlying issues.
227 base::MessageLoop::current()->PostTask(
229 base::Bind(&CompositorSwapClient::OnLostContext
, this->AsWeakPtr()));
233 void OnLostContext();
234 ui::Compositor
* compositor_
;
235 GpuProcessTransportFactory
* factory_
;
237 DISALLOW_COPY_AND_ASSIGN(CompositorSwapClient
);
240 class BrowserCompositorOutputSurface
;
242 // Directs vsync updates to the appropriate BrowserCompositorOutputSurface.
243 class BrowserCompositorOutputSurfaceProxy
244 : public base::RefCountedThreadSafe
<BrowserCompositorOutputSurfaceProxy
> {
246 BrowserCompositorOutputSurfaceProxy()
247 : message_handler_set_(false) {
250 void AddSurface(BrowserCompositorOutputSurface
* surface
, int surface_id
) {
251 if (!message_handler_set_
) {
252 uint32 messages_to_filter
[] = {GpuHostMsg_UpdateVSyncParameters::ID
};
253 BrowserGpuChannelHostFactory::instance()->SetHandlerForControlMessages(
255 arraysize(messages_to_filter
),
256 base::Bind(&BrowserCompositorOutputSurfaceProxy::OnMessageReceived
,
258 base::MessageLoop::current()->message_loop_proxy());
259 message_handler_set_
= true;
261 surface_map_
.AddWithID(surface
, surface_id
);
264 BrowserCompositorOutputSurface
* GetOutputSurface(int surface_id
) {
265 return surface_map_
.Lookup(surface_id
);
268 void RemoveSurface(int surface_id
) {
269 surface_map_
.Remove(surface_id
);
273 void OnMessageReceived(const IPC::Message
& message
) {
274 IPC_BEGIN_MESSAGE_MAP(BrowserCompositorOutputSurfaceProxy
, message
)
275 IPC_MESSAGE_HANDLER(GpuHostMsg_UpdateVSyncParameters
,
276 OnUpdateVSyncParameters
);
277 IPC_END_MESSAGE_MAP()
280 void OnUpdateVSyncParameters(int surface_id
,
281 base::TimeTicks timebase
,
282 base::TimeDelta interval
);
285 base::RefCountedThreadSafe
<BrowserCompositorOutputSurfaceProxy
>;
286 ~BrowserCompositorOutputSurfaceProxy() {}
287 IDMap
<BrowserCompositorOutputSurface
> surface_map_
;
288 bool message_handler_set_
;
290 DISALLOW_COPY_AND_ASSIGN(BrowserCompositorOutputSurfaceProxy
);
293 // A reflector implementation that copies the framebuffer content
294 // to the texture, then draw it onto the mirroring compositor.
295 class ReflectorImpl
: public ImageTransportFactoryObserver
,
296 public base::SupportsWeakPtr
<ReflectorImpl
>,
297 public ui::Reflector
{
299 ReflectorImpl(ui::Compositor
* mirrored_compositor
,
300 ui::Layer
* mirroring_layer
,
301 BrowserCompositorOutputSurfaceProxy
* output_surface_proxy
,
304 texture_size_(mirrored_compositor
->size()),
305 output_surface_proxy_(output_surface_proxy
),
306 mirrored_compositor_(mirrored_compositor
),
307 mirroring_compositor_(mirroring_layer
->GetCompositor()),
308 mirroring_layer_(mirroring_layer
),
309 impl_message_loop_(ui::Compositor::GetCompositorMessageLoop()),
310 main_message_loop_(base::MessageLoopProxy::current()),
311 surface_id_(surface_id
) {
312 CreateSharedTexture();
313 impl_message_loop_
->PostTask(
315 base::Bind(&ReflectorImpl::InitOnImplThread
,
319 ui::Compositor
* mirrored_compositor() {
320 return mirrored_compositor_
;
323 void InitOnImplThread();
326 mirroring_compositor_
= NULL
;
327 mirroring_layer_
= NULL
;
328 shared_texture_
= NULL
;
329 impl_message_loop_
->PostTask(
331 base::Bind(&ReflectorImpl::ShutdownOnImplThread
,
335 void ShutdownOnImplThread();
337 // This must be called on ImplThread, or before the surface is passed to
339 void AttachToOutputSurface(BrowserCompositorOutputSurface
* surface
);
341 // ui::Reflector overrides:
342 virtual void OnMirroringCompositorResized() OVERRIDE
{
343 mirroring_compositor_
->ScheduleFullRedraw();
346 // ImageTransportFactoryObsever overrides:
347 virtual void OnLostResources() OVERRIDE
{
348 shared_texture_
= NULL
;
349 mirroring_layer_
->SetExternalTexture(NULL
);
352 // Called when the output surface's size has changed.
353 // This must be called on ImplThread.
354 void OnReshape(gfx::Size size
) {
355 if (texture_size_
== size
)
357 texture_size_
= size
;
359 gl_helper_
->ResizeTexture(texture_id_
, size
);
360 main_message_loop_
->PostTask(
362 base::Bind(&ReflectorImpl::UpdateTextureSizeOnMainThread
,
367 // Called in |BrowserCompositorOutputSurface::SwapBuffers| to copy
368 // the full screen image to the |texture_id_|. This must be called
370 void OnSwapBuffers() {
372 gl_helper_
->CopyTextureFullImage(texture_id_
, texture_size_
);
373 main_message_loop_
->PostTask(
375 base::Bind(&ReflectorImpl::FullRedrawOnMainThread
,
380 // Called in |BrowserCompositorOutputSurface::PostSubBuffer| copy
381 // the sub image given by |rect| to the texture.This must be called
383 void OnPostSubBuffer(gfx::Rect rect
) {
385 gl_helper_
->CopyTextureSubImage(texture_id_
, rect
);
386 main_message_loop_
->PostTask(
388 base::Bind(&ReflectorImpl::UpdateSubBufferOnMainThread
,
394 // Create a shared texture that will be used to copy the content of
395 // mirrored compositor to the mirroring compositor. This must be
396 // called before the reflector is attached to OutputSurface to avoid
397 // race with ImplThread accessing |texture_id_|.
398 void CreateSharedTexture() {
399 texture_id_
= ImageTransportFactory::GetInstance()->GetGLHelper()->
401 shared_texture_
= ImageTransportFactory::GetInstance()->
402 CreateOwnedTexture(texture_size_
, 1.0f
, texture_id_
);
403 mirroring_layer_
->SetExternalTexture(shared_texture_
.get());
407 virtual ~ReflectorImpl() {
408 // Make sure the reflector is deleted on main thread.
409 DCHECK_EQ(main_message_loop_
.get(),
410 base::MessageLoopProxy::current().get());
413 void UpdateTextureSizeOnMainThread(gfx::Size size
) {
414 if (!mirroring_layer_
)
416 mirroring_layer_
->SetBounds(gfx::Rect(size
));
419 // Request full redraw on mirroring compositor.
420 void FullRedrawOnMainThread(gfx::Size size
) {
421 if (!mirroring_compositor_
)
423 UpdateTextureSizeOnMainThread(size
);
424 mirroring_compositor_
->ScheduleFullRedraw();
427 void UpdateSubBufferOnMainThread(gfx::Size size
,
429 if (!mirroring_compositor_
)
431 UpdateTextureSizeOnMainThread(size
);
432 // Flip the coordinates to compositor's one.
433 int y
= size
.height() - rect
.y() - rect
.height();
434 gfx::Rect
new_rect(rect
.x(), y
, rect
.width(), rect
.height());
435 mirroring_layer_
->SchedulePaint(new_rect
);
438 // Request full redraw on mirrored compositor so that
439 // the full content will be copied to mirroring compositor.
440 void FullRedrawContentOnMainThread() {
441 mirrored_compositor_
->ScheduleFullRedraw();
444 static void DeleteOnMainThread(ReflectorImpl
* reflector
) {
445 // reflector gets deleted when the function returns.
448 // These variables are initialized on MainThread before
449 // the reflector is attached to the output surface. Once
450 // attached, they must be accessed only on ImplThraed unless
451 // the context is lost. When the context is lost, these
452 // will be re-ininitiailzed when the new output-surface
453 // is created on MainThread.
455 gfx::Size texture_size_
;
457 // Must be accessed only on ImplThread.
458 scoped_refptr
<BrowserCompositorOutputSurfaceProxy
> output_surface_proxy_
;
459 scoped_ptr
<GLHelper
> gl_helper_
;
461 // Must be accessed only on MainThread.
462 ui::Compositor
* mirrored_compositor_
;
463 ui::Compositor
* mirroring_compositor_
;
464 ui::Layer
* mirroring_layer_
;
465 scoped_refptr
<ui::Texture
> shared_texture_
;
466 scoped_refptr
<base::MessageLoopProxy
> impl_message_loop_
;
467 scoped_refptr
<base::MessageLoopProxy
> main_message_loop_
;
471 // Adapts a WebGraphicsContext3DCommandBufferImpl into a
472 // cc::OutputSurface that also handles vsync parameter updates
473 // arriving from the GPU process.
474 class BrowserCompositorOutputSurface
475 : public cc::OutputSurface
,
476 public base::NonThreadSafe
{
478 BrowserCompositorOutputSurface(
479 scoped_ptr
<WebKit::WebGraphicsContext3D
> context
,
481 BrowserCompositorOutputSurfaceProxy
* output_surface_proxy
,
482 base::MessageLoopProxy
* compositor_message_loop
,
483 base::WeakPtr
<ui::Compositor
> compositor
)
484 : OutputSurface(context
.Pass()),
485 surface_id_(surface_id
),
486 output_surface_proxy_(output_surface_proxy
),
487 compositor_message_loop_(compositor_message_loop
),
488 compositor_(compositor
) {
489 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
490 if (command_line
->HasSwitch(switches::kUIMaxFramesPending
)) {
491 std::string string_value
= command_line
->GetSwitchValueASCII(
492 switches::kUIMaxFramesPending
);
494 if (base::StringToInt(string_value
, &int_value
))
495 capabilities_
.max_frames_pending
= int_value
;
497 LOG(ERROR
) << "Trouble parsing --" << switches::kUIMaxFramesPending
;
499 capabilities_
.adjust_deadline_for_parent
= false;
503 virtual ~BrowserCompositorOutputSurface() {
504 DCHECK(CalledOnValidThread());
507 output_surface_proxy_
->RemoveSurface(surface_id_
);
510 virtual bool BindToClient(
511 cc::OutputSurfaceClient
* client
) OVERRIDE
{
512 DCHECK(CalledOnValidThread());
514 if (!OutputSurface::BindToClient(client
))
517 output_surface_proxy_
->AddSurface(this, surface_id_
);
521 void OnUpdateVSyncParameters(
522 base::TimeTicks timebase
, base::TimeDelta interval
) {
523 DCHECK(CalledOnValidThread());
525 OnVSyncParametersChanged(timebase
, interval
);
526 compositor_message_loop_
->PostTask(
528 base::Bind(&ui::Compositor::OnUpdateVSyncParameters
,
529 compositor_
, timebase
, interval
));
532 virtual void Reshape(gfx::Size size
, float scale_factor
) OVERRIDE
{
533 OutputSurface::Reshape(size
, scale_factor
);
534 if (reflector_
.get())
535 reflector_
->OnReshape(size
);
538 virtual void SwapBuffers(cc::CompositorFrame
* frame
) OVERRIDE
{
539 DCHECK(frame
->gl_frame_data
);
541 WebGraphicsContext3DCommandBufferImpl
* command_buffer
=
542 static_cast<WebGraphicsContext3DCommandBufferImpl
*>(context3d());
543 CommandBufferProxyImpl
* command_buffer_proxy
=
544 command_buffer
->GetCommandBufferProxy();
545 DCHECK(command_buffer_proxy
);
546 context3d()->shallowFlushCHROMIUM();
547 command_buffer_proxy
->SetLatencyInfo(frame
->metadata
.latency_info
);
549 if (reflector_
.get()) {
550 if (frame
->gl_frame_data
->sub_buffer_rect
==
551 gfx::Rect(frame
->gl_frame_data
->size
))
552 reflector_
->OnSwapBuffers();
554 reflector_
->OnPostSubBuffer(frame
->gl_frame_data
->sub_buffer_rect
);
557 OutputSurface::SwapBuffers(frame
);
560 void SetReflector(ReflectorImpl
* reflector
) {
561 reflector_
= reflector
;
566 scoped_refptr
<BrowserCompositorOutputSurfaceProxy
> output_surface_proxy_
;
568 scoped_refptr
<base::MessageLoopProxy
> compositor_message_loop_
;
569 base::WeakPtr
<ui::Compositor
> compositor_
;
570 scoped_refptr
<ReflectorImpl
> reflector_
;
573 void BrowserCompositorOutputSurfaceProxy::OnUpdateVSyncParameters(
574 int surface_id
, base::TimeTicks timebase
, base::TimeDelta interval
) {
575 BrowserCompositorOutputSurface
* surface
= surface_map_
.Lookup(surface_id
);
577 surface
->OnUpdateVSyncParameters(timebase
, interval
);
580 void ReflectorImpl::AttachToOutputSurface(
581 BrowserCompositorOutputSurface
* output_surface
) {
582 gl_helper_
.reset(new GLHelper(output_surface
->context3d()));
583 output_surface
->SetReflector(this);
586 void ReflectorImpl::InitOnImplThread() {
587 AttachToOutputSurface(output_surface_proxy_
->GetOutputSurface(surface_id_
));
588 gl_helper_
->CopyTextureFullImage(texture_id_
, texture_size_
);
589 // The shared texture doesn't have the data, so invokes full redraw
591 main_message_loop_
->PostTask(
593 base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread
,
594 scoped_refptr
<ReflectorImpl
>(this)));
597 void ReflectorImpl::ShutdownOnImplThread() {
598 BrowserCompositorOutputSurface
* output_surface
=
599 output_surface_proxy_
->GetOutputSurface(surface_id_
);
600 output_surface
->SetReflector(NULL
);
602 // The instance must be deleted on main thread.
603 main_message_loop_
->PostTask(
605 base::Bind(&ReflectorImpl::DeleteOnMainThread
,
606 scoped_refptr
<ReflectorImpl
>(this)));
609 class GpuProcessTransportFactory
610 : public ui::ContextFactory
,
611 public ImageTransportFactory
{
613 GpuProcessTransportFactory()
614 : callback_factory_(this) {
615 output_surface_proxy_
= new BrowserCompositorOutputSurfaceProxy();
618 virtual ~GpuProcessTransportFactory() {
619 DCHECK(per_compositor_data_
.empty());
622 scoped_ptr
<WebGraphicsContext3DCommandBufferImpl
>
623 CreateOffscreenCommandBufferContext() {
624 base::WeakPtr
<WebGraphicsContext3DSwapBuffersClient
> swap_client
;
625 return CreateContextCommon(swap_client
, 0);
628 virtual scoped_ptr
<WebKit::WebGraphicsContext3D
> CreateOffscreenContext()
630 return CreateOffscreenCommandBufferContext()
631 .PassAs
<WebKit::WebGraphicsContext3D
>();
634 virtual cc::OutputSurface
* CreateOutputSurface(
635 ui::Compositor
* compositor
) OVERRIDE
{
636 PerCompositorData
* data
= per_compositor_data_
[compositor
];
638 data
= CreatePerCompositorData(compositor
);
639 BrowserCompositorOutputSurface
* surface
=
640 new BrowserCompositorOutputSurface(
641 CreateContextCommon(data
->swap_client
->AsWeakPtr(),
643 .PassAs
<WebKit::WebGraphicsContext3D
>(),
644 per_compositor_data_
[compositor
]->surface_id
,
645 output_surface_proxy_
.get(),
646 base::MessageLoopProxy::current(),
647 compositor
->AsWeakPtr());
648 if (data
->reflector
.get()) {
649 data
->reflector
->CreateSharedTexture();
650 data
->reflector
->AttachToOutputSurface(surface
);
655 virtual scoped_refptr
<ui::Reflector
> CreateReflector(
656 ui::Compositor
* source
,
657 ui::Layer
* target
) OVERRIDE
{
658 PerCompositorData
* data
= per_compositor_data_
[source
];
661 if (data
->reflector
.get())
662 RemoveObserver(data
->reflector
.get());
664 data
->reflector
= new ReflectorImpl(
665 source
, target
, output_surface_proxy_
.get(), data
->surface_id
);
666 AddObserver(data
->reflector
.get());
667 return data
->reflector
;
670 virtual void RemoveReflector(
671 scoped_refptr
<ui::Reflector
> reflector
) OVERRIDE
{
672 ReflectorImpl
* reflector_impl
=
673 static_cast<ReflectorImpl
*>(reflector
.get());
674 PerCompositorData
* data
=
675 per_compositor_data_
[reflector_impl
->mirrored_compositor()];
677 RemoveObserver(reflector_impl
);
678 data
->reflector
->Shutdown();
679 data
->reflector
= NULL
;
682 virtual void RemoveCompositor(ui::Compositor
* compositor
) OVERRIDE
{
683 PerCompositorDataMap::iterator it
= per_compositor_data_
.find(compositor
);
684 if (it
== per_compositor_data_
.end())
686 PerCompositorData
* data
= it
->second
;
688 GpuSurfaceTracker::Get()->RemoveSurface(data
->surface_id
);
690 per_compositor_data_
.erase(it
);
691 if (per_compositor_data_
.empty()) {
693 callback_factory_
.InvalidateWeakPtrs();
697 virtual ui::ContextFactory
* AsContextFactory() OVERRIDE
{
701 virtual gfx::GLSurfaceHandle
CreateSharedSurfaceHandle() OVERRIDE
{
702 CreateSharedContextLazy();
703 gfx::GLSurfaceHandle handle
= gfx::GLSurfaceHandle(
704 gfx::kNullPluginWindow
, gfx::TEXTURE_TRANSPORT
);
705 handle
.parent_gpu_process_id
=
706 shared_contexts_main_thread_
->Context3d()->GetGPUProcessID();
707 handle
.parent_client_id
=
708 shared_contexts_main_thread_
->Context3d()->GetChannelID();
712 virtual void DestroySharedSurfaceHandle(
713 gfx::GLSurfaceHandle surface
) OVERRIDE
{
716 virtual scoped_refptr
<ui::Texture
> CreateTransportClient(
717 float device_scale_factor
) OVERRIDE
{
718 if (!shared_contexts_main_thread_
.get())
720 scoped_refptr
<ImageTransportClientTexture
> image(
721 new ImageTransportClientTexture(
722 shared_contexts_main_thread_
->Context3d(),
723 device_scale_factor
));
727 virtual scoped_refptr
<ui::Texture
> CreateOwnedTexture(
728 const gfx::Size
& size
,
729 float device_scale_factor
,
730 unsigned int texture_id
) OVERRIDE
{
731 if (!shared_contexts_main_thread_
.get())
733 scoped_refptr
<OwnedTexture
> image(new OwnedTexture(
734 shared_contexts_main_thread_
->Context3d(),
741 virtual GLHelper
* GetGLHelper() OVERRIDE
{
743 CreateSharedContextLazy();
744 WebGraphicsContext3DCommandBufferImpl
* context_for_main_thread
=
745 shared_contexts_main_thread_
->Context3d();
746 gl_helper_
.reset(new GLHelper(context_for_main_thread
));
748 return gl_helper_
.get();
751 virtual uint32
InsertSyncPoint() OVERRIDE
{
752 if (!shared_contexts_main_thread_
.get())
754 return shared_contexts_main_thread_
->Context3d()->insertSyncPoint();
757 virtual void WaitSyncPoint(uint32 sync_point
) OVERRIDE
{
758 if (!shared_contexts_main_thread_
.get())
760 shared_contexts_main_thread_
->Context3d()->waitSyncPoint(sync_point
);
763 virtual void AddObserver(ImageTransportFactoryObserver
* observer
) OVERRIDE
{
764 observer_list_
.AddObserver(observer
);
767 virtual void RemoveObserver(
768 ImageTransportFactoryObserver
* observer
) OVERRIDE
{
769 observer_list_
.RemoveObserver(observer
);
772 void OnLostContext(ui::Compositor
* compositor
) {
773 LOG(ERROR
) << "Lost UI compositor context.";
774 PerCompositorData
* data
= per_compositor_data_
[compositor
];
777 // Prevent callbacks from other contexts in the same share group from
779 data
->swap_client
.reset(new CompositorSwapClient(compositor
, this));
780 compositor
->OnSwapBuffersAborted();
784 struct PerCompositorData
{
786 scoped_ptr
<CompositorSwapClient
> swap_client
;
788 scoped_ptr
<AcceleratedSurface
> accelerated_surface
;
790 scoped_refptr
<ReflectorImpl
> reflector
;
793 PerCompositorData
* CreatePerCompositorData(ui::Compositor
* compositor
) {
794 DCHECK(!per_compositor_data_
[compositor
]);
796 CreateSharedContextLazy();
798 gfx::AcceleratedWidget widget
= compositor
->widget();
799 GpuSurfaceTracker
* tracker
= GpuSurfaceTracker::Get();
801 PerCompositorData
* data
= new PerCompositorData
;
802 data
->surface_id
= tracker
->AddSurfaceForNativeWidget(widget
);
803 data
->swap_client
.reset(new CompositorSwapClient(compositor
, this));
805 if (GpuDataManagerImpl::GetInstance()->IsUsingAcceleratedSurface())
806 data
->accelerated_surface
.reset(new AcceleratedSurface(widget
));
808 tracker
->SetSurfaceHandle(
810 gfx::GLSurfaceHandle(widget
, gfx::NATIVE_DIRECT
));
812 per_compositor_data_
[compositor
] = data
;
817 scoped_ptr
<WebGraphicsContext3DCommandBufferImpl
> CreateContextCommon(
818 const base::WeakPtr
<WebGraphicsContext3DSwapBuffersClient
>& swap_client
,
820 WebKit::WebGraphicsContext3D::Attributes attrs
;
821 attrs
.shareResources
= true;
823 attrs
.stencil
= false;
824 attrs
.antialias
= false;
825 attrs
.noAutomaticFlushes
= true;
826 GpuChannelHostFactory
* factory
= BrowserGpuChannelHostFactory::instance();
827 GURL
url("chrome://gpu/GpuProcessTransportFactory::CreateContextCommon");
828 scoped_ptr
<WebGraphicsContext3DCommandBufferImpl
> context(
829 new WebGraphicsContext3DCommandBufferImpl(
834 if (!context
->InitializeWithDefaultBufferSizes(
837 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE
))
838 return scoped_ptr
<WebGraphicsContext3DCommandBufferImpl
>();
839 return context
.Pass();
842 // Crash given that we are unable to show any UI whatsoever. On Windows we
843 // also trigger code in breakpad causes a system process to show message box.
844 // In all cases a crash dump is generated.
845 void FatalGPUError(const char* message
) {
847 // 0xC01E0200 corresponds to STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE.
848 ::RaiseException(0xC01E0200, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
850 LOG(FATAL
) << message
;
854 class MainThreadContextProvider
: public ContextProviderCommandBuffer
{
856 static scoped_refptr
<MainThreadContextProvider
> Create(
857 GpuProcessTransportFactory
* factory
) {
858 scoped_refptr
<MainThreadContextProvider
> provider
=
859 new MainThreadContextProvider(factory
);
860 if (!provider
->InitializeOnMainThread())
866 explicit MainThreadContextProvider(GpuProcessTransportFactory
* factory
)
867 : factory_(factory
) {}
868 virtual ~MainThreadContextProvider() {}
870 virtual scoped_ptr
<WebGraphicsContext3DCommandBufferImpl
>
871 CreateOffscreenContext3d() OVERRIDE
{
872 return factory_
->CreateOffscreenCommandBufferContext();
875 virtual void OnLostContext() OVERRIDE
{
876 base::MessageLoop::current()->PostTask(
878 base::Bind(&GpuProcessTransportFactory::OnLostMainThreadSharedContext
,
879 factory_
->callback_factory_
.GetWeakPtr()));
883 GpuProcessTransportFactory
* factory_
;
886 virtual scoped_refptr
<cc::ContextProvider
>
887 OffscreenContextProviderForMainThread() OVERRIDE
{
888 if (!shared_contexts_main_thread_
.get() ||
889 shared_contexts_main_thread_
->DestroyedOnMainThread()) {
890 shared_contexts_main_thread_
= MainThreadContextProvider::Create(this);
891 if (shared_contexts_main_thread_
.get() &&
892 !shared_contexts_main_thread_
->BindToCurrentThread())
893 shared_contexts_main_thread_
= NULL
;
895 return shared_contexts_main_thread_
;
898 class CompositorThreadContextProvider
: public ContextProviderCommandBuffer
{
900 static scoped_refptr
<CompositorThreadContextProvider
> Create(
901 GpuProcessTransportFactory
* factory
) {
902 scoped_refptr
<CompositorThreadContextProvider
> provider
=
903 new CompositorThreadContextProvider(factory
);
904 if (!provider
->InitializeOnMainThread())
910 explicit CompositorThreadContextProvider(
911 GpuProcessTransportFactory
* factory
) : factory_(factory
) {}
912 virtual ~CompositorThreadContextProvider() {}
914 virtual scoped_ptr
<WebGraphicsContext3DCommandBufferImpl
>
915 CreateOffscreenContext3d() OVERRIDE
{
916 return factory_
->CreateOffscreenCommandBufferContext();
920 GpuProcessTransportFactory
* factory_
;
923 virtual scoped_refptr
<cc::ContextProvider
>
924 OffscreenContextProviderForCompositorThread() OVERRIDE
{
925 if (!shared_contexts_compositor_thread_
.get() ||
926 shared_contexts_compositor_thread_
->DestroyedOnMainThread()) {
927 shared_contexts_compositor_thread_
=
928 CompositorThreadContextProvider::Create(this);
930 return shared_contexts_compositor_thread_
;
933 void CreateSharedContextLazy() {
934 scoped_refptr
<cc::ContextProvider
> provider
=
935 OffscreenContextProviderForMainThread();
936 if (!provider
.get()) {
937 // If we can't recreate contexts, we won't be able to show the UI.
938 // Better crash at this point.
939 FatalGPUError("Failed to initialize UI shared context.");
943 void OnLostMainThreadSharedContext() {
944 LOG(ERROR
) << "Lost UI shared context.";
945 // Keep old resources around while we call the observers, but ensure that
946 // new resources are created if needed.
948 scoped_refptr
<MainThreadContextProvider
> old_contexts_main_thread
=
949 shared_contexts_main_thread_
;
950 shared_contexts_main_thread_
= NULL
;
952 scoped_ptr
<GLHelper
> old_helper(gl_helper_
.release());
954 FOR_EACH_OBSERVER(ImageTransportFactoryObserver
,
959 typedef std::map
<ui::Compositor
*, PerCompositorData
*> PerCompositorDataMap
;
960 PerCompositorDataMap per_compositor_data_
;
961 scoped_refptr
<MainThreadContextProvider
> shared_contexts_main_thread_
;
962 scoped_refptr
<CompositorThreadContextProvider
>
963 shared_contexts_compositor_thread_
;
964 scoped_ptr
<GLHelper
> gl_helper_
;
965 ObserverList
<ImageTransportFactoryObserver
> observer_list_
;
966 base::WeakPtrFactory
<GpuProcessTransportFactory
> callback_factory_
;
967 scoped_refptr
<BrowserCompositorOutputSurfaceProxy
> output_surface_proxy_
;
969 DISALLOW_COPY_AND_ASSIGN(GpuProcessTransportFactory
);
972 void CompositorSwapClient::OnLostContext() {
973 factory_
->OnLostContext(compositor_
);
974 // Note: previous line destroyed this. Don't access members from now on.
977 class SoftwareOutputSurface
: public cc::OutputSurface
{
979 explicit SoftwareOutputSurface(
980 scoped_ptr
<cc::SoftwareOutputDevice
> software_device
)
981 : cc::OutputSurface(software_device
.Pass()) {}
983 virtual void SwapBuffers(cc::CompositorFrame
* frame
) OVERRIDE
{
984 ui::LatencyInfo latency_info
= frame
->metadata
.latency_info
;
985 latency_info
.swap_timestamp
= base::TimeTicks::HighResNow();
986 RenderWidgetHostImpl::CompositorFrameDrawn(latency_info
);
987 cc::OutputSurface::SwapBuffers(frame
);
991 class SoftwareContextFactory
: public ui::ContextFactory
{
993 SoftwareContextFactory() {}
994 virtual ~SoftwareContextFactory() {}
995 virtual scoped_ptr
<WebKit::WebGraphicsContext3D
> CreateOffscreenContext()
997 return scoped_ptr
<WebKit::WebGraphicsContext3D
>();
999 virtual cc::OutputSurface
* CreateOutputSurface(
1000 ui::Compositor
* compositor
) OVERRIDE
{
1002 scoped_ptr
<SoftwareOutputDeviceWin
> software_device(
1003 new SoftwareOutputDeviceWin(compositor
));
1004 return new SoftwareOutputSurface(
1005 software_device
.PassAs
<cc::SoftwareOutputDevice
>());
1006 #elif defined(USE_X11)
1007 scoped_ptr
<SoftwareOutputDeviceX11
> software_device(
1008 new SoftwareOutputDeviceX11(compositor
));
1009 return new SoftwareOutputSurface(
1010 software_device
.PassAs
<cc::SoftwareOutputDevice
>());
1017 virtual scoped_refptr
<ui::Reflector
> CreateReflector(
1018 ui::Compositor
* source
,
1019 ui::Layer
* target
) OVERRIDE
{
1022 virtual void RemoveReflector(
1023 scoped_refptr
<ui::Reflector
> reflector
) OVERRIDE
{}
1025 virtual void RemoveCompositor(ui::Compositor
* compositor
) OVERRIDE
{}
1027 virtual scoped_refptr
<cc::ContextProvider
>
1028 OffscreenContextProviderForMainThread() OVERRIDE
{
1032 virtual scoped_refptr
<cc::ContextProvider
>
1033 OffscreenContextProviderForCompositorThread() OVERRIDE
{
1038 DISALLOW_COPY_AND_ASSIGN(SoftwareContextFactory
);
1041 } // anonymous namespace
1044 void ImageTransportFactory::Initialize() {
1045 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
1046 if (command_line
->HasSwitch(switches::kTestCompositor
)) {
1047 ui::SetupTestCompositor();
1049 if (ui::IsTestCompositorEnabled()) {
1050 g_factory
= new NoTransportFactory(new ui::TestContextFactory
);
1051 } else if (command_line
->HasSwitch(switches::kUIEnableSoftwareCompositing
)) {
1052 g_factory
= new NoTransportFactory(new SoftwareContextFactory
);
1054 g_factory
= new GpuProcessTransportFactory
;
1056 ui::ContextFactory::SetInstance(g_factory
->AsContextFactory());
1060 void ImageTransportFactory::Terminate() {
1061 ui::ContextFactory::SetInstance(NULL
);
1067 ImageTransportFactory
* ImageTransportFactory::GetInstance() {
1071 } // namespace content