OLD | NEW |
(Empty) | |
| 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.h" |
| 15 #include "ui/gl/gl_surface_glx.h" |
| 16 |
| 17 namespace gfx { |
| 18 |
| 19 namespace { |
| 20 |
| 21 // scoped_ptr functor for XFree(). Use as follows: |
| 22 // scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...); |
| 23 // where "XVisualInfo" is any X type that is freed with XFree. |
| 24 class ScopedPtrXFree { |
| 25 public: |
| 26 void operator()(void* x) const { |
| 27 ::XFree(x); |
| 28 } |
| 29 }; |
| 30 |
| 31 int BindToTextureFormat(int depth) { |
| 32 if (depth == 32) |
| 33 return GLX_BIND_TO_TEXTURE_RGBA_EXT; |
| 34 |
| 35 return GLX_BIND_TO_TEXTURE_RGB_EXT; |
| 36 } |
| 37 |
| 38 int TextureFormat(int depth) { |
| 39 if (depth == 32) |
| 40 return GLX_TEXTURE_FORMAT_RGBA_EXT; |
| 41 |
| 42 return GLX_TEXTURE_FORMAT_RGB_EXT; |
| 43 } |
| 44 |
| 45 } // namespace anonymous |
| 46 |
| 47 GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window) |
| 48 : display_(base::MessagePumpForUI::GetDefaultXDisplay()), |
| 49 window_(window), |
| 50 pixmap_(0), |
| 51 glx_pixmap_(0) { |
| 52 } |
| 53 |
| 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_malloc<XVisualInfo, ScopedPtrXFree> visinfo( |
| 70 XGetVisualInfo(display_, |
| 71 VisualIDMask, |
| 72 &templ, |
| 73 &num_visinfo)); |
| 74 if (!visinfo.get()) { |
| 75 LOG(ERROR) << "XGetVisualInfo failed for visual id " << |
| 76 templ.visualid << "."; |
| 77 return false; |
| 78 } |
| 79 if (!num_visinfo) { |
| 80 LOG(ERROR) << "XGetVisualInfo returned 0 elements."; |
| 81 return false; |
| 82 } |
| 83 |
| 84 int config_attribs[] = { |
| 85 GLX_VISUAL_ID, visinfo->visualid, |
| 86 GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, |
| 87 GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_EXT, |
| 88 BindToTextureFormat(visinfo->depth), GL_TRUE, |
| 89 0 |
| 90 }; |
| 91 int num_elements = 0; |
| 92 scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config( |
| 93 glXChooseFBConfig(display_, |
| 94 DefaultScreen(display_), |
| 95 config_attribs, |
| 96 &num_elements)); |
| 97 if (!config.get()) { |
| 98 LOG(ERROR) << "glXChooseFBConfig failed."; |
| 99 return false; |
| 100 } |
| 101 if (!num_elements) { |
| 102 LOG(ERROR) << "glXChooseFBConfig returned 0 elements."; |
| 103 return false; |
| 104 } |
| 105 |
| 106 // Create backing pixmap reference. |
| 107 pixmap_ = XCompositeNameWindowPixmap(display_, window_); |
| 108 |
| 109 XID root = 0; |
| 110 int x = 0; |
| 111 int y = 0; |
| 112 unsigned int width = 0; |
| 113 unsigned int height = 0; |
| 114 unsigned int bw = 0; |
| 115 unsigned int depth = 0; |
| 116 if (!XGetGeometry( |
| 117 display_, pixmap_, &root, &x, &y, &width, &height, &bw, &depth)) { |
| 118 LOG(ERROR) << "XGetGeometry failed for pixmap " << pixmap_ << "."; |
| 119 return false; |
| 120 } |
| 121 |
| 122 int pixmap_attribs[] = { |
| 123 GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, |
| 124 GLX_TEXTURE_FORMAT_EXT, TextureFormat(visinfo->depth), |
| 125 0 |
| 126 }; |
| 127 glx_pixmap_ = glXCreatePixmap( |
| 128 display_, |
| 129 *config.get(), |
| 130 pixmap_, |
| 131 pixmap_attribs); |
| 132 if (!glx_pixmap_) { |
| 133 LOG(ERROR) << "glXCreatePixmap failed."; |
| 134 return false; |
| 135 } |
| 136 |
| 137 size_ = gfx::Size(width, height); |
| 138 return true; |
| 139 } |
| 140 |
| 141 void GLImageGLX::Destroy() { |
| 142 if (glx_pixmap_) { |
| 143 glXDestroyGLXPixmap(display_, glx_pixmap_); |
| 144 glx_pixmap_ = 0; |
| 145 } |
| 146 if (pixmap_) { |
| 147 XFreePixmap(display_, pixmap_); |
| 148 pixmap_ = 0; |
| 149 } |
| 150 } |
| 151 |
| 152 gfx::Size GLImageGLX::GetSize() { |
| 153 return size_; |
| 154 } |
| 155 |
| 156 bool GLImageGLX::BindTexImage() { |
| 157 if (!glx_pixmap_) |
| 158 return false; |
| 159 |
| 160 glXBindTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, 0); |
| 161 return true; |
| 162 } |
| 163 |
| 164 void GLImageGLX::ReleaseTexImage() { |
| 165 if (!glx_pixmap_) |
| 166 return; |
| 167 |
| 168 glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT); |
| 169 } |
| 170 |
| 171 GLImageGLX::~GLImageGLX() { |
| 172 Destroy(); |
| 173 } |
| 174 |
| 175 } // namespace gfx |
OLD | NEW |