diff options
author | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-26 17:28:45 +0000 |
---|---|---|
committer | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-26 17:28:45 +0000 |
commit | ef29f34b4144247658d1580049eb968b0394eccb (patch) | |
tree | 80b8b91f4c86cda87510fb6eacfcf22bd61d5b37 | |
parent | d6fe4385d153e0a57f693117ad4db2481bdbbea6 (diff) | |
download | chromium_src-ef29f34b4144247658d1580049eb968b0394eccb.zip chromium_src-ef29f34b4144247658d1580049eb968b0394eccb.tar.gz chromium_src-ef29f34b4144247658d1580049eb968b0394eccb.tar.bz2 |
Vend common GL context
We can't rely on having a compositor for set-up and tear-down of cross process texture transport. This CL creates a shared offscreen context appropriate for that. It further separates TextureGL objects from CompositorGL objects. In particular
- I've plumbed through the size of the surface backing the Compositor to the Texture
- I've allows the TextureGL to release it's GL resources using the shared context
It's necessary to make the vendor of the offscreen context a LeakySingletonTrait singleton so that we don't race with destruction of GL bindings on process shutdown.
BUG=fixes dereferencing NULL pointers in RWHVVTouch when images come from GPU process
TEST=3D CSS on TOUCH_UI, views_desktop on Windows
Review URL: http://codereview.chromium.org/7552039
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98441 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/renderer_host/accelerated_surface_container_touch.cc | 55 | ||||
-rw-r--r-- | chrome/browser/renderer_host/accelerated_surface_container_touch.h | 5 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_views_touch.cc | 1 | ||||
-rw-r--r-- | ui/gfx/compositor/compositor.h | 20 | ||||
-rw-r--r-- | ui/gfx/compositor/compositor_gl.cc | 258 | ||||
-rw-r--r-- | ui/gfx/compositor/compositor_gl.h | 53 | ||||
-rw-r--r-- | ui/gfx/compositor/compositor_win.cc | 181 | ||||
-rw-r--r-- | ui/gfx/compositor/layer.cc | 1 | ||||
-rw-r--r-- | views/view_unittest.cc | 4 | ||||
-rw-r--r-- | views/widget/native_widget_gtk.cc | 2 | ||||
-rw-r--r-- | views/widget/native_widget_win.cc | 2 |
11 files changed, 312 insertions, 270 deletions
diff --git a/chrome/browser/renderer_host/accelerated_surface_container_touch.cc b/chrome/browser/renderer_host/accelerated_surface_container_touch.cc index e3a5237..ab0db73 100644 --- a/chrome/browser/renderer_host/accelerated_surface_container_touch.cc +++ b/chrome/browser/renderer_host/accelerated_surface_container_touch.cc @@ -13,8 +13,8 @@ #include "ui/gfx/gl/gl_bindings.h" #include "ui/gfx/gl/gl_implementation.h" #include "ui/gfx/gl/gl_surface_egl.h" -#include "ui/gfx/rect.h" #include "ui/gfx/gl/gl_surface_glx.h" +#include "ui/gfx/rect.h" #include "ui/gfx/transform.h" namespace { @@ -22,8 +22,7 @@ namespace { class AcceleratedSurfaceContainerTouchEGL : public AcceleratedSurfaceContainerTouch { public: - AcceleratedSurfaceContainerTouchEGL(ui::CompositorGL* compositor, - const gfx::Size& size, + AcceleratedSurfaceContainerTouchEGL(const gfx::Size& size, uint64 surface_handle); // TextureGL implementation virtual void Draw(const ui::TextureDrawParams& params, @@ -33,14 +32,14 @@ class AcceleratedSurfaceContainerTouchEGL ~AcceleratedSurfaceContainerTouchEGL(); void* image_; + DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerTouchEGL); }; class AcceleratedSurfaceContainerTouchGLX : public AcceleratedSurfaceContainerTouch { public: - AcceleratedSurfaceContainerTouchGLX(ui::CompositorGL* compositor, - const gfx::Size& size, + AcceleratedSurfaceContainerTouchGLX(const gfx::Size& size, uint64 surface_handle); // TextureGL implementation virtual void Draw(const ui::TextureDrawParams& params, @@ -51,6 +50,7 @@ class AcceleratedSurfaceContainerTouchGLX XID pixmap_; XID glx_pixmap_; + DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerTouchGLX); }; @@ -62,12 +62,13 @@ class ScopedPtrXFree { }; AcceleratedSurfaceContainerTouchEGL::AcceleratedSurfaceContainerTouchEGL( - ui::CompositorGL* compositor, const gfx::Size& size, uint64 surface_handle) - : AcceleratedSurfaceContainerTouch(compositor, size), + : AcceleratedSurfaceContainerTouch(size), image_(NULL) { - compositor_->MakeCurrent(); + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + instance->MakeSharedContextCurrent(); image_ = eglCreateImageKHR( gfx::GLSurfaceEGL::GetHardwareDisplay(), EGL_NO_CONTEXT, @@ -84,6 +85,10 @@ AcceleratedSurfaceContainerTouchEGL::AcceleratedSurfaceContainerTouchEGL( } AcceleratedSurfaceContainerTouchEGL::~AcceleratedSurfaceContainerTouchEGL() { + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + instance->MakeSharedContextCurrent(); + eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), image_); glFlush(); } @@ -91,7 +96,8 @@ AcceleratedSurfaceContainerTouchEGL::~AcceleratedSurfaceContainerTouchEGL() { void AcceleratedSurfaceContainerTouchEGL::Draw( const ui::TextureDrawParams& params, const gfx::Rect& clip_bounds_in_texture) { - DCHECK(compositor_->program_no_swizzle()); + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); ui::TextureDrawParams modified_params = params; @@ -103,18 +109,21 @@ void AcceleratedSurfaceContainerTouchEGL::Draw( modified_params.transform = flipped; - DrawInternal(*compositor_->program_no_swizzle(), + DrawInternal(*instance->program_no_swizzle(), modified_params, clip_bounds_in_texture); } AcceleratedSurfaceContainerTouchGLX::AcceleratedSurfaceContainerTouchGLX( - ui::CompositorGL* compositor, const gfx::Size& size, uint64 surface_handle) - : AcceleratedSurfaceContainerTouch(compositor, size), + : AcceleratedSurfaceContainerTouch(size), pixmap_(0), glx_pixmap_(0) { + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + instance->MakeSharedContextCurrent(); + // Create pixmap from window. Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); int event_base, error_base; @@ -186,7 +195,6 @@ AcceleratedSurfaceContainerTouchGLX::AcceleratedSurfaceContainerTouchGLX( dpy, fbconfigs.get()[config], pixmap_, pixmapAttribs); // Create texture. - compositor_->MakeCurrent(); glGenTextures(1, &texture_id_); glBindTexture(GL_TEXTURE_2D, texture_id_); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -196,6 +204,10 @@ AcceleratedSurfaceContainerTouchGLX::AcceleratedSurfaceContainerTouchGLX( } AcceleratedSurfaceContainerTouchGLX::~AcceleratedSurfaceContainerTouchGLX() { + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + instance->MakeSharedContextCurrent(); + Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); if (glx_pixmap_) glXDestroyGLXPixmap(dpy, glx_pixmap_); @@ -206,12 +218,14 @@ AcceleratedSurfaceContainerTouchGLX::~AcceleratedSurfaceContainerTouchGLX() { void AcceleratedSurfaceContainerTouchGLX::Draw( const ui::TextureDrawParams& params, const gfx::Rect& clip_bounds_in_texture) { - DCHECK(compositor_->program_no_swizzle()); + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); glBindTexture(GL_TEXTURE_2D, texture_id_); glXBindTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL); - DrawInternal(*compositor_->program_no_swizzle(), + DrawInternal(*instance->program_no_swizzle(), params, clip_bounds_in_texture); glXReleaseTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT); @@ -220,25 +234,20 @@ void AcceleratedSurfaceContainerTouchGLX::Draw( } // namespace AcceleratedSurfaceContainerTouch::AcceleratedSurfaceContainerTouch( - ui::CompositorGL* compositor, - const gfx::Size& size) : - TextureGL(compositor, size) { + const gfx::Size& size) : TextureGL(size) { } // static AcceleratedSurfaceContainerTouch* AcceleratedSurfaceContainerTouch::CreateAcceleratedSurfaceContainer( - ui::CompositorGL* compositor, const gfx::Size& size, uint64 surface_handle) { switch (gfx::GetGLImplementation()) { case gfx::kGLImplementationDesktopGL: - return new AcceleratedSurfaceContainerTouchGLX(compositor, - size, + return new AcceleratedSurfaceContainerTouchGLX(size, surface_handle); case gfx::kGLImplementationEGLGLES2: - return new AcceleratedSurfaceContainerTouchEGL(compositor, - size, + return new AcceleratedSurfaceContainerTouchEGL(size, surface_handle); default: NOTREACHED(); diff --git a/chrome/browser/renderer_host/accelerated_surface_container_touch.h b/chrome/browser/renderer_host/accelerated_surface_container_touch.h index e38532a..4303cd8 100644 --- a/chrome/browser/renderer_host/accelerated_surface_container_touch.h +++ b/chrome/browser/renderer_host/accelerated_surface_container_touch.h @@ -16,7 +16,6 @@ class AcceleratedSurfaceContainerTouch : public ui::TextureGL { public: static AcceleratedSurfaceContainerTouch* CreateAcceleratedSurfaceContainer( - ui::CompositorGL* compositor, const gfx::Size& size, uint64 surface_handle); @@ -26,9 +25,7 @@ class AcceleratedSurfaceContainerTouch : public ui::TextureGL { const gfx::Size& overall_size) OVERRIDE; protected: - AcceleratedSurfaceContainerTouch( - ui::CompositorGL* compositor, - const gfx::Size& size); + explicit AcceleratedSurfaceContainerTouch(const gfx::Size& size); private: DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerTouch); diff --git a/chrome/browser/renderer_host/render_widget_host_view_views_touch.cc b/chrome/browser/renderer_host/render_widget_host_view_views_touch.cc index 2357f4d..2cc3a6c 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_views_touch.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_views_touch.cc @@ -191,7 +191,6 @@ void RenderWidgetHostViewViews::AcceleratedSurfaceSetIOSurface( int32 width, int32 height, uint64 surface_id) { accelerated_surface_containers_[surface_id] = AcceleratedSurfaceContainerTouch::CreateAcceleratedSurfaceContainer( - static_cast<ui::CompositorGL*>(GetWidget()->GetCompositor()), gfx::Size(width, height), surface_id); } diff --git a/ui/gfx/compositor/compositor.h b/ui/gfx/compositor/compositor.h index df575dd..42bb770 100644 --- a/ui/gfx/compositor/compositor.h +++ b/ui/gfx/compositor/compositor.h @@ -10,18 +10,18 @@ #include "ui/gfx/compositor/compositor_export.h" #include "ui/gfx/transform.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gfx/size.h" class SkCanvas; namespace gfx { class Point; class Rect; -class Size; } namespace ui { struct TextureDrawParams { - TextureDrawParams() : transform(), blend(false) {} + TextureDrawParams() : transform(), blend(false), compositor_size() {} // The transform to be applied to the texture. ui::Transform transform; @@ -30,6 +30,9 @@ struct TextureDrawParams { // Otherwise, the drawn pixels clobber the old pixels. bool blend; + // The size of the surface that the texture is drawn to. + gfx::Size compositor_size; + // Copy and assignment are allowed. }; @@ -91,12 +94,23 @@ class COMPOSITOR_EXPORT Compositor : public base::RefCounted<Compositor> { // Notifies the compositor that the size of the widget that it is // drawing to has changed. - virtual void OnWidgetSizeChanged(const gfx::Size& size) = 0; + void WidgetSizeChanged(const gfx::Size& size) { + size_ = size; + OnWidgetSizeChanged(); + } + + // Returns the size of the widget that is being drawn to. + const gfx::Size& size() { return size_; } protected: + explicit Compositor(const gfx::Size& size) : size_(size) {} virtual ~Compositor() {} + virtual void OnWidgetSizeChanged() = 0; + private: + gfx::Size size_; + friend class base::RefCounted<Compositor>; }; diff --git a/ui/gfx/compositor/compositor_gl.cc b/ui/gfx/compositor/compositor_gl.cc index 6d7bd29..c9e6dfa 100644 --- a/ui/gfx/compositor/compositor_gl.cc +++ b/ui/gfx/compositor/compositor_gl.cc @@ -84,35 +84,6 @@ class TextureProgramSwizzleGL : public ui::TextureProgramGL { DISALLOW_COPY_AND_ASSIGN(TextureProgramSwizzleGL); }; -// We share between compositor contexts so that we don't have to compile -// shaders if they have already been compiled in another context. -class SharedResources { - public: - static SharedResources* GetInstance(); - - // Creates a context with shaders active. - scoped_refptr<gfx::GLContext> CreateContext(gfx::GLSurface* surface); - void ContextDestroyed(); - - ui::TextureProgramGL* program_no_swizzle() { - return program_no_swizzle_.get(); - } - - ui::TextureProgramGL* program_swizzle() { return program_swizzle_.get(); } - - private: - friend struct DefaultSingletonTraits<SharedResources>; - - SharedResources(); - virtual ~SharedResources(); - - scoped_refptr<gfx::GLShareGroup> share_group_; - scoped_ptr<ui::TextureProgramGL> program_swizzle_; - scoped_ptr<ui::TextureProgramGL> program_no_swizzle_; - - DISALLOW_COPY_AND_ASSIGN(SharedResources); -}; - GLuint CompileShader(GLenum type, const GLchar* source) { GLuint shader = glCreateShader(type); if (!shader) @@ -175,61 +146,6 @@ bool TextureProgramSwizzleGL::Initialize() { return InitializeCommon(); } -SharedResources::SharedResources() { -} - -SharedResources::~SharedResources() { -} - -// static -SharedResources* SharedResources::GetInstance() { - return Singleton<SharedResources>::get(); -} - -scoped_refptr<gfx::GLContext> SharedResources::CreateContext( - gfx::GLSurface* surface) { - if (share_group_.get()) { - return gfx::GLContext::CreateGLContext(share_group_.get(), surface); - } else { - scoped_refptr<gfx::GLContext> context( - gfx::GLContext::CreateGLContext(NULL, surface)); - context->MakeCurrent(surface); - - if (!program_no_swizzle_.get()) { - scoped_ptr<ui::TextureProgramGL> temp_program( - new TextureProgramNoSwizzleGL()); - if (!temp_program->Initialize()) { - LOG(ERROR) << "Unable to initialize shaders (context = " - << static_cast<void*>(context.get()) << ")"; - return NULL; - } - program_no_swizzle_.swap(temp_program); - } - - if (!program_swizzle_.get()) { - scoped_ptr<ui::TextureProgramGL> temp_program( - new TextureProgramSwizzleGL()); - if (!temp_program->Initialize()) { - LOG(ERROR) << "Unable to initialize shaders (context = " - << static_cast<void*>(context.get()) << ")"; - return NULL; - } - program_swizzle_.swap(temp_program); - } - - share_group_ = context->share_group(); - return context; - } -} - -void SharedResources::ContextDestroyed() { - if (share_group_.get() && share_group_->GetHandle() == NULL) { - share_group_ = NULL; - program_no_swizzle_.reset(); - program_swizzle_.reset(); - } -} - } // namespace namespace ui { @@ -275,20 +191,117 @@ bool TextureProgramGL::InitializeCommon() { return true; } -TextureGL::TextureGL(CompositorGL* compositor) : texture_id_(0), - compositor_(compositor) { +SharedResources::SharedResources() : initialized_(false) { +} + + +SharedResources::~SharedResources() { +} + +// 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; + } +} + +bool SharedResources::Initialize() { + if (initialized_) + return true; + + { + // 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; + } + } + + surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)); + if (!surface_.get()) { + LOG(ERROR) << "Unable to create offscreen GL surface."; + return false; + } + + context_ = gfx::GLContext::CreateGLContext(NULL, surface_.get()); + if (!context_.get()) { + LOG(ERROR) << "Unable to create GL context."; + return false; + } + + program_no_swizzle_.reset(); + program_swizzle_.reset(); + + context_->MakeCurrent(surface_.get()); + + scoped_ptr<ui::TextureProgramGL> temp_program_no_swizzle( + new TextureProgramNoSwizzleGL()); + if (!temp_program_no_swizzle->Initialize()) { + LOG(ERROR) << "Unable to initialize shader."; + return false; + } + + scoped_ptr<ui::TextureProgramGL> temp_program_swizzle( + new TextureProgramSwizzleGL()); + if (!temp_program_swizzle->Initialize()) { + LOG(ERROR) << "Unable to initialize shader."; + return false; + } + + program_no_swizzle_.swap(temp_program_no_swizzle); + program_swizzle_.swap(temp_program_swizzle); + + initialized_ = true; + return true; +} + +void SharedResources::Destroy() { + program_swizzle_.reset(); + program_no_swizzle_.reset(); + + context_ = NULL; + surface_ = NULL; + + initialized_ = false; +} + +bool SharedResources::MakeSharedContextCurrent() { + if (!initialized_) + return false; + else + return context_->MakeCurrent(surface_.get()); +} + +scoped_refptr<gfx::GLContext> SharedResources::CreateContext( + gfx::GLSurface* surface) { + if (initialized_) + return gfx::GLContext::CreateGLContext(context_->share_group(), surface); + else + return NULL; +} + +TextureGL::TextureGL() : texture_id_(0) { } -TextureGL::TextureGL(CompositorGL* compositor, - const gfx::Size& size) - : texture_id_(0), - size_(size), - compositor_(compositor) { +TextureGL::TextureGL(const gfx::Size& size) : texture_id_(0), size_(size) { } TextureGL::~TextureGL() { if (texture_id_) { - compositor_->MakeCurrent(); + SharedResources* instance = SharedResources::GetInstance(); + DCHECK(instance); + instance->MakeSharedContextCurrent(); glDeleteTextures(1, &texture_id_); } } @@ -333,21 +346,27 @@ void TextureGL::SetCanvas(const SkCanvas& canvas, } void TextureGL::Draw(const ui::TextureDrawParams& params) { - DCHECK(compositor_->program_swizzle()); Draw(params, gfx::Rect(0, 0, size_.width(), size_.height())); } void TextureGL::Draw(const ui::TextureDrawParams& params, const gfx::Rect& clip_bounds_in_texture) { - DCHECK(compositor_->program_swizzle()); - DrawInternal(*compositor_->program_swizzle(), params, clip_bounds_in_texture); + SharedResources* instance = SharedResources::GetInstance(); + DCHECK(instance); + DrawInternal(*instance->program_swizzle(), + params, + clip_bounds_in_texture); } + void TextureGL::DrawInternal(const ui::TextureProgramGL& program, const ui::TextureDrawParams& params, const gfx::Rect& clip_bounds_in_texture) { - // clip clip_bounds_in_layer to size of texture - gfx::Rect clip_bounds = clip_bounds_in_texture.Intersect( - gfx::Rect(gfx::Point(0, 0), size_)); + // Clip clip_bounds_in_texture to size of texture. + gfx::Rect clip_bounds = clip_bounds_in_texture.Intersect( + gfx::Rect(gfx::Point(0, 0), size_)); + + // Verify that compositor_size has been set. + DCHECK(params.compositor_size != gfx::Size(0,0)); if (params.blend) glEnable(GL_BLEND); @@ -360,8 +379,6 @@ void TextureGL::DrawInternal(const ui::TextureProgramGL& program, glUniform1i(program.u_tex_loc(), 0); glBindTexture(GL_TEXTURE_2D, texture_id_); - gfx::Size window_size = compositor_->GetSize(); - ui::Transform t; t.ConcatTranslate(1, 1); t.ConcatScale(size_.width()/2.0f, size_.height()/2.0f); @@ -370,15 +387,16 @@ void TextureGL::DrawInternal(const ui::TextureProgramGL& program, t.ConcatTransform(params.transform); // Add view transform. - t.ConcatTranslate(0, -window_size.height()); + t.ConcatTranslate(0, -params.compositor_size.height()); t.ConcatScale(1, -1); - t.ConcatTranslate(-window_size.width() / 2.0f, -window_size.height() / 2.0f); - t.ConcatScale(2.0f / window_size.width(), 2.0f / window_size.height()); + t.ConcatTranslate(-params.compositor_size.width() / 2.0f, + -params.compositor_size.height() / 2.0f); + t.ConcatScale(2.0f / params.compositor_size.width(), + 2.0f / params.compositor_size.height()); GLfloat m[16]; t.matrix().asColMajorf(m); - // TODO(pkotwicz) window_size != size_, fix this SkRect texture_rect = SkRect::MakeXYWH( clip_bounds.x(), clip_bounds.y(), @@ -429,7 +447,7 @@ void TextureGL::DrawInternal(const ui::TextureProgramGL& program, CompositorGL::CompositorGL(gfx::AcceleratedWidget widget, const gfx::Size& size) - : size_(size), + : Compositor(size), started_(false) { gl_surface_ = gfx::GLSurface::CreateViewGLSurface(false, widget); gl_context_ = SharedResources::GetInstance()-> @@ -441,34 +459,24 @@ CompositorGL::CompositorGL(gfx::AcceleratedWidget widget, CompositorGL::~CompositorGL() { gl_context_ = NULL; - SharedResources::GetInstance()->ContextDestroyed(); } void CompositorGL::MakeCurrent() { gl_context_->MakeCurrent(gl_surface_.get()); } -gfx::Size CompositorGL::GetSize() { - return size_; -} - -TextureProgramGL* CompositorGL::program_no_swizzle() { - return SharedResources::GetInstance()->program_no_swizzle(); -} - -TextureProgramGL* CompositorGL::program_swizzle() { - return SharedResources::GetInstance()->program_swizzle(); +void CompositorGL::OnWidgetSizeChanged() { } Texture* CompositorGL::CreateTexture() { - Texture* texture = new TextureGL(this); + Texture* texture = new TextureGL(); return texture; } void CompositorGL::NotifyStart() { started_ = true; gl_context_->MakeCurrent(gl_surface_.get()); - glViewport(0, 0, size_.width(), size_.height()); + glViewport(0, 0, size().width(), size().height()); glColorMask(true, true, true, true); #if defined(DEBUG) @@ -494,21 +502,13 @@ void CompositorGL::SchedulePaint() { NOTIMPLEMENTED(); } -void CompositorGL::OnWidgetSizeChanged(const gfx::Size& size) { - size_ = size; -} - // static Compositor* Compositor::Create(gfx::AcceleratedWidget widget, const gfx::Size& size) { - // 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) + if (SharedResources::GetInstance() == NULL) + return NULL; + else return new CompositorGL(widget, size); - return NULL; } } // namespace ui diff --git a/ui/gfx/compositor/compositor_gl.h b/ui/gfx/compositor/compositor_gl.h index 0872d1e..cfa4756 100644 --- a/ui/gfx/compositor/compositor_gl.h +++ b/ui/gfx/compositor/compositor_gl.h @@ -8,6 +8,8 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" +#include "base/memory/ref_counted.h" #include "ui/gfx/compositor/compositor.h" #include "ui/gfx/size.h" @@ -22,9 +24,48 @@ namespace ui { class CompositorGL; class TextureProgramGL; +// We share resources (such as shaders) between different Compositors via +// GLContext sharing so that we only have to create/destroy them once. +class COMPOSITOR_EXPORT SharedResources { + public: + static SharedResources* GetInstance(); + + bool MakeSharedContextCurrent(); + + // Creates a context that shares the resources hosted by this singleton. + scoped_refptr<gfx::GLContext> CreateContext(gfx::GLSurface* surface); + + ui::TextureProgramGL* program_no_swizzle() { + return program_no_swizzle_.get(); + } + + ui::TextureProgramGL* program_swizzle() { + return program_swizzle_.get(); + } + + private: + friend struct DefaultSingletonTraits<SharedResources>; + + SharedResources(); + virtual ~SharedResources(); + + bool Initialize(); + void Destroy(); + + bool initialized_; + + scoped_refptr<gfx::GLContext> context_; + scoped_refptr<gfx::GLSurface> surface_; + + scoped_ptr<ui::TextureProgramGL> program_swizzle_; + scoped_ptr<ui::TextureProgramGL> program_no_swizzle_; + + DISALLOW_COPY_AND_ASSIGN(SharedResources); +}; + class COMPOSITOR_EXPORT TextureGL : public Texture { public: - explicit TextureGL(CompositorGL* compositor); + TextureGL(); virtual void SetCanvas(const SkCanvas& canvas, const gfx::Point& origin, @@ -39,7 +80,7 @@ class COMPOSITOR_EXPORT TextureGL : public Texture { const gfx::Rect& clip_bounds_in_texture) OVERRIDE; protected: - TextureGL(CompositorGL* compositor, const gfx::Size& size); + explicit TextureGL(const gfx::Size& size); virtual ~TextureGL(); // Actually draws the texture. @@ -50,7 +91,6 @@ class COMPOSITOR_EXPORT TextureGL : public Texture { unsigned int texture_id_; gfx::Size size_; - CompositorGL* compositor_; private: DISALLOW_COPY_AND_ASSIGN(TextureGL); @@ -64,8 +104,8 @@ class COMPOSITOR_EXPORT CompositorGL : public Compositor { void MakeCurrent(); gfx::Size GetSize(); - TextureProgramGL* program_no_swizzle(); - TextureProgramGL* program_swizzle(); + protected: + virtual void OnWidgetSizeChanged() OVERRIDE; private: // Overridden from Compositor. @@ -74,14 +114,11 @@ class COMPOSITOR_EXPORT CompositorGL : public Compositor { virtual void NotifyEnd() OVERRIDE; virtual void Blur(const gfx::Rect& bounds) OVERRIDE; virtual void SchedulePaint() OVERRIDE; - virtual void OnWidgetSizeChanged(const gfx::Size& size) OVERRIDE; // The GL context used for compositing. scoped_refptr<gfx::GLSurface> gl_surface_; scoped_refptr<gfx::GLContext> gl_context_; - gfx::Size size_; - // Keep track of whether compositing has started or not. bool started_; diff --git a/ui/gfx/compositor/compositor_win.cc b/ui/gfx/compositor/compositor_win.cc index 3afb3c4..346fd13 100644 --- a/ui/gfx/compositor/compositor_win.cc +++ b/ui/gfx/compositor/compositor_win.cc @@ -56,7 +56,6 @@ class ViewTexture : public Texture { const gfx::Point& origin, const gfx::Size& overall_size) OVERRIDE; virtual void Draw(const ui::TextureDrawParams& params) OVERRIDE; - virtual void Draw(const ui::TextureDrawParams& params, const gfx::Rect& clip_bounds_in_texture) OVERRIDE; @@ -97,9 +96,6 @@ class CompositorWin : public Compositor { void UpdatePerspective(const ui::Transform& transform, const gfx::Size& view_size); - // Returns the overall size of the compositor. - const gfx::Size& GetHostSize(); - // Returns the index buffer used for drawing a texture. ID3D10Buffer* GetTextureIndexBuffer(); @@ -109,7 +105,9 @@ class CompositorWin : public Compositor { virtual void NotifyEnd() OVERRIDE; virtual void Blur(const gfx::Rect& bounds) OVERRIDE; virtual void SchedulePaint() OVERRIDE; - virtual void OnWidgetSizeChanged(const gfx::Size& size) OVERRIDE; + + protected: + virtual void OnWidgetSizeChanged() OVERRIDE; private: enum Direction { @@ -127,8 +125,6 @@ class CompositorWin : public Compositor { void InitVertexLayout(); - void Resize(const gfx::Size& size); - // Updates the kernel used for blurring. Size is the size of the texture // being drawn to along the appropriate axis. void UpdateBlurKernel(Direction direction, int size); @@ -151,9 +147,6 @@ class CompositorWin : public Compositor { gfx::AcceleratedWidget host_; - // Size the device was last created at. - gfx::Size last_size_; - ScopedComPtr<ID3D10Device> device_; ScopedComPtr<IDXGISwapChain> swap_chain_; ScopedComPtr<ID3D10RenderTargetView> dest_render_target_view_; @@ -305,7 +298,7 @@ void ViewTexture::ConvertBitmapToD3DData( void ViewTexture::CreateVertexBuffer(const gfx::Size& size) { vertex_buffer_.Release(); - const gfx::Size& host_size = compositor_->GetHostSize(); + const gfx::Size& host_size = compositor_->size(); float x = static_cast<float>(host_size.width()) / 2.0f; float y = static_cast<float>(host_size.height()) / 2.0f; float w = static_cast<float>(size.width()); @@ -332,15 +325,15 @@ void ViewTexture::CreateVertexBuffer(const gfx::Size& size) { CompositorWin::CompositorWin(gfx::AcceleratedWidget widget, const gfx::Size& size) - : host_(widget), - technique_(NULL), - last_size_(size) { + : Compositor(size), + host_(widget), + technique_(NULL) { } void CompositorWin::Init() { CreateDevice(); LoadEffects(); - Resize(last_size_); + OnWidgetSizeChanged(); InitVertexLayout(); CreateVertexBuffer(); CreateIndexBuffer(); @@ -362,8 +355,8 @@ void CompositorWin::UpdatePerspective(const ui::Transform& transform, D3DXMATRIX scale_matrix; D3DXMatrixScaling( &scale_matrix, - 2.0f / static_cast<float>(last_size_.width()), - 2.0f / static_cast<float>(last_size_.height()), + 2.0f / static_cast<float>(size().width()), + 2.0f / static_cast<float>(size().height()), 1.0f); // Translate so x and y are from -1,-1 to 1,1. @@ -387,10 +380,6 @@ void CompositorWin::UpdatePerspective(const ui::Transform& transform, fx_->GetVariableByName("gWVP")->AsMatrix()->SetMatrix(wvp); } -const gfx::Size& CompositorWin::GetHostSize() { - return last_size_; -} - ID3D10Buffer* CompositorWin::GetTextureIndexBuffer() { return index_buffer_.get(); } @@ -469,7 +458,7 @@ void CompositorWin::Blur(const gfx::Rect& bounds) { D3DXMatrixIdentity(&identity_matrix); // Horizontal blur from the main texture to blur texture. - UpdateBlurKernel(HORIZONTAL, last_size_.width()); + UpdateBlurKernel(HORIZONTAL, size().width()); ID3D10RenderTargetView* target_view = blur_render_target_view_.get(); device_->OMSetRenderTargets(1, &target_view, NULL); RETURN_IF_FAILED( @@ -495,7 +484,7 @@ void CompositorWin::Blur(const gfx::Rect& bounds) { RETURN_IF_FAILED( blur_fx_->GetVariableByName("textureMap")->AsShaderResource()-> SetResource(blur_texture_shader_view_.get())); - UpdateBlurKernel(VERTICAL, last_size_.height()); + UpdateBlurKernel(VERTICAL, size().height()); target_view = main_render_target_view_.get(); device_->OMSetRenderTargets(1, &target_view, NULL); for(UINT p = 0; p < tech_desc.Passes; ++p) @@ -518,8 +507,69 @@ void CompositorWin::SchedulePaint() { InvalidateRect(host_, &bounds, FALSE); } -void CompositorWin::OnWidgetSizeChanged(const gfx::Size& size) { - Resize(size); +void CompositorWin::OnWidgetSizeChanged() { + dest_render_target_view_ = NULL; + depth_stencil_buffer_ = NULL; + depth_stencil_view_ = NULL; + + main_render_target_view_ = NULL; + main_texture_ = NULL; + main_texture_shader_view_ = NULL; + + blur_render_target_view_ = NULL; + blur_texture_ = NULL; + blur_texture_shader_view_ = NULL; + + CreateTexture(size(), main_texture_.Receive(), + main_render_target_view_.Receive(), + main_texture_shader_view_.Receive()); + + CreateTexture(size(), blur_texture_.Receive(), + blur_render_target_view_.Receive(), + blur_texture_shader_view_.Receive()); + + // Resize the swap chain and recreate the render target view. + RETURN_IF_FAILED(swap_chain_->ResizeBuffers( + 1, size().width(), size().height(), DXGI_FORMAT_R8G8B8A8_UNORM, 0)); + ScopedComPtr<ID3D10Texture2D> back_buffer; + RETURN_IF_FAILED(swap_chain_->GetBuffer( + 0, __uuidof(ID3D10Texture2D), + reinterpret_cast<void**>(back_buffer.Receive()))); + RETURN_IF_FAILED(device_->CreateRenderTargetView( + back_buffer.get(), 0, + dest_render_target_view_.Receive())); + + // Create the depth/stencil buffer and view. + D3D10_TEXTURE2D_DESC depth_stencil_desc; + depth_stencil_desc.Width = size().width(); + depth_stencil_desc.Height = size().height(); + depth_stencil_desc.MipLevels = 1; + depth_stencil_desc.ArraySize = 1; + depth_stencil_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + depth_stencil_desc.SampleDesc.Count = 1; // multisampling must match + depth_stencil_desc.SampleDesc.Quality = 0; // swap chain values. + depth_stencil_desc.Usage = D3D10_USAGE_DEFAULT; + depth_stencil_desc.BindFlags = D3D10_BIND_DEPTH_STENCIL; + depth_stencil_desc.CPUAccessFlags = 0; + depth_stencil_desc.MiscFlags = 0; + + RETURN_IF_FAILED(device_->CreateTexture2D(&depth_stencil_desc, 0, + depth_stencil_buffer_.Receive())); + RETURN_IF_FAILED(device_->CreateDepthStencilView( + depth_stencil_buffer_.get(), 0, + depth_stencil_view_.Receive())); + + + // Set the viewport transform. + D3D10_VIEWPORT vp; + vp.TopLeftX = 0; + vp.TopLeftY = 0; + vp.Width = size().width(); + vp.Height = size().height(); + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + + device_->RSSetViewports(1, &vp); } CompositorWin::~CompositorWin() { @@ -532,8 +582,8 @@ void CompositorWin::Errored(HRESULT error_code) { void CompositorWin::CreateDevice() { DXGI_SWAP_CHAIN_DESC sd; - sd.BufferDesc.Width = last_size_.width(); - sd.BufferDesc.Height = last_size_.height(); + sd.BufferDesc.Width = size().width(); + sd.BufferDesc.Height = size().height(); sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; @@ -616,73 +666,6 @@ void CompositorWin::InitVertexLayout() { vertex_layout_.Receive())); } -void CompositorWin::Resize(const gfx::Size& size) { - last_size_ = size; - - dest_render_target_view_ = NULL; - depth_stencil_buffer_ = NULL; - depth_stencil_view_ = NULL; - - main_render_target_view_ = NULL; - main_texture_ = NULL; - main_texture_shader_view_ = NULL; - - blur_render_target_view_ = NULL; - blur_texture_ = NULL; - blur_texture_shader_view_ = NULL; - - CreateTexture(size, main_texture_.Receive(), - main_render_target_view_.Receive(), - main_texture_shader_view_.Receive()); - - CreateTexture(size, blur_texture_.Receive(), - blur_render_target_view_.Receive(), - blur_texture_shader_view_.Receive()); - - // Resize the swap chain and recreate the render target view. - RETURN_IF_FAILED(swap_chain_->ResizeBuffers( - 1, size.width(), size.height(), DXGI_FORMAT_R8G8B8A8_UNORM, 0)); - ScopedComPtr<ID3D10Texture2D> back_buffer; - RETURN_IF_FAILED(swap_chain_->GetBuffer( - 0, __uuidof(ID3D10Texture2D), - reinterpret_cast<void**>(back_buffer.Receive()))); - RETURN_IF_FAILED(device_->CreateRenderTargetView( - back_buffer.get(), 0, - dest_render_target_view_.Receive())); - - // Create the depth/stencil buffer and view. - D3D10_TEXTURE2D_DESC depth_stencil_desc; - depth_stencil_desc.Width = size.width(); - depth_stencil_desc.Height = size.height(); - depth_stencil_desc.MipLevels = 1; - depth_stencil_desc.ArraySize = 1; - depth_stencil_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; - depth_stencil_desc.SampleDesc.Count = 1; // multisampling must match - depth_stencil_desc.SampleDesc.Quality = 0; // swap chain values. - depth_stencil_desc.Usage = D3D10_USAGE_DEFAULT; - depth_stencil_desc.BindFlags = D3D10_BIND_DEPTH_STENCIL; - depth_stencil_desc.CPUAccessFlags = 0; - depth_stencil_desc.MiscFlags = 0; - - RETURN_IF_FAILED(device_->CreateTexture2D(&depth_stencil_desc, 0, - depth_stencil_buffer_.Receive())); - RETURN_IF_FAILED(device_->CreateDepthStencilView( - depth_stencil_buffer_.get(), 0, - depth_stencil_view_.Receive())); - - - // Set the viewport transform. - D3D10_VIEWPORT vp; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - vp.Width = size.width(); - vp.Height = size.height(); - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - - device_->RSSetViewports(1, &vp); -} - void CompositorWin::UpdateBlurKernel(Direction direction, int size) { // Update the blur data. const int kSize = 13; @@ -773,14 +756,14 @@ void CompositorWin::CreateIndexBuffer() { ID3D10Buffer* CompositorWin::CreateVertexBufferForRegion( const gfx::Rect& bounds) { float x = static_cast<float>(bounds.x()) / - static_cast<float>(last_size_.width()) * 2.0f - 1.0f; + static_cast<float>(size().width()) * 2.0f - 1.0f; float max_x = - x + bounds.width() / static_cast<float>(last_size_.width()) * 2.0f; + x + bounds.width() / static_cast<float>(size().width()) * 2.0f; float y = - static_cast<float>(last_size_.height() - bounds.y() - bounds.height()) / - static_cast<float>(last_size_.height()) * 2.0f - 1.0f; + static_cast<float>(size().height() - bounds.y() - bounds.height()) / + static_cast<float>(size().height()) * 2.0f - 1.0f; float max_y = - y + bounds.height() / static_cast<float>(last_size_.height()) * 2.0f; + y + bounds.height() / static_cast<float>(size().height()) * 2.0f; float tex_x = x / 2.0f + .5f; float max_tex_x = max_x / 2.0f + .5f; float tex_y = 1.0f - (max_y + 1.0f) / 2.0f; diff --git a/ui/gfx/compositor/layer.cc b/ui/gfx/compositor/layer.cc index 214b07e..8061294 100644 --- a/ui/gfx/compositor/layer.cc +++ b/ui/gfx/compositor/layer.cc @@ -92,6 +92,7 @@ void Layer::Draw() { // Only blend for transparent child layers. // The root layer will clobber the cleared bg. texture_draw_params.blend = parent_ != NULL && !fills_bounds_opaquely_; + texture_draw_params.compositor_size = compositor_->size(); #if defined(OS_WIN) texture_->Draw(texture_draw_params); diff --git a/views/view_unittest.cc b/views/view_unittest.cc index 09483bc..94d6d4d 100644 --- a/views/view_unittest.cc +++ b/views/view_unittest.cc @@ -2358,7 +2358,9 @@ class TestCompositor : public ui::Compositor { virtual void NotifyEnd() OVERRIDE {} virtual void Blur(const gfx::Rect& bounds) OVERRIDE {} virtual void SchedulePaint() OVERRIDE {} - virtual void OnWidgetSizeChanged(const gfx::Size& size) OVERRIDE {} + + protected: + virtual void OnWidgetSizeChanged() OVERRIDE {} private: DISALLOW_COPY_AND_ASSIGN(TestCompositor); diff --git a/views/widget/native_widget_gtk.cc b/views/widget/native_widget_gtk.cc index 75778c9..dae9c95 100644 --- a/views/widget/native_widget_gtk.cc +++ b/views/widget/native_widget_gtk.cc @@ -1350,7 +1350,7 @@ void NativeWidgetGtk::OnSizeAllocate(GtkWidget* widget, return; size_ = new_size; if (compositor_.get()) - compositor_->OnWidgetSizeChanged(size_); + compositor_->WidgetSizeChanged(size_); delegate_->OnNativeWidgetSizeChanged(size_); if (GetWidget()->non_client_view()) { diff --git a/views/widget/native_widget_win.cc b/views/widget/native_widget_win.cc index 8c20b03..9e1415b 100644 --- a/views/widget/native_widget_win.cc +++ b/views/widget/native_widget_win.cc @@ -2304,7 +2304,7 @@ void NativeWidgetWin::ClientAreaSizeChanged() { gfx::Size s(std::max(0, static_cast<int>(r.right - r.left)), std::max(0, static_cast<int>(r.bottom - r.top))); if (compositor_.get()) - compositor_->OnWidgetSizeChanged(s); + compositor_->WidgetSizeChanged(s); delegate_->OnNativeWidgetSizeChanged(s); if (use_layered_buffer_) { layered_window_contents_.reset( |