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 5extern "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 19namespace gfx { 20 21namespace { 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. 26struct ScopedPtrXFree { 27 void operator()(void* x) const { ::XFree(x); } 28}; 29 30int 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 37int 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 46GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window) 47 : display_(gfx::GetXDisplay()), 48 window_(window), 49 pixmap_(0), 50 glx_pixmap_(0) {} 51 52GLImageGLX::~GLImageGLX() { Destroy(); } 53 54bool 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 129void 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 140gfx::Size GLImageGLX::GetSize() { return size_; } 141 142bool 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 154void 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