Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / ui / gl / gl_image_glx.cc
blob4b7e883781cd8160e6bc6c49d38be238088fc6bd
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.
5 extern "C" {
6 #include <X11/extensions/Xcomposite.h>
9 #include "ui/gl/gl_image_glx.h"
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"
19 namespace gfx {
21 namespace {
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 {
27 void operator()(void* x) const { ::XFree(x); }
30 int BindToTextureFormat(int depth) {
31 if (depth == 32)
32 return GLX_BIND_TO_TEXTURE_RGBA_EXT;
34 return GLX_BIND_TO_TEXTURE_RGB_EXT;
37 int TextureFormat(int depth) {
38 if (depth == 32)
39 return GLX_TEXTURE_FORMAT_RGBA_EXT;
41 return GLX_TEXTURE_FORMAT_RGB_EXT;
44 } // namespace anonymous
46 GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window)
47 : display_(gfx::GetXDisplay()),
48 window_(window),
49 pixmap_(0),
50 glx_pixmap_(0) {}
52 GLImageGLX::~GLImageGLX() { Destroy(); }
54 bool GLImageGLX::Initialize() {
55 if (!GLSurfaceGLX::IsTextureFromPixmapSupported()) {
56 LOG(ERROR) << "GLX_EXT_texture_from_pixmap not supported.";
57 return false;
60 XWindowAttributes attributes;
61 if (!XGetWindowAttributes(display_, window_, &attributes)) {
62 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
63 return false;
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;
76 if (!num_visinfo) {
77 LOG(ERROR) << "XGetVisualInfo returned 0 elements.";
78 return false;
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;
94 if (!num_elements) {
95 LOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
96 return false;
99 // Create backing pixmap reference.
100 pixmap_ = XCompositeNameWindowPixmap(display_, window_);
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;
115 int pixmap_attribs[] = {GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
116 GLX_TEXTURE_FORMAT_EXT, TextureFormat(visinfo->depth),
118 glx_pixmap_ =
119 glXCreatePixmap(display_, *config.get(), pixmap_, pixmap_attribs);
120 if (!glx_pixmap_) {
121 LOG(ERROR) << "glXCreatePixmap failed.";
122 return false;
125 size_ = gfx::Size(width, height);
126 return true;
129 void GLImageGLX::Destroy() {
130 if (glx_pixmap_) {
131 glXDestroyGLXPixmap(display_, glx_pixmap_);
132 glx_pixmap_ = 0;
134 if (pixmap_) {
135 XFreePixmap(display_, pixmap_);
136 pixmap_ = 0;
140 gfx::Size GLImageGLX::GetSize() { return size_; }
142 bool GLImageGLX::BindTexImage(unsigned target) {
143 if (!glx_pixmap_)
144 return false;
146 // Requires TEXTURE_2D target.
147 if (target != GL_TEXTURE_2D)
148 return false;
150 glXBindTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, 0);
151 return true;
154 void GLImageGLX::ReleaseTexImage(unsigned target) {
155 DCHECK(glx_pixmap_);
156 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), target);
158 glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT);
161 } // namespace gfx