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 |