Index: webkit/api/src/GraphicsContext3D.cpp |
=================================================================== |
--- webkit/api/src/GraphicsContext3D.cpp (revision 28060) |
+++ webkit/api/src/GraphicsContext3D.cpp (working copy) |
@@ -81,6 +81,11 @@ |
#define USE_TEXTURE_RECTANGLE_FOR_FRAMEBUFFER |
#endif |
+#if PLATFORM(LINUX) |
+#include <dlfcn.h> |
+#include "GL/glxew.h" |
+#endif |
+ |
using namespace std; |
namespace WebCore { |
@@ -167,6 +172,24 @@ |
CGLContextObj m_contextObj; |
unsigned char* m_renderOutput; |
CGContextRef m_cgContext; |
+#elif PLATFORM(LINUX) |
+ Display* m_display; |
+ GLXContext m_contextObj; |
+ GLXPbuffer m_pbuffer; |
+ // In order to avoid problems caused by linking against libGL, we |
+ // dynamically look up all the symbols we need. |
+ // http://code.google.com/p/chromium/issues/detail?id=16800 |
+ void* m_libGL; |
+ PFNGLXCHOOSEFBCONFIGPROC m_glXChooseFBConfig; |
+ PFNGLXCREATENEWCONTEXTPROC m_glXCreateNewContext; |
+ PFNGLXCREATEPBUFFERPROC m_glXCreatePbuffer; |
+ PFNGLXDESTROYPBUFFERPROC m_glXDestroyPbuffer; |
+ typedef Bool (* PFNGLXMAKECURRENTPROC)(Display* dpy, GLXDrawable drawable, GLXContext ctx); |
+ PFNGLXMAKECURRENTPROC m_glXMakeCurrent; |
+ typedef void (* PFNGLXDESTROYCONTEXTPROC)(Display* dpy, GLXContext ctx); |
+ PFNGLXDESTROYCONTEXTPROC m_glXDestroyContext; |
+ typedef GLXContext (* PFNGLXGETCURRENTCONTEXTPROC)(void); |
+ PFNGLXGETCURRENTCONTEXTPROC m_glXGetCurrentContext; |
#else |
#error Must port GraphicsContext3D to your platform |
#endif |
@@ -184,6 +207,15 @@ |
{ |
} |
+#if PLATFORM(LINUX) |
+static void* tryLoad(const char* libName) { |
+ // We use RTLD_GLOBAL semantics so that GLEW initialization works; |
+ // GLEW expects to be able to open the current process's handle |
+ // and do dlsym's of GL entry points from there. |
+ return dlopen(libName, RTLD_LAZY | RTLD_GLOBAL); |
+} |
+#endif |
+ |
GraphicsContext3DInternal::GraphicsContext3DInternal() |
: m_texture(0) |
, m_fbo(0) |
@@ -201,6 +233,17 @@ |
, m_contextObj(NULL) |
, m_renderOutput(NULL) |
, m_cgContext(NULL) |
+#elif PLATFORM(LINUX) |
+ , m_display(NULL) |
+ , m_contextObj(NULL) |
+ , m_pbuffer(NULL) |
+ , m_glXChooseFBConfig(NULL) |
+ , m_glXCreateNewContext(NULL) |
+ , m_glXCreatePbuffer(NULL) |
+ , m_glXDestroyPbuffer(NULL) |
+ , m_glXMakeCurrent(NULL) |
+ , m_glXDestroyContext(NULL) |
+ , m_glXGetCurrentContext(NULL) |
#else |
#error Must port to your platform |
#endif |
@@ -317,20 +360,107 @@ |
} |
m_pbuffer = pbuffer; |
m_contextObj = context; |
+#elif PLATFORM(LINUX) |
+ m_display = XOpenDisplay(NULL); |
+ if (m_display == NULL) { |
+ printf("GraphicsContext3D: error opening X display\n"); |
+ return; |
+ } |
+ |
+ const char* libNames[] = { |
+ "/usr/lib/libGL.so.1", |
+ "/usr/lib32/libGL.so.1", |
+ "/usr/lib64/libGL.so.1", |
+ }; |
+ for (int i = 0; i < sizeof(libNames) / sizeof(const char*); i++) { |
+ m_libGL = tryLoad(libNames[i]); |
+ if (m_libGL != NULL) |
+ break; |
+ } |
+ if (m_libGL == NULL) { |
+ printf("GraphicsContext3D: error opening libGL.so.1\n"); |
+ printf("GraphicsContext3D: tried:"); |
+ for (int i = 0; i < sizeof(libNames) / sizeof(const char*); i++) { |
+ printf(" %s", libNames[i]); |
+ } |
+ return; |
+ } |
+ m_glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) dlsym(m_libGL, "glXChooseFBConfig"); |
+ m_glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC) dlsym(m_libGL, "glXCreateNewContext"); |
+ m_glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC) dlsym(m_libGL, "glXCreatePbuffer"); |
+ m_glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC) dlsym(m_libGL, "glXDestroyPbuffer"); |
+ m_glXMakeCurrent = (PFNGLXMAKECURRENTPROC) dlsym(m_libGL, "glXMakeCurrent"); |
+ m_glXDestroyContext = (PFNGLXDESTROYCONTEXTPROC) dlsym(m_libGL, "glXDestroyContext"); |
+ m_glXGetCurrentContext = (PFNGLXGETCURRENTCONTEXTPROC) dlsym(m_libGL, "glXGetCurrentContext"); |
+ if (!m_glXChooseFBConfig || !m_glXCreateNewContext || !m_glXCreatePbuffer || |
+ !m_glXDestroyPbuffer || !m_glXMakeCurrent || !m_glXDestroyContext || |
+ !m_glXGetCurrentContext) { |
+ printf("GraphicsContext3D: error looking up bootstrapping entry points\n"); |
+ return; |
+ } |
+ int configAttrs[] = { |
+ GLX_DRAWABLE_TYPE, |
+ GLX_PBUFFER_BIT, |
+ GLX_RENDER_TYPE, |
+ GLX_RGBA_BIT, |
+ GLX_DOUBLEBUFFER, |
+ 0, |
+ 0 |
+ }; |
+ int nelements = 0; |
+ GLXFBConfig* config = m_glXChooseFBConfig(m_display, 0, configAttrs, &nelements); |
+ if (config == NULL) { |
+ printf("GraphicsContext3D: glXChooseFBConfig failed\n"); |
+ return; |
+ } |
+ if (nelements == 0) { |
+ printf("GraphicsContext3D: glXChooseFBConfig returned 0 elements\n"); |
+ XFree(config); |
+ return; |
+ } |
+ GLXContext context = m_glXCreateNewContext(m_display, config[0], GLX_RGBA_TYPE, NULL, True); |
+ if (context == NULL) { |
+ printf("GraphicsContext3D: glXCreateNewContext failed\n"); |
+ XFree(config); |
+ return; |
+ } |
+ int pbufferAttrs[] = { |
+ GLX_PBUFFER_WIDTH, |
+ 1, |
+ GLX_PBUFFER_HEIGHT, |
+ 1, |
+ 0 |
+ }; |
+ GLXPbuffer pbuffer = m_glXCreatePbuffer(m_display, config[0], pbufferAttrs); |
+ XFree(config); |
+ if (!pbuffer) { |
+ printf("GraphicsContext3D: glxCreatePbuffer failed\n"); |
+ return; |
+ } |
+ if (!m_glXMakeCurrent(m_display, pbuffer, context)) { |
+ printf("GraphicsContext3D: glXMakeCurrent failed\n"); |
+ return; |
+ } |
+ m_contextObj = context; |
+ m_pbuffer = pbuffer; |
#else |
#error Must port to your platform |
#endif |
- // Initialize GLEW and check for GL 2.0 support by the drivers. |
- GLenum glewInitResult = glewInit(); |
- if (glewInitResult != GLEW_OK) { |
- printf("GraphicsContext3D: GLEW initialization failed\n"); |
- return; |
+ static bool initializedGLEW = false; |
+ if (!initializedGLEW) { |
+ // Initialize GLEW and check for GL 2.0 support by the drivers. |
+ GLenum glewInitResult = glewInit(); |
+ if (glewInitResult != GLEW_OK) { |
+ printf("GraphicsContext3D: GLEW initialization failed\n"); |
+ return; |
+ } |
+ if (!glewIsSupported("GL_VERSION_2_0")) { |
+ printf("GraphicsContext3D: OpenGL 2.0 not supported\n"); |
+ return; |
+ } |
+ initializedGLEW = true; |
} |
- if (!glewIsSupported("GL_VERSION_2_0")) { |
- printf("GraphicsContext3D: OpenGL 2.0 not supported\n"); |
- return; |
- } |
} |
GraphicsContext3DInternal::~GraphicsContext3DInternal() |
@@ -358,6 +488,12 @@ |
CGContextRelease(m_cgContext); |
if (m_renderOutput != NULL) |
delete[] m_renderOutput; |
+#elif PLATFORM(LINUX) |
+ m_glXMakeCurrent(m_display, NULL, NULL); |
+ m_glXDestroyContext(m_display, m_contextObj); |
+ m_glXDestroyPbuffer(m_display, m_pbuffer); |
+ XCloseDisplay(m_display); |
+ dlclose(m_libGL); |
#else |
#error Must port to your platform |
#endif |
@@ -385,6 +521,10 @@ |
if (CGLGetCurrentContext() != m_contextObj) |
if (CGLSetCurrentContext(m_contextObj) == kCGLNoError) |
return true; |
+#elif PLATFORM(LINUX) |
+ if (m_glXGetCurrentContext() != m_contextObj) |
+ if (m_glXMakeCurrent(m_display, m_pbuffer, m_contextObj)) |
+ return true; |
#else |
#error Must port to your platform |
#endif |