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/gfx/x/x11_types.h"
     16 #include "ui/gl/gl_bindings.h"
     17 #include "ui/gl/gl_surface_glx.h"
     18 
     19 namespace gfx {
     20 
     21 namespace {
     22 
     23 // scoped_ptr functor for XFree(). Use as follows:
     24 //   scoped_ptr<XVisualInfo, ScopedPtrXFree> foo(...);
     25 // where "XVisualInfo" is any X type that is freed with XFree.
     26 struct ScopedPtrXFree {
     27   void operator()(void* x) const { ::XFree(x); }
     28 };
     29 
     30 int BindToTextureFormat(int depth) {
     31   if (depth == 32)
     32     return GLX_BIND_TO_TEXTURE_RGBA_EXT;
     33 
     34   return GLX_BIND_TO_TEXTURE_RGB_EXT;
     35 }
     36 
     37 int TextureFormat(int depth) {
     38   if (depth == 32)
     39     return GLX_TEXTURE_FORMAT_RGBA_EXT;
     40 
     41   return GLX_TEXTURE_FORMAT_RGB_EXT;
     42 }
     43 
     44 }  // namespace anonymous
     45 
     46 GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window)
     47     : display_(gfx::GetXDisplay()),
     48       window_(window),
     49       pixmap_(0),
     50       glx_pixmap_(0) {}
     51 
     52 GLImageGLX::~GLImageGLX() { Destroy(); }
     53 
     54 bool GLImageGLX::Initialize() {
     55   if (!GLSurfaceGLX::IsTextureFromPixmapSupported()) {
     56     LOG(ERROR) << "GLX_EXT_texture_from_pixmap not supported.";
     57     return false;
     58   }
     59 
     60   XWindowAttributes attributes;
     61   if (!XGetWindowAttributes(display_, window_, &attributes)) {
     62     LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
     63     return false;
     64   }
     65 
     66   XVisualInfo templ;
     67   templ.visualid = XVisualIDFromVisual(attributes.visual);
     68   int num_visinfo = 0;
     69   scoped_ptr<XVisualInfo, ScopedPtrXFree> visinfo(
     70       XGetVisualInfo(display_, VisualIDMask, &templ, &num_visinfo));
     71   if (!visinfo.get()) {
     72     LOG(ERROR) << "XGetVisualInfo failed for visual id " << templ.visualid
     73                << ".";
     74     return false;
     75   }
     76   if (!num_visinfo) {
     77     LOG(ERROR) << "XGetVisualInfo returned 0 elements.";
     78     return false;
     79   }
     80 
     81   int config_attribs[] = {
     82       static_cast<int>(GLX_VISUAL_ID),     static_cast<int>(visinfo->visualid),
     83       GLX_DRAWABLE_TYPE,                   GLX_PIXMAP_BIT,
     84       GLX_BIND_TO_TEXTURE_TARGETS_EXT,     GLX_TEXTURE_2D_EXT,
     85       BindToTextureFormat(visinfo->depth), GL_TRUE,
     86       0};
     87   int num_elements = 0;
     88   scoped_ptr<GLXFBConfig, ScopedPtrXFree> config(glXChooseFBConfig(
     89       display_, DefaultScreen(display_), config_attribs, &num_elements));
     90   if (!config.get()) {
     91     LOG(ERROR) << "glXChooseFBConfig failed.";
     92     return false;
     93   }
     94   if (!num_elements) {
     95     LOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
     96     return false;
     97   }
     98 
     99   // Create backing pixmap reference.
    100   pixmap_ = XCompositeNameWindowPixmap(display_, window_);
    101 
    102   XID root = 0;
    103   int x = 0;
    104   int y = 0;
    105   unsigned int width = 0;
    106   unsigned int height = 0;
    107   unsigned int bw = 0;
    108   unsigned int depth = 0;
    109   if (!XGetGeometry(
    110           display_, pixmap_, &root, &x, &y, &width, &height, &bw, &depth)) {
    111     LOG(ERROR) << "XGetGeometry failed for pixmap " << pixmap_ << ".";
    112     return false;
    113   }
    114 
    115   int pixmap_attribs[] = {GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
    116                           GLX_TEXTURE_FORMAT_EXT, TextureFormat(visinfo->depth),
    117                           0};
    118   glx_pixmap_ =
    119       glXCreatePixmap(display_, *config.get(), pixmap_, pixmap_attribs);
    120   if (!glx_pixmap_) {
    121     LOG(ERROR) << "glXCreatePixmap failed.";
    122     return false;
    123   }
    124 
    125   size_ = gfx::Size(width, height);
    126   return true;
    127 }
    128 
    129 void GLImageGLX::Destroy() {
    130   if (glx_pixmap_) {
    131     glXDestroyGLXPixmap(display_, glx_pixmap_);
    132     glx_pixmap_ = 0;
    133   }
    134   if (pixmap_) {
    135     XFreePixmap(display_, pixmap_);
    136     pixmap_ = 0;
    137   }
    138 }
    139 
    140 gfx::Size GLImageGLX::GetSize() { return size_; }
    141 
    142 bool GLImageGLX::BindTexImage(unsigned target) {
    143   if (!glx_pixmap_)
    144     return false;
    145 
    146   // Requires TEXTURE_2D target.
    147   if (target != GL_TEXTURE_2D)
    148     return false;
    149 
    150   glXBindTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, 0);
    151   return true;
    152 }
    153 
    154 void GLImageGLX::ReleaseTexImage(unsigned target) {
    155   DCHECK(glx_pixmap_);
    156   DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), target);
    157 
    158   glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT);
    159 }
    160 
    161 }  // namespace gfx
    162