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..5bb407761eb4e0e0fe9ca9ceb7abf22d480b27f1 |
--- /dev/null |
+++ b/ui/gl/gl_image_glx.cc |
@@ -0,0 +1,175 @@ |
+// 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. |
+ |
+extern "C" { |
+#include <X11/extensions/Xcomposite.h> |
+} |
+ |
+#include "ui/gl/gl_image_glx.h" |
+ |
+#include "base/basictypes.h" |
+#include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop.h" |
+#include "ui/gl/gl_surface_glx.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); |
+ } |
+}; |
+ |
+int BindToTextureFormat(int depth) { |
+ if (depth == 32) |
+ return GLX_BIND_TO_TEXTURE_RGBA_EXT; |
+ |
+ return GLX_BIND_TO_TEXTURE_RGB_EXT; |
+} |
+ |
+int TextureFormat(int depth) { |
+ if (depth == 32) |
+ return GLX_TEXTURE_FORMAT_RGBA_EXT; |
+ |
+ return GLX_TEXTURE_FORMAT_RGB_EXT; |
+} |
+ |
+} // namespace anonymous |
+ |
+GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window) |
+ : display_(base::MessagePumpForUI::GetDefaultXDisplay()), |
+ window_(window), |
+ pixmap_(0), |
+ glx_pixmap_(0) { |
+} |
+ |
+bool GLImageGLX::Initialize() { |
+ if (!GLSurfaceGLX::IsTextureFromPixmapSupported()) { |
+ LOG(ERROR) << "GLX_EXT_texture_from_pixmap not supported."; |
+ return false; |
+ } |
+ |
+ XWindowAttributes attributes; |
+ if (!XGetWindowAttributes(display_, window_, &attributes)) { |
+ LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; |
+ return false; |
+ } |
+ |
+ XVisualInfo templ; |
+ templ.visualid = XVisualIDFromVisual(attributes.visual); |
+ int num_visinfo = 0; |
+ scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visinfo( |
+ XGetVisualInfo(display_, |
+ VisualIDMask, |
+ &templ, |
+ &num_visinfo)); |
+ if (!visinfo.get()) { |
+ LOG(ERROR) << "XGetVisualInfo failed for visual id " << |
+ templ.visualid << "."; |
+ return false; |
+ } |
+ if (!num_visinfo) { |
+ LOG(ERROR) << "XGetVisualInfo returned 0 elements."; |
+ return false; |
+ } |
+ |
+ int config_attribs[] = { |
+ GLX_VISUAL_ID, visinfo->visualid, |
+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, |
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_EXT, |
+ BindToTextureFormat(visinfo->depth), GL_TRUE, |
+ 0 |
+ }; |
+ int num_elements = 0; |
+ scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config( |
+ glXChooseFBConfig(display_, |
+ DefaultScreen(display_), |
+ config_attribs, |
+ &num_elements)); |
+ if (!config.get()) { |
+ LOG(ERROR) << "glXChooseFBConfig failed."; |
+ return false; |
+ } |
+ if (!num_elements) { |
+ LOG(ERROR) << "glXChooseFBConfig returned 0 elements."; |
+ return false; |
+ } |
+ |
+ // Create backing pixmap reference. |
+ pixmap_ = XCompositeNameWindowPixmap(display_, window_); |
+ |
+ XID root = 0; |
+ int x = 0; |
+ int y = 0; |
+ unsigned int width = 0; |
+ unsigned int height = 0; |
+ unsigned int bw = 0; |
+ unsigned int depth = 0; |
+ if (!XGetGeometry( |
+ display_, pixmap_, &root, &x, &y, &width, &height, &bw, &depth)) { |
+ LOG(ERROR) << "XGetGeometry failed for pixmap " << pixmap_ << "."; |
+ return false; |
+ } |
+ |
+ int pixmap_attribs[] = { |
+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, |
+ GLX_TEXTURE_FORMAT_EXT, TextureFormat(visinfo->depth), |
+ 0 |
+ }; |
+ glx_pixmap_ = glXCreatePixmap( |
+ display_, |
+ *config.get(), |
+ pixmap_, |
+ pixmap_attribs); |
+ if (!glx_pixmap_) { |
+ LOG(ERROR) << "glXCreatePixmap failed."; |
+ return false; |
+ } |
+ |
+ size_ = gfx::Size(width, height); |
+ return true; |
+} |
+ |
+void GLImageGLX::Destroy() { |
+ if (glx_pixmap_) { |
+ glXDestroyGLXPixmap(display_, glx_pixmap_); |
+ glx_pixmap_ = 0; |
+ } |
+ if (pixmap_) { |
+ XFreePixmap(display_, pixmap_); |
+ pixmap_ = 0; |
+ } |
+} |
+ |
+gfx::Size GLImageGLX::GetSize() { |
+ return size_; |
+} |
+ |
+bool GLImageGLX::BindTexImage() { |
+ if (!glx_pixmap_) |
+ return false; |
+ |
+ glXBindTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, 0); |
+ return true; |
+} |
+ |
+void GLImageGLX::ReleaseTexImage() { |
+ if (!glx_pixmap_) |
+ return; |
+ |
+ glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT); |
+} |
+ |
+GLImageGLX::~GLImageGLX() { |
+ Destroy(); |
+} |
+ |
+} // namespace gfx |