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/gl/gl_bindings.h" 16#include "ui/gl/gl_surface_glx.h" 17 18namespace gfx { 19 20namespace { 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. 25class ScopedPtrXFree { 26 public: 27 void operator()(void* x) const { 28 ::XFree(x); 29 } 30}; 31 32int 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 39int 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 48GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window) 49 : display_(base::MessagePumpForUI::GetDefaultXDisplay()), 50 window_(window), 51 pixmap_(0), 52 glx_pixmap_(0) { 53} 54 55GLImageGLX::~GLImageGLX() { 56 Destroy(); 57} 58 59bool 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 147void 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 158gfx::Size GLImageGLX::GetSize() { 159 return size_; 160} 161 162bool GLImageGLX::BindTexImage() { 163 if (!glx_pixmap_) 164 return false; 165 166 glXBindTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, 0); 167 return true; 168} 169 170void GLImageGLX::ReleaseTexImage() { 171 if (!glx_pixmap_) 172 return; 173 174 glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT); 175} 176 177void GLImageGLX::WillUseTexImage() { 178} 179 180void GLImageGLX::DidUseTexImage() { 181} 182 183} // namespace gfx 184