• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
operator ()gfx::__anon6c09bc510111::ScopedPtrXFree27   void operator()(void* x) const { ::XFree(x); }
28 };
29 
BindToTextureFormat(int depth)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 
TextureFormat(int depth)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 
GLImageGLX(gfx::PluginWindowHandle window)46 GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window)
47     : display_(gfx::GetXDisplay()),
48       window_(window),
49       pixmap_(0),
50       glx_pixmap_(0) {}
51 
~GLImageGLX()52 GLImageGLX::~GLImageGLX() { Destroy(); }
53 
Initialize()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 
Destroy()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 
GetSize()140 gfx::Size GLImageGLX::GetSize() { return size_; }
141 
BindTexImage(unsigned target)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 
ReleaseTexImage(unsigned target)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