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