| // 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. |
| |
| extern "C" { |
| #include <X11/extensions/Xcomposite.h> |
| } |
| |
| #include "ui/gl/gl_image_glx.h" |
| |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/message_loop/message_loop.h" |
| #include "ui/gl/gl_bindings.h" |
| #include "ui/gl/gl_surface_glx.h" |
| |
| namespace gfx { |
| |
| namespace { |
| |
| // scoped_ptr functor for XFree(). Use as follows: |
| // scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...); |
| // where "XVisualInfo" is any X type that is freed with XFree. |
| class ScopedPtrXFree { |
| public: |
| void operator()(void* x) const { |
| ::XFree(x); |
| } |
| }; |
| |
| int BindToTextureFormat(int depth) { |
| if (depth == 32) |
| return GLX_BIND_TO_TEXTURE_RGBA_EXT; |
| |
| return GLX_BIND_TO_TEXTURE_RGB_EXT; |
| } |
| |
| int TextureFormat(int depth) { |
| if (depth == 32) |
| return GLX_TEXTURE_FORMAT_RGBA_EXT; |
| |
| return GLX_TEXTURE_FORMAT_RGB_EXT; |
| } |
| |
| } // namespace anonymous |
| |
| GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window) |
| : display_(base::MessagePumpForUI::GetDefaultXDisplay()), |
| window_(window), |
| pixmap_(0), |
| glx_pixmap_(0) { |
| } |
| |
| GLImageGLX::~GLImageGLX() { |
| Destroy(); |
| } |
| |
| bool GLImageGLX::Initialize() { |
| if (!GLSurfaceGLX::IsTextureFromPixmapSupported()) { |
| LOG(ERROR) << "GLX_EXT_texture_from_pixmap not supported."; |
| return false; |
| } |
| |
| XWindowAttributes attributes; |
| if (!XGetWindowAttributes(display_, window_, &attributes)) { |
| LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; |
| return false; |
| } |
| |
| XVisualInfo templ; |
| templ.visualid = XVisualIDFromVisual(attributes.visual); |
| int num_visinfo = 0; |
| scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visinfo( |
| XGetVisualInfo(display_, |
| VisualIDMask, |
| &templ, |
| &num_visinfo)); |
| if (!visinfo.get()) { |
| LOG(ERROR) << "XGetVisualInfo failed for visual id " << |
| templ.visualid << "."; |
| return false; |
| } |
| if (!num_visinfo) { |
| LOG(ERROR) << "XGetVisualInfo returned 0 elements."; |
| return false; |
| } |
| |
| int config_attribs[] = { |
| static_cast<int>(GLX_VISUAL_ID), |
| static_cast<int>(visinfo->visualid), |
| GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, |
| GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_EXT, |
| BindToTextureFormat(visinfo->depth), GL_TRUE, |
| 0 |
| }; |
| int num_elements = 0; |
| scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config( |
| glXChooseFBConfig(display_, |
| DefaultScreen(display_), |
| config_attribs, |
| &num_elements)); |
| if (!config.get()) { |
| LOG(ERROR) << "glXChooseFBConfig failed."; |
| return false; |
| } |
| if (!num_elements) { |
| LOG(ERROR) << "glXChooseFBConfig returned 0 elements."; |
| return false; |
| } |
| |
| // Create backing pixmap reference. |
| pixmap_ = XCompositeNameWindowPixmap(display_, window_); |
| |
| XID root = 0; |
| int x = 0; |
| int y = 0; |
| unsigned int width = 0; |
| unsigned int height = 0; |
| unsigned int bw = 0; |
| unsigned int depth = 0; |
| if (!XGetGeometry( |
| display_, pixmap_, &root, &x, &y, &width, &height, &bw, &depth)) { |
| LOG(ERROR) << "XGetGeometry failed for pixmap " << pixmap_ << "."; |
| return false; |
| } |
| |
| int pixmap_attribs[] = { |
| GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, |
| GLX_TEXTURE_FORMAT_EXT, TextureFormat(visinfo->depth), |
| 0 |
| }; |
| glx_pixmap_ = glXCreatePixmap( |
| display_, |
| *config.get(), |
| pixmap_, |
| pixmap_attribs); |
| if (!glx_pixmap_) { |
| LOG(ERROR) << "glXCreatePixmap failed."; |
| return false; |
| } |
| |
| size_ = gfx::Size(width, height); |
| return true; |
| } |
| |
| void GLImageGLX::Destroy() { |
| if (glx_pixmap_) { |
| glXDestroyGLXPixmap(display_, glx_pixmap_); |
| glx_pixmap_ = 0; |
| } |
| if (pixmap_) { |
| XFreePixmap(display_, pixmap_); |
| pixmap_ = 0; |
| } |
| } |
| |
| gfx::Size GLImageGLX::GetSize() { |
| return size_; |
| } |
| |
| bool GLImageGLX::BindTexImage() { |
| if (!glx_pixmap_) |
| return false; |
| |
| glXBindTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, 0); |
| return true; |
| } |
| |
| void GLImageGLX::ReleaseTexImage() { |
| if (!glx_pixmap_) |
| return; |
| |
| glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT); |
| } |
| |
| void GLImageGLX::WillUseTexImage() { |
| } |
| |
| void GLImageGLX::DidUseTexImage() { |
| } |
| |
| } // namespace gfx |