Home | History | Annotate | Download | only in gl
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 extern "C" {
      6 #include <X11/extensions/Xcomposite.h>
      7 }
      8 
      9 #include "ui/gl/gl_image_glx.h"
     10 
     11 #include "base/basictypes.h"
     12 #include "base/logging.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/message_loop/message_loop.h"
     15 #include "ui/gl/gl_bindings.h"
     16 #include "ui/gl/gl_surface_glx.h"
     17 
     18 namespace gfx {
     19 
     20 namespace {
     21 
     22 // scoped_ptr functor for XFree(). Use as follows:
     23 //   scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
     24 // where "XVisualInfo" is any X type that is freed with XFree.
     25 class ScopedPtrXFree {
     26  public:
     27   void operator()(void* x) const {
     28     ::XFree(x);
     29   }
     30 };
     31 
     32 int BindToTextureFormat(int depth) {
     33   if (depth == 32)
     34     return GLX_BIND_TO_TEXTURE_RGBA_EXT;
     35 
     36   return GLX_BIND_TO_TEXTURE_RGB_EXT;
     37 }
     38 
     39 int TextureFormat(int depth) {
     40   if (depth == 32)
     41     return GLX_TEXTURE_FORMAT_RGBA_EXT;
     42 
     43   return GLX_TEXTURE_FORMAT_RGB_EXT;
     44 }
     45 
     46 }  // namespace anonymous
     47 
     48 GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window)
     49   : display_(base::MessagePumpForUI::GetDefaultXDisplay()),
     50     window_(window),
     51     pixmap_(0),
     52     glx_pixmap_(0) {
     53 }
     54 
     55 GLImageGLX::~GLImageGLX() {
     56   Destroy();
     57 }
     58 
     59 bool GLImageGLX::Initialize() {
     60   if (!GLSurfaceGLX::IsTextureFromPixmapSupported()) {
     61     LOG(ERROR) << "GLX_EXT_texture_from_pixmap not supported.";
     62     return false;
     63   }
     64 
     65   XWindowAttributes attributes;
     66   if (!XGetWindowAttributes(display_, window_, &attributes)) {
     67     LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
     68     return false;
     69   }
     70 
     71   XVisualInfo templ;
     72   templ.visualid = XVisualIDFromVisual(attributes.visual);
     73   int num_visinfo = 0;
     74   scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visinfo(
     75       XGetVisualInfo(display_,
     76                      VisualIDMask,
     77                      &templ,
     78                      &num_visinfo));
     79   if (!visinfo.get()) {
     80     LOG(ERROR) << "XGetVisualInfo failed for visual id " <<
     81         templ.visualid << ".";
     82     return false;
     83   }
     84   if (!num_visinfo) {
     85     LOG(ERROR) << "XGetVisualInfo returned 0 elements.";
     86     return false;
     87   }
     88 
     89   int config_attribs[] = {
     90     static_cast<int>(GLX_VISUAL_ID),
     91     static_cast<int>(visinfo->visualid),
     92     GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
     93     GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_EXT,
     94     BindToTextureFormat(visinfo->depth), GL_TRUE,
     95     0
     96   };
     97   int num_elements = 0;
     98   scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config(
     99       glXChooseFBConfig(display_,
    100                         DefaultScreen(display_),
    101                         config_attribs,
    102                         &num_elements));
    103   if (!config.get()) {
    104     LOG(ERROR) << "glXChooseFBConfig failed.";
    105     return false;
    106   }
    107   if (!num_elements) {
    108     LOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
    109     return false;
    110   }
    111 
    112   // Create backing pixmap reference.
    113   pixmap_ = XCompositeNameWindowPixmap(display_, window_);
    114 
    115   XID root = 0;
    116   int x = 0;
    117   int y = 0;
    118   unsigned int width = 0;
    119   unsigned int height = 0;
    120   unsigned int bw = 0;
    121   unsigned int depth = 0;
    122   if (!XGetGeometry(
    123           display_, pixmap_, &root, &x, &y, &width, &height, &bw, &depth)) {
    124     LOG(ERROR) << "XGetGeometry failed for pixmap " << pixmap_ << ".";
    125     return false;
    126   }
    127 
    128   int pixmap_attribs[] = {
    129     GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
    130     GLX_TEXTURE_FORMAT_EXT, TextureFormat(visinfo->depth),
    131     0
    132   };
    133   glx_pixmap_ = glXCreatePixmap(
    134       display_,
    135       *config.get(),
    136       pixmap_,
    137       pixmap_attribs);
    138   if (!glx_pixmap_) {
    139     LOG(ERROR) << "glXCreatePixmap failed.";
    140     return false;
    141   }
    142 
    143   size_ = gfx::Size(width, height);
    144   return true;
    145 }
    146 
    147 void GLImageGLX::Destroy() {
    148   if (glx_pixmap_) {
    149     glXDestroyGLXPixmap(display_, glx_pixmap_);
    150     glx_pixmap_ = 0;
    151   }
    152   if (pixmap_) {
    153     XFreePixmap(display_, pixmap_);
    154     pixmap_ = 0;
    155   }
    156 }
    157 
    158 gfx::Size GLImageGLX::GetSize() {
    159   return size_;
    160 }
    161 
    162 bool GLImageGLX::BindTexImage(unsigned target) {
    163   if (!glx_pixmap_)
    164     return false;
    165 
    166   // Requires TEXTURE_2D target.
    167   if (target != GL_TEXTURE_2D)
    168     return false;
    169 
    170   glXBindTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, 0);
    171   return true;
    172 }
    173 
    174 void GLImageGLX::ReleaseTexImage(unsigned target) {
    175   DCHECK(glx_pixmap_);
    176   DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), target);
    177 
    178   glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT);
    179 }
    180 
    181 void GLImageGLX::WillUseTexImage() {
    182 }
    183 
    184 void GLImageGLX::DidUseTexImage() {
    185 }
    186 
    187 }  // namespace gfx
    188