| Index: ui/gl/gl_image_glx.cc
|
| diff --git a/ui/gl/gl_image_glx.cc b/ui/gl/gl_image_glx.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..dc289d204cd2e83f487e0c6cfcef78569fd6c0f4
|
| --- /dev/null
|
| +++ b/ui/gl/gl_image_glx.cc
|
| @@ -0,0 +1,171 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "ui/gl/gl_image_glx.h"
|
| +
|
| +#include "base/basictypes.h"
|
| +#include "base/logging.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "ui/gl/gl_surface.h"
|
| +
|
| +namespace gfx {
|
| +
|
| +namespace {
|
| +
|
| +// scoped_ptr functor for XFree(). Use as follows:
|
| +// scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
|
| +// where "XVisualInfo" is any X type that is freed with XFree.
|
| +class ScopedPtrXFree {
|
| + public:
|
| + void operator()(void* x) const {
|
| + ::XFree(x);
|
| + }
|
| +};
|
| +
|
| +} // namespace anonymous
|
| +
|
| +
|
| +PixmapGLImageGLX::PixmapGLImageGLX()
|
| + : display_(NULL),
|
| + pixmap_(0),
|
| + glx_pixmap_(0) {
|
| +}
|
| +
|
| +bool PixmapGLImageGLX::Initialize(GLSurface* compatible_surface) {
|
| + display_ = static_cast<Display*>(compatible_surface->GetDisplay());
|
| + return true;
|
| +}
|
| +
|
| +void PixmapGLImageGLX::Destroy() {
|
| + pixmap_ = 0;
|
| + if (glx_pixmap_) {
|
| + glXDestroyGLXPixmap(display_, glx_pixmap_);
|
| + glx_pixmap_ = 0;
|
| + }
|
| +}
|
| +
|
| +gfx::Size PixmapGLImageGLX::GetSize() {
|
| + return size_;
|
| +}
|
| +
|
| +bool PixmapGLImageGLX::RebindPixmap(GLuint pixmap) {
|
| + XID glx_pixmap = glx_pixmap_;
|
| +
|
| + if (pixmap && pixmap != pixmap_) {
|
| + XID root;
|
| + int x, y;
|
| + unsigned int width, height, border_width, depth;
|
| + if (!XGetGeometry(display_, pixmap, &root, &x, &y, &width, &height,
|
| + &border_width, &depth)) {
|
| + LOG(ERROR) << "XGetGeometry failed for pixmap " << pixmap << ".";
|
| + return false;
|
| + }
|
| + size_ = gfx::Size(width, height);
|
| +
|
| + int num_elements = 0;
|
| + scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs(
|
| + glXGetFBConfigs(display_,
|
| + DefaultScreen(display_),
|
| + &num_elements));
|
| + if (!configs.get()) {
|
| + LOG(ERROR) << "glXGetFBConfigs failed.";
|
| + return false;
|
| + }
|
| + if (!num_elements) {
|
| + LOG(ERROR) << "glXGetFBConfigs returned 0 elements.";
|
| + return false;
|
| + }
|
| + bool found = false;
|
| + int i;
|
| + for (i = 0; i < num_elements; ++i) {
|
| + int value;
|
| + if (glXGetFBConfigAttrib(
|
| + display_, configs.get()[i], GLX_DRAWABLE_TYPE, &value)) {
|
| + LOG(ERROR) << "glXGetFBConfigAttrib failed.";
|
| + return false;
|
| + }
|
| + if (!(value & GLX_PIXMAP_BIT))
|
| + continue;
|
| + if (glXGetFBConfigAttrib(
|
| + display_, configs.get()[i], GLX_BIND_TO_TEXTURE_TARGETS_EXT,
|
| + &value)) {
|
| + LOG(ERROR) << "glXGetFBConfigAttrib failed.";
|
| + return false;
|
| + }
|
| + if (!(value & GLX_TEXTURE_2D_BIT_EXT))
|
| + continue;
|
| + if (glXGetFBConfigAttrib(
|
| + display_, configs.get()[i], (depth == 32) ?
|
| + GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT,
|
| + &value)) {
|
| + LOG(ERROR) << "glXGetFBConfigAttrib failed.";
|
| + return false;
|
| + }
|
| + if (value == GL_FALSE)
|
| + continue;
|
| + if (glXGetFBConfigAttrib(
|
| + display_, configs.get()[i], GLX_DOUBLEBUFFER, &value)) {
|
| + LOG(ERROR) << "glXGetFBConfigAttrib failed.";
|
| + return false;
|
| + }
|
| + // Avoid double buffered config.
|
| + if (value == GL_TRUE)
|
| + continue;
|
| + if (glXGetFBConfigAttrib(
|
| + display_, configs.get()[i], GLX_BUFFER_SIZE, &value)) {
|
| + LOG(ERROR) << "glXGetFBConfigAttrib failed.";
|
| + return false;
|
| + }
|
| + if (value < static_cast<int>(depth))
|
| + continue;
|
| +
|
| + found = true;
|
| + break;
|
| + }
|
| +
|
| + if (!found) {
|
| + LOG(ERROR) << "Failed to find valid FBConfig for pixmap.";
|
| + return false;
|
| + }
|
| +
|
| + std::vector<int> attribs;
|
| + attribs.push_back(GLX_TEXTURE_TARGET_EXT);
|
| + attribs.push_back(GLX_TEXTURE_2D_EXT);
|
| + attribs.push_back(GLX_TEXTURE_FORMAT_EXT);
|
| + if (depth == 32)
|
| + attribs.push_back(GLX_TEXTURE_FORMAT_RGBA_EXT);
|
| + else
|
| + attribs.push_back(GLX_TEXTURE_FORMAT_RGB_EXT);
|
| + attribs.push_back(0);
|
| +
|
| + glx_pixmap = glXCreatePixmap(
|
| + display_,
|
| + configs.get()[i],
|
| + pixmap,
|
| + &attribs.front());
|
| + if (!glx_pixmap) {
|
| + LOG(ERROR) << "glXCreatePixmap failed.";
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + // Release currently bound pixmap from texture.
|
| + if (glx_pixmap_)
|
| + glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT);
|
| +
|
| + pixmap_ = pixmap;
|
| + glx_pixmap_ = glx_pixmap;
|
| +
|
| + // Bind new pixmap to texture.
|
| + if (glx_pixmap_)
|
| + glXBindTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, 0);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +PixmapGLImageGLX::~PixmapGLImageGLX() {
|
| + Destroy();
|
| +}
|
| +
|
| +} // namespace gfx
|
|
|