Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Unified Diff: gpu/command_buffer/service/x_utils.cc

Issue 1540004: Implemented offscreen rendering path for GLES2CmdDecoder on Linux.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/command_buffer/service/x_utils.h ('k') | third_party/glew/README.chromium » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/command_buffer/service/x_utils.cc
===================================================================
--- gpu/command_buffer/service/x_utils.cc (revision 43138)
+++ gpu/command_buffer/service/x_utils.cc (working copy)
@@ -6,21 +6,33 @@
#include <dlfcn.h>
+#include "base/scoped_ptr.h"
#include "gpu/command_buffer/service/precompile.h"
#include "gpu/command_buffer/common/logging.h"
#include "gpu/command_buffer/service/x_utils.h"
namespace gpu {
+// 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);
+ }
+};
+
// Some versions of NVIDIA's GL libGL.so include a broken version of
// dlopen/dlsym, and so linking it into chrome breaks it. So we dynamically
// load it, and use glew to dynamically resolve symbols.
// See http://code.google.com/p/chromium/issues/detail?id=16800
+static bool g_glxew_initialized = false;
static bool g_glew_initialized = false;
-bool XWindowWrapper::Initialize() {
- if (!g_glew_initialized) {
+static bool InitializeGLXEW() {
+ if (!g_glxew_initialized) {
void* handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
if (!handle) {
LOG(ERROR) << "Could not find libGL.so.1";
@@ -29,78 +41,210 @@
// Initializes context-independent parts of GLEW
if (glxewInit() != GLEW_OK) {
- LOG(ERROR) << "GLXEW failed initialization";
+ LOG(ERROR) << "glxewInit failed";
return false;
}
+ // Hack to work around apparently incorrect assumption in
+ // glxewContextInit. Documentation indicates that all of the work
+ // it does is actually context-independent. We require GLX 1.3
+ // entry points to be present for successful initialization of the
+ // off-screen code path in the GLES2Decoder. TODO(kbr): clean this
+ // up.
+ if (glxewContextInit() != GLEW_OK) {
+ LOG(ERROR) << "glxewContextInit failed";
+ return false;
+ }
+ g_glxew_initialized = true;
+ }
+ return true;
+}
+
+// GLEW initialization is extremely expensive because it looks up
+// hundreds of function pointers. Realistically we are not going to
+// switch between GL implementations on the fly, so for the time being
+// we only do the context-dependent GLEW initialization once.
+static bool InitializeGLEW() {
+ if (!g_glew_initialized) {
+ // Initializes context-dependent parts of GLEW
+ if (glewInit() != GLEW_OK) {
+ LOG(ERROR) << "GLEW failed initialization";
+ return false;
+ }
+
+ if (!glewIsSupported("GL_VERSION_2_0")) {
+ LOG(ERROR) << "GL implementation doesn't support GL version 2.0";
+ return false;
+ }
g_glew_initialized = true;
}
+ return true;
+}
+
+GLXContextWrapper::~GLXContextWrapper() {
+}
+
+bool GLXContextWrapper::Initialize() {
+ if (!MakeCurrent()) {
+ Destroy();
+ DLOG(ERROR) << "Couldn't make context current for initialization.";
+ return false;
+ }
+
+ if (!InitializeGLEW()) {
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void GLXContextWrapper::Destroy() {
+ Bool result = glXMakeCurrent(GetDisplay(), 0, 0);
+ // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
+ // we have pending draws on an invalid window - which shouldn't be the case
+ // here.
+ DCHECK(result);
+ if (GetContext()) {
+ glXDestroyContext(GetDisplay(), GetContext());
+ SetContext(NULL);
+ }
+}
+
+bool XWindowWrapper::Initialize() {
+ if (!InitializeGLXEW())
+ return false;
+
XWindowAttributes attributes;
- XGetWindowAttributes(display_, window_, &attributes);
+ XGetWindowAttributes(GetDisplay(), window_, &attributes);
XVisualInfo visual_info_template;
visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
int visual_info_count = 0;
- XVisualInfo *visual_info_list = XGetVisualInfo(display_, VisualIDMask,
- &visual_info_template,
- &visual_info_count);
- DCHECK(visual_info_list);
+ scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list(
+ XGetVisualInfo(GetDisplay(), VisualIDMask,
+ &visual_info_template,
+ &visual_info_count));
+ DCHECK(visual_info_list.get());
DCHECK_GT(visual_info_count, 0);
- context_ = 0;
+ SetContext(NULL);
for (int i = 0; i < visual_info_count; ++i) {
- context_ = glXCreateContext(display_, visual_info_list + i, 0,
- True);
- if (context_) break;
+ SetContext(glXCreateContext(GetDisplay(), visual_info_list.get() + i, 0,
+ True));
+ if (GetContext())
+ break;
}
- XFree(visual_info_list);
- if (!context_) {
+ if (!GetContext()) {
DLOG(ERROR) << "Couldn't create GL context.";
return false;
}
- if (!MakeCurrent()) {
+ return GLXContextWrapper::Initialize();
+}
+
+bool XWindowWrapper::MakeCurrent() {
+ if (glXGetCurrentDrawable() == window_ &&
+ glXGetCurrentContext() == GetContext()) {
+ return true;
+ }
+ if (glXMakeCurrent(GetDisplay(), window_, GetContext()) != True) {
+ glXDestroyContext(GetDisplay(), GetContext());
+ SetContext(0);
+ DLOG(ERROR) << "Couldn't make context current.";
return false;
}
+ return true;
+}
- // Initializes context-dependent parts of GLEW
- if (glewInit() != GLEW_OK) {
- LOG(ERROR) << "GLEW failed initialization";
+bool XWindowWrapper::IsOffscreen() {
+ return false;
+}
+
+void XWindowWrapper::SwapBuffers() {
+ glXSwapBuffers(GetDisplay(), window_);
+}
+
+bool GLXPbufferWrapper::Initialize() {
+ if (!InitializeGLXEW())
return false;
+
+ if (!glXChooseFBConfig ||
+ !glXCreateNewContext ||
+ !glXCreatePbuffer ||
+ !glXDestroyPbuffer) {
+ DLOG(ERROR) << "Pbuffer support not available.";
+ return false;
}
- if (!glewIsSupported("GL_VERSION_2_0")) {
- LOG(ERROR) << "GL implementation doesn't support GL version 2.0";
+ static const int config_attributes[] = {
+ GLX_DRAWABLE_TYPE,
+ GLX_PBUFFER_BIT,
+ GLX_RENDER_TYPE,
+ GLX_RGBA_BIT,
+ GLX_DOUBLEBUFFER,
+ 0,
+ 0
+ };
+
+ int nelements = 0;
+ // TODO(kbr): figure out whether hardcoding screen to 0 is sufficient.
+ scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config(
+ glXChooseFBConfig(GetDisplay(), 0, config_attributes, &nelements));
+ if (!config.get()) {
+ DLOG(ERROR) << "glXChooseFBConfig failed.";
return false;
}
+ if (!nelements) {
+ DLOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
+ return false;
+ }
+ SetContext(glXCreateNewContext(GetDisplay(),
+ config.get()[0], GLX_RGBA_TYPE, 0, True));
+ if (!GetContext()) {
+ DLOG(ERROR) << "glXCreateNewContext failed.";
+ return false;
+ }
+ static const int pbuffer_attributes[] = {
+ GLX_PBUFFER_WIDTH,
+ 1,
+ GLX_PBUFFER_HEIGHT,
+ 1,
+ 0
+ };
+ pbuffer_ = glXCreatePbuffer(GetDisplay(),
+ config.get()[0], pbuffer_attributes);
+ if (!pbuffer_) {
+ Destroy();
+ DLOG(ERROR) << "glXCreatePbuffer failed.";
+ return false;
+ }
+ return GLXContextWrapper::Initialize();
+}
- return true;
+void GLXPbufferWrapper::Destroy() {
+ GLXContextWrapper::Destroy();
+ if (pbuffer_) {
+ glXDestroyPbuffer(GetDisplay(), pbuffer_);
+ pbuffer_ = NULL;
+ }
}
-bool XWindowWrapper::MakeCurrent() {
- if (glXGetCurrentDrawable() == window_ &&
- glXGetCurrentContext() == context_) {
+bool GLXPbufferWrapper::MakeCurrent() {
+ if (glXGetCurrentDrawable() == pbuffer_ &&
+ glXGetCurrentContext() == GetContext()) {
return true;
}
- if (glXMakeCurrent(display_, window_, context_) != True) {
- glXDestroyContext(display_, context_);
- context_ = 0;
+ if (glXMakeCurrent(GetDisplay(), pbuffer_, GetContext()) != True) {
+ glXDestroyContext(GetDisplay(), GetContext());
+ SetContext(0);
DLOG(ERROR) << "Couldn't make context current.";
return false;
}
return true;
}
-void XWindowWrapper::Destroy() {
- Bool result = glXMakeCurrent(display_, 0, 0);
- // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
- // we have pending draws on an invalid window - which shouldn't be the case
- // here.
- DCHECK(result);
- if (context_) {
- glXDestroyContext(display_, context_);
- context_ = 0;
- }
+bool GLXPbufferWrapper::IsOffscreen() {
+ return true;
}
-void XWindowWrapper::SwapBuffers() {
- glXSwapBuffers(display_, window_);
+void GLXPbufferWrapper::SwapBuffers() {
}
} // namespace gpu
« no previous file with comments | « gpu/command_buffer/service/x_utils.h ('k') | third_party/glew/README.chromium » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698