Chromium Code Reviews| 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..95b70da64acf6c3f8959fe794fe7a718cb6352ff |
| --- /dev/null |
| +++ b/ui/gl/gl_image_glx.cc |
| @@ -0,0 +1,178 @@ |
| +// 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); |
| + } |
| +}; |
| + |
| +} // namespace anonymous |
| + |
| +GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window) |
| + : display_(base::MessagePumpForUI::GetDefaultXDisplay()), |
| + pixmap_(XCompositeNameWindowPixmap(display_, window)), |
| + glx_pixmap_(0) { |
| +} |
| + |
| +bool GLImageGLX::Initialize() { |
| + if (!GLSurfaceGLX::IsTextureFromPixmapSupported()) { |
| + LOG(ERROR) << "GLX_EXT_texture_from_pixmap not supported."; |
| + return false; |
| + } |
| + |
| + XID root; |
| + int x, y; |
| + unsigned int width, height, border_width, depth; |
|
piman
2012/10/12 22:05:11
nit: please initialize all local variables.
reveman
2012/10/13 05:25:53
Done.
|
| + if (!XGetGeometry(display_, pixmap_, &root, &x, &y, &width, &height, |
| + &border_width, &depth)) { |
| + LOG(ERROR) << "XGetGeometry failed for pixmap " << pixmap_ << "."; |
| + return false; |
| + } |
| + |
| + 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; |
|
piman
2012/10/12 22:05:11
nit move the = 0 initialization here.
reveman
2012/10/13 05:25:53
Done.
|
| + for (i = 0; i < num_elements; ++i) { |
| + int value; |
|
piman
2012/10/12 22:05:11
nit: initialize
reveman
2012/10/13 05:25:53
Done.
|
| + 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, |
|
piman
2012/10/12 22:05:11
so, techincally, we can have RGB windows in a 32 b
reveman
2012/10/13 05:25:53
Done.
|
| + &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; |
| + } |
|
piman
2012/10/12 22:05:11
Can we replace all this by glXChooseFBConfig?
reveman
2012/10/13 05:25:53
Done.
|
| + |
| + 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); |
|
piman
2012/10/12 22:05:11
Since the array is fixed size, can we just make th
reveman
2012/10/13 05:25:53
Done.
|
| + |
| + glx_pixmap_ = glXCreatePixmap( |
| + display_, |
| + configs.get()[i], |
| + pixmap_, |
| + &attribs.front()); |
| + 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 |