diff options
author | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-16 01:40:24 +0000 |
---|---|---|
committer | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-16 01:40:24 +0000 |
commit | 58b4b6dac3eeb9af7a3e46482552679ba3db6ed7 (patch) | |
tree | 2f11456c5cdc2dd81fadd2af7497378e99659682 | |
parent | 4eec71c33f6469fdec8ba5494842c1c16ab22cd5 (diff) | |
download | chromium_src-58b4b6dac3eeb9af7a3e46482552679ba3db6ed7.zip chromium_src-58b4b6dac3eeb9af7a3e46482552679ba3db6ed7.tar.gz chromium_src-58b4b6dac3eeb9af7a3e46482552679ba3db6ed7.tar.bz2 |
aura: Use GPU process for UI
This is behind a flag (--ui-use-gpu-process).
Currently problems occur when the GPU process crash, this will be handled in a follow-up CL.
BUG=99516
TEST=chrome --ui-use-gpu-process (with an aura build)
Review URL: http://codereview.chromium.org/9348117
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@122213 0039d316-1c4b-4281-b951-d872f2087c98
37 files changed, 774 insertions, 233 deletions
diff --git a/chrome/browser/chrome_browser_main_extra_parts_aura.cc b/chrome/browser/chrome_browser_main_extra_parts_aura.cc index 18ead25..54eac8b 100644 --- a/chrome/browser/chrome_browser_main_extra_parts_aura.cc +++ b/chrome/browser/chrome_browser_main_extra_parts_aura.cc @@ -29,10 +29,6 @@ ChromeBrowserMainExtraPartsAura::ChromeBrowserMainExtraPartsAura() } void ChromeBrowserMainExtraPartsAura::PreProfileInit() { - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestCompositor)) { - ui::SetupTestCompositor(); - } - #if defined(OS_CHROMEOS) if (chromeos::system::runtime_environment::IsRunningOnChromeOS()) { aura::RootWindow::set_use_fullscreen_host_window(true); diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 24262eb..c961834 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -1295,11 +1295,6 @@ const char kDisablePrintPreview[] = "disable-print-preview"; const char kEnablePrintPreview[] = "enable-print-preview"; #endif -#if defined(USE_AURA) -// Forces usage of the test compositor. Needed to run ui tests on bots. -extern const char kTestCompositor[] = "test-compositor"; -#endif - // ----------------------------------------------------------------------------- // DO NOT ADD YOUR CRAP TO THE BOTTOM OF THIS FILE. // diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 3830cbd..1c7f2fd 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -379,10 +379,6 @@ extern const char kDisablePrintPreview[]; extern const char kEnablePrintPreview[]; #endif -#if defined(USE_AURA) -extern const char kTestCompositor[]; -#endif - // DON'T ADD RANDOM STUFF HERE. Put it in the main section above in // alphabetical order, or in one of the ifdefs (also in order in each section). diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 4096821..41b3dd2 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -37,6 +37,10 @@ #include "net/socket/client_socket_factory.h" #include "net/socket/tcp_client_socket.h" +#if defined(USE_AURA) +#include "content/browser/renderer_host/image_transport_factory.h" +#endif + #if defined(OS_WIN) #include <windows.h> #include <commctrl.h> @@ -409,6 +413,9 @@ void BrowserMainLoop::CreateThreads() { } BrowserGpuChannelHostFactory::Initialize(); +#if defined(USE_AURA) + ImageTransportFactory::Initialize(); +#endif BrowserThreadsStarted(); @@ -455,6 +462,9 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() { if (resource_dispatcher_host_.get()) resource_dispatcher_host_.get()->Shutdown(); +#if defined(USE_AURA) + ImageTransportFactory::Terminate(); +#endif BrowserGpuChannelHostFactory::Terminate(); // Must be size_t so we can subtract from it. diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc index a706fb3..7caccb7 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc @@ -39,6 +39,10 @@ void BrowserGpuChannelHostFactory::Terminate() { delete instance(); } +BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::Get() { + return static_cast<BrowserGpuChannelHostFactory*>(instance()); +} + BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory() : gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), shutdown_event_(new base::WaitableEvent(true, false)), @@ -142,6 +146,7 @@ void BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO( host->EstablishGpuChannel( gpu_client_id_, + 0, base::Bind(&BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO, request)); } @@ -202,7 +207,7 @@ GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync( browser_process_for_gpu = base::GetCurrentProcessHandle(); #endif - gpu_channel_ = new GpuChannelHost(this); + gpu_channel_ = new GpuChannelHost(this, gpu_client_id_); gpu_channel_->set_gpu_info(request.gpu_info); content::GetContentClient()->SetGpuInfo(request.gpu_info); diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h index cecb3c4..f9a7bd6 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.h +++ b/content/browser/gpu/browser_gpu_channel_host_factory.h @@ -19,6 +19,7 @@ class BrowserGpuChannelHostFactory : public GpuChannelHostFactory { public: static void Initialize(); static void Terminate(); + static BrowserGpuChannelHostFactory* Get(); // GpuChannelHostFactory implementation. virtual bool IsMainThread() OVERRIDE; @@ -34,6 +35,8 @@ class BrowserGpuChannelHostFactory : public GpuChannelHostFactory { virtual GpuChannelHost* EstablishGpuChannelSync( CauseForGpuLaunch cause_for_gpu_launch) OVERRIDE; + int gpu_client_id() { return gpu_client_id_; } + private: struct CreateRequest { CreateRequest(); diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index e6f5d93..e3eae00 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -417,6 +417,7 @@ void GpuProcessHost::OnChannelConnected(int32 peer_pid) { void GpuProcessHost::EstablishGpuChannel( int client_id, + int share_client_id, const EstablishChannelCallback& callback) { DCHECK(CalledOnValidThread()); TRACE_EVENT0("gpu", "GpuProcessHostUIShim::EstablishGpuChannel"); @@ -429,7 +430,7 @@ void GpuProcessHost::EstablishGpuChannel( return; } - if (Send(new GpuMsg_EstablishChannel(client_id, 0))) { + if (Send(new GpuMsg_EstablishChannel(client_id, share_client_id))) { channel_requests_.push(callback); } else { EstablishChannelError( diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h index c0c8b73..854268b 100644 --- a/content/browser/gpu/gpu_process_host.h +++ b/content/browser/gpu/gpu_process_host.h @@ -64,8 +64,9 @@ class GpuProcessHost : public content::BrowserChildProcessHostDelegate, // Tells the GPU process to create a new channel for communication with a // client. Once the GPU process responds asynchronously with the IPC handle // and GPUInfo, we call the callback. - void EstablishGpuChannel( - int client_id, const EstablishChannelCallback& callback); + void EstablishGpuChannel(int client_id, + int share_client_id, + const EstablishChannelCallback& callback); typedef base::Callback<void(int32)> CreateCommandBufferCallback; diff --git a/content/browser/gpu/gpu_process_host_ui_shim.cc b/content/browser/gpu/gpu_process_host_ui_shim.cc index ef3f310..3ded9e3 100644 --- a/content/browser/gpu/gpu_process_host_ui_shim.cc +++ b/content/browser/gpu/gpu_process_host_ui_shim.cc @@ -197,12 +197,12 @@ bool GpuProcessHostUIShim::OnControlMessageReceived( IPC_MESSAGE_HANDLER(GpuHostMsg_ResizeView, OnResizeView) #endif -#if defined(OS_MACOSX) || defined(UI_COMPOSITOR_IMAGE_TRANSPORT) +#if defined(OS_MACOSX) || defined(USE_AURA) IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceNew, OnAcceleratedSurfaceNew) #endif -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) +#if defined(USE_AURA) IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceRelease, OnAcceleratedSurfaceRelease) #endif @@ -278,7 +278,7 @@ void GpuProcessHostUIShim::OnResizeView(int32 surface_id, #endif -#if defined(OS_MACOSX) || defined(UI_COMPOSITOR_IMAGE_TRANSPORT) +#if defined(OS_MACOSX) || defined(USE_AURA) void GpuProcessHostUIShim::OnAcceleratedSurfaceNew( const GpuHostMsg_AcceleratedSurfaceNew_Params& params) { @@ -324,7 +324,7 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceNew( params.height, surface_handle); } -#else // defined(UI_COMPOSITOR_IMAGE_TRANSPORT) +#else // defined(USE_AURA) view->AcceleratedSurfaceNew( params.width, params.height, &surface_handle, &shm_handle); #endif @@ -387,7 +387,7 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend(int32 surface_id) { view->AcceleratedSurfaceSuspend(); } -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) +#if defined(USE_AURA) void GpuProcessHostUIShim::OnAcceleratedSurfaceRelease( const GpuHostMsg_AcceleratedSurfaceRelease_Params& params) { diff --git a/content/browser/gpu/gpu_process_host_ui_shim.h b/content/browser/gpu/gpu_process_host_ui_shim.h index 2ce9866..c5da9ef 100644 --- a/content/browser/gpu/gpu_process_host_ui_shim.h +++ b/content/browser/gpu/gpu_process_host_ui_shim.h @@ -96,12 +96,12 @@ class GpuProcessHostUIShim const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params); void OnAcceleratedSurfaceSuspend(int32 surface_id); -#if defined(OS_MACOSX) || defined(UI_COMPOSITOR_IMAGE_TRANSPORT) +#if defined(OS_MACOSX) || defined(USE_AURA) void OnAcceleratedSurfaceNew( const GpuHostMsg_AcceleratedSurfaceNew_Params& params); #endif -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) +#if defined(USE_AURA) void OnAcceleratedSurfaceRelease( const GpuHostMsg_AcceleratedSurfaceRelease_Params& params); #endif diff --git a/content/browser/renderer_host/gpu_message_filter.cc b/content/browser/renderer_host/gpu_message_filter.cc index 7ec5083..b19f640 100644 --- a/content/browser/renderer_host/gpu_message_filter.cc +++ b/content/browser/renderer_host/gpu_message_filter.cc @@ -9,11 +9,14 @@ #include "content/browser/renderer_host/gpu_message_filter.h" #include "base/bind.h" +#include "base/command_line.h" #include "base/process_util.h" +#include "content/browser/gpu/browser_gpu_channel_host_factory.h" #include "content/browser/gpu/gpu_process_host.h" #include "content/browser/gpu/gpu_surface_tracker.h" #include "content/browser/renderer_host/render_widget_helper.h" #include "content/common/gpu/gpu_messages.h" +#include "content/public/common/content_switches.h" using content::BrowserThread; @@ -21,8 +24,17 @@ GpuMessageFilter::GpuMessageFilter(int render_process_id, RenderWidgetHelper* render_widget_helper) : gpu_host_id_(0), render_process_id_(render_process_id), + share_client_id_(0), render_widget_helper_(render_widget_helper) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kUIUseGPUProcess)) { + // When using the GPU process for UI, we need to share renderer GL contexts + // with the compositor context. + share_client_id_ = + content::BrowserGpuChannelHostFactory::Get()->gpu_client_id(); + } } GpuMessageFilter::~GpuMessageFilter() { @@ -70,6 +82,7 @@ void GpuMessageFilter::OnEstablishGpuChannel( host->EstablishGpuChannel( render_process_id_, + share_client_id_, base::Bind(&GpuMessageFilter::EstablishChannelCallback, AsWeakPtr(), reply)); @@ -142,7 +155,7 @@ void GpuMessageFilter::EstablishChannelCallback( } GpuHostMsg_EstablishGpuChannel::WriteReplyParams( - reply, channel, renderer_process_for_gpu, gpu_info); + reply, render_process_id_, channel, renderer_process_for_gpu, gpu_info); Send(reply); } diff --git a/content/browser/renderer_host/gpu_message_filter.h b/content/browser/renderer_host/gpu_message_filter.h index afd5b4e..b286797 100644 --- a/content/browser/renderer_host/gpu_message_filter.h +++ b/content/browser/renderer_host/gpu_message_filter.h @@ -55,6 +55,7 @@ class GpuMessageFilter : public content::BrowserMessageFilter, int gpu_host_id_; int render_process_id_; + int share_client_id_; scoped_refptr<RenderWidgetHelper> render_widget_helper_; diff --git a/content/browser/renderer_host/image_transport_client.cc b/content/browser/renderer_host/image_transport_client.cc index 96c2ff1..f2a893b 100644 --- a/content/browser/renderer_host/image_transport_client.cc +++ b/content/browser/renderer_host/image_transport_client.cc @@ -11,6 +11,7 @@ #include "base/lazy_instance.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop.h" +#include "content/browser/renderer_host/image_transport_factory.h" #include "third_party/angle/include/EGL/egl.h" #include "third_party/angle/include/EGL/eglext.h" #include "ui/gfx/gl/gl_bindings.h" @@ -42,30 +43,31 @@ GLuint CreateTexture() { class ImageTransportClientEGL : public ImageTransportClient { public: - ImageTransportClientEGL(ui::SharedResources* resources, const gfx::Size& size) + ImageTransportClientEGL(ImageTransportFactory* factory, const gfx::Size& size) : ImageTransportClient(true, size), - resources_(resources), + factory_(factory), image_(NULL) { } virtual ~ImageTransportClientEGL() { - scoped_ptr<gfx::ScopedMakeCurrent> bind(resources_->GetScopedMakeCurrent()); + scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent()); if (image_) eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), image_); - if (texture_id_) - glDeleteTextures(1, &texture_id_); + unsigned int texture = texture_id(); + if (texture) + glDeleteTextures(1, &texture); glFlush(); } virtual bool Initialize(uint64* surface_handle) { - scoped_ptr<gfx::ScopedMakeCurrent> bind(resources_->GetScopedMakeCurrent()); + scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent()); image_ = eglCreateImageKHR( gfx::GLSurfaceEGL::GetHardwareDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, reinterpret_cast<void*>(*surface_handle), NULL); if (!image_) return false; - texture_id_ = CreateTexture(); - glBindTexture(GL_TEXTURE_2D, texture_id_); + set_texture_id(CreateTexture()); + glBindTexture(GL_TEXTURE_2D, texture_id()); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_); glFlush(); return true; @@ -77,7 +79,7 @@ class ImageTransportClientEGL : public ImageTransportClient { } private: - ui::SharedResources* resources_; + ImageTransportFactory* factory_; EGLImageKHR image_; }; @@ -85,16 +87,16 @@ class ImageTransportClientEGL : public ImageTransportClient { class ImageTransportClientGLX : public ImageTransportClient { public: - ImageTransportClientGLX(ui::SharedResources* resources, const gfx::Size& size) + ImageTransportClientGLX(ImageTransportFactory* factory, const gfx::Size& size) : ImageTransportClient(false, size), - resources_(resources), + factory_(factory), pixmap_(0), glx_pixmap_(0), acquired_(false) { } virtual ~ImageTransportClientGLX() { - scoped_ptr<gfx::ScopedMakeCurrent> bind(resources_->GetScopedMakeCurrent()); + scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent()); Display* dpy = base::MessagePumpForUI::GetDefaultXDisplay(); if (glx_pixmap_) { if (acquired_) @@ -103,8 +105,9 @@ class ImageTransportClientGLX : public ImageTransportClient { } if (pixmap_) XFreePixmap(dpy, pixmap_); - if (texture_id_) - glDeleteTextures(1, &texture_id_); + unsigned int texture = texture_id(); + if (texture) + glDeleteTextures(1, &texture); glFlush(); } @@ -112,7 +115,7 @@ class ImageTransportClientGLX : public ImageTransportClient { TRACE_EVENT0("renderer_host", "ImageTransportClientGLX::Initialize"); Display* dpy = base::MessagePumpForUI::GetDefaultXDisplay(); - scoped_ptr<gfx::ScopedMakeCurrent> bind(resources_->GetScopedMakeCurrent()); + scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent()); if (!InitializeOneOff(dpy)) return false; @@ -130,7 +133,7 @@ class ImageTransportClientGLX : public ImageTransportClient { glx_pixmap_ = glXCreatePixmap(dpy, fbconfig_.Get(), pixmap_, pixmapAttribs); - texture_id_ = CreateTexture(); + set_texture_id(CreateTexture()); glFlush(); return true; } @@ -138,8 +141,8 @@ class ImageTransportClientGLX : public ImageTransportClient { virtual void Update() { TRACE_EVENT0("renderer_host", "ImageTransportClientGLX::Update"); Display* dpy = base::MessagePumpForUI::GetDefaultXDisplay(); - scoped_ptr<gfx::ScopedMakeCurrent> bind(resources_->GetScopedMakeCurrent()); - glBindTexture(GL_TEXTURE_2D, texture_id_); + scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent()); + glBindTexture(GL_TEXTURE_2D, texture_id()); if (acquired_) glXReleaseTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT); glXBindTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL); @@ -218,7 +221,7 @@ class ImageTransportClientGLX : public ImageTransportClient { return initialized; } - ui::SharedResources* resources_; + ImageTransportFactory* factory_; XID pixmap_; XID glx_pixmap_; bool acquired_; @@ -230,17 +233,18 @@ base::LazyInstance<GLXFBConfig> ImageTransportClientGLX::fbconfig_ = class ImageTransportClientOSMesa : public ImageTransportClient { public: - ImageTransportClientOSMesa(ui::SharedResources* resources, + ImageTransportClientOSMesa(ImageTransportFactory* factory, const gfx::Size& size) : ImageTransportClient(false, size), - resources_(resources) { + factory_(factory) { } virtual ~ImageTransportClientOSMesa() { - if (texture_id_) { + unsigned int texture = texture_id(); + if (texture) { scoped_ptr<gfx::ScopedMakeCurrent> bind( - resources_->GetScopedMakeCurrent()); - glDeleteTextures(1, &texture_id_); + factory_->GetScopedMakeCurrent()); + glDeleteTextures(1, &texture); glFlush(); } } @@ -257,21 +261,21 @@ class ImageTransportClientOSMesa : public ImageTransportClient { *surface_handle = next_handle_++; shared_mem_.reset( - TransportDIB::Create(size_.GetArea() * 4, // GL_RGBA=4 B/px + TransportDIB::Create(size().GetArea() * 4, // GL_RGBA=4 B/px *surface_handle)); if (!shared_mem_.get()) return false; - scoped_ptr<gfx::ScopedMakeCurrent> bind(resources_->GetScopedMakeCurrent()); - texture_id_ = CreateTexture(); + scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent()); + set_texture_id(CreateTexture()); glFlush(); return true; } virtual void Update() { - glBindTexture(GL_TEXTURE_2D, texture_id_); + glBindTexture(GL_TEXTURE_2D, texture_id()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - size_.width(), size_.height(), 0, + size().width(), size().height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, shared_mem_->memory()); glFlush(); } @@ -279,7 +283,7 @@ class ImageTransportClientOSMesa : public ImageTransportClient { virtual TransportDIB::Handle Handle() const { return shared_mem_->handle(); } private: - ui::SharedResources* resources_; + ImageTransportFactory* factory_; scoped_ptr<TransportDIB> shared_mem_; static uint32 next_handle_; }; @@ -294,17 +298,17 @@ ImageTransportClient::ImageTransportClient(bool flipped, const gfx::Size& size) } ImageTransportClient* ImageTransportClient::Create( - ui::SharedResources* resources, + ImageTransportFactory* factory, const gfx::Size& size) { switch (gfx::GetGLImplementation()) { #if !defined(USE_WAYLAND) case gfx::kGLImplementationOSMesaGL: - return new ImageTransportClientOSMesa(resources, size); + return new ImageTransportClientOSMesa(factory, size); case gfx::kGLImplementationDesktopGL: - return new ImageTransportClientGLX(resources, size); + return new ImageTransportClientGLX(factory, size); #endif case gfx::kGLImplementationEGLGLES2: - return new ImageTransportClientEGL(resources, size); + return new ImageTransportClientEGL(factory, size); default: NOTREACHED(); return NULL; diff --git a/content/browser/renderer_host/image_transport_client.h b/content/browser/renderer_host/image_transport_client.h index e11e9ae..a3b40c7 100644 --- a/content/browser/renderer_host/image_transport_client.h +++ b/content/browser/renderer_host/image_transport_client.h @@ -13,11 +13,12 @@ namespace gfx { class Size; } +class ImageTransportFactory; // This is a client for ImageTransportSurface, that handles the // platform-specific task of binding the transport surface to a GL texture. -// The GL texture is allocated in the SharedResources context, and the data is -// only valid after the first Update(). +// The GL texture is allocated in the ImageTransportFactory context, and the +// data is only valid after the first Update(). class ImageTransportClient : public ui::Texture { public: virtual ~ImageTransportClient() {} @@ -33,7 +34,7 @@ class ImageTransportClient : public ui::Texture { virtual TransportDIB::Handle Handle() const = 0; // Creates a platform-specific client. - static ImageTransportClient* Create(ui::SharedResources* resources, + static ImageTransportClient* Create(ImageTransportFactory* factory, const gfx::Size& size); protected: diff --git a/content/browser/renderer_host/image_transport_factory.cc b/content/browser/renderer_host/image_transport_factory.cc new file mode 100644 index 0000000..59ee6d9 --- /dev/null +++ b/content/browser/renderer_host/image_transport_factory.cc @@ -0,0 +1,349 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/image_transport_factory.h" + +#include <map> + +#include "base/command_line.h" +#include "base/memory/ref_counted.h" +#include "content/browser/gpu/gpu_surface_tracker.h" +#include "content/browser/renderer_host/image_transport_client.h" +#include "content/common/gpu/client/command_buffer_proxy.h" +#include "content/common/gpu/client/gpu_channel_host.h" +#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" +#include "content/public/common/content_switches.h" +#include "ui/gfx/compositor/compositor.h" +#include "ui/gfx/compositor/compositor_setup.h" +#include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/gl/gl_surface.h" +#include "ui/gfx/gl/scoped_make_current.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/size.h" +#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h" + +namespace { + +ImageTransportFactory* g_factory; + +class TestTransportFactory + : public ui::TestContextFactory, + public ImageTransportFactory { + public: + TestTransportFactory() {} + + virtual ui::ContextFactory* AsContextFactory() OVERRIDE { + return this; + } + + virtual gfx::GLSurfaceHandle CreateSharedSurfaceHandle( + ui::Compositor* compositor) OVERRIDE { + return gfx::GLSurfaceHandle(); + } + + virtual void DestroySharedSurfaceHandle( + gfx::GLSurfaceHandle surface) OVERRIDE { + } + + virtual scoped_refptr<ImageTransportClient> CreateTransportClient( + const gfx::Size& size, + uint64* transport_handle) OVERRIDE { + return NULL; + } + + virtual gfx::ScopedMakeCurrent* GetScopedMakeCurrent() OVERRIDE { + return NULL; + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestTransportFactory); +}; + +class DefaultTransportFactory + : public ui::DefaultContextFactory, + public ImageTransportFactory { + public: + DefaultTransportFactory() { + ui::DefaultContextFactory::Initialize(); + } + + virtual ui::ContextFactory* AsContextFactory() OVERRIDE { + return this; + } + + virtual gfx::GLSurfaceHandle CreateSharedSurfaceHandle( + ui::Compositor* compositor) OVERRIDE { + return gfx::GLSurfaceHandle(); + } + + virtual void DestroySharedSurfaceHandle( + gfx::GLSurfaceHandle surface) OVERRIDE { + } + + virtual scoped_refptr<ImageTransportClient> CreateTransportClient( + const gfx::Size& size, + uint64* transport_handle) OVERRIDE { + return NULL; + } + + virtual gfx::ScopedMakeCurrent* GetScopedMakeCurrent() OVERRIDE { + return NULL; + } + + private: + DISALLOW_COPY_AND_ASSIGN(DefaultTransportFactory); +}; + +#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) +class InProcessTransportFactory : public DefaultTransportFactory { + public: + InProcessTransportFactory() { + surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)); + CHECK(surface_.get()) << "Unable to create compositor GL surface."; + + context_ = gfx::GLContext::CreateGLContext( + NULL, surface_.get(), gfx::PreferIntegratedGpu); + CHECK(context_.get()) <<"Unable to create compositor GL context."; + + set_share_group(context_->share_group()); + } + + virtual ~InProcessTransportFactory() {} + + virtual gfx::ScopedMakeCurrent* GetScopedMakeCurrent() OVERRIDE { + return new gfx::ScopedMakeCurrent(context_.get(), surface_.get()); + } + + virtual gfx::GLSurfaceHandle CreateSharedSurfaceHandle( + ui::Compositor* compositor) OVERRIDE { + return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, true); + } + + virtual scoped_refptr<ImageTransportClient> CreateTransportClient( + const gfx::Size& size, + uint64* transport_handle) OVERRIDE { + scoped_refptr<ImageTransportClient> surface( + ImageTransportClient::Create(this, size)); + if (!surface || !surface->Initialize(transport_handle)) { + LOG(ERROR) << "Failed to create ImageTransportClient"; + return NULL; + } + return surface; + } + + private: + scoped_refptr<gfx::GLContext> context_; + scoped_refptr<gfx::GLSurface> surface_; + + DISALLOW_COPY_AND_ASSIGN(InProcessTransportFactory); +}; +#endif + +class ImageTransportClientTexture : public ImageTransportClient { + public: + explicit ImageTransportClientTexture(const gfx::Size& size) + : ImageTransportClient(true, size) { + } + + virtual bool Initialize(uint64* surface_id) OVERRIDE { + set_texture_id(*surface_id); + return true; + } + + virtual ~ImageTransportClientTexture() {} + virtual void Update() OVERRIDE {} + virtual TransportDIB::Handle Handle() const OVERRIDE { + return TransportDIB::DefaultHandleValue(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ImageTransportClientTexture); +}; + +class CompositorSwapClient : public base::SupportsWeakPtr<CompositorSwapClient>, + public WebGraphicsContext3DSwapBuffersClient { + public: + explicit CompositorSwapClient(ui::Compositor* compositor) + : compositor_(compositor) { + } + + ~CompositorSwapClient() { + } + + virtual void OnViewContextSwapBuffersPosted() OVERRIDE { + compositor_->OnSwapBuffersPosted(); + } + + virtual void OnViewContextSwapBuffersComplete() OVERRIDE { + compositor_->OnSwapBuffersComplete(); + } + + virtual void OnViewContextSwapBuffersAborted() OVERRIDE { + compositor_->OnSwapBuffersAborted(); + } + + private: + ui::Compositor* compositor_; + + DISALLOW_COPY_AND_ASSIGN(CompositorSwapClient); +}; + +class GpuProcessTransportFactory : public ui::ContextFactory, + public ImageTransportFactory { + public: + GpuProcessTransportFactory() {} + virtual ~GpuProcessTransportFactory() { + DCHECK(per_compositor_data_.empty()); + } + + virtual WebKit::WebGraphicsContext3D* CreateContext( + ui::Compositor* compositor) OVERRIDE { + PerCompositorData* data = per_compositor_data_[compositor]; + if (!data) + data = CreatePerCompositorData(compositor); + + WebKit::WebGraphicsContext3D::Attributes attrs; + attrs.shareResources = true; + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( + new WebGraphicsContext3DCommandBufferImpl( + data->surface_id, GURL(), data->swap_client->AsWeakPtr())); + if (!context->Initialize(attrs)) + return NULL; + return context.release(); + } + + virtual void RemoveCompositor(ui::Compositor* compositor) OVERRIDE { + PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor); + if (it == per_compositor_data_.end()) + return; + PerCompositorData* data = it->second; + DCHECK(data); + GpuSurfaceTracker::Get()->RemoveSurface(data->surface_id); + delete data; + per_compositor_data_.erase(it); + } + + virtual ui::ContextFactory* AsContextFactory() OVERRIDE { + return this; + } + + virtual gfx::GLSurfaceHandle CreateSharedSurfaceHandle( + ui::Compositor* compositor) OVERRIDE { + PerCompositorData* data = per_compositor_data_[compositor]; + if (!data) + data = CreatePerCompositorData(compositor); + gfx::GLSurfaceHandle handle = gfx::GLSurfaceHandle( + gfx::kNullPluginWindow, true); + ContentGLContext* context = data->shared_context->content_gl_context(); + handle.parent_client_id = context->GetChannelID(); + handle.parent_context_id = context->GetContextID(); + handle.parent_texture_id[0] = data->shared_context->createTexture(); + handle.parent_texture_id[1] = data->shared_context->createTexture(); + data->shared_context->flush(); + + // This handle will not be correct after a GPU process crash / context lost. + // TODO(piman): Fix this. + return handle; + } + + virtual void DestroySharedSurfaceHandle( + gfx::GLSurfaceHandle surface) OVERRIDE { + for (PerCompositorDataMap::iterator it = per_compositor_data_.begin(); + it != per_compositor_data_.end(); ++it) { + PerCompositorData* data = it->second; + DCHECK(data); + ContentGLContext* context = data->shared_context->content_gl_context(); + uint32 client_id = context->GetChannelID(); + uint32 context_id = context->GetContextID(); + if (surface.parent_client_id == client_id && + surface.parent_context_id == context_id) { + data->shared_context->deleteTexture(surface.parent_texture_id[0]); + data->shared_context->deleteTexture(surface.parent_texture_id[1]); + data->shared_context->flush(); + break; + } + } + } + + virtual scoped_refptr<ImageTransportClient> CreateTransportClient( + const gfx::Size& size, + uint64* transport_handle) { + scoped_refptr<ImageTransportClientTexture> image( + new ImageTransportClientTexture(size)); + image->Initialize(transport_handle); + return image; + } + + virtual gfx::ScopedMakeCurrent* GetScopedMakeCurrent() { return NULL; } + + private: + struct PerCompositorData { + int surface_id; + scoped_ptr<CompositorSwapClient> swap_client; + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> shared_context; + }; + + PerCompositorData* CreatePerCompositorData(ui::Compositor* compositor) { + DCHECK(!per_compositor_data_[compositor]); + + gfx::AcceleratedWidget widget = compositor->widget(); + GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get(); + + PerCompositorData* data = new PerCompositorData; + data->surface_id = tracker->AddSurfaceForNativeWidget(widget); + tracker->SetSurfaceHandle( + data->surface_id, + gfx::GLSurfaceHandle(widget, false)); + data->swap_client.reset(new CompositorSwapClient(compositor)); + + WebKit::WebGraphicsContext3D::Attributes attrs; + attrs.shareResources = true; + data->shared_context.reset(new WebGraphicsContext3DCommandBufferImpl( + data->surface_id, GURL(), data->swap_client->AsWeakPtr())); + data->shared_context->Initialize(attrs); + data->shared_context->makeContextCurrent(); + + per_compositor_data_[compositor] = data; + return data; + } + + typedef std::map<ui::Compositor*, PerCompositorData*> PerCompositorDataMap; + PerCompositorDataMap per_compositor_data_; + + DISALLOW_COPY_AND_ASSIGN(GpuProcessTransportFactory); +}; + +} // anonymous namespace + +// static +void ImageTransportFactory::Initialize() { + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kTestCompositor)) { + ui::SetupTestCompositor(); + } + if (ui::IsTestCompositorEnabled()) { + g_factory = new TestTransportFactory(); + } else if (command_line->HasSwitch(switches::kUIUseGPUProcess)) { + g_factory = new GpuProcessTransportFactory(); + } else { +#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) + g_factory = new InProcessTransportFactory(); +#else + g_factory = new DefaultTransportFactory(); +#endif + } + ui::ContextFactory::SetInstance(g_factory->AsContextFactory()); +} + +// static +void ImageTransportFactory::Terminate() { + ui::ContextFactory::SetInstance(NULL); + delete g_factory; + g_factory = NULL; +} + +// static +ImageTransportFactory* ImageTransportFactory::GetInstance() { + return g_factory; +} diff --git a/content/browser/renderer_host/image_transport_factory.h b/content/browser/renderer_host/image_transport_factory.h new file mode 100644 index 0000000..b650a68 --- /dev/null +++ b/content/browser/renderer_host/image_transport_factory.h @@ -0,0 +1,67 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_IMAGE_TRANSPORT_FACTORY_H_ +#define CONTENT_BROWSER_RENDERER_HOST_IMAGE_TRANSPORT_FACTORY_H_ +#pragma once + +#include "base/memory/ref_counted.h" +#include "ui/gfx/native_widget_types.h" + +namespace gfx { +class Size; +class ScopedMakeCurrent; +} + +namespace ui { +class Compositor; +class ContextFactory; +class Texture; +} + +class ImageTransportClient; + +// This class provides the interface for creating the support for the +// cross-process image transport, both for creating the shared surface handle +// (destination surface for the GPU process) and the transport client (logic for +// using that surface as a texture). The factory is a process-wide singleton. +// As this is intimately linked to the type of 3D context we use (in-process or +// command-buffer), implementations of this also implement ui::ContextFactory. +class ImageTransportFactory { + public: + virtual ~ImageTransportFactory() { } + + // Initialize the global transport factory. + static void Initialize(); + + // Terminates the global transport factory. + static void Terminate(); + + // Gets the factory instance. + static ImageTransportFactory* GetInstance(); + + // Gets the image transport factory as a context factory for the compositor. + virtual ui::ContextFactory* AsContextFactory() = 0; + + // Creates a shared surface handle, associated with the compositor. + virtual gfx::GLSurfaceHandle CreateSharedSurfaceHandle( + ui::Compositor* compositor) = 0; + + // Destroys a shared surface handle. + virtual void DestroySharedSurfaceHandle(gfx::GLSurfaceHandle surface) = 0; + + // Creates a transport client of a given size, and using the opaque handle + // sent by the GPU process. + virtual scoped_refptr<ImageTransportClient> CreateTransportClient( + const gfx::Size& size, + uint64* transport_handle) = 0; + + // Returns a ScopedMakeCurrent that can be used to make current a context that + // is shared with the compositor context, e.g. to create a texture in its + // namespace. The caller gets ownership of the object. + // This will return NULL when using out-of-process (command buffer) contexts. + virtual gfx::ScopedMakeCurrent* GetScopedMakeCurrent() = 0; +}; + +#endif // CONTENT_BROWSER_RENDERER_HOST_IMAGE_TRANSPORT_FACTORY_H_ diff --git a/content/browser/renderer_host/render_widget_host_view.h b/content/browser/renderer_host/render_widget_host_view.h index 99a7c91..d5942d1 100644 --- a/content/browser/renderer_host/render_widget_host_view.h +++ b/content/browser/renderer_host/render_widget_host_view.h @@ -349,7 +349,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView { TransportDIB::Handle transport_dib) = 0; #endif -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) +#if defined(USE_AURA) virtual void AcceleratedSurfaceNew( int32 width, int32 height, diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index d7bc0cf..9626243 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -4,8 +4,11 @@ #include "content/browser/renderer_host/render_widget_host_view_aura.h" +#include "base/bind.h" #include "base/logging.h" #include "content/browser/renderer_host/backing_store_skia.h" +#include "content/browser/renderer_host/image_transport_factory.h" +#include "content/browser/renderer_host/image_transport_client.h" #include "content/browser/renderer_host/render_widget_host.h" #include "content/browser/renderer_host/web_input_event_aura.h" #include "content/common/gpu/gpu_messages.h" @@ -25,15 +28,11 @@ #include "ui/base/ui_base_types.h" #include "ui/gfx/canvas.h" #include "ui/gfx/canvas_skia.h" +#include "ui/gfx/compositor/compositor.h" #include "ui/gfx/compositor/layer.h" #include "ui/gfx/screen.h" #include "ui/gfx/skia_util.h" -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) -#include "base/bind.h" -#include "content/browser/renderer_host/image_transport_client.h" -#endif - using WebKit::WebTouchEvent; namespace { @@ -102,12 +101,10 @@ class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver { // Overridden from aura::WindowObserver: virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE { -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) // TODO: It would be better to not use aura::RootWindow here ui::Compositor* compositor = view_->GetCompositor(); if (compositor && compositor->HasObserver(view_)) compositor->RemoveObserver(view_); -#endif } private: @@ -129,9 +126,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host) text_input_type_(ui::TEXT_INPUT_TYPE_NONE), can_compose_inline_(true), has_composition_text_(false), -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) current_surface_(gfx::kNullPluginWindow), -#endif paint_canvas_(NULL), synthetic_move_sent_(false) { host_->SetView(this); @@ -331,6 +326,10 @@ void RenderWidgetHostViewAura::RenderViewGone(base::TerminationStatus status, } void RenderWidgetHostViewAura::Destroy() { + if (!shared_surface_handle_.is_null()) { + ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); + factory->DestroySharedSurfaceHandle(shared_surface_handle_); + } delete window_; } @@ -362,7 +361,6 @@ void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() { } void RenderWidgetHostViewAura::UpdateExternalTexture() { -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) if (current_surface_ != gfx::kNullPluginWindow && host_->is_accelerated_compositing_active()) { ImageTransportClient* container = @@ -373,13 +371,11 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() { } else { window_->SetExternalTexture(NULL); } -#endif } void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped( const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, int gpu_host_id) { -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) current_surface_ = params.surface_handle; UpdateExternalTexture(); @@ -400,15 +396,11 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped( if (!compositor->HasObserver(this)) compositor->AddObserver(this); } -#else - NOTREACHED(); -#endif } void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, int gpu_host_id) { -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) current_surface_ = params.surface_handle; UpdateExternalTexture(); @@ -436,25 +428,20 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( if (!compositor->HasObserver(this)) compositor->AddObserver(this); } -#else - NOTREACHED(); -#endif } void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() { } -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) void RenderWidgetHostViewAura::AcceleratedSurfaceNew( int32 width, int32 height, uint64* surface_handle, TransportDIB::Handle* shm_handle) { - ui::SharedResources* instance = ui::SharedResources::GetInstance(); - DCHECK(instance); - scoped_refptr<ImageTransportClient> surface( - ImageTransportClient::Create(instance, gfx::Size(width, height))); - if (!surface || !surface->Initialize(surface_handle)) { + ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); + scoped_refptr<ImageTransportClient> surface(factory->CreateTransportClient( + gfx::Size(width, height), surface_handle)); + if (!surface) { LOG(ERROR) << "Failed to create ImageTransportClient"; return; } @@ -474,14 +461,11 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceRelease( } image_transport_clients_.erase(surface_handle); } -#endif void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) { RenderWidgetHostViewBase::SetBackground(background); host_->SetBackground(background); -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) window_->layer()->SetFillsBoundsOpaquely(background.isOpaque()); -#endif } void RenderWidgetHostViewAura::GetScreenInfo(WebKit::WebScreenInfo* results) { @@ -519,20 +503,14 @@ void RenderWidgetHostViewAura::SetScrollOffsetPinning( // Not needed. Mac-only. } -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) -gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() { - return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, true); -} -#else gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() { - // TODO(oshima): The original implementation was broken as - // GtkNativeViewManager doesn't know about NativeWidgetGtk. Figure - // out if this makes sense without compositor. If it does, then find - // out the right way to handle. - NOTIMPLEMENTED(); - return gfx::GLSurfaceHandle(); + ui::Compositor* compositor = GetCompositor(); + if (shared_surface_handle_.is_null() && compositor) { + ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); + shared_surface_handle_ = factory->CreateSharedSurfaceHandle(compositor); + } + return shared_surface_handle_; } -#endif bool RenderWidgetHostViewAura::LockMouse() { aura::RootWindow* root_window = window_->GetRootWindow(); diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index aea4688..88de55a 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -8,6 +8,8 @@ #include <map> +#include "base/callback.h" +#include "base/memory/ref_counted.h" #include "content/browser/renderer_host/render_widget_host_view.h" #include "content/common/content_export.h" #include "ui/aura/client/activation_delegate.h" @@ -17,11 +19,6 @@ #include "ui/gfx/compositor/compositor_observer.h" #include "webkit/glue/webcursor.h" -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#endif - namespace gfx { class Canvas; } @@ -34,15 +31,11 @@ namespace WebKit { class WebTouchEvent; } -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) class ImageTransportClient; -#endif class RenderWidgetHostViewAura : public RenderWidgetHostViewBase, -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) public ui::CompositorObserver, -#endif public ui::TextInputClient, public aura::WindowDelegate, public aura::client::ActivationDelegate { @@ -100,14 +93,12 @@ class RenderWidgetHostViewAura const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, int gpu_host_id) OVERRIDE; virtual void AcceleratedSurfaceSuspend() OVERRIDE; -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) virtual void AcceleratedSurfaceNew( int32 width, int32 height, uint64* surface_id, TransportDIB::Handle* surface_handle) OVERRIDE; virtual void AcceleratedSurfaceRelease(uint64 surface_id) OVERRIDE; -#endif virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE; virtual gfx::Rect GetRootWindowBounds() OVERRIDE; virtual void ProcessTouchAck(bool processed) OVERRIDE; @@ -175,10 +166,8 @@ class RenderWidgetHostViewAura class WindowObserver; friend class WindowObserver; -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) // Overridden from ui::CompositorObserver: virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE; -#endif void UpdateCursorIfOverSelf(); void UpdateExternalTexture(); @@ -246,14 +235,14 @@ class RenderWidgetHostViewAura // Current tooltip text. string16 tooltip_; -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) std::vector< base::Callback<void(void)> > on_compositing_ended_callbacks_; std::map<uint64, scoped_refptr<ImageTransportClient> > image_transport_clients_; gfx::PluginWindowHandle current_surface_; -#endif + + gfx::GLSurfaceHandle shared_surface_handle_; // If non-NULL we're in OnPaint() and this is the supplied canvas. gfx::Canvas* paint_canvas_; diff --git a/content/common/gpu/client/command_buffer_proxy.h b/content/common/gpu/client/command_buffer_proxy.h index 398f794..994d4e1 100644 --- a/content/common/gpu/client/command_buffer_proxy.h +++ b/content/common/gpu/client/command_buffer_proxy.h @@ -103,6 +103,8 @@ class CommandBufferProxy : public gpu::CommandBuffer, void SetOnConsoleMessageCallback(const GpuConsoleMessageCallback& callback); + GpuChannelHost* channel() const { return channel_; } + private: // Send an IPC message over the GPU channel. This is private to fully // encapsulate the channel; all callers of this function must explicitly diff --git a/content/common/gpu/client/content_gl_context.cc b/content/common/gpu/client/content_gl_context.cc index 86a89f5..f184293 100644 --- a/content/common/gpu/client/content_gl_context.cc +++ b/content/common/gpu/client/content_gl_context.cc @@ -263,6 +263,14 @@ CommandBufferProxy* ContentGLContext::GetCommandBufferProxy() { return command_buffer_; } +int ContentGLContext::GetChannelID() { + return channel_->client_id(); +} + +int ContentGLContext::GetContextID() { + return command_buffer_->route_id(); +} + bool ContentGLContext::SetSurfaceVisible(bool visible) { return GetCommandBufferProxy()->SetSurfaceVisible(visible); } diff --git a/content/common/gpu/client/content_gl_context.h b/content/common/gpu/client/content_gl_context.h index e704aa1..95a6cf8 100644 --- a/content/common/gpu/client/content_gl_context.h +++ b/content/common/gpu/client/content_gl_context.h @@ -177,6 +177,12 @@ class ContentGLContext : public base::SupportsWeakPtr<ContentGLContext>, CommandBufferProxy* GetCommandBufferProxy(); + // The following 2 IDs let one uniquely identify this context. + // Gets the channel ID for this context. + int GetChannelID(); + // Gets the context ID (relative to the channel). + int GetContextID(); + private: explicit ContentGLContext(GpuChannelHost* channel); diff --git a/content/common/gpu/client/gpu_channel_host.cc b/content/common/gpu/client/gpu_channel_host.cc index 16fee44..19e1500 100644 --- a/content/common/gpu/client/gpu_channel_host.cc +++ b/content/common/gpu/client/gpu_channel_host.cc @@ -99,8 +99,9 @@ void GpuChannelHost::MessageFilter::OnChannelError() { base::Bind(&GpuChannelHost::OnChannelError, parent_)); } -GpuChannelHost::GpuChannelHost(GpuChannelHostFactory* factory) +GpuChannelHost::GpuChannelHost(GpuChannelHostFactory* factory, int client_id) : factory_(factory), + client_id_(client_id), state_(kUnconnected) { } diff --git a/content/common/gpu/client/gpu_channel_host.h b/content/common/gpu/client/gpu_channel_host.h index 38d0403..888451b 100644 --- a/content/common/gpu/client/gpu_channel_host.h +++ b/content/common/gpu/client/gpu_channel_host.h @@ -90,7 +90,7 @@ class GpuChannelHost : public IPC::Message::Sender, }; // Called on the render thread - explicit GpuChannelHost(GpuChannelHostFactory* factory); + GpuChannelHost(GpuChannelHostFactory* factory, int client_id); virtual ~GpuChannelHost(); // Connect to GPU process channel. @@ -158,6 +158,7 @@ class GpuChannelHost : public IPC::Message::Sender, void ForciblyCloseChannel(); GpuChannelHostFactory* factory() const { return factory_; } + int client_id() const { return client_id_; } private: // A filter used internally to route incoming messages from the IO thread @@ -184,6 +185,7 @@ class GpuChannelHost : public IPC::Message::Sender, }; GpuChannelHostFactory* factory_; + int client_id_; State state_; diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h index 2eda115..c11e6b7 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h @@ -478,6 +478,8 @@ class WebGraphicsContext3DCommandBufferImpl WGC3Denum target, WGC3Dint levels, WGC3Duint internalformat, WGC3Dint width, WGC3Dint height); + ContentGLContext* content_gl_context() const { return context_; } + protected: #if WEBKIT_USING_SKIA virtual GrGLInterface* onCreateGrGLInterface(); diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index c33b60e..338e4ae 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -195,8 +195,9 @@ IPC_MESSAGE_CONTROL0(GpuMsg_Hang) // A renderer sends this when it wants to create a connection to the GPU // process. The browser will create the GPU process if necessary, and will // return a handle to the channel via a GpuChannelEstablished message. -IPC_SYNC_MESSAGE_CONTROL1_3(GpuHostMsg_EstablishGpuChannel, +IPC_SYNC_MESSAGE_CONTROL1_4(GpuHostMsg_EstablishGpuChannel, content::CauseForGpuLaunch, + int /* client id */, IPC::ChannelHandle /* handle to channel */, base::ProcessHandle /* renderer_process_for_gpu */, content::GPUInfo /* stats about GPU process*/) diff --git a/content/content_browser.gypi b/content/content_browser.gypi index d792939..dd09dd1 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -454,6 +454,8 @@ 'browser/renderer_host/gtk_window_utils.h', 'browser/renderer_host/image_transport_client.cc', 'browser/renderer_host/image_transport_client.h', + 'browser/renderer_host/image_transport_factory.cc', + 'browser/renderer_host/image_transport_factory.h', 'browser/renderer_host/java/java_bound_object.cc', 'browser/renderer_host/java/java_bound_object.h', 'browser/renderer_host/java/java_bridge_channel_host.cc', @@ -816,6 +818,8 @@ ], }, { 'sources/': [ + ['exclude', '^browser/renderer_host/image_transport_factory.cc'], + ['exclude', '^browser/renderer_host/image_transport_factory.h'], ['exclude', '^browser/renderer_host/render_widget_host_view_aura.cc'], ['exclude', '^browser/renderer_host/render_widget_host_view_aura.h'], ], diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 708fdd6..1e28e57 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc @@ -556,6 +556,9 @@ const char kTraceStartupFile[] = "trace-startup-file"; // --startup-trace-file=none was supplied. const char kTraceStartupDuration[] = "trace-startup-duration"; +// Enables the use of the GPU process for UI. Only meaningful for Aura. +const char kUIUseGPUProcess[] = "ui-use-gpu-process"; + // A string used to override the default user agent with a custom one. const char kUserAgent[] = "user-agent"; @@ -621,4 +624,9 @@ const char kEnablePerTilePainting[] = "enable-per-tile-painting"; // Disables the use of a 3D software rasterizer. const char kDisableSoftwareRasterizer[] = "disable-software-rasterizer"; +#if defined(USE_AURA) +// Forces usage of the test compositor. Needed to run ui tests on bots. +extern const char kTestCompositor[] = "test-compositor"; +#endif + } // namespace switches diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 1c05a199..7f56348 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h @@ -165,6 +165,7 @@ extern const char kTouchOptimizedUI[]; extern const char kTraceStartup[]; extern const char kTraceStartupFile[]; extern const char kTraceStartupDuration[]; +extern const char kUIUseGPUProcess[]; CONTENT_EXPORT extern const char kUserAgent[]; extern const char kUtilityCmdPrefix[]; CONTENT_EXPORT extern const char kUtilityProcess[]; @@ -194,6 +195,10 @@ CONTENT_EXPORT extern const char kRendererCheckFalseTest[]; extern const char kEnablePerTilePainting[]; +#if defined(USE_AURA) +CONTENT_EXPORT extern const char kTestCompositor[]; +#endif + } // namespace switches #endif // CONTENT_PUBLIC_COMMON_CONTENT_SWITCHES_H_ diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index bb50ee5..ee709ee 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -853,18 +853,16 @@ GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync( return GetGpuChannel(); // Recreate the channel if it has been lost. - if (gpu_channel_->state() == GpuChannelHost::kLost) - gpu_channel_ = NULL; + gpu_channel_ = NULL; } - if (!gpu_channel_.get()) - gpu_channel_ = new GpuChannelHost(this); - // Ask the browser for the channel name. + int client_id = 0; IPC::ChannelHandle channel_handle; base::ProcessHandle renderer_process_for_gpu; content::GPUInfo gpu_info; if (!Send(new GpuHostMsg_EstablishGpuChannel(cause_for_gpu_launch, + &client_id, &channel_handle, &renderer_process_for_gpu, &gpu_info)) || @@ -878,6 +876,7 @@ GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync( return NULL; } + gpu_channel_ = new GpuChannelHost(this, client_id); gpu_channel_->set_gpu_info(gpu_info); content::GetContentClient()->SetGpuInfo(gpu_info); diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 5182e4c..4428c53 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -132,6 +132,11 @@ void RootWindow::Run() { } void RootWindow::Draw() { + if (waiting_on_compositing_end_) { + draw_on_compositing_end_ = true; + return; + } + waiting_on_compositing_end_ = true; compositor_->Draw(false); } @@ -449,6 +454,17 @@ void RootWindow::ScheduleDraw() { } //////////////////////////////////////////////////////////////////////////////// +// RootWindow, ui::CompositorObserver implementation: + +void RootWindow::OnCompositingEnded(ui::Compositor*) { + waiting_on_compositing_end_ = false; + if (draw_on_compositing_end_) { + draw_on_compositing_end_ = false; + Draw(); + } +} + +//////////////////////////////////////////////////////////////////////////////// // RootWindow, private: RootWindow::RootWindow() @@ -467,7 +483,9 @@ RootWindow::RootWindow() touch_event_handler_(NULL), gesture_handler_(NULL), gesture_recognizer_(GestureRecognizer::Create()), - synthesize_mouse_move_(false) { + synthesize_mouse_move_(false), + waiting_on_compositing_end_(false), + draw_on_compositing_end_(false) { SetName("RootWindow"); gfx::Screen::SetInstance(screen_); last_mouse_location_ = host_->QueryMouseLocation(); @@ -476,9 +494,11 @@ RootWindow::RootWindow() compositor_.reset(new ui::Compositor(this, host_->GetAcceleratedWidget(), host_->GetSize())); DCHECK(compositor_.get()); + compositor_->AddObserver(this); } RootWindow::~RootWindow() { + compositor_->RemoveObserver(this); // Make sure to destroy the compositor before terminating so that state is // cleared and we don't hit asserts. compositor_.reset(); diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index 7396059..207896a 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -17,6 +17,7 @@ #include "ui/aura/window.h" #include "ui/base/events.h" #include "ui/gfx/compositor/compositor.h" +#include "ui/gfx/compositor/compositor_observer.h" #include "ui/gfx/compositor/layer_animation_observer.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/point.h" @@ -44,6 +45,7 @@ class GestureEvent; // RootWindow is responsible for hosting a set of windows. class AURA_EXPORT RootWindow : public ui::CompositorDelegate, + public ui::CompositorObserver, public Window, public internal::FocusManager, public ui::LayerAnimationObserver { @@ -203,6 +205,9 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // Overridden from ui::CompositorDelegate: virtual void ScheduleDraw() OVERRIDE; + // Overridden from ui::CompositorObserver: + virtual void OnCompositingEnded(ui::Compositor*) OVERRIDE; + private: friend class Window; @@ -312,6 +317,8 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, scoped_ptr<GestureRecognizer> gesture_recognizer_; bool synthesize_mouse_move_; + bool waiting_on_compositing_end_; + bool draw_on_compositing_end_; DISALLOW_COPY_AND_ASSIGN(RootWindow); }; diff --git a/ui/gfx/compositor/compositor.cc b/ui/gfx/compositor/compositor.cc index 9d290e2..8c8f2ee 100644 --- a/ui/gfx/compositor/compositor.cc +++ b/ui/gfx/compositor/compositor.cc @@ -5,6 +5,7 @@ #include "ui/gfx/compositor/compositor.h" #include "base/command_line.h" +#include "base/threading/thread_restrictions.h" #include "third_party/skia/include/images/SkImageEncoder.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositor.h" @@ -18,7 +19,6 @@ #include "ui/gfx/gl/gl_context.h" #include "ui/gfx/gl/gl_surface.h" #include "ui/gfx/gl/gl_implementation.h" -#include "ui/gfx/gl/scoped_make_current.h" #include "webkit/glue/webthread_impl.h" #include "webkit/gpu/webgraphicscontext3d_in_process_impl.h" @@ -31,82 +31,90 @@ webkit_glue::WebThreadImpl* g_compositor_thread = NULL; bool test_compositor_enabled = false; +ui::ContextFactory* g_context_factory = NULL; + } // anonymous namespace namespace ui { -SharedResources::SharedResources() : initialized_(false) { +// static +ContextFactory* ContextFactory::GetInstance() { + // We leak the shared resources so that we don't race with + // the tear down of the gl_bindings. + if (!g_context_factory) { + if (test_compositor_enabled) { + VLOG(1) << "Using TestSharedResource"; + g_context_factory = new TestContextFactory(); + } else { + VLOG(1) << "Using DefaultSharedResource"; + scoped_ptr<DefaultContextFactory> instance( + new DefaultContextFactory()); + if (instance->Initialize()) + g_context_factory = instance.release(); + } + } + return g_context_factory; } +// static +void ContextFactory::SetInstance(ContextFactory* instance) { + DCHECK(!g_context_factory); + g_context_factory = instance; +} -SharedResources::~SharedResources() { +TestContextFactory::TestContextFactory() { } -// static -SharedResources* SharedResources::GetInstance() { - // We use LeakySingletonTraits so that we don't race with - // the tear down of the gl_bindings. - SharedResources* instance = Singleton<SharedResources, - LeakySingletonTraits<SharedResources> >::get(); - if (instance->Initialize()) { - return instance; - } else { - instance->Destroy(); - return NULL; - } +TestContextFactory::~TestContextFactory() { } -bool SharedResources::Initialize() { - if (initialized_) - return true; +WebKit::WebGraphicsContext3D* TestContextFactory::CreateContext( + ui::Compositor* compositor) { + ui::TestWebGraphicsContext3D* test_context = + new ui::TestWebGraphicsContext3D(); + test_context->Initialize(); + return test_context; +} +void TestContextFactory::RemoveCompositor(ui::Compositor* compositor) { +} - { - // The following line of code exists soley to disable IO restrictions - // on this thread long enough to perform the GL bindings. - // TODO(wjmaclean) Remove this when GL initialisation cleaned up. - base::ThreadRestrictions::ScopedAllowIO allow_io; - if (!gfx::GLSurface::InitializeOneOff() || - gfx::GetGLImplementation() == gfx::kGLImplementationNone) { - LOG(ERROR) << "Could not load the GL bindings"; - return false; - } - } +DefaultContextFactory::DefaultContextFactory() { +} - surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)); - if (!surface_.get()) { - LOG(ERROR) << "Unable to create offscreen GL surface."; - return false; - } +DefaultContextFactory::~DefaultContextFactory() { +} - context_ = gfx::GLContext::CreateGLContext( - NULL, surface_.get(), gfx::PreferIntegratedGpu); - if (!context_.get()) { - LOG(ERROR) << "Unable to create GL context."; +bool DefaultContextFactory::Initialize() { + // The following line of code exists soley to disable IO restrictions + // on this thread long enough to perform the GL bindings. + // TODO(wjmaclean) Remove this when GL initialisation cleaned up. + base::ThreadRestrictions::ScopedAllowIO allow_io; + if (!gfx::GLSurface::InitializeOneOff() || + gfx::GetGLImplementation() == gfx::kGLImplementationNone) { + LOG(ERROR) << "Could not load the GL bindings"; return false; } - - initialized_ = true; return true; } -void SharedResources::Destroy() { - context_ = NULL; - surface_ = NULL; - - initialized_ = false; -} - -gfx::ScopedMakeCurrent* SharedResources::GetScopedMakeCurrent() { - DCHECK(initialized_); - if (initialized_) - return new gfx::ScopedMakeCurrent(context_.get(), surface_.get()); - else - return NULL; +WebKit::WebGraphicsContext3D* DefaultContextFactory::CreateContext( + Compositor* compositor) { + WebKit::WebGraphicsContext3D::Attributes attrs; + attrs.shareResources = true; + WebKit::WebGraphicsContext3D* context = + webkit::gpu::WebGraphicsContext3DInProcessImpl::CreateForWindow( + attrs, compositor->widget(), share_group_.get()); + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(switches::kDisableUIVsync)) { + context->makeContextCurrent(); + gfx::GLContext* gl_context = gfx::GLContext::GetCurrent(); + gl_context->SetSwapInterval(1); + gl_context->ReleaseCurrent(NULL); + } + return context; } -gfx::GLShareGroup* SharedResources::GetShareGroup() { - DCHECK(initialized_); - return context_->share_group(); +void DefaultContextFactory::RemoveCompositor(Compositor* compositor) { } Texture::Texture(bool flipped, const gfx::Size& size) @@ -125,7 +133,8 @@ Compositor::Compositor(CompositorDelegate* delegate, size_(size), root_layer_(NULL), widget_(widget), - root_web_layer_(WebKit::WebLayer::create()) { + root_web_layer_(WebKit::WebLayer::create()), + swap_posted_(false) { WebKit::WebLayerTreeView::Settings settings; CommandLine* command_line = CommandLine::ForCurrentProcess(); settings.showFPSCounter = @@ -153,6 +162,7 @@ Compositor::~Compositor() { host_.setRootLayer(NULL); if (root_layer_) root_layer_->SetCompositor(NULL); + ContextFactory::GetInstance()->RemoveCompositor(this); } void Compositor::Initialize(bool use_thread) { @@ -194,7 +204,7 @@ void Compositor::Draw(bool force_clear) { return; host_.composite(); - if (!g_compositor_thread) + if (!g_compositor_thread && !swap_posted_) NotifyEnd(); } @@ -242,6 +252,22 @@ bool Compositor::HasObserver(CompositorObserver* observer) { return observer_list_.HasObserver(observer); } +void Compositor::OnSwapBuffersPosted() { + swap_posted_ = true; +} + +void Compositor::OnSwapBuffersComplete() { + DCHECK(swap_posted_); + swap_posted_ = false; + NotifyEnd(); +} + +void Compositor::OnSwapBuffersAborted() { + if (swap_posted_) { + swap_posted_ = false; + NotifyEnd(); + } +} void Compositor::updateAnimations(double frameBeginTime) { } @@ -254,29 +280,7 @@ void Compositor::applyScrollAndScale(const WebKit::WebSize& scrollDelta, } WebKit::WebGraphicsContext3D* Compositor::createContext3D() { - WebKit::WebGraphicsContext3D* context; - if (test_compositor_enabled) { - // Use context that results in no rendering to the screen. - TestWebGraphicsContext3D* test_context = new TestWebGraphicsContext3D(); - test_context->Initialize(); - context = test_context; - } else { - gfx::GLShareGroup* share_group = - SharedResources::GetInstance()->GetShareGroup(); - WebKit::WebGraphicsContext3D::Attributes attrs; - context = webkit::gpu::WebGraphicsContext3DInProcessImpl::CreateForWindow( - attrs, widget_, share_group); - } - - CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (!command_line->HasSwitch(switches::kDisableUIVsync)) { - context->makeContextCurrent(); - gfx::GLContext* gl_context = gfx::GLContext::GetCurrent(); - gl_context->SetSwapInterval(1); - gl_context->ReleaseCurrent(NULL); - } - - return context; + return ContextFactory::GetInstance()->CreateContext(this); } void Compositor::didCompleteSwapBuffers() { @@ -328,6 +332,14 @@ COMPOSITOR_EXPORT void SetupTestCompositor() { COMPOSITOR_EXPORT void DisableTestCompositor() { test_compositor_enabled = false; + if (g_context_factory) { + delete g_context_factory; + g_context_factory = NULL; + } +} + +COMPOSITOR_EXPORT bool IsTestCompositorEnabled() { + return test_compositor_enabled; } } // namespace ui diff --git a/ui/gfx/compositor/compositor.h b/ui/gfx/compositor/compositor.h index 04fcddf..ebbc3ad 100644 --- a/ui/gfx/compositor/compositor.h +++ b/ui/gfx/compositor/compositor.h @@ -6,59 +6,94 @@ #define UI_GFX_COMPOSITOR_COMPOSITOR_H_ #pragma once +#include "base/hash_tables.h" #include "base/memory/ref_counted.h" -#include "base/memory/singleton.h" #include "base/observer_list.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebLayer.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebLayerTreeView.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebLayerTreeViewClient.h" #include "ui/gfx/compositor/compositor_export.h" -#include "ui/gfx/transform.h" +#include "ui/gfx/gl/gl_share_group.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/size.h" +#include "ui/gfx/transform.h" class SkBitmap; -class SkCanvas; namespace gfx { class GLContext; class GLSurface; class GLShareGroup; class Point; class Rect; -class ScopedMakeCurrent; } namespace ui { +class Compositor; class CompositorObserver; class Layer; -class COMPOSITOR_EXPORT SharedResources { +// This class abstracts the creation of the 3D context for the compositor. It is +// a global object. +class COMPOSITOR_EXPORT ContextFactory { public: - static SharedResources* GetInstance(); + virtual ~ContextFactory() { } + + // Gets the global instance. + static ContextFactory* GetInstance(); - // Creates an instance of ScopedMakeCurrent. - // Note: Caller is responsible for managing lifetime of returned pointer. - gfx::ScopedMakeCurrent* GetScopedMakeCurrent(); + // Sets the global instance. Caller keeps ownership. + // If this function isn't called (for tests), a "default" factory will be + // created on the first call of GetInstance. + static void SetInstance(ContextFactory* instance); - gfx::GLShareGroup* GetShareGroup(); + // Creates a context for given compositor. The factory may keep per-compositor + // data (e.g. a shared context), that needs to be cleaned up by calling + // RemoveCompositor when the compositor gets destroyed. + virtual WebKit::WebGraphicsContext3D* CreateContext( + Compositor* compositor) = 0; + + // Destroys per-compositor data. + virtual void RemoveCompositor(Compositor* compositor) = 0; +}; + +// A factory that creates test contexts (that don't draw anything). +class TestContextFactory : public ui::ContextFactory { + public: + TestContextFactory(); + virtual ~TestContextFactory(); + + // ContextFactory implementation + virtual WebKit::WebGraphicsContext3D* CreateContext( + ui::Compositor* compositor) OVERRIDE; + virtual void RemoveCompositor(ui::Compositor* compositor) OVERRIDE; private: - friend struct DefaultSingletonTraits<SharedResources>; + DISALLOW_COPY_AND_ASSIGN(TestContextFactory); +}; + +// The default factory that creates in-process contexts. +class COMPOSITOR_EXPORT DefaultContextFactory : public ContextFactory { + public: + DefaultContextFactory(); + virtual ~DefaultContextFactory(); - SharedResources(); - ~SharedResources(); + // ContextFactory implementation + virtual WebKit::WebGraphicsContext3D* CreateContext( + Compositor* compositor) OVERRIDE; + virtual void RemoveCompositor(Compositor* compositor) OVERRIDE; bool Initialize(); - void Destroy(); - bool initialized_; + void set_share_group(gfx::GLShareGroup* share_group) { + share_group_ = share_group; + } - scoped_refptr<gfx::GLContext> context_; - scoped_refptr<gfx::GLSurface> surface_; + private: + scoped_refptr<gfx::GLShareGroup> share_group_; - DISALLOW_COPY_AND_ASSIGN(SharedResources); + DISALLOW_COPY_AND_ASSIGN(DefaultContextFactory); }; // Texture provide an abstraction over the external texture that can be passed @@ -69,15 +104,15 @@ class COMPOSITOR_EXPORT Texture : public base::RefCounted<Texture> { virtual ~Texture(); unsigned int texture_id() const { return texture_id_; } + void set_texture_id(unsigned int id) { texture_id_ = id; } bool flipped() const { return flipped_; } gfx::Size size() const { return size_; } - protected: + private: unsigned int texture_id_; bool flipped_; gfx::Size size_; - private: DISALLOW_COPY_AND_ASSIGN(Texture); }; @@ -139,7 +174,10 @@ class COMPOSITOR_EXPORT Compositor void WidgetSizeChanged(const gfx::Size& size); // Returns the size of the widget that is being drawn to. - const gfx::Size& size() { return size_; } + const gfx::Size& size() const { return size_; } + + // Returns the widget for this compositor. + gfx::AcceleratedWidget widget() const { return widget_; } // Compositor does not own observers. It is the responsibility of the // observer to remove itself when it is done observing. @@ -147,6 +185,18 @@ class COMPOSITOR_EXPORT Compositor void RemoveObserver(CompositorObserver* observer); bool HasObserver(CompositorObserver* observer); + // Internal functions, called back by command-buffer contexts on swap buffer + // events. + + // Signals swap has been posted. + void OnSwapBuffersPosted(); + + // Signals swap has completed. + void OnSwapBuffersComplete(); + + // Signals swap has aborted (e.g. lost context). + void OnSwapBuffersAborted(); + // WebLayerTreeViewClient implementation. virtual void updateAnimations(double frameBeginTime); virtual void layout(); @@ -178,6 +228,10 @@ class COMPOSITOR_EXPORT Compositor WebKit::WebLayer root_web_layer_; WebKit::WebLayerTreeView host_; + // This is set to true when the swap buffers has been posted and we're waiting + // for completion. + bool swap_posted_; + friend class base::RefCounted<Compositor>; }; diff --git a/ui/gfx/compositor/compositor_observer.h b/ui/gfx/compositor/compositor_observer.h index 5012f0c..0025799 100644 --- a/ui/gfx/compositor/compositor_observer.h +++ b/ui/gfx/compositor/compositor_observer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,12 +6,14 @@ #define UI_GFX_COMPOSITOR_COMPOSITOR_OBSERVER_H_ #pragma once +#include "ui/gfx/compositor/compositor_export.h" + namespace ui { class Compositor; // A compositor observer is notified when compositing completes. -class CompositorObserver { +class COMPOSITOR_EXPORT CompositorObserver { public: // Called when compositing completes. virtual void OnCompositingEnded(Compositor* compositor) = 0; diff --git a/ui/gfx/compositor/compositor_setup.h b/ui/gfx/compositor/compositor_setup.h index 9978e7f..1f59d86 100644 --- a/ui/gfx/compositor/compositor_setup.h +++ b/ui/gfx/compositor/compositor_setup.h @@ -22,6 +22,7 @@ COMPOSITOR_EXPORT void SetupTestCompositor(); // Disables the test compositor so that the normal compositor is used. COMPOSITOR_EXPORT void DisableTestCompositor(); +COMPOSITOR_EXPORT bool IsTestCompositorEnabled(); #endif } // namespace ui diff --git a/ui/gfx/compositor/layer.h b/ui/gfx/compositor/layer.h index ee2b429..f7b6e3d 100644 --- a/ui/gfx/compositor/layer.h +++ b/ui/gfx/compositor/layer.h @@ -171,8 +171,6 @@ class COMPOSITOR_EXPORT Layer : // Assigns a new external texture. |texture| can be NULL to disable external // updates. - // TODO(beng): This can be removed from the API when we are in a - // single-compositor world. void SetExternalTexture(ui::Texture* texture); // Sets the layer's fill color. May only be called for LAYER_SOLID_COLOR. |