summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service/gl_context_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer/service/gl_context_linux.cc')
-rw-r--r--gpu/command_buffer/service/gl_context_linux.cc175
1 files changed, 115 insertions, 60 deletions
diff --git a/gpu/command_buffer/service/gl_context_linux.cc b/gpu/command_buffer/service/gl_context_linux.cc
index acafd3b2..1c04d91 100644
--- a/gpu/command_buffer/service/gl_context_linux.cc
+++ b/gpu/command_buffer/service/gl_context_linux.cc
@@ -4,21 +4,79 @@
// This file implements the ViewGLContext and PbufferGLContext classes.
-#if !defined(UNIT_TEST)
#include <dlfcn.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#endif
+
+// Ensure that gl_utils.h is included before any GL headers.
+#include "gpu/command_buffer/service/gl_utils.h"
#include "app/x11_util.h"
-#include "gpu/command_buffer/service/gl_context.h"
#include "base/scoped_ptr.h"
-#include "gpu/command_buffer/service/gl_utils.h"
+#include "gpu/command_buffer/service/gl_context.h"
+#include "gpu/command_buffer/service/gl_context_osmesa.h"
#include "gpu/command_buffer/common/logging.h"
namespace gpu {
-#if !defined(UNIT_TEST)
+typedef GLXContext GLContextHandle;
+typedef GLXPbuffer PbufferHandle;
+
+// This class is a wrapper around a GL context that renders directly to a
+// window.
+class ViewGLContext : public GLContext {
+ public:
+ explicit ViewGLContext(gfx::PluginWindowHandle window)
+ : window_(window),
+ context_(NULL) {
+ DCHECK(window);
+ }
+
+ // Initializes the GL context.
+ bool Initialize(bool multisampled);
+
+ virtual void Destroy();
+ virtual bool MakeCurrent();
+ virtual bool IsCurrent();
+ virtual bool IsOffscreen();
+ virtual void SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ private:
+ gfx::PluginWindowHandle window_;
+ GLContextHandle context_;
+
+ DISALLOW_COPY_AND_ASSIGN(ViewGLContext);
+};
+
+// This class is a wrapper around a GL context used for offscreen rendering.
+// It is initially backed by a 1x1 pbuffer. Use it to create an FBO to do useful
+// rendering.
+class PbufferGLContext : public GLContext {
+ public:
+ explicit PbufferGLContext()
+ : context_(NULL),
+ pbuffer_(NULL) {
+ }
+
+ // Initializes the GL context.
+ bool Initialize(void* shared_handle);
+
+ virtual void Destroy();
+ virtual bool MakeCurrent();
+ virtual bool IsCurrent();
+ virtual bool IsOffscreen();
+ virtual void SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ private:
+ GLContextHandle context_;
+ PbufferHandle pbuffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(PbufferGLContext);
+};
// scoped_ptr functor for XFree(). Use as follows:
// scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
@@ -35,9 +93,13 @@ class ScopedPtrXFree {
// load it, and use glew to dynamically resolve symbols.
// See http://code.google.com/p/chromium/issues/detail?id=16800
-static bool InitializeGLXEW(Display* display) {
- static bool glxew_initialized = false;
- if (!glxew_initialized) {
+static bool InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ osmewInit();
+ if (!OSMesaCreateContext) {
void* handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
if (!handle) {
LOG(ERROR) << "Could not find libGL.so.1";
@@ -53,28 +115,23 @@ static bool InitializeGLXEW(Display* display) {
// complete, and we don't want to have to create an OpenGL context
// just to get access to GLX 1.3 entry points to create pbuffers.
// We therefore added a glxewContextInitWithDisplay entry point.
+ Display* display = x11_util::GetXDisplay();
if (glxewContextInitWithDisplay(display) != GLEW_OK) {
LOG(ERROR) << "glxewContextInit failed";
return false;
}
- glxew_initialized = true;
}
+ initialized = true;
return true;
}
-#endif // UNIT_TEST
-
bool ViewGLContext::Initialize(bool multisampled) {
-#if !defined(UNIT_TEST)
if (multisampled) {
DLOG(WARNING) << "Multisampling not implemented.";
}
Display* display = x11_util::GetXDisplay();
- if (!InitializeGLXEW(display))
- return false;
-
XWindowAttributes attributes;
XGetWindowAttributes(display, window_, &attributes);
XVisualInfo visual_info_template;
@@ -113,13 +170,10 @@ bool ViewGLContext::Initialize(bool multisampled) {
return false;
}
-#endif // UNIT_TEST
-
return true;
}
void ViewGLContext::Destroy() {
-#if !defined(UNIT_TEST)
Display* display = x11_util::GetXDisplay();
Bool result = glXMakeCurrent(display, 0, 0);
@@ -131,11 +185,9 @@ void ViewGLContext::Destroy() {
glXDestroyContext(display, context_);
context_ = NULL;
}
-#endif // UNIT_TEST
}
bool ViewGLContext::MakeCurrent() {
-#if !defined(UNIT_TEST)
if (IsCurrent()) {
return true;
}
@@ -147,18 +199,13 @@ bool ViewGLContext::MakeCurrent() {
DLOG(ERROR) << "Couldn't make context current.";
return false;
}
-#endif // UNIT_TEST
return true;
}
bool ViewGLContext::IsCurrent() {
-#if !defined(UNIT_TEST)
return glXGetCurrentDrawable() == window_ &&
glXGetCurrentContext() == context_;
-#else
- return true;
-#endif
}
bool ViewGLContext::IsOffscreen() {
@@ -166,41 +213,41 @@ bool ViewGLContext::IsOffscreen() {
}
void ViewGLContext::SwapBuffers() {
-#if !defined(UNIT_TEST)
Display* display = x11_util::GetXDisplay();
glXSwapBuffers(display, window_);
-#endif // UNIT_TEST
}
gfx::Size ViewGLContext::GetSize() {
-#if !defined(UNIT_TEST)
XWindowAttributes attributes;
Display* display = x11_util::GetXDisplay();
XGetWindowAttributes(display, window_, &attributes);
return gfx::Size(attributes.width, attributes.height);
-#else
- return gfx::Size();
-#endif // UNIT_TEST
}
-GLContextHandle ViewGLContext::GetHandle() {
-#if !defined(UNIT_TEST)
+void* ViewGLContext::GetHandle() {
return context_;
-#else
- return NULL;
-#endif // UNIT_TEST
}
-bool PbufferGLContext::Initialize(GLContext* shared_context) {
- return Initialize(shared_context ? shared_context->GetHandle() : NULL);
-}
+GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window,
+ bool multisampled) {
+ if (!InitializeOneOff())
+ return NULL;
-bool PbufferGLContext::Initialize(GLContextHandle shared_handle) {
-#if !defined(UNIT_TEST)
- Display* display = x11_util::GetXDisplay();
- if (!InitializeGLXEW(display))
- return false;
+ if (OSMesaCreateContext) {
+ // TODO(apatrick): Support OSMesa rendering to a window on Linux.
+ NOTREACHED() << "OSMesa rendering to a window is not yet implemented.";
+ return NULL;
+ } else {
+ scoped_ptr<ViewGLContext> context(new ViewGLContext(window));
+
+ if (!context->Initialize(multisampled))
+ return NULL;
+
+ return context.release();
+ }
+}
+bool PbufferGLContext::Initialize(void* shared_handle) {
if (!glXChooseFBConfig ||
!glXCreateNewContext ||
!glXCreatePbuffer ||
@@ -219,6 +266,8 @@ bool PbufferGLContext::Initialize(GLContextHandle shared_handle) {
0
};
+ Display* display = x11_util::GetXDisplay();
+
int nelements = 0;
// TODO(kbr): figure out whether hardcoding screen to 0 is sufficient.
scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config(
@@ -234,7 +283,7 @@ bool PbufferGLContext::Initialize(GLContextHandle shared_handle) {
context_ = glXCreateNewContext(display,
config.get()[0],
GLX_RGBA_TYPE,
- shared_handle,
+ static_cast<GLContextHandle>(shared_handle),
True);
if (!context_) {
DLOG(ERROR) << "glXCreateNewContext failed.";
@@ -271,13 +320,10 @@ bool PbufferGLContext::Initialize(GLContextHandle shared_handle) {
return false;
}
-#endif // UNIT_TEST
-
return true;
}
void PbufferGLContext::Destroy() {
-#if !defined(UNIT_TEST)
Display* display = x11_util::GetXDisplay();
Bool result = glXMakeCurrent(display, 0, 0);
// glXMakeCurrent isn't supposed to fail when unsetting the context, unless
@@ -293,11 +339,9 @@ void PbufferGLContext::Destroy() {
glXDestroyPbuffer(display, pbuffer_);
pbuffer_ = NULL;
}
-#endif // UNIT_TEST
}
bool PbufferGLContext::MakeCurrent() {
-#if !defined(UNIT_TEST)
if (IsCurrent()) {
return true;
}
@@ -308,18 +352,13 @@ bool PbufferGLContext::MakeCurrent() {
DLOG(ERROR) << "Couldn't make context current.";
return false;
}
-#endif // UNIT_TEST
return true;
}
bool PbufferGLContext::IsCurrent() {
-#if !defined(UNIT_TEST)
return glXGetCurrentDrawable() == pbuffer_ &&
glXGetCurrentContext() == context_;
-#else
- return true;
-#endif
}
bool PbufferGLContext::IsOffscreen() {
@@ -335,12 +374,28 @@ gfx::Size PbufferGLContext::GetSize() {
return gfx::Size(1, 1);
}
-GLContextHandle PbufferGLContext::GetHandle() {
-#if !defined(UNIT_TEST)
+void* PbufferGLContext::GetHandle() {
return context_;
-#else
- return NULL;
-#endif // UNIT_TEST
+}
+
+GLContext* GLContext::CreateOffscreenGLContext(void* shared_handle) {
+ if (!InitializeOneOff())
+ return NULL;
+
+ if (OSMesaCreateContext) {
+ scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext);
+
+ if (!context->Initialize(shared_handle))
+ return NULL;
+
+ return context.release();
+ } else {
+ scoped_ptr<PbufferGLContext> context(new PbufferGLContext);
+ if (!context->Initialize(shared_handle))
+ return NULL;
+
+ return context.release();
+ }
}
} // namespace gpu