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/Xlib.h>
      7 }
      8 
      9 #include "ui/gl/gl_image_glx.h"
     10 
     11 #include "base/logging.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "ui/gl/gl_bindings.h"
     14 #include "ui/gl/gl_surface_glx.h"
     15 
     16 namespace gfx {
     17 
     18 namespace {
     19 
     20 // scoped_ptr functor for XFree(). Use as follows:
     21 //   scoped_ptr<XVisualInfo, ScopedPtrXFree> foo(...);
     22 // where "XVisualInfo" is any X type that is freed with XFree.
     23 struct ScopedPtrXFree {
     24   void operator()(void* x) const { ::XFree(x); }
     25 };
     26 
     27 bool ValidFormat(unsigned internalformat) {
     28   switch (internalformat) {
     29     case GL_BGRA8_EXT:
     30       return true;
     31     default:
     32       return false;
     33   }
     34 }
     35 
     36 int TextureFormat(unsigned internalformat) {
     37   switch (internalformat) {
     38     case GL_BGRA8_EXT:
     39       return GLX_TEXTURE_FORMAT_RGBA_EXT;
     40     default:
     41       NOTREACHED();
     42       return 0;
     43   }
     44 }
     45 
     46 int BindToTextureFormat(unsigned internalformat) {
     47   switch (internalformat) {
     48     case GL_BGRA8_EXT:
     49       return GLX_BIND_TO_TEXTURE_RGBA_EXT;
     50     default:
     51       NOTREACHED();
     52       return 0;
     53   }
     54 }
     55 
     56 unsigned PixmapDepth(unsigned internalformat) {
     57   switch (internalformat) {
     58     case GL_BGRA8_EXT:
     59       return 32u;
     60     default:
     61       NOTREACHED();
     62       return 0u;
     63   }
     64 }
     65 
     66 bool ActualPixmapGeometry(XID pixmap, gfx::Size* size, unsigned* depth) {
     67   XID root_return;
     68   int x_return;
     69   int y_return;
     70   unsigned width_return;
     71   unsigned height_return;
     72   unsigned border_width_return;
     73   unsigned depth_return;
     74   if (!XGetGeometry(gfx::GetXDisplay(),
     75                     pixmap,
     76                     &root_return,
     77                     &x_return,
     78                     &y_return,
     79                     &width_return,
     80                     &height_return,
     81                     &border_width_return,
     82                     &depth_return))
     83     return false;
     84 
     85   if (size)
     86     *size = gfx::Size(width_return, height_return);
     87   if (depth)
     88     *depth = depth_return;
     89   return true;
     90 }
     91 
     92 unsigned ActualPixmapDepth(XID pixmap) {
     93   unsigned depth;
     94   if (!ActualPixmapGeometry(pixmap, NULL, &depth))
     95     return -1;
     96 
     97   return depth;
     98 }
     99 
    100 gfx::Size ActualPixmapSize(XID pixmap) {
    101   gfx::Size size;
    102   if (!ActualPixmapGeometry(pixmap, &size, NULL))
    103     return gfx::Size();
    104 
    105   return size;
    106 }
    107 
    108 }  // namespace anonymous
    109 
    110 GLImageGLX::GLImageGLX(const gfx::Size& size, unsigned internalformat)
    111     : glx_pixmap_(0), size_(size), internalformat_(internalformat) {
    112 }
    113 
    114 GLImageGLX::~GLImageGLX() {
    115   DCHECK_EQ(0u, glx_pixmap_);
    116 }
    117 
    118 bool GLImageGLX::Initialize(XID pixmap) {
    119   if (!GLSurfaceGLX::IsTextureFromPixmapSupported()) {
    120     DVLOG(0) << "GLX_EXT_texture_from_pixmap not supported.";
    121     return false;
    122   }
    123 
    124   if (!ValidFormat(internalformat_)) {
    125     DVLOG(0) << "Invalid format: " << internalformat_;
    126     return false;
    127   }
    128 
    129   DCHECK_EQ(PixmapDepth(internalformat_), ActualPixmapDepth(pixmap));
    130   DCHECK_EQ(size_.ToString(), ActualPixmapSize(pixmap).ToString());
    131 
    132   int config_attribs[] = {
    133       GLX_DRAWABLE_TYPE,                    GLX_PIXMAP_BIT,
    134       GLX_BIND_TO_TEXTURE_TARGETS_EXT,      GLX_TEXTURE_2D_EXT,
    135       BindToTextureFormat(internalformat_), GL_TRUE,
    136       0};
    137   int num_elements = 0;
    138   scoped_ptr<GLXFBConfig, ScopedPtrXFree> config(
    139       glXChooseFBConfig(gfx::GetXDisplay(),
    140                         DefaultScreen(gfx::GetXDisplay()),
    141                         config_attribs,
    142                         &num_elements));
    143   if (!config.get()) {
    144     DVLOG(0) << "glXChooseFBConfig failed.";
    145     return false;
    146   }
    147   if (!num_elements) {
    148     DVLOG(0) << "glXChooseFBConfig returned 0 elements.";
    149     return false;
    150   }
    151 
    152   int pixmap_attribs[] = {GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
    153                           GLX_TEXTURE_FORMAT_EXT,
    154                           TextureFormat(internalformat_), 0};
    155   glx_pixmap_ = glXCreatePixmap(
    156       gfx::GetXDisplay(), *config.get(), pixmap, pixmap_attribs);
    157   if (!glx_pixmap_) {
    158     DVLOG(0) << "glXCreatePixmap failed.";
    159     return false;
    160   }
    161 
    162   return true;
    163 }
    164 
    165 void GLImageGLX::Destroy(bool have_context) {
    166   if (glx_pixmap_) {
    167     glXDestroyGLXPixmap(gfx::GetXDisplay(), glx_pixmap_);
    168     glx_pixmap_ = 0;
    169   }
    170 }
    171 
    172 gfx::Size GLImageGLX::GetSize() { return size_; }
    173 
    174 bool GLImageGLX::BindTexImage(unsigned target) {
    175   if (!glx_pixmap_)
    176     return false;
    177 
    178   // Requires TEXTURE_2D target.
    179   if (target != GL_TEXTURE_2D)
    180     return false;
    181 
    182   glXBindTexImageEXT(gfx::GetXDisplay(), glx_pixmap_, GLX_FRONT_LEFT_EXT, 0);
    183   return true;
    184 }
    185 
    186 void GLImageGLX::ReleaseTexImage(unsigned target) {
    187   DCHECK_NE(0u, glx_pixmap_);
    188   DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), target);
    189 
    190   glXReleaseTexImageEXT(gfx::GetXDisplay(), glx_pixmap_, GLX_FRONT_LEFT_EXT);
    191 }
    192 
    193 bool GLImageGLX::CopyTexImage(unsigned target) {
    194   return false;
    195 }
    196 
    197 bool GLImageGLX::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
    198                                       int z_order,
    199                                       OverlayTransform transform,
    200                                       const Rect& bounds_rect,
    201                                       const RectF& crop_rect) {
    202   return false;
    203 }
    204 
    205 }  // namespace gfx
    206