diff options
23 files changed, 212 insertions, 482 deletions
diff --git a/ash/wm/window_animations.cc b/ash/wm/window_animations.cc index 28a2480..8faaef5 100644 --- a/ash/wm/window_animations.cc +++ b/ash/wm/window_animations.cc @@ -566,6 +566,8 @@ class CrossFadeObserver : public ui::CompositorObserver, } // ui::CompositorObserver overrides: + virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE { + } virtual void OnCompositingWillStart(ui::Compositor* compositor) OVERRIDE { } virtual void OnCompositingStarted(ui::Compositor* compositor) OVERRIDE { diff --git a/chrome/test/gpu/gpu_feature_browsertest.cc b/chrome/test/gpu/gpu_feature_browsertest.cc index 0cace7a..1823786 100644 --- a/chrome/test/gpu/gpu_feature_browsertest.cc +++ b/chrome/test/gpu/gpu_feature_browsertest.cc @@ -22,6 +22,7 @@ #include "content/test/gpu/test_switches.h" #include "net/base/net_util.h" #include "ui/gl/gl_switches.h" +#include "ui/compositor/compositor_setup.h" #if defined(OS_MACOSX) #include "ui/surface/io_surface_support_mac.h" #endif @@ -66,6 +67,7 @@ class GpuFeatureTest : public InProcessBrowserTest { gpu_enabled_ = true; } command_line->AppendSwitch(switches::kDisablePopupBlocking); + ui::DisableTestCompositor(); command_line->AppendSwitchASCII(switches::kWindowSize, "400,300"); } diff --git a/content/browser/renderer_host/image_transport_client.cc b/content/browser/renderer_host/image_transport_client.cc deleted file mode 100644 index dcbc05b..0000000 --- a/content/browser/renderer_host/image_transport_client.cc +++ /dev/null @@ -1,9 +0,0 @@ -// 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_client.h" - -ImageTransportClient::ImageTransportClient(bool flipped, const gfx::Size& size) - : ui::Texture(flipped, size) { -} diff --git a/content/browser/renderer_host/image_transport_client.h b/content/browser/renderer_host/image_transport_client.h deleted file mode 100644 index e73d5fd..0000000 --- a/content/browser/renderer_host/image_transport_client.h +++ /dev/null @@ -1,46 +0,0 @@ -// 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_CLIENT_H_ -#define CONTENT_BROWSER_RENDERER_HOST_IMAGE_TRANSPORT_CLIENT_H_ - -#include "base/basictypes.h" -#include "ui/compositor/compositor.h" -#include "ui/surface/transport_dib.h" - -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 ImageTransportFactory context, and the -// data is only valid after the first Update(). -class ImageTransportClient : public ui::Texture { - public: - // Initializes the client with the surface id. - virtual bool Initialize(uint64* surface_handle) = 0; - - // Updates the surface data into the texture. - virtual void Update() = 0; - - // Returns the shared memory handle used to transfer software data if needed. - // Can be a NULL handle. - virtual TransportDIB::Handle Handle() const = 0; - - // Creates a platform-specific client. - static ImageTransportClient* Create(ImageTransportFactory* factory, - const gfx::Size& size); - - protected: - ImageTransportClient(bool flipped, const gfx::Size& size); - virtual ~ImageTransportClient() {} - - private: - DISALLOW_COPY_AND_ASSIGN(ImageTransportClient); -}; - -#endif // CONTENT_BROWSER_RENDERER_HOST_IMAGE_TRANSPORT_CLIENT_H_ - diff --git a/content/browser/renderer_host/image_transport_client_linux.cc b/content/browser/renderer_host/image_transport_client_linux.cc deleted file mode 100644 index dd6aeb9..0000000 --- a/content/browser/renderer_host/image_transport_client_linux.cc +++ /dev/null @@ -1,311 +0,0 @@ -// 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_client.h" - -#include <X11/Xlib.h> -#include <X11/extensions/Xcomposite.h> - -#include "base/debug/trace_event.h" -#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/size.h" -#include "ui/gl/gl_bindings.h" -#include "ui/gl/gl_implementation.h" -#include "ui/gl/gl_surface_egl.h" -#include "ui/gl/gl_surface_glx.h" -#include "ui/gl/scoped_make_current.h" - -namespace { - -class ScopedPtrXFree { - public: - void operator()(void* x) const { - ::XFree(x); - } -}; - -GLuint CreateTexture() { - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - return texture; -} - -class ImageTransportClientEGL : public ImageTransportClient { - public: - ImageTransportClientEGL(ImageTransportFactory* factory, const gfx::Size& size) - : ImageTransportClient(true, size), - factory_(factory), - image_(NULL) { - } - - virtual bool Initialize(uint64* surface_handle) OVERRIDE { - 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; - set_texture_id(CreateTexture()); - glBindTexture(GL_TEXTURE_2D, texture_id()); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_); - glFlush(); - return true; - } - - virtual void Update() OVERRIDE {} - virtual TransportDIB::Handle Handle() const OVERRIDE { - return TransportDIB::DefaultHandleValue(); - } - - protected: - virtual ~ImageTransportClientEGL() { - scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent()); - if (image_) - eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), image_); - unsigned int texture = texture_id(); - if (texture) - glDeleteTextures(1, &texture); - glFlush(); - } - - private: - ImageTransportFactory* factory_; - EGLImageKHR image_; -}; - -class ImageTransportClientGLX : public ImageTransportClient { - public: - ImageTransportClientGLX(ImageTransportFactory* factory, const gfx::Size& size) - : ImageTransportClient(false, size), - factory_(factory), - pixmap_(0), - glx_pixmap_(0), - acquired_(false) { - } - - virtual bool Initialize(uint64* surface_handle) OVERRIDE { - TRACE_EVENT0("renderer_host", "ImageTransportClientGLX::Initialize"); - Display* dpy = base::MessagePumpForUI::GetDefaultXDisplay(); - - scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent()); - if (!InitializeOneOff(dpy)) - return false; - - // Create pixmap from window. - // We receive a window here rather than a pixmap directly because drivers - // require (or required) that the pixmap used to create the GL texture be - // created in the same process as the texture. - pixmap_ = XCompositeNameWindowPixmap(dpy, *surface_handle); - - const int pixmapAttribs[] = { - GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, - GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT, - 0 - }; - - glx_pixmap_ = glXCreatePixmap(dpy, fbconfig_.Get(), pixmap_, pixmapAttribs); - - set_texture_id(CreateTexture()); - glFlush(); - return true; - } - - virtual void Update() OVERRIDE { - TRACE_EVENT0("renderer_host", "ImageTransportClientGLX::Update"); - Display* dpy = base::MessagePumpForUI::GetDefaultXDisplay(); - 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); - acquired_ = true; - glFlush(); - } - - virtual TransportDIB::Handle Handle() const OVERRIDE { - return TransportDIB::DefaultHandleValue(); - } - - protected: - virtual ~ImageTransportClientGLX() { - scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent()); - Display* dpy = base::MessagePumpForUI::GetDefaultXDisplay(); - if (glx_pixmap_) { - if (acquired_) - glXReleaseTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT); - glXDestroyGLXPixmap(dpy, glx_pixmap_); - } - if (pixmap_) - XFreePixmap(dpy, pixmap_); - unsigned int texture = texture_id(); - if (texture) - glDeleteTextures(1, &texture); - glFlush(); - } - - private: - static bool InitializeOneOff(Display* dpy) { - static bool initialized = false; - if (initialized) - return true; - - int event_base, error_base; - if (XCompositeQueryExtension(dpy, &event_base, &error_base)) { - int major = 0, minor = 2; - XCompositeQueryVersion(dpy, &major, &minor); - if (major == 0 && minor < 2) { - LOG(ERROR) << "Pixmap from window not supported."; - return false; - } - } - // Wrap the pixmap in a GLXPixmap - int screen = DefaultScreen(dpy); - XWindowAttributes gwa; - XGetWindowAttributes(dpy, RootWindow(dpy, screen), &gwa); - unsigned int visualid = XVisualIDFromVisual(gwa.visual); - - int nfbconfigs, config; - scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> fbconfigs( - glXGetFBConfigs(dpy, screen, &nfbconfigs)); - - for (config = 0; config < nfbconfigs; config++) { - XVisualInfo* visinfo = glXGetVisualFromFBConfig( - dpy, fbconfigs.get()[config]); - if (!visinfo || visinfo->visualid != visualid) - continue; - - int value; - glXGetFBConfigAttrib(dpy, - fbconfigs.get()[config], - GLX_DRAWABLE_TYPE, - &value); - if (!(value & GLX_PIXMAP_BIT)) - continue; - - glXGetFBConfigAttrib(dpy, - fbconfigs.get()[config], - GLX_BIND_TO_TEXTURE_TARGETS_EXT, - &value); - if (!(value & GLX_TEXTURE_2D_BIT_EXT)) - continue; - - glXGetFBConfigAttrib(dpy, - fbconfigs.get()[config], - GLX_BIND_TO_TEXTURE_RGB_EXT, - &value); - if (value == GL_FALSE) - continue; - - break; - } - - if (config == nfbconfigs) { - LOG(ERROR) - << "Could not find configuration suitable for binding a pixmap " - << "as a texture."; - return false; - } - fbconfig_.Get() = fbconfigs.get()[config]; - initialized = true; - return initialized; - } - - ImageTransportFactory* factory_; - XID pixmap_; - XID glx_pixmap_; - bool acquired_; - static base::LazyInstance<GLXFBConfig> fbconfig_; -}; - -base::LazyInstance<GLXFBConfig> ImageTransportClientGLX::fbconfig_ = - LAZY_INSTANCE_INITIALIZER; - -class ImageTransportClientOSMesa : public ImageTransportClient { - public: - ImageTransportClientOSMesa(ImageTransportFactory* factory, - const gfx::Size& size) - : ImageTransportClient(false, size), - factory_(factory) { - } - - virtual bool Initialize(uint64* surface_handle) OVERRIDE { - // We expect to make the handle here, so don't want the other end giving us - // one. - DCHECK_EQ(*surface_handle, static_cast<uint64>(0)); - - // It's possible that this ID gneration could clash with IDs from other - // AcceleratedSurfaceContainerTouch* objects, however we should never have - // ids active from more than one type at the same time, so we have free - // reign of the id namespace. - *surface_handle = next_handle_++; - - shared_mem_.reset( - TransportDIB::Create(size().GetArea() * 4, // GL_RGBA=4 B/px - *surface_handle)); - if (!shared_mem_.get()) - return false; - - scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent()); - set_texture_id(CreateTexture()); - glFlush(); - return true; - } - - virtual void Update() OVERRIDE { - glBindTexture(GL_TEXTURE_2D, texture_id()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - size().width(), size().height(), 0, - GL_RGBA, GL_UNSIGNED_BYTE, shared_mem_->memory()); - glFlush(); - } - - virtual TransportDIB::Handle Handle() const OVERRIDE { - return shared_mem_->handle(); - } - - protected: - virtual ~ImageTransportClientOSMesa() { - unsigned int texture = texture_id(); - if (texture) { - scoped_ptr<gfx::ScopedMakeCurrent> bind( - factory_->GetScopedMakeCurrent()); - glDeleteTextures(1, &texture); - glFlush(); - } - } - - private: - ImageTransportFactory* factory_; - scoped_ptr<TransportDIB> shared_mem_; - static uint32 next_handle_; -}; -uint32 ImageTransportClientOSMesa::next_handle_ = 0; - -} // anonymous namespace - -ImageTransportClient* ImageTransportClient::Create( - ImageTransportFactory* factory, - const gfx::Size& size) { - switch (gfx::GetGLImplementation()) { - case gfx::kGLImplementationOSMesaGL: - return new ImageTransportClientOSMesa(factory, size); - case gfx::kGLImplementationDesktopGL: - return new ImageTransportClientGLX(factory, size); - case gfx::kGLImplementationEGLGLES2: - return new ImageTransportClientEGL(factory, size); - default: - NOTREACHED(); - return NULL; - } -} diff --git a/content/browser/renderer_host/image_transport_factory.cc b/content/browser/renderer_host/image_transport_factory.cc index 56a6aa5..a9112fe 100644 --- a/content/browser/renderer_host/image_transport_factory.cc +++ b/content/browser/renderer_host/image_transport_factory.cc @@ -13,7 +13,6 @@ #include "base/observer_list.h" #include "content/browser/gpu/browser_gpu_channel_host_factory.h" #include "content/browser/gpu/gpu_surface_tracker.h" -#include "content/browser/renderer_host/image_transport_client.h" #include "content/common/gpu/client/gl_helper.h" #include "content/common/gpu/client/gpu_channel_host.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" @@ -23,6 +22,7 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h" #include "ui/compositor/compositor.h" #include "ui/compositor/compositor_setup.h" +#include "ui/compositor/test_web_graphics_context_3d.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/size.h" #include "ui/gl/scoped_make_current.h" @@ -55,9 +55,10 @@ class DefaultTransportFactory gfx::GLSurfaceHandle surface) OVERRIDE { } - virtual scoped_refptr<ImageTransportClient> CreateTransportClient( + virtual scoped_refptr<ui::Texture> CreateTransportClient( const gfx::Size& size, - uint64* transport_handle) OVERRIDE { + uint64* transport_handle, + ui::Compositor* compositor) OVERRIDE { return NULL; } @@ -69,10 +70,6 @@ class DefaultTransportFactory return 0; } - virtual gfx::ScopedMakeCurrent* GetScopedMakeCurrent() OVERRIDE { - return NULL; - } - // We don't generate lost context events, so we don't need to keep track of // observers virtual void AddObserver(ImageTransportFactoryObserver* observer) OVERRIDE { @@ -86,55 +83,30 @@ class DefaultTransportFactory DISALLOW_COPY_AND_ASSIGN(DefaultTransportFactory); }; -class TestTransportFactory : public DefaultTransportFactory { +class ImageTransportClientTexture : public ui::Texture { public: - TestTransportFactory() {} - - virtual gfx::GLSurfaceHandle CreateSharedSurfaceHandle( - ui::Compositor* compositor) OVERRIDE { - return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, true); - } - - virtual scoped_refptr<ImageTransportClient> CreateTransportClient( + ImageTransportClientTexture( + WebKit::WebGraphicsContext3D* host_context, const gfx::Size& size, - uint64* transport_handle) OVERRIDE { -#if defined(UI_COMPOSITOR_IMAGE_TRANSPORT) - scoped_refptr<ImageTransportClient> surface( - ImageTransportClient::Create(this, size)); - if (!surface || !surface->Initialize(transport_handle)) { - LOG(ERROR) << "Failed to create ImageTransportClient"; - return NULL; - } - return surface; -#else - return NULL; -#endif + uint64 surface_id) + : ui::Texture(true, size), + host_context_(host_context) { + set_texture_id(surface_id); } - private: - DISALLOW_COPY_AND_ASSIGN(TestTransportFactory); -}; - -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 void Update() OVERRIDE {} - virtual TransportDIB::Handle Handle() const OVERRIDE { - return TransportDIB::DefaultHandleValue(); + virtual WebKit::WebGraphicsContext3D* HostContext3D() { + return host_context_; } protected: virtual ~ImageTransportClientTexture() {} private: + // A raw pointer. This |ImageTransportClientTexture| will be destroyed + // before the |host_context_| via + // |ImageTransportFactoryObserver::OnLostContext()| handlers. + WebKit::WebGraphicsContext3D* host_context_; + DISALLOW_COPY_AND_ASSIGN(ImageTransportClientTexture); }; @@ -247,12 +219,15 @@ class GpuProcessTransportFactory : public ui::ContextFactory, } } - virtual scoped_refptr<ImageTransportClient> CreateTransportClient( + virtual scoped_refptr<ui::Texture> CreateTransportClient( const gfx::Size& size, - uint64* transport_handle) { + uint64* transport_handle, + ui::Compositor* compositor) { + PerCompositorData* data = per_compositor_data_[compositor]; + DCHECK(data); scoped_refptr<ImageTransportClientTexture> image( - new ImageTransportClientTexture(size)); - image->Initialize(transport_handle); + new ImageTransportClientTexture(data->shared_context.get(), + size, *transport_handle)); return image; } @@ -278,8 +253,6 @@ class GpuProcessTransportFactory : public ui::ContextFactory, return data->shared_context->insertSyncPoint(); } - virtual gfx::ScopedMakeCurrent* GetScopedMakeCurrent() { return NULL; } - virtual void AddObserver(ImageTransportFactoryObserver* observer) { observer_list_.AddObserver(observer); } @@ -412,7 +385,7 @@ void ImageTransportFactory::Initialize() { ui::SetupTestCompositor(); } if (ui::IsTestCompositorEnabled()) { - g_factory = new TestTransportFactory(); + g_factory = new DefaultTransportFactory(); } else { #if defined(OS_WIN) g_factory = new DefaultTransportFactory(); diff --git a/content/browser/renderer_host/image_transport_factory.h b/content/browser/renderer_host/image_transport_factory.h index 10a841e..99363f5 100644 --- a/content/browser/renderer_host/image_transport_factory.h +++ b/content/browser/renderer_host/image_transport_factory.h @@ -27,8 +27,6 @@ namespace WebKit { class WebGraphicsContext3D; } -class ImageTransportClient; - // This class provides a way to get notified when surface handles get lost. class ImageTransportFactoryObserver { public: @@ -74,11 +72,12 @@ class ImageTransportFactory { // 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 + // Creates a transport texture of a given size, and using the opaque handle // sent by the GPU process. - virtual scoped_refptr<ImageTransportClient> CreateTransportClient( + virtual scoped_refptr<ui::Texture> CreateTransportClient( const gfx::Size& size, - uint64* transport_handle) = 0; + uint64* transport_handle, + ui::Compositor* compositor) = 0; // Gets a GLHelper instance, associated with the compositor context. This // GLHelper will get destroyed whenever the context is lost ( @@ -87,12 +86,6 @@ class ImageTransportFactory { // Inserts a SyncPoint into the compositor's context. virtual uint32 InsertSyncPoint(ui::Compositor* compositor) = 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; - virtual void AddObserver(ImageTransportFactoryObserver* observer) = 0; virtual void RemoveObserver(ImageTransportFactoryObserver* observer) = 0; }; 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 9d57145..1c277b4 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -14,7 +14,6 @@ #include "base/string_number_conversions.h" #include "content/browser/renderer_host/backing_store_aura.h" #include "content/browser/renderer_host/dip_util.h" -#include "content/browser/renderer_host/image_transport_client.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/web_input_event_aura.h" #include "content/common/gpu/client/gl_helper.h" @@ -450,12 +449,12 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurface( if (!compositor) return; - std::map<uint64, scoped_refptr<ImageTransportClient> >::iterator it = + std::map<uint64, scoped_refptr<ui::Texture> >::iterator it = image_transport_clients_.find(current_surface_); if (it == image_transport_clients_.end()) return; - ImageTransportClient* container = it->second; + ui::Texture* container = it->second; DCHECK(container); gfx::Size size_in_pixel = content::ConvertSizeToPixel(this, size); @@ -505,10 +504,8 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() { if (current_surface_ != 0 && host_->is_accelerated_compositing_active()) { - ImageTransportClient* container = + ui::Texture* container = image_transport_clients_[current_surface_]; - if (container) - container->Update(); window_->SetExternalTexture(container); released_front_lock_ = NULL; @@ -562,7 +559,7 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped( if (!compositor) { // We have no compositor, so we have no way to display the surface. // Must still send the ACK. - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id); + InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, NULL); } else { gfx::Size surface_size_in_pixel = image_transport_clients_[params_in_pixel.surface_handle]->size(); @@ -572,12 +569,25 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped( if (!resize_locks_.empty()) { // If we are waiting for the resize, fast-track the ACK. - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id); + if (compositor->IsThreaded()) { + // We need the compositor thread to pick up the active buffer before + // ACKing. + on_compositing_did_commit_callbacks_.push_back( + base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK, + params_in_pixel.route_id, + gpu_host_id)); + if (!compositor->HasObserver(this)) + compositor->AddObserver(this); + } else { + // The compositor will pickup the active buffer during a draw, so we + // can ACK immediately. + InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, + compositor); + } } else { // Add sending an ACK to the list of things to do OnCompositingWillStart on_compositing_will_start_callbacks_.push_back( base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK, - base::Unretained(this), params_in_pixel.route_id, gpu_host_id)); if (!compositor->HasObserver(this)) @@ -596,7 +606,7 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( if (!compositor) { // We have no compositor, so we have no way to display the surface // Must still send the ACK - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id); + InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, NULL); } else { gfx::Size surface_size_in_pixel = image_transport_clients_[params_in_pixel.surface_handle]->size(); @@ -613,12 +623,25 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( if (!resize_locks_.empty()) { // If we are waiting for the resize, fast-track the ACK. - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id); + if (compositor->IsThreaded()) { + // We need the compositor thread to pick up the active buffer before + // ACKing. + on_compositing_did_commit_callbacks_.push_back( + base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK, + params_in_pixel.route_id, + gpu_host_id)); + if (!compositor->HasObserver(this)) + compositor->AddObserver(this); + } else { + // The compositor will pickup the active buffer during a draw, so we + // can ACK immediately. + InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, + compositor); + } } else { // Add sending an ACK to the list of things to do OnCompositingWillStart on_compositing_will_start_callbacks_.push_back( base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK, - base::Unretained(this), params_in_pixel.route_id, gpu_host_id)); if (!compositor->HasObserver(this)) @@ -638,19 +661,21 @@ bool RenderWidgetHostViewAura::HasAcceleratedSurface( return false; } +// TODO(backer): Drop the |shm_handle| once I remove some unused service side +// code. void RenderWidgetHostViewAura::AcceleratedSurfaceNew( int32 width_in_pixel, int32 height_in_pixel, uint64* surface_handle, TransportDIB::Handle* shm_handle) { ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); - scoped_refptr<ImageTransportClient> surface(factory->CreateTransportClient( - gfx::Size(width_in_pixel, height_in_pixel), surface_handle)); + scoped_refptr<ui::Texture> surface(factory->CreateTransportClient( + gfx::Size(width_in_pixel, height_in_pixel), surface_handle, + GetCompositor())); if (!surface) { - LOG(ERROR) << "Failed to create ImageTransportClient"; + LOG(ERROR) << "Failed to create ImageTransport texture"; return; } - *shm_handle = surface->Handle(); image_transport_clients_[*surface_handle] = surface; } @@ -1224,19 +1249,23 @@ void RenderWidgetHostViewAura::OnLostActive() { //////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewAura, ui::CompositorObserver implementation: +void RenderWidgetHostViewAura::OnCompositingDidCommit( + ui::Compositor* compositor) { + RunCompositingDidCommitCallbacks(compositor); +} void RenderWidgetHostViewAura::OnCompositingWillStart( ui::Compositor* compositor) { - RunCompositingCallbacks(); + RunCompositingWillStartCallbacks(compositor); } void RenderWidgetHostViewAura::OnCompositingStarted( ui::Compositor* compositor) { locks_pending_draw_.clear(); - compositor->RemoveObserver(this); } -void RenderWidgetHostViewAura::OnCompositingEnded(ui::Compositor* compositor) { +void RenderWidgetHostViewAura::OnCompositingEnded( + ui::Compositor* compositor) { } void RenderWidgetHostViewAura::OnCompositingAborted( @@ -1375,20 +1404,39 @@ bool RenderWidgetHostViewAura::ShouldMoveToCenter() { global_mouse_position_.y() > rect.bottom() - border_y; } -void RenderWidgetHostViewAura::RunCompositingCallbacks() { - for (std::vector< base::Callback<void(void)> >::const_iterator +void RenderWidgetHostViewAura::RunCompositingDidCommitCallbacks( + ui::Compositor* compositor) { + for (std::vector< base::Callback<void(ui::Compositor*)> >::const_iterator + it = on_compositing_did_commit_callbacks_.begin(); + it != on_compositing_did_commit_callbacks_.end(); ++it) { + it->Run(compositor); + } + on_compositing_did_commit_callbacks_.clear(); +} + +void RenderWidgetHostViewAura::RunCompositingWillStartCallbacks( + ui::Compositor* compositor) { + for (std::vector< base::Callback<void(ui::Compositor*)> >::const_iterator it = on_compositing_will_start_callbacks_.begin(); it != on_compositing_will_start_callbacks_.end(); ++it) { - it->Run(); + it->Run(compositor); } on_compositing_will_start_callbacks_.clear(); } -void RenderWidgetHostViewAura::InsertSyncPointAndACK(int32 route_id, - int gpu_host_id) { - ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); +// static +void RenderWidgetHostViewAura::InsertSyncPointAndACK( + int32 route_id, int gpu_host_id, ui::Compositor* compositor) { + uint32 sync_point = 0; + // If we have no compositor, so we must still send the ACK. A zero + // sync point will not be waited for in the GPU process. + if (compositor) { + ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); + sync_point = factory->InsertSyncPoint(compositor); + } + RenderWidgetHostImpl::AcknowledgeBufferPresent( - route_id, gpu_host_id, factory->InsertSyncPoint(GetCompositor())); + route_id, gpu_host_id, sync_point); } void RenderWidgetHostViewAura::RemovingFromRootWindow() { @@ -1398,9 +1446,10 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() { // drawing to the buffer we haven't yet displayed. This will only show for 1 // frame though, because we will reissue a new frame right away without that // composited data. - RunCompositingCallbacks(); - locks_pending_draw_.clear(); ui::Compositor* compositor = GetCompositor(); + RunCompositingDidCommitCallbacks(compositor); + RunCompositingWillStartCallbacks(compositor); + locks_pending_draw_.clear(); if (compositor && compositor->HasObserver(this)) compositor->RemoveObserver(this); DetachFromInputMethod(); 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 bb16418..b3e95ba 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -36,14 +36,13 @@ class Canvas; namespace ui { class InputMethod; +class Texture; } namespace WebKit { class WebTouchEvent; } -class ImageTransportClient; - // RenderWidgetHostView class hierarchy described in render_widget_host_view.h. class RenderWidgetHostViewAura : public content::RenderWidgetHostViewBase, @@ -194,6 +193,7 @@ class RenderWidgetHostViewAura friend class WindowObserver; // Overridden from ui::CompositorObserver: + virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE; virtual void OnCompositingWillStart(ui::Compositor* compositor) OVERRIDE; virtual void OnCompositingStarted(ui::Compositor* compositor) OVERRIDE; virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE; @@ -228,11 +228,14 @@ class RenderWidgetHostViewAura bool ShouldMoveToCenter(); // Run the compositing callbacks. - void RunCompositingCallbacks(); + void RunCompositingDidCommitCallbacks(ui::Compositor* compositor); + void RunCompositingWillStartCallbacks(ui::Compositor* compositor); // Insert a sync point into the compositor's command stream and acknowledge // that we have presented the accelerated surface buffer. - void InsertSyncPointAndACK(int32 route_id, int gpu_host_id); + static void InsertSyncPointAndACK(int32 route_id, + int gpu_host_id, + ui::Compositor* compositor); // Called when window_ is removed from the window tree. void RemovingFromRootWindow(); @@ -294,10 +297,13 @@ class RenderWidgetHostViewAura // Current tooltip text. string16 tooltip_; - std::vector< base::Callback<void(void)> > + std::vector< base::Callback<void(ui::Compositor*)> > + on_compositing_did_commit_callbacks_; + + std::vector< base::Callback<void(ui::Compositor*)> > on_compositing_will_start_callbacks_; - std::map<uint64, scoped_refptr<ImageTransportClient> > + std::map<uint64, scoped_refptr<ui::Texture> > image_transport_clients_; uint64 current_surface_; diff --git a/content/common/gpu/image_transport_surface.cc b/content/common/gpu/image_transport_surface.cc index 8e8de9e..8ac506d 100644 --- a/content/common/gpu/image_transport_surface.cc +++ b/content/common/gpu/image_transport_surface.cc @@ -16,6 +16,7 @@ #include "content/common/gpu/gpu_messages.h" #include "gpu/command_buffer/service/gpu_scheduler.h" #include "ui/gl/gl_switches.h" +#include "ui/gl/gl_implementation.h" ImageTransportSurface::ImageTransportSurface() {} @@ -112,6 +113,10 @@ void ImageTransportHelper::SendAcceleratedSurfaceNew( void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped( GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) { + // TRACE_EVENT for gpu tests: + TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers", + "GLImpl", static_cast<int>(gfx::GetGLImplementation()), + "width", surface_->GetSize().width()); params.surface_id = stub_->surface_id(); params.route_id = route_id_; #if defined(OS_MACOSX) @@ -326,6 +331,10 @@ void PassThroughImageTransportSurface::OnResize(gfx::Size size) { } } +gfx::Size PassThroughImageTransportSurface::GetSize() { + return GLSurfaceAdapter::GetSize(); +} + PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {} #endif // defined(ENABLE_GPU) diff --git a/content/common/gpu/image_transport_surface.h b/content/common/gpu/image_transport_surface.h index 33c33d3..0bc4bcc 100644 --- a/content/common/gpu/image_transport_surface.h +++ b/content/common/gpu/image_transport_surface.h @@ -71,6 +71,8 @@ class ImageTransportSurface { GpuCommandBufferStub* stub, const gfx::GLSurfaceHandle& handle); + virtual gfx::Size GetSize() = 0; + protected: // Used by certain implements of PostSubBuffer to determine // how much needs to be copied between frames. @@ -177,6 +179,7 @@ class PassThroughImageTransportSurface virtual void OnBufferPresented(uint32 sync_point) OVERRIDE; virtual void OnResizeViewACK() OVERRIDE; virtual void OnResize(gfx::Size size) OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; protected: virtual ~PassThroughImageTransportSurface(); diff --git a/content/common/gpu/image_transport_surface_win.cc b/content/common/gpu/image_transport_surface_win.cc index cc6dc87..78e090a 100644 --- a/content/common/gpu/image_transport_surface_win.cc +++ b/content/common/gpu/image_transport_surface_win.cc @@ -51,6 +51,7 @@ class PbufferImageTransportSurface virtual void OnBufferPresented(uint32 sync_point) OVERRIDE; virtual void OnResizeViewACK() OVERRIDE; virtual void OnResize(gfx::Size size) OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; private: virtual ~PbufferImageTransportSurface(); @@ -230,6 +231,10 @@ void PbufferImageTransportSurface::OnResize(gfx::Size size) { visible_size_ = size; } +gfx::Size PbufferImageTransportSurface::GetSize() { + return GLSurfaceAdapter::GetSize(); +} + } // namespace anonymous // static diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 4953ca6..ca17790 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -525,9 +525,6 @@ 'browser/renderer_host/gtk_key_bindings_handler.h', 'browser/renderer_host/gtk_window_utils.cc', '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_client_linux.cc', 'browser/renderer_host/image_transport_factory.cc', 'browser/renderer_host/image_transport_factory.h', 'browser/renderer_host/java/java_bound_object.cc', @@ -984,10 +981,6 @@ 'include_dirs': [ '../third_party/angle/include', ], - }, { - 'sources/': [ - ['exclude', '^browser/renderer_host/image_transport_client_linux.cc'], - ], }], ['java_bridge==1', { 'defines': [ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 81ecee4..ae0ab29 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -8233,11 +8233,6 @@ error::Error GLES2DecoderImpl::HandleSwapBuffers( } int this_frame_number = frame_number_++; - // TRACE_EVENT for gpu tests: - TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers", - "GLImpl", static_cast<int>(gfx::GetGLImplementation()), - "width", (is_offscreen ? offscreen_size_.width() : - surface_->GetSize().width())); TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers", "offscreen", is_offscreen, "frame", this_frame_number); diff --git a/ui/aura/bench/bench_main.cc b/ui/aura/bench/bench_main.cc index 7d416757..0430901 100644 --- a/ui/aura/bench/bench_main.cc +++ b/ui/aura/bench/bench_main.cc @@ -91,6 +91,9 @@ class BenchCompositorObserver : public ui::CompositorObserver { frames_(0), max_frames_(max_frames) { } + + virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE {} + virtual void OnCompositingWillStart(Compositor* compositor) OVERRIDE {} virtual void OnCompositingStarted(Compositor* compositor) OVERRIDE {} @@ -144,6 +147,10 @@ class WebGLTexture : public ui::Texture { GL_RGBA, GL_UNSIGNED_BYTE, NULL); } + virtual WebGraphicsContext3D* HostContext3D() OVERRIDE { + return context_; + } + private: virtual ~WebGLTexture() { context_->deleteTexture(texture_id()); diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 3165eed..6c45b23 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -560,6 +560,9 @@ void RootWindow::ScheduleDraw() { //////////////////////////////////////////////////////////////////////////////// // RootWindow, ui::CompositorObserver implementation: +void RootWindow::OnCompositingDidCommit(ui::Compositor*) { +} + void RootWindow::OnCompositingWillStart(ui::Compositor*) { } diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index b81888e..54ad607 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -247,6 +247,7 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, virtual void ScheduleDraw() OVERRIDE; // Overridden from ui::CompositorObserver: + virtual void OnCompositingDidCommit(ui::Compositor*) OVERRIDE; virtual void OnCompositingWillStart(ui::Compositor*) OVERRIDE; virtual void OnCompositingStarted(ui::Compositor*) OVERRIDE; virtual void OnCompositingEnded(ui::Compositor*) OVERRIDE; diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 148a5bd..f9f75aa 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc @@ -170,6 +170,11 @@ Compositor::~Compositor() { host_.setRootLayer(NULL); if (root_layer_) root_layer_->SetCompositor(NULL); + + // Stop all outstanding draws before telling the ContextFactory to tear + // down any contexts that the |host_| may rely upon. + host_.reset(); + if (!test_compositor_enabled) ContextFactory::GetInstance()->RemoveCompositor(this); } @@ -292,6 +297,10 @@ bool Compositor::HasObserver(CompositorObserver* observer) { return observer_list_.HasObserver(observer); } +bool Compositor::IsThreaded() const { + return g_compositor_thread != NULL; +} + void Compositor::OnSwapBuffersPosted() { swap_posted_ = true; } @@ -342,6 +351,14 @@ WebKit::WebGraphicsContext3D* Compositor::createContext3D() { void Compositor::didRebindGraphicsContext(bool success) { } +// Called once per draw in single-threaded compositor mode and potentially +// many times between draws in the multi-threaded compositor mode. +void Compositor::didCommit() { + FOR_EACH_OBSERVER(CompositorObserver, + observer_list_, + OnCompositingDidCommit(this)); +} + void Compositor::didCommitAndDrawFrame() { // TODO(backer): Plumb through an earlier impl side will start. if (g_compositor_thread) diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index 0b129cf..ea57724 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h @@ -101,6 +101,7 @@ class COMPOSITOR_EXPORT Texture : public base::RefCounted<Texture> { void set_texture_id(unsigned int id) { texture_id_ = id; } bool flipped() const { return flipped_; } gfx::Size size() const { return size_; } + virtual WebKit::WebGraphicsContext3D* HostContext3D() = 0; protected: virtual ~Texture(); @@ -190,6 +191,10 @@ class COMPOSITOR_EXPORT Compositor // and the OnCompositingEnded. bool DrawPending() const { return swap_posted_; } + // Returns whether the drawing is issued from a separate thread + // (i.e. |Compositor::Initialize(true)| was called). + bool IsThreaded() const; + // Internal functions, called back by command-buffer contexts on swap buffer // events. @@ -209,6 +214,7 @@ class COMPOSITOR_EXPORT Compositor float scaleFactor); virtual WebKit::WebGraphicsContext3D* createContext3D(); virtual void didRebindGraphicsContext(bool success); + virtual void didCommit(); virtual void didCommitAndDrawFrame(); virtual void didCompleteSwapBuffers(); virtual void scheduleComposite(); @@ -251,6 +257,8 @@ class COMPOSITOR_EXPORT Compositor int last_ended_frame_; bool disable_schedule_composite_; + + DISALLOW_COPY_AND_ASSIGN(Compositor); }; } // namespace ui diff --git a/ui/compositor/compositor_observer.h b/ui/compositor/compositor_observer.h index f76609f..830f170 100644 --- a/ui/compositor/compositor_observer.h +++ b/ui/compositor/compositor_observer.h @@ -14,6 +14,14 @@ class Compositor; // A compositor observer is notified when compositing completes. class COMPOSITOR_EXPORT CompositorObserver { public: + // A commit proxies information from the main thread to the compositor + // thread. It typically happens when some state changes that will require a + // composite. In the multi-threaded case, many commits may happen between + // two successive composites. In the single-threaded, a single commit + // between two composites (just before the composite as part of the + // composite cycle). + virtual void OnCompositingDidCommit(Compositor* compositor) = 0; + // Called when compositing will start. virtual void OnCompositingWillStart(Compositor* compositor) = 0; diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 63d287e..d3eb226 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc @@ -341,10 +341,14 @@ void Layer::SetExternalTexture(Texture* texture) { WebKit::WebLayer new_layer; if (layer_updated_externally_) { WebKit::WebExternalTextureLayer texture_layer = - WebKit::WebExternalTextureLayer::create(); + WebKit::WebExternalTextureLayer::create(this); texture_layer.setFlipped(texture_->flipped()); new_layer = texture_layer; } else { + // Tell the compositor to clear references to the old texture. + WebKit::WebExternalTextureLayer texture_layer = + web_layer_.to<WebKit::WebExternalTextureLayer>(); + texture_layer.willModifyTexture(); new_layer = WebKit::WebContentLayer::create(this); } if (parent_) { @@ -465,6 +469,16 @@ void Layer::paintContents(WebKit::WebCanvas* web_canvas, delegate_->OnPaintLayer(&canvas); } +unsigned Layer::prepareTexture(WebKit::WebTextureUpdater& /* updater */) { + DCHECK(layer_updated_externally_); + return texture_->texture_id(); +} + +WebKit::WebGraphicsContext3D* Layer::context() { + DCHECK(layer_updated_externally_); + return texture_->HostContext3D(); +} + void Layer::SetForceRenderSurface(bool force) { if (force_render_surface_ == force) return; @@ -664,10 +678,8 @@ void Layer::RecomputeDrawsContentAndUVRect() { web_layer_.setBounds(ConvertSizeToPixel(this, bounds_.size())); } else { DCHECK(texture_); - unsigned int texture_id = texture_->texture_id(); WebKit::WebExternalTextureLayer texture_layer = web_layer_.to<WebKit::WebExternalTextureLayer>(); - texture_layer.setTextureId(should_draw ? texture_id : 0); gfx::Size texture_size; if (scale_content_) diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index cadd4f3..2a0772c 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h @@ -13,6 +13,7 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop.h" #include "third_party/WebKit/Source/Platform/chromium/public/WebContentLayerClient.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebExternalTextureLayerClient.h" #include "third_party/WebKit/Source/Platform/chromium/public/WebLayer.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkRegion.h" @@ -41,9 +42,10 @@ class Texture; // NOTE: unlike Views, each Layer does *not* own its children views. If you // delete a Layer and it has children, the parent of each child layer is set to // NULL, but the children are not deleted. -class COMPOSITOR_EXPORT Layer : - public LayerAnimationDelegate, - NON_EXPORTED_BASE(public WebKit::WebContentLayerClient) { +class COMPOSITOR_EXPORT Layer + : public LayerAnimationDelegate, + NON_EXPORTED_BASE(public WebKit::WebContentLayerClient), + NON_EXPORTED_BASE(public WebKit::WebExternalTextureLayerClient) { public: Layer(); explicit Layer(LayerType type); @@ -244,6 +246,11 @@ class COMPOSITOR_EXPORT Layer : WebKit::WebLayer web_layer() { return web_layer_; } + // WebExternalTextureLayerClient + virtual unsigned prepareTexture( + WebKit::WebTextureUpdater& /* updater */) OVERRIDE; + virtual WebKit::WebGraphicsContext3D* context() OVERRIDE; + float device_scale_factor() const { return device_scale_factor_; } // Forces a render surface to be used on this layer. This has no positive diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index a1e805d..c72bdd4 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc @@ -337,6 +337,9 @@ class TestCompositorObserver : public CompositorObserver { } private: + virtual void OnCompositingDidCommit(Compositor* compositor) OVERRIDE { + } + virtual void OnCompositingWillStart(Compositor* compositor) OVERRIDE { will_start_ = true; } |