diff options
24 files changed, 638 insertions, 60 deletions
diff --git a/content/browser/renderer_host/accelerated_surface_container_linux.cc b/content/browser/renderer_host/accelerated_surface_container_linux.cc new file mode 100644 index 0000000..bae032da --- /dev/null +++ b/content/browser/renderer_host/accelerated_surface_container_linux.cc @@ -0,0 +1,397 @@ +// Copyright (c) 2011 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/accelerated_surface_container_linux.h" + +#include <X11/Xlib.h> +#include <X11/extensions/Xcomposite.h> + +#include "base/lazy_instance.h" +#include "base/memory/scoped_ptr.h" +#include "third_party/angle/include/EGL/egl.h" +#include "third_party/angle/include/EGL/eglext.h" +#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/gl/gl_surface_glx.h" +#include "ui/gfx/rect.h" +#include "ui/gfx/transform.h" + +namespace { + +class AcceleratedSurfaceContainerLinuxEGL + : public AcceleratedSurfaceContainerLinux { + public: + explicit AcceleratedSurfaceContainerLinuxEGL(const gfx::Size& size); + + virtual bool Initialize(uint64* surface_id) OVERRIDE; + + // TextureGL implementation + virtual void Draw(const ui::TextureDrawParams& params, + const gfx::Rect& clip_bounds_in_texture) OVERRIDE; + + private: + virtual ~AcceleratedSurfaceContainerLinuxEGL(); + + void* image_; + + DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxEGL); +}; + +class AcceleratedSurfaceContainerLinuxGLX + : public AcceleratedSurfaceContainerLinux { + public: + explicit AcceleratedSurfaceContainerLinuxGLX(const gfx::Size& size); + + virtual bool Initialize(uint64* surface_id) OVERRIDE; + + // TextureGL implementation + virtual void Draw(const ui::TextureDrawParams& params, + const gfx::Rect& clip_bounds_in_texture) OVERRIDE; + + protected: + static bool InitializeOneOff(); + + static base::LazyInstance<GLXFBConfig> fbconfig_; + + private: + virtual ~AcceleratedSurfaceContainerLinuxGLX(); + + XID pixmap_; + XID glx_pixmap_; + + DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxGLX); +}; + +class AcceleratedSurfaceContainerLinuxOSMesa + : public AcceleratedSurfaceContainerLinux { + public: + explicit AcceleratedSurfaceContainerLinuxOSMesa(const gfx::Size& size); + + virtual bool Initialize(uint64* surface_id) OVERRIDE; + + // TextureGL implementation + virtual void Draw(const ui::TextureDrawParams& params, + const gfx::Rect& clip_bounds_in_texture) OVERRIDE; + + // Some implementations of this class use shared memory, this gives the handle + // to the shared buffer, which is part of the surface container. + // When shared memory is not used, this will return + // TransportDIB::DefaultHandleValue(). + virtual TransportDIB::Handle Handle() const OVERRIDE; + + private: + virtual ~AcceleratedSurfaceContainerLinuxOSMesa(); + + scoped_ptr<TransportDIB> shared_mem_; + + DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxOSMesa); +}; + +class ScopedPtrXFree { + public: + void operator()(void* x) const { + ::XFree(x); + } +}; + +// static +base::LazyInstance<GLXFBConfig> AcceleratedSurfaceContainerLinuxGLX::fbconfig_( + base::LINKER_INITIALIZED); + +AcceleratedSurfaceContainerLinuxEGL::AcceleratedSurfaceContainerLinuxEGL( + const gfx::Size& size) + : AcceleratedSurfaceContainerLinux(size), + image_(NULL) { +} + +bool AcceleratedSurfaceContainerLinuxEGL::Initialize(uint64* surface_id) { + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + instance->MakeSharedContextCurrent(); + + image_ = eglCreateImageKHR( + gfx::GLSurfaceEGL::GetHardwareDisplay(), EGL_NO_CONTEXT, + EGL_NATIVE_PIXMAP_KHR, reinterpret_cast<void*>(*surface_id), NULL); + + glGenTextures(1, &texture_id_); + glBindTexture(GL_TEXTURE_2D, texture_id_); + 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); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_); + glFlush(); + + return true; +} + +AcceleratedSurfaceContainerLinuxEGL::~AcceleratedSurfaceContainerLinuxEGL() { + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + instance->MakeSharedContextCurrent(); + + eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), image_); + glFlush(); +} + +void AcceleratedSurfaceContainerLinuxEGL::Draw( + const ui::TextureDrawParams& params, + const gfx::Rect& clip_bounds_in_texture) { + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + + ui::TextureDrawParams modified_params = params; + modified_params.vertically_flipped = true; + + DrawInternal(*instance->program_no_swizzle(), + modified_params, + clip_bounds_in_texture); +} + +AcceleratedSurfaceContainerLinuxGLX::AcceleratedSurfaceContainerLinuxGLX( + const gfx::Size& size) + : AcceleratedSurfaceContainerLinux(size), + pixmap_(0), + glx_pixmap_(0) { +} + +bool AcceleratedSurfaceContainerLinuxGLX::Initialize(uint64* surface_id) { + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + instance->MakeSharedContextCurrent(); + + if (!AcceleratedSurfaceContainerLinuxGLX::InitializeOneOff()) + 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. + Display* dpy = instance->GetDisplay(); + pixmap_ = XCompositeNameWindowPixmap(dpy, *surface_id); + + // Wrap the pixmap in a GLXPixmap + 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); + + // Create texture. + glGenTextures(1, &texture_id_); + glBindTexture(GL_TEXTURE_2D, texture_id_); + 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 true; +} + +AcceleratedSurfaceContainerLinuxGLX::~AcceleratedSurfaceContainerLinuxGLX() { + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + instance->MakeSharedContextCurrent(); + + Display* dpy = instance->GetDisplay(); + if (glx_pixmap_) + glXDestroyGLXPixmap(dpy, glx_pixmap_); + if (pixmap_) + XFreePixmap(dpy, pixmap_); +} + +void AcceleratedSurfaceContainerLinuxGLX::Draw( + const ui::TextureDrawParams& params, + const gfx::Rect& clip_bounds_in_texture) { + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + + Display* dpy = instance->GetDisplay(); + + glBindTexture(GL_TEXTURE_2D, texture_id_); + glXBindTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL); + DrawInternal(*instance->program_no_swizzle(), + params, + clip_bounds_in_texture); + glXReleaseTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT); +} + +// static +bool AcceleratedSurfaceContainerLinuxGLX::InitializeOneOff() +{ + static bool initialized = false; + if (initialized) + return true; + + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + + Display* dpy = instance->GetDisplay(); + 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; +} + +AcceleratedSurfaceContainerLinuxOSMesa::AcceleratedSurfaceContainerLinuxOSMesa( + const gfx::Size& size) + : AcceleratedSurfaceContainerLinux(size) { +} + +bool AcceleratedSurfaceContainerLinuxOSMesa::Initialize(uint64* surface_id) { + static uint32 next_id = 1; + + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + instance->MakeSharedContextCurrent(); + + // We expect to make the id here, so don't want the other end giving us one + DCHECK_EQ(*surface_id, static_cast<uint64>(0)); + + // It's possible that this ID gneration could clash with IDs from other + // AcceleratedSurfaceContainerLinux* 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_id = next_id++; + + shared_mem_.reset( + TransportDIB::Create(size_.GetArea() * 4, // GL_RGBA=4 B/px + *surface_id)); + // Create texture. + glGenTextures(1, &texture_id_); + glBindTexture(GL_TEXTURE_2D, texture_id_); + 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); + + // we generate the ID to be used here. + return true; +} + +void AcceleratedSurfaceContainerLinuxOSMesa::Draw( + const ui::TextureDrawParams& params, + const gfx::Rect& clip_bounds_in_texture) { + ui::SharedResources* instance = ui::SharedResources::GetInstance(); + DCHECK(instance); + + if (shared_mem_.get()) { + 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()); + + DrawInternal(*instance->program_no_swizzle(), + params, + clip_bounds_in_texture); + } +} + +TransportDIB::Handle AcceleratedSurfaceContainerLinuxOSMesa::Handle() const { + if (shared_mem_.get()) + return shared_mem_->handle(); + else + return TransportDIB::DefaultHandleValue(); +} + +AcceleratedSurfaceContainerLinuxOSMesa:: + ~AcceleratedSurfaceContainerLinuxOSMesa() { +} + +} // namespace + +AcceleratedSurfaceContainerLinux::AcceleratedSurfaceContainerLinux( + const gfx::Size& size) : TextureGL(size) { +} + +TransportDIB::Handle AcceleratedSurfaceContainerLinux::Handle() const { + return TransportDIB::DefaultHandleValue(); +} + +// static +AcceleratedSurfaceContainerLinux* +AcceleratedSurfaceContainerLinux::CreateAcceleratedSurfaceContainer( + const gfx::Size& size) { + switch (gfx::GetGLImplementation()) { + case gfx::kGLImplementationDesktopGL: + return new AcceleratedSurfaceContainerLinuxGLX(size); + case gfx::kGLImplementationEGLGLES2: + return new AcceleratedSurfaceContainerLinuxEGL(size); + case gfx::kGLImplementationOSMesaGL: + return new AcceleratedSurfaceContainerLinuxOSMesa(size); + default: + NOTREACHED(); + return NULL; + } +} + +void AcceleratedSurfaceContainerLinux::SetCanvas( + const SkCanvas& canvas, + const gfx::Point& origin, + const gfx::Size& overall_size) { + NOTREACHED(); +} + diff --git a/content/browser/renderer_host/image_transport_client.cc b/content/browser/renderer_host/image_transport_client.cc index 4d0c7fd..c2b2b1e 100644 --- a/content/browser/renderer_host/image_transport_client.cc +++ b/content/browser/renderer_host/image_transport_client.cc @@ -88,7 +88,7 @@ class ImageTransportClientGLX : public ImageTransportClient { } virtual ~ImageTransportClientGLX() { - Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + Display* dpy = static_cast<Display*>(resources_->GetDisplay()); if (glx_pixmap_) glXDestroyGLXPixmap(dpy, glx_pixmap_); if (pixmap_) @@ -96,15 +96,16 @@ class ImageTransportClientGLX : public ImageTransportClient { } virtual unsigned int Initialize(uint64* surface_id) { + Display* dpy = static_cast<Display*>(resources_->GetDisplay()); + resources_->MakeSharedContextCurrent(); - if (!InitializeOneOff()) + if (!InitializeOneOff(dpy)) return 0; // 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. - Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); pixmap_ = XCompositeNameWindowPixmap(dpy, *surface_id); const int pixmapAttribs[] = { @@ -120,13 +121,13 @@ class ImageTransportClientGLX : public ImageTransportClient { } virtual void Acquire() { - Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + Display* dpy = static_cast<Display*>(resources_->GetDisplay()); glBindTexture(GL_TEXTURE_2D, texture_); glXBindTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL); } virtual void Release() { - Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + Display* dpy = static_cast<Display*>(resources_->GetDisplay()); glXReleaseTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT); } @@ -136,13 +137,11 @@ class ImageTransportClientGLX : public ImageTransportClient { } private: - static bool InitializeOneOff() { + static bool InitializeOneOff(Display* dpy) { static bool initialized = false; if (initialized) return true; - Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); - int event_base, error_base; if (XCompositeQueryExtension(dpy, &event_base, &error_base)) { int major = 0, minor = 2; diff --git a/content/common/gpu/image_transport_surface_linux.cc b/content/common/gpu/image_transport_surface_linux.cc index bd63e04..77f176e 100644 --- a/content/common/gpu/image_transport_surface_linux.cc +++ b/content/common/gpu/image_transport_surface_linux.cc @@ -393,7 +393,7 @@ GLXImageTransportSurface::~GLXImageTransportSurface() { bool GLXImageTransportSurface::Initialize() { // Create a dummy window to host the real window. - Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + Display* dpy = static_cast<Display*>(GetDisplay()); XSetWindowAttributes swa; swa.event_mask = StructureNotifyMask; swa.override_redirect = True; @@ -439,7 +439,7 @@ void GLXImageTransportSurface::Destroy() { ReleaseSurface(); if (window_) { - Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + Display* dpy = static_cast<Display*>(GetDisplay()); XDestroyWindow(dpy, window_); XDestroyWindow(dpy, dummy_parent_); } @@ -462,7 +462,7 @@ void GLXImageTransportSurface::OnResize(gfx::Size size) { bound_ = false; } - Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + Display* dpy = static_cast<Display*>(GetDisplay()); XResizeWindow(dpy, window_, size_.width(), size_.height()); XFlush(dpy); @@ -496,7 +496,7 @@ bool GLXImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { return true; // Check for driver support. - Display* dpy = gfx::GLSurfaceGLX::GetDisplay(); + Display* dpy = static_cast<Display*>(GetDisplay()); int event_base, error_base; if (XCompositeQueryExtension(dpy, &event_base, &error_base)) { int major = 0, minor = 2; diff --git a/ui/gfx/compositor/compositor.h b/ui/gfx/compositor/compositor.h index 78c4a60..2522364 100644 --- a/ui/gfx/compositor/compositor.h +++ b/ui/gfx/compositor/compositor.h @@ -28,6 +28,7 @@ class SharedResources { public: virtual ~SharedResources() {} virtual bool MakeSharedContextCurrent() = 0; + virtual void* GetDisplay() = 0; }; struct TextureDrawParams { diff --git a/ui/gfx/compositor/compositor_cc.cc b/ui/gfx/compositor/compositor_cc.cc index d8b8e5a5..754b6a8 100644 --- a/ui/gfx/compositor/compositor_cc.cc +++ b/ui/gfx/compositor/compositor_cc.cc @@ -86,6 +86,10 @@ bool SharedResourcesCC::MakeSharedContextCurrent() { return context_->MakeCurrent(surface_.get()); } +void* SharedResourcesCC::GetDisplay() { + return surface_->GetDisplay(); +} + gfx::GLShareGroup* SharedResourcesCC::GetShareGroup() { DCHECK(initialized_); return context_->share_group(); diff --git a/ui/gfx/compositor/compositor_cc.h b/ui/gfx/compositor/compositor_cc.h index a4e9f69..1bd4b58 100644 --- a/ui/gfx/compositor/compositor_cc.h +++ b/ui/gfx/compositor/compositor_cc.h @@ -30,6 +30,8 @@ class COMPOSITOR_EXPORT SharedResourcesCC : public SharedResources { static SharedResourcesCC* GetInstance(); virtual bool MakeSharedContextCurrent(); + virtual void* GetDisplay(); + gfx::GLShareGroup* GetShareGroup(); private: diff --git a/ui/gfx/compositor/compositor_gl.cc b/ui/gfx/compositor/compositor_gl.cc index 2a6d0d5..0f0451b 100644 --- a/ui/gfx/compositor/compositor_gl.cc +++ b/ui/gfx/compositor/compositor_gl.cc @@ -314,6 +314,10 @@ scoped_refptr<gfx::GLContext> SharedResourcesGL::CreateContext( return NULL; } +void* SharedResourcesGL::GetDisplay() { + return surface_->GetDisplay(); +} + TextureGL::TextureGL() : texture_id_(0) { } diff --git a/ui/gfx/compositor/compositor_gl.h b/ui/gfx/compositor/compositor_gl.h index 00088b4..cc59c68 100644 --- a/ui/gfx/compositor/compositor_gl.h +++ b/ui/gfx/compositor/compositor_gl.h @@ -35,6 +35,8 @@ class COMPOSITOR_EXPORT SharedResourcesGL : public SharedResources { // Creates a context that shares the resources hosted by this singleton. scoped_refptr<gfx::GLContext> CreateContext(gfx::GLSurface* surface); + virtual void* GetDisplay(); + ui::TextureProgramGL* program_no_swizzle() { return program_no_swizzle_.get(); } diff --git a/ui/gfx/gl/generate_bindings.py b/ui/gfx/gl/generate_bindings.py index b3f52fb..9d5ecf8 100644 --- a/ui/gfx/gl/generate_bindings.py +++ b/ui/gfx/gl/generate_bindings.py @@ -362,6 +362,8 @@ EGL_FUNCTIONS = [ 'EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target'], ['__eglMustCastToProperFunctionPointerType', ['eglGetProcAddress'], 'const char* procname'], +['EGLBoolean', ['eglQuerySurfacePointerANGLE'], + 'EGLDisplay dpy, EGLSurface surface, EGLint attribute, void** value'], ] WGL_FUNCTIONS = [ diff --git a/ui/gfx/gl/gl_context_egl.cc b/ui/gfx/gl/gl_context_egl.cc index ffaaaea..6c69f79 100644 --- a/ui/gfx/gl/gl_context_egl.cc +++ b/ui/gfx/gl/gl_context_egl.cc @@ -8,8 +8,8 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "third_party/angle/include/EGL/egl.h" -#include "ui/gfx/gl/gl_surface_egl.h" #include "ui/gfx/gl/egl_util.h" +#include "ui/gfx/gl/gl_surface.h" // This header must come after the above third-party include, as // it brings in #defines that cause conflicts. @@ -52,9 +52,8 @@ bool GLContextEGL::Initialize( EGL_NONE }; - GLSurfaceEGL* egl_surface = static_cast<GLSurfaceEGL*>(compatible_surface); - display_ = egl_surface->GetDisplay(); - config_ = egl_surface->GetConfig(); + display_ = compatible_surface->GetDisplay(); + config_ = compatible_surface->GetConfig(); context_ = eglCreateContext( display_, diff --git a/ui/gfx/gl/gl_context_glx.cc b/ui/gfx/gl/gl_context_glx.cc index 0797721..0f392e6 100644 --- a/ui/gfx/gl/gl_context_glx.cc +++ b/ui/gfx/gl/gl_context_glx.cc @@ -46,7 +46,8 @@ bool IsCompositingWindowManagerActive(Display* display) { GLContextGLX::GLContextGLX(GLShareGroup* share_group) : GLContext(share_group), - context_(NULL) { + context_(NULL), + display_(NULL) { } GLContextGLX::~GLContextGLX() { @@ -55,7 +56,7 @@ GLContextGLX::~GLContextGLX() { bool GLContextGLX::Initialize( GLSurface* compatible_surface, GpuPreference gpu_preference) { - GLSurfaceGLX* surface_glx = static_cast<GLSurfaceGLX*>(compatible_surface); + display_ = static_cast<Display*>(compatible_surface->GetDisplay()); GLXContext share_handle = static_cast<GLXContext>( share_group() ? share_group()->GetHandle() : NULL); @@ -68,14 +69,15 @@ bool GLContextGLX::Initialize( attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB); attribs.push_back(0); context_ = glXCreateContextAttribsARB( - GLSurfaceGLX::GetDisplay(), - static_cast<GLXFBConfig>(surface_glx->GetConfig()), + display_, + static_cast<GLXFBConfig>(compatible_surface->GetConfig()), share_handle, True, &attribs.front()); if (context_) { DLOG(INFO) << " Successfully allocated " - << (surface_glx->IsOffscreen() ? "offscreen" : "onscreen") + << (compatible_surface->IsOffscreen() ? + "offscreen" : "onscreen") << " GL context with LOSE_CONTEXT_ON_RESET_ARB"; } else { // TODO(kbr): it is not expected that things will work properly @@ -93,24 +95,23 @@ bool GLContextGLX::Initialize( // The means by which the context is created depends on whether // the drawable type works reliably with GLX 1.3. If it does not // then fall back to GLX 1.2. - if (surface_glx->IsOffscreen()) { + if (compatible_surface->IsOffscreen()) { context_ = glXCreateNewContext( - GLSurfaceGLX::GetDisplay(), - static_cast<GLXFBConfig>(surface_glx->GetConfig()), + display_, + static_cast<GLXFBConfig>(compatible_surface->GetConfig()), GLX_RGBA_TYPE, share_handle, True); } else { - Display* display = GLSurfaceGLX::GetDisplay(); - // Get the visuals for the X drawable. XWindowAttributes attributes; if (!XGetWindowAttributes( - display, - reinterpret_cast<GLXDrawable>(surface_glx->GetHandle()), + display_, + reinterpret_cast<GLXDrawable>(compatible_surface->GetHandle()), &attributes)) { LOG(ERROR) << "XGetWindowAttributes failed for window " << - reinterpret_cast<GLXDrawable>(surface_glx->GetHandle()) << "."; + reinterpret_cast<GLXDrawable>( + compatible_surface->GetHandle()) << "."; return false; } @@ -119,7 +120,7 @@ bool GLContextGLX::Initialize( int visual_info_count = 0; scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list( - XGetVisualInfo(display, VisualIDMask, + XGetVisualInfo(display_, VisualIDMask, &visual_info_template, &visual_info_count)); @@ -131,7 +132,7 @@ bool GLContextGLX::Initialize( // Attempt to create a context with each visual in turn until one works. context_ = glXCreateContext( - display, + display_, visual_info_list.get(), share_handle, True); @@ -144,9 +145,9 @@ bool GLContextGLX::Initialize( return false; } - DLOG(INFO) << (surface_glx->IsOffscreen() ? "Offscreen" : "Onscreen") + DLOG(INFO) << (compatible_surface->IsOffscreen() ? "Offscreen" : "Onscreen") << " context was " - << (glXIsDirect(GLSurfaceGLX::GetDisplay(), + << (glXIsDirect(display_, static_cast<GLXContext>(context_)) ? "direct" : "indirect") << "."; @@ -156,7 +157,7 @@ bool GLContextGLX::Initialize( void GLContextGLX::Destroy() { if (context_) { - glXDestroyContext(GLSurfaceGLX::GetDisplay(), + glXDestroyContext(display_, static_cast<GLXContext>(context_)); context_ = NULL; } @@ -168,7 +169,7 @@ bool GLContextGLX::MakeCurrent(GLSurface* surface) { return true; if (!glXMakeCurrent( - GLSurfaceGLX::GetDisplay(), + display_, reinterpret_cast<GLXDrawable>(surface->GetHandle()), static_cast<GLXContext>(context_))) { LOG(ERROR) << "Couldn't make context current with X drawable."; @@ -190,7 +191,7 @@ void GLContextGLX::ReleaseCurrent(GLSurface* surface) { return; SetCurrent(NULL, NULL); - glXMakeContextCurrent(GLSurfaceGLX::GetDisplay(), 0, 0, NULL); + glXMakeContextCurrent(display_, 0, 0, NULL); } bool GLContextGLX::IsCurrent(GLSurface* surface) { @@ -227,13 +228,13 @@ void GLContextGLX::SetSwapInterval(int interval) { // respect this setting anyway (tearing still occurs) and it // dramatically increases latency. if (interval == 1 && - IsCompositingWindowManagerActive(GLSurfaceGLX::GetDisplay())) { + IsCompositingWindowManagerActive(display_)) { LOG(INFO) << "Forcing vsync off because compositing window manager was detected."; interval = 0; } glXSwapIntervalEXT( - GLSurfaceGLX::GetDisplay(), + display_, glXGetCurrentDrawable(), interval); } else { diff --git a/ui/gfx/gl/gl_context_glx.h b/ui/gfx/gl/gl_context_glx.h index 3f8a535..f5cfa14 100644 --- a/ui/gfx/gl/gl_context_glx.h +++ b/ui/gfx/gl/gl_context_glx.h @@ -4,6 +4,7 @@ #include <string> +#include "ui/base/x/x11_util.h" #include "ui/gfx/gl/gl_context.h" namespace gfx { @@ -30,6 +31,7 @@ class GLContextGLX : public GLContext { private: void* context_; + Display* display_; DISALLOW_COPY_AND_ASSIGN(GLContextGLX); }; diff --git a/ui/gfx/gl/gl_context_osmesa.cc b/ui/gfx/gl/gl_context_osmesa.cc index 3af14ae..df7766d 100644 --- a/ui/gfx/gl/gl_context_osmesa.cc +++ b/ui/gfx/gl/gl_context_osmesa.cc @@ -8,7 +8,8 @@ #include "base/logging.h" #include "ui/gfx/gl/gl_bindings.h" -#include "ui/gfx/gl/gl_surface_osmesa.h" +#include "ui/gfx/gl/gl_surface.h" +#include "ui/gfx/size.h" namespace gfx { @@ -28,8 +29,7 @@ bool GLContextOSMesa::Initialize( OSMesaContext share_handle = static_cast<OSMesaContext>( share_group() ? share_group()->GetHandle() : NULL); - GLuint format = - static_cast<GLSurfaceOSMesa*>(compatible_surface)->GetFormat(); + GLuint format = compatible_surface->GetFormat(); DCHECK_NE(format, (unsigned)0); context_ = OSMesaCreateContextExt(format, 0, // depth bits diff --git a/ui/gfx/gl/gl_context_wgl.cc b/ui/gfx/gl/gl_context_wgl.cc index dc75b78..01506c0 100644 --- a/ui/gfx/gl/gl_context_wgl.cc +++ b/ui/gfx/gl/gl_context_wgl.cc @@ -28,7 +28,7 @@ std::string GLContextWGL::GetExtensions() { // able to use surface_ here. Either use a display device context or the // surface that was passed to MakeCurrent. const char* extensions = wglGetExtensionsStringARB( - GLSurfaceWGL::GetDisplay()); + GLSurfaceWGL::GetDisplayDC()); if (extensions) { return GLContext::GetExtensions() + " " + extensions; } @@ -39,13 +39,12 @@ std::string GLContextWGL::GetExtensions() { bool GLContextWGL::Initialize( GLSurface* compatible_surface, GpuPreference gpu_preference) { - GLSurfaceWGL* surface_wgl = static_cast<GLSurfaceWGL*>(compatible_surface); - // TODO(apatrick): When contexts and surfaces are separated, we won't be // able to use surface_ here. Either use a display device context or a // surface that the context is compatible with not necessarily limited to // rendering to. - context_ = wglCreateContext(static_cast<HDC>(surface_wgl->GetHandle())); + context_ = wglCreateContext( + static_cast<HDC>(compatible_surface->GetHandle())); if (!context_) { LOG(ERROR) << "Failed to create GL context."; Destroy(); diff --git a/ui/gfx/gl/gl_surface.cc b/ui/gfx/gl/gl_surface.cc index 868b1b29..ed849c2 100644 --- a/ui/gfx/gl/gl_surface.cc +++ b/ui/gfx/gl/gl_surface.cc @@ -4,6 +4,7 @@ #include "ui/gfx/gl/gl_surface.h" +#include "base/logging.h" #include "base/threading/thread_local.h" #include "ui/gfx/gl/gl_context.h" @@ -24,6 +25,11 @@ bool GLSurface::Initialize() return true; } +bool GLSurface::Resize(const gfx::Size& size) { + NOTIMPLEMENTED(); + return false; +} + unsigned int GLSurface::GetBackingFrameBufferObject() { return 0; } @@ -35,6 +41,26 @@ bool GLSurface::OnMakeCurrent(GLContext* context) { void GLSurface::SetVisible(bool visible) { } +void* GLSurface::GetShareHandle() { + NOTIMPLEMENTED(); + return NULL; +} + +void* GLSurface::GetDisplay() { + NOTIMPLEMENTED(); + return NULL; +} + +void* GLSurface::GetConfig() { + NOTIMPLEMENTED(); + return NULL; +} + +unsigned GLSurface::GetFormat() { + NOTIMPLEMENTED(); + return 0; +} + GLSurface* GLSurface::GetCurrent() { return current_surface_.Get(); } @@ -43,4 +69,62 @@ void GLSurface::SetCurrent(GLSurface* surface) { current_surface_.Set(surface); } +GLSurfaceAdapter::GLSurfaceAdapter(GLSurface* surface) : surface_(surface) { +} + +GLSurfaceAdapter::~GLSurfaceAdapter() { +} + +bool GLSurfaceAdapter::Initialize() { + return surface_->Initialize(); +} + +void GLSurfaceAdapter::Destroy() { + surface_->Destroy(); +} + +bool GLSurfaceAdapter::Resize(const gfx::Size& size) { + return surface_->Resize(size); +} + +bool GLSurfaceAdapter::IsOffscreen() { + return surface_->IsOffscreen(); +} + +bool GLSurfaceAdapter::SwapBuffers() { + return surface_->SwapBuffers(); +} + +gfx::Size GLSurfaceAdapter::GetSize() { + return surface_->GetSize(); +} + +void* GLSurfaceAdapter::GetHandle() { + return surface_->GetHandle(); +} + +unsigned int GLSurfaceAdapter::GetBackingFrameBufferObject() { + return surface_->GetBackingFrameBufferObject(); +} + +bool GLSurfaceAdapter::OnMakeCurrent(GLContext* context) { + return surface_->OnMakeCurrent(context); +} + +void* GLSurfaceAdapter::GetShareHandle() { + return surface_->GetShareHandle(); +} + +void* GLSurfaceAdapter::GetDisplay() { + return surface_->GetDisplay(); +} + +void* GLSurfaceAdapter::GetConfig() { + return surface_->GetConfig(); +} + +unsigned GLSurfaceAdapter::GetFormat() { + return surface_->GetFormat(); +} + } // namespace gfx diff --git a/ui/gfx/gl/gl_surface.h b/ui/gfx/gl/gl_surface.h index 60e32c4..6cc3e22 100644 --- a/ui/gfx/gl/gl_surface.h +++ b/ui/gfx/gl/gl_surface.h @@ -31,6 +31,8 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> { // Destroys the surface. virtual void Destroy() = 0; + virtual bool Resize(const gfx::Size& size); + // Returns true if this surface is offscreen. virtual bool IsOffscreen() = 0; @@ -54,8 +56,24 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> { // on error. virtual bool OnMakeCurrent(GLContext* context); + // This gives a hint as to whether this surface is visible. If it is not + // visible, the backing store need not be preserved. virtual void SetVisible(bool visible); + // Get a handle used to share the surface with another process. Returns null + // if this is not possible. + virtual void* GetShareHandle(); + + // Get the platform specific display on which this surface resides, if + // available. + virtual void* GetDisplay(); + + // Get the platfrom specific configuration for this surface, if available. + virtual void* GetConfig(); + + // Get the GL pixel format of the surface, if available. + virtual unsigned GetFormat(); + // Create a GL surface that renders directly to a view. static scoped_refptr<GLSurface> CreateViewGLSurface( bool software, @@ -78,6 +96,34 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> { DISALLOW_COPY_AND_ASSIGN(GLSurface); }; +// Implementation of GLSurface that forwards all calls through to another +// GLSurface. +class GL_EXPORT GLSurfaceAdapter : public GLSurface { + public: + explicit GLSurfaceAdapter(GLSurface* surface); + virtual ~GLSurfaceAdapter(); + + virtual bool Initialize(); + virtual void Destroy(); + virtual bool Resize(const gfx::Size& size); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual unsigned int GetBackingFrameBufferObject(); + virtual bool OnMakeCurrent(GLContext* context); + virtual void* GetShareHandle(); + virtual void* GetDisplay(); + virtual void* GetConfig(); + virtual unsigned GetFormat(); + + GLSurface* surface() const { return surface_.get(); } + + private: + scoped_refptr<GLSurface> surface_; + DISALLOW_COPY_AND_ASSIGN(GLSurfaceAdapter); +}; + } // namespace gfx #endif // UI_GFX_GL_GL_SURFACE_H_ diff --git a/ui/gfx/gl/gl_surface_egl.cc b/ui/gfx/gl/gl_surface_egl.cc index a69466d..6f6d630 100644 --- a/ui/gfx/gl/gl_surface_egl.cc +++ b/ui/gfx/gl/gl_surface_egl.cc @@ -307,8 +307,33 @@ gfx::Size PbufferGLSurfaceEGL::GetSize() { return size_; } +bool PbufferGLSurfaceEGL::Resize(const gfx::Size& size) { + if (size == size_) + return true; + + Destroy(); + size_ = size; + return Initialize(); +} + EGLSurface PbufferGLSurfaceEGL::GetHandle() { return surface_; } +void* PbufferGLSurfaceEGL::GetShareHandle() { + const char* extensions = eglQueryString(g_display, EGL_EXTENSIONS); + if (!strstr(extensions, "EGL_ANGLE_query_surface_pointer")) + return NULL; + + void* handle; + if (!eglQuerySurfacePointerANGLE(g_display, + GetHandle(), + EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, + &handle)) { + return NULL; + } + + return handle; +} + } // namespace gfx diff --git a/ui/gfx/gl/gl_surface_egl.h b/ui/gfx/gl/gl_surface_egl.h index 8cb5caf..de68fc8 100644 --- a/ui/gfx/gl/gl_surface_egl.h +++ b/ui/gfx/gl/gl_surface_egl.h @@ -34,9 +34,11 @@ class GL_EXPORT GLSurfaceEGL : public GLSurface { GLSurfaceEGL(); virtual ~GLSurfaceEGL(); + // Implement GLSurface. + virtual EGLDisplay GetDisplay(); + virtual EGLConfig GetConfig(); + static bool InitializeOneOff(); - EGLDisplay GetDisplay(); - EGLConfig GetConfig(); static EGLDisplay GetHardwareDisplay(); static EGLDisplay GetSoftwareDisplay(); static EGLNativeDisplayType GetNativeDisplay(); @@ -81,7 +83,9 @@ class GL_EXPORT PbufferGLSurfaceEGL : public GLSurfaceEGL { virtual bool IsOffscreen(); virtual bool SwapBuffers(); virtual gfx::Size GetSize(); + virtual bool Resize(const gfx::Size& size); virtual EGLSurface GetHandle(); + virtual void* GetShareHandle(); private: gfx::Size size_; diff --git a/ui/gfx/gl/gl_surface_glx.cc b/ui/gfx/gl/gl_surface_glx.cc index d380f8f..2f2380f 100644 --- a/ui/gfx/gl/gl_surface_glx.cc +++ b/ui/gfx/gl/gl_surface_glx.cc @@ -73,10 +73,6 @@ bool GLSurfaceGLX::InitializeOneOff() { return true; } -Display* GLSurfaceGLX::GetDisplay() { - return g_display; -} - const char* GLSurfaceGLX::GetGLXExtensions() { return g_glx_extensions; } @@ -99,6 +95,10 @@ bool GLSurfaceGLX::IsCreateContextRobustnessSupported() { return g_glx_create_context_robustness_supported; } +void* GLSurfaceGLX::GetDisplay() { + return g_display; +} + NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::PluginWindowHandle window) : window_(window), config_(NULL) { diff --git a/ui/gfx/gl/gl_surface_glx.h b/ui/gfx/gl/gl_surface_glx.h index dda14b4..7784a79 100644 --- a/ui/gfx/gl/gl_surface_glx.h +++ b/ui/gfx/gl/gl_surface_glx.h @@ -21,7 +21,6 @@ class GL_EXPORT GLSurfaceGLX : public GLSurface { virtual ~GLSurfaceGLX(); static bool InitializeOneOff(); - static Display* GetDisplay(); // These aren't particularly tied to surfaces, but since we already // have the static InitializeOneOff here, it's easiest to reuse its @@ -30,6 +29,8 @@ class GL_EXPORT GLSurfaceGLX : public GLSurface { static bool HasGLXExtension(const char* name); static bool IsCreateContextRobustnessSupported(); + virtual void* GetDisplay(); + // Get the FB config that the surface was created with or NULL if it is not // a GLX drawable. virtual void* GetConfig() = 0; diff --git a/ui/gfx/gl/gl_surface_osmesa.cc b/ui/gfx/gl/gl_surface_osmesa.cc index 3fdf8fb..2fe5e38 100644 --- a/ui/gfx/gl/gl_surface_osmesa.cc +++ b/ui/gfx/gl/gl_surface_osmesa.cc @@ -17,9 +17,9 @@ GLSurfaceOSMesa::~GLSurfaceOSMesa() { Destroy(); } -void GLSurfaceOSMesa::Resize(const gfx::Size& new_size) { +bool GLSurfaceOSMesa::Resize(const gfx::Size& new_size) { if (new_size == size_) - return; + return true; // Preserve the old buffer. scoped_array<int32> old_buffer(buffer_.release()); @@ -37,6 +37,7 @@ void GLSurfaceOSMesa::Resize(const gfx::Size& new_size) { } size_ = new_size; + return true; } bool GLSurfaceOSMesa::Initialize() { diff --git a/ui/gfx/gl/gl_surface_osmesa.h b/ui/gfx/gl/gl_surface_osmesa.h index 14897c2..f0a4663 100644 --- a/ui/gfx/gl/gl_surface_osmesa.h +++ b/ui/gfx/gl/gl_surface_osmesa.h @@ -22,7 +22,7 @@ class GL_EXPORT GLSurfaceOSMesa : public GLSurface { // Resize the back buffer, preserving the old content. Does nothing if the // size is unchanged. - void Resize(const gfx::Size& new_size); + virtual bool Resize(const gfx::Size& new_size); // Implement GLSurface. virtual bool Initialize(); @@ -31,9 +31,7 @@ class GL_EXPORT GLSurfaceOSMesa : public GLSurface { virtual bool SwapBuffers(); virtual gfx::Size GetSize(); virtual void* GetHandle(); - - // Get the surface's format. - unsigned GetFormat(); + virtual unsigned GetFormat(); private: void AllocateBuffer(const Size& size); diff --git a/ui/gfx/gl/gl_surface_wgl.cc b/ui/gfx/gl/gl_surface_wgl.cc index 52772ff..9c774d4 100644 --- a/ui/gfx/gl/gl_surface_wgl.cc +++ b/ui/gfx/gl/gl_surface_wgl.cc @@ -60,6 +60,10 @@ GLSurfaceWGL::GLSurfaceWGL() { GLSurfaceWGL::~GLSurfaceWGL() { } +void* GLSurfaceWGL::GetDisplay() { + return g_display_dc; +} + bool GLSurfaceWGL::InitializeOneOff() { static bool initialized = false; if (initialized) @@ -162,7 +166,7 @@ bool GLSurfaceWGL::InitializeOneOff() { return true; } -HDC GLSurfaceWGL::GetDisplay() { +HDC GLSurfaceWGL::GetDisplayDC() { return g_display_dc; } diff --git a/ui/gfx/gl/gl_surface_wgl.h b/ui/gfx/gl/gl_surface_wgl.h index bb4b71b..7a4ed69 100644 --- a/ui/gfx/gl/gl_surface_wgl.h +++ b/ui/gfx/gl/gl_surface_wgl.h @@ -16,8 +16,11 @@ class GLSurfaceWGL : public GLSurface { GLSurfaceWGL(); virtual ~GLSurfaceWGL(); + // Implement GLSurface. + virtual void* GetDisplay(); + static bool InitializeOneOff(); - static HDC GetDisplay(); + static HDC GetDisplayDC(); private: DISALLOW_COPY_AND_ASSIGN(GLSurfaceWGL); |