From 29dda80c0178371feea3aa81d72e1f8ff3b17bb6 Mon Sep 17 00:00:00 2001 From: derekf Date: Wed, 1 Oct 2014 10:52:52 -0700 Subject: Add support for EGL on linux Allow setting skia_egl=1 to build skia against EGL instead of GLX on unix Review URL: https://codereview.chromium.org/604853003 --- src/gpu/gl/android/SkNativeGLContext_android.cpp | 182 ------------- src/gpu/gl/egl/GrGLCreateNativeInterface_egl.cpp | 22 ++ src/gpu/gl/egl/SkNativeGLContext_egl.cpp | 182 +++++++++++++ src/gpu/gl/glx/GrGLCreateNativeInterface_glx.cpp | 27 ++ src/gpu/gl/glx/SkNativeGLContext_glx.cpp | 288 +++++++++++++++++++++ src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp | 27 -- src/gpu/gl/unix/SkNativeGLContext_unix.cpp | 288 --------------------- 7 files changed, 519 insertions(+), 497 deletions(-) delete mode 100644 src/gpu/gl/android/SkNativeGLContext_android.cpp create mode 100644 src/gpu/gl/egl/GrGLCreateNativeInterface_egl.cpp create mode 100644 src/gpu/gl/egl/SkNativeGLContext_egl.cpp create mode 100644 src/gpu/gl/glx/GrGLCreateNativeInterface_glx.cpp create mode 100644 src/gpu/gl/glx/SkNativeGLContext_glx.cpp delete mode 100644 src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp delete mode 100644 src/gpu/gl/unix/SkNativeGLContext_unix.cpp (limited to 'src/gpu/gl') diff --git a/src/gpu/gl/android/SkNativeGLContext_android.cpp b/src/gpu/gl/android/SkNativeGLContext_android.cpp deleted file mode 100644 index d4d7219b5b..0000000000 --- a/src/gpu/gl/android/SkNativeGLContext_android.cpp +++ /dev/null @@ -1,182 +0,0 @@ - -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "gl/SkNativeGLContext.h" - -SkNativeGLContext::AutoContextRestore::AutoContextRestore() { - fOldEGLContext = eglGetCurrentContext(); - fOldDisplay = eglGetCurrentDisplay(); - fOldSurface = eglGetCurrentSurface(EGL_DRAW); - -} - -SkNativeGLContext::AutoContextRestore::~AutoContextRestore() { - if (fOldDisplay) { - eglMakeCurrent(fOldDisplay, fOldSurface, fOldSurface, fOldEGLContext); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -SkNativeGLContext::SkNativeGLContext() - : fContext(EGL_NO_CONTEXT) - , fDisplay(EGL_NO_DISPLAY) - , fSurface(EGL_NO_SURFACE) { -} - -SkNativeGLContext::~SkNativeGLContext() { - this->destroyGLContext(); -} - -void SkNativeGLContext::destroyGLContext() { - if (fDisplay) { - eglMakeCurrent(fDisplay, 0, 0, 0); - - if (fContext) { - eglDestroyContext(fDisplay, fContext); - fContext = EGL_NO_CONTEXT; - } - - if (fSurface) { - eglDestroySurface(fDisplay, fSurface); - fSurface = EGL_NO_SURFACE; - } - - //TODO should we close the display? - fDisplay = EGL_NO_DISPLAY; - } -} - -const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { - static const EGLint kEGLContextAttribsForOpenGL[] = { - EGL_NONE - }; - - static const EGLint kEGLContextAttribsForOpenGLES[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - static const struct { - const EGLint* fContextAttribs; - EGLenum fAPI; - EGLint fRenderableTypeBit; - GrGLStandard fStandard; - } kAPIs[] = { - { // OpenGL - kEGLContextAttribsForOpenGL, - EGL_OPENGL_API, - EGL_OPENGL_BIT, - kGL_GrGLStandard - }, - { // OpenGL ES. This seems to work for both ES2 and 3 (when available). - kEGLContextAttribsForOpenGLES, - EGL_OPENGL_ES_API, - EGL_OPENGL_ES2_BIT, - kGLES_GrGLStandard - }, - }; - - size_t apiLimit = SK_ARRAY_COUNT(kAPIs); - size_t api = 0; - if (forcedGpuAPI == kGL_GrGLStandard) { - apiLimit = 1; - } else if (forcedGpuAPI == kGLES_GrGLStandard) { - api = 1; - } - SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kAPIs[api].fStandard == forcedGpuAPI); - - const GrGLInterface* interface = NULL; - - for (; NULL == interface && api < apiLimit; ++api) { - fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - - EGLint majorVersion; - EGLint minorVersion; - eglInitialize(fDisplay, &majorVersion, &minorVersion); - -#if 0 - SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR)); - SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS)); - SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION)); - SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS)); -#endif - - if (!eglBindAPI(kAPIs[api].fAPI)) { - continue; - } - - EGLint numConfigs; - const EGLint configAttribs[] = { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_NONE - }; - - EGLConfig surfaceConfig; - if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) { - SkDebugf("eglChooseConfig failed. EGL Error: 0x%08x\n", eglGetError()); - continue; - } - - fContext = eglCreateContext(fDisplay, surfaceConfig, NULL, kAPIs[api].fContextAttribs); - if (EGL_NO_CONTEXT == fContext) { - SkDebugf("eglCreateContext failed. EGL Error: 0x%08x\n", eglGetError()); - continue; - } - - static const EGLint kSurfaceAttribs[] = { - EGL_WIDTH, 1, - EGL_HEIGHT, 1, - EGL_NONE - }; - - fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, kSurfaceAttribs); - if (EGL_NO_SURFACE == fSurface) { - SkDebugf("eglCreatePbufferSurface failed. EGL Error: 0x%08x\n", eglGetError()); - this->destroyGLContext(); - continue; - } - - if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { - SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError()); - this->destroyGLContext(); - continue; - } - - interface = GrGLCreateNativeInterface(); - if (NULL == interface) { - SkDebugf("Failed to create gl interface.\n"); - this->destroyGLContext(); - continue; - } - - if (!interface->validate()) { - interface->unref(); - interface = NULL; - this->destroyGLContext(); - } - } - - return interface; -} - -void SkNativeGLContext::makeCurrent() const { - if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { - SkDebugf("Could not set the context.\n"); - } -} - -void SkNativeGLContext::swapBuffers() const { - if (!eglSwapBuffers(fDisplay, fSurface)) { - SkDebugf("Could not complete eglSwapBuffers.\n"); - } -} diff --git a/src/gpu/gl/egl/GrGLCreateNativeInterface_egl.cpp b/src/gpu/gl/egl/GrGLCreateNativeInterface_egl.cpp new file mode 100644 index 0000000000..ddc9e693a4 --- /dev/null +++ b/src/gpu/gl/egl/GrGLCreateNativeInterface_egl.cpp @@ -0,0 +1,22 @@ + +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "gl/GrGLInterface.h" +#include "gl/GrGLAssembleInterface.h" +#include "gl/GrGLUtil.h" + +#include +#include + +static GrGLFuncPtr egl_get_gl_proc(void* ctx, const char name[]) { + SkASSERT(NULL == ctx); + return eglGetProcAddress(name); +} + +const GrGLInterface* GrGLCreateNativeInterface() { + return GrGLAssembleInterface(NULL, egl_get_gl_proc); +} diff --git a/src/gpu/gl/egl/SkNativeGLContext_egl.cpp b/src/gpu/gl/egl/SkNativeGLContext_egl.cpp new file mode 100644 index 0000000000..d4d7219b5b --- /dev/null +++ b/src/gpu/gl/egl/SkNativeGLContext_egl.cpp @@ -0,0 +1,182 @@ + +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "gl/SkNativeGLContext.h" + +SkNativeGLContext::AutoContextRestore::AutoContextRestore() { + fOldEGLContext = eglGetCurrentContext(); + fOldDisplay = eglGetCurrentDisplay(); + fOldSurface = eglGetCurrentSurface(EGL_DRAW); + +} + +SkNativeGLContext::AutoContextRestore::~AutoContextRestore() { + if (fOldDisplay) { + eglMakeCurrent(fOldDisplay, fOldSurface, fOldSurface, fOldEGLContext); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +SkNativeGLContext::SkNativeGLContext() + : fContext(EGL_NO_CONTEXT) + , fDisplay(EGL_NO_DISPLAY) + , fSurface(EGL_NO_SURFACE) { +} + +SkNativeGLContext::~SkNativeGLContext() { + this->destroyGLContext(); +} + +void SkNativeGLContext::destroyGLContext() { + if (fDisplay) { + eglMakeCurrent(fDisplay, 0, 0, 0); + + if (fContext) { + eglDestroyContext(fDisplay, fContext); + fContext = EGL_NO_CONTEXT; + } + + if (fSurface) { + eglDestroySurface(fDisplay, fSurface); + fSurface = EGL_NO_SURFACE; + } + + //TODO should we close the display? + fDisplay = EGL_NO_DISPLAY; + } +} + +const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { + static const EGLint kEGLContextAttribsForOpenGL[] = { + EGL_NONE + }; + + static const EGLint kEGLContextAttribsForOpenGLES[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + static const struct { + const EGLint* fContextAttribs; + EGLenum fAPI; + EGLint fRenderableTypeBit; + GrGLStandard fStandard; + } kAPIs[] = { + { // OpenGL + kEGLContextAttribsForOpenGL, + EGL_OPENGL_API, + EGL_OPENGL_BIT, + kGL_GrGLStandard + }, + { // OpenGL ES. This seems to work for both ES2 and 3 (when available). + kEGLContextAttribsForOpenGLES, + EGL_OPENGL_ES_API, + EGL_OPENGL_ES2_BIT, + kGLES_GrGLStandard + }, + }; + + size_t apiLimit = SK_ARRAY_COUNT(kAPIs); + size_t api = 0; + if (forcedGpuAPI == kGL_GrGLStandard) { + apiLimit = 1; + } else if (forcedGpuAPI == kGLES_GrGLStandard) { + api = 1; + } + SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kAPIs[api].fStandard == forcedGpuAPI); + + const GrGLInterface* interface = NULL; + + for (; NULL == interface && api < apiLimit; ++api) { + fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + EGLint majorVersion; + EGLint minorVersion; + eglInitialize(fDisplay, &majorVersion, &minorVersion); + +#if 0 + SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR)); + SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS)); + SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION)); + SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS)); +#endif + + if (!eglBindAPI(kAPIs[api].fAPI)) { + continue; + } + + EGLint numConfigs; + const EGLint configAttribs[] = { + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_NONE + }; + + EGLConfig surfaceConfig; + if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) { + SkDebugf("eglChooseConfig failed. EGL Error: 0x%08x\n", eglGetError()); + continue; + } + + fContext = eglCreateContext(fDisplay, surfaceConfig, NULL, kAPIs[api].fContextAttribs); + if (EGL_NO_CONTEXT == fContext) { + SkDebugf("eglCreateContext failed. EGL Error: 0x%08x\n", eglGetError()); + continue; + } + + static const EGLint kSurfaceAttribs[] = { + EGL_WIDTH, 1, + EGL_HEIGHT, 1, + EGL_NONE + }; + + fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, kSurfaceAttribs); + if (EGL_NO_SURFACE == fSurface) { + SkDebugf("eglCreatePbufferSurface failed. EGL Error: 0x%08x\n", eglGetError()); + this->destroyGLContext(); + continue; + } + + if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { + SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError()); + this->destroyGLContext(); + continue; + } + + interface = GrGLCreateNativeInterface(); + if (NULL == interface) { + SkDebugf("Failed to create gl interface.\n"); + this->destroyGLContext(); + continue; + } + + if (!interface->validate()) { + interface->unref(); + interface = NULL; + this->destroyGLContext(); + } + } + + return interface; +} + +void SkNativeGLContext::makeCurrent() const { + if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { + SkDebugf("Could not set the context.\n"); + } +} + +void SkNativeGLContext::swapBuffers() const { + if (!eglSwapBuffers(fDisplay, fSurface)) { + SkDebugf("Could not complete eglSwapBuffers.\n"); + } +} diff --git a/src/gpu/gl/glx/GrGLCreateNativeInterface_glx.cpp b/src/gpu/gl/glx/GrGLCreateNativeInterface_glx.cpp new file mode 100644 index 0000000000..19eec7e8ac --- /dev/null +++ b/src/gpu/gl/glx/GrGLCreateNativeInterface_glx.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#include "gl/GrGLInterface.h" +#include "gl/GrGLAssembleInterface.h" +#include "gl/GrGLUtil.h" + +#include + +static GrGLFuncPtr glx_get(void* ctx, const char name[]) { + SkASSERT(NULL == ctx); + SkASSERT(glXGetCurrentContext()); + return glXGetProcAddress(reinterpret_cast(name)); +} + +const GrGLInterface* GrGLCreateNativeInterface() { + if (NULL == glXGetCurrentContext()) { + return NULL; + } + + return GrGLAssembleInterface(NULL, glx_get); +} diff --git a/src/gpu/gl/glx/SkNativeGLContext_glx.cpp b/src/gpu/gl/glx/SkNativeGLContext_glx.cpp new file mode 100644 index 0000000000..bd130b545c --- /dev/null +++ b/src/gpu/gl/glx/SkNativeGLContext_glx.cpp @@ -0,0 +1,288 @@ + +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "gl/SkNativeGLContext.h" + +#include + +/* Note: Skia requires glx 1.3 or newer */ + +SkNativeGLContext::AutoContextRestore::AutoContextRestore() { + fOldGLXContext = glXGetCurrentContext(); + fOldDisplay = glXGetCurrentDisplay(); + fOldDrawable = glXGetCurrentDrawable(); +} + +SkNativeGLContext::AutoContextRestore::~AutoContextRestore() { + if (fOldDisplay) { + glXMakeCurrent(fOldDisplay, fOldDrawable, fOldGLXContext); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +static bool ctxErrorOccurred = false; +static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) { + ctxErrorOccurred = true; + return 0; +} + +SkNativeGLContext::SkNativeGLContext() + : fContext(NULL) + , fDisplay(NULL) + , fPixmap(0) + , fGlxPixmap(0) { +} + +SkNativeGLContext::~SkNativeGLContext() { + this->destroyGLContext(); +} + +void SkNativeGLContext::destroyGLContext() { + if (fDisplay) { + glXMakeCurrent(fDisplay, 0, 0); + + if (fContext) { + glXDestroyContext(fDisplay, fContext); + fContext = NULL; + } + + if (fGlxPixmap) { + glXDestroyGLXPixmap(fDisplay, fGlxPixmap); + fGlxPixmap = 0; + } + + if (fPixmap) { + XFreePixmap(fDisplay, fPixmap); + fPixmap = 0; + } + + XCloseDisplay(fDisplay); + fDisplay = NULL; + } +} + +const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { + fDisplay = XOpenDisplay(0); + + if (!fDisplay) { + SkDebugf("Failed to open X display.\n"); + this->destroyGLContext(); + return NULL; + } + + // Get a matching FB config + static int visual_attribs[] = { + GLX_X_RENDERABLE , True, + GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT, + None + }; + + int glx_major, glx_minor; + + // FBConfigs were added in GLX version 1.3. + if (!glXQueryVersion(fDisplay, &glx_major, &glx_minor) || + ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) { + SkDebugf("GLX version 1.3 or higher required.\n"); + this->destroyGLContext(); + return NULL; + } + + //SkDebugf("Getting matching framebuffer configs.\n"); + int fbcount; + GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay), + visual_attribs, &fbcount); + if (!fbc) { + SkDebugf("Failed to retrieve a framebuffer config.\n"); + this->destroyGLContext(); + return NULL; + } + //SkDebugf("Found %d matching FB configs.\n", fbcount); + + // Pick the FB config/visual with the most samples per pixel + //SkDebugf("Getting XVisualInfos.\n"); + int best_fbc = -1, best_num_samp = -1; + + int i; + for (i = 0; i < fbcount; ++i) { + XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, fbc[i]); + if (vi) { + int samp_buf, samples; + glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); + glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLES, &samples); + + //SkDebugf(" Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d," + // " SAMPLES = %d\n", + // i, (unsigned int)vi->visualid, samp_buf, samples); + + if (best_fbc < 0 || (samp_buf && samples > best_num_samp)) + best_fbc = i, best_num_samp = samples; + } + XFree(vi); + } + + GLXFBConfig bestFbc = fbc[best_fbc]; + + // Be sure to free the FBConfig list allocated by glXChooseFBConfig() + XFree(fbc); + + // Get a visual + XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc); + //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid); + + fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10, vi->depth); + + if (!fPixmap) { + SkDebugf("Failed to create pixmap.\n"); + this->destroyGLContext(); + return NULL; + } + + fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap); + + // Done with the visual info data + XFree(vi); + + // Create the context + + // Install an X error handler so the application won't exit if GL 3.0 + // context allocation fails. + // + // Note this error handler is global. + // All display connections in all threads of a process use the same + // error handler, so be sure to guard against other threads issuing + // X commands while this code is running. + ctxErrorOccurred = false; + int (*oldHandler)(Display*, XErrorEvent*) = + XSetErrorHandler(&ctxErrorHandler); + + // Get the default screen's GLX extension list + const char *glxExts = glXQueryExtensionsString( + fDisplay, DefaultScreen(fDisplay) + ); + + + // Check for the GLX_ARB_create_context extension string and the function. + // If either is not present, use GLX 1.3 context creation method. + if (!gluCheckExtension(reinterpret_cast("GLX_ARB_create_context"), + reinterpret_cast(glxExts))) { + if (kGLES_GrGLStandard != forcedGpuAPI) { + fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True); + } + } else { + //SkDebugf("Creating context.\n"); + PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = + (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((GrGLubyte*)"glXCreateContextAttribsARB"); + + if (kGLES_GrGLStandard == forcedGpuAPI) { + if (gluCheckExtension( + reinterpret_cast("GLX_EXT_create_context_es2_profile"), + reinterpret_cast(glxExts))) { + static const int context_attribs_gles[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, + None + }; + fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, + context_attribs_gles); + } + } else { + // Well, unfortunately GLX will not just give us the highest context so instead we have + // to do this nastiness + for (i = NUM_GL_VERSIONS - 2; i > 0 ; i--) { + /* don't bother below GL 3.0 */ + if (gl_versions[i].major == 3 && gl_versions[i].minor == 0) { + break; + } + // On Nvidia GPUs, to use Nv Path rendering we need a compatibility profile for the + // time being. + // TODO when Nvidia implements NVPR on Core profiles, we should start requesting + // core here + static const int context_attribs_gl[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, gl_versions[i].major, + GLX_CONTEXT_MINOR_VERSION_ARB, gl_versions[i].minor, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + None + }; + fContext = + glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, context_attribs_gl); + + // Sync to ensure any errors generated are processed. + XSync(fDisplay, False); + + if (!ctxErrorOccurred && fContext) { + break; + } + // try again + ctxErrorOccurred = false; + } + + // Couldn't create GL 3.0 context. + // Fall back to old-style 2.x context. + // When a context version below 3.0 is requested, + // implementations will return the newest context version + // compatible with OpenGL versions less than version 3.0. + if (ctxErrorOccurred || !fContext) { + static const int context_attribs_gl_fallback[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 1, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + None + }; + + ctxErrorOccurred = false; + + fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, + context_attribs_gl_fallback); + } + } + } + + // Sync to ensure any errors generated are processed. + XSync(fDisplay, False); + + // Restore the original error handler + XSetErrorHandler(oldHandler); + + if (ctxErrorOccurred || !fContext) { + SkDebugf("Failed to create an OpenGL context.\n"); + this->destroyGLContext(); + return NULL; + } + + // Verify that context is a direct context + if (!glXIsDirect(fDisplay, fContext)) { + //SkDebugf("Indirect GLX rendering context obtained.\n"); + } else { + //SkDebugf("Direct GLX rendering context obtained.\n"); + } + + //SkDebugf("Making context current.\n"); + if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { + SkDebugf("Could not set the context.\n"); + this->destroyGLContext(); + return NULL; + } + + const GrGLInterface* interface = GrGLCreateNativeInterface(); + if (!interface) { + SkDebugf("Failed to create gl interface"); + this->destroyGLContext(); + return NULL; + } + return interface; +} + +void SkNativeGLContext::makeCurrent() const { + if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { + SkDebugf("Could not set the context.\n"); + } +} + +void SkNativeGLContext::swapBuffers() const { + glXSwapBuffers(fDisplay, fGlxPixmap); +} diff --git a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp b/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp deleted file mode 100644 index 19eec7e8ac..0000000000 --- a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - -#include "gl/GrGLInterface.h" -#include "gl/GrGLAssembleInterface.h" -#include "gl/GrGLUtil.h" - -#include - -static GrGLFuncPtr glx_get(void* ctx, const char name[]) { - SkASSERT(NULL == ctx); - SkASSERT(glXGetCurrentContext()); - return glXGetProcAddress(reinterpret_cast(name)); -} - -const GrGLInterface* GrGLCreateNativeInterface() { - if (NULL == glXGetCurrentContext()) { - return NULL; - } - - return GrGLAssembleInterface(NULL, glx_get); -} diff --git a/src/gpu/gl/unix/SkNativeGLContext_unix.cpp b/src/gpu/gl/unix/SkNativeGLContext_unix.cpp deleted file mode 100644 index bd130b545c..0000000000 --- a/src/gpu/gl/unix/SkNativeGLContext_unix.cpp +++ /dev/null @@ -1,288 +0,0 @@ - -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "gl/SkNativeGLContext.h" - -#include - -/* Note: Skia requires glx 1.3 or newer */ - -SkNativeGLContext::AutoContextRestore::AutoContextRestore() { - fOldGLXContext = glXGetCurrentContext(); - fOldDisplay = glXGetCurrentDisplay(); - fOldDrawable = glXGetCurrentDrawable(); -} - -SkNativeGLContext::AutoContextRestore::~AutoContextRestore() { - if (fOldDisplay) { - glXMakeCurrent(fOldDisplay, fOldDrawable, fOldGLXContext); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -static bool ctxErrorOccurred = false; -static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) { - ctxErrorOccurred = true; - return 0; -} - -SkNativeGLContext::SkNativeGLContext() - : fContext(NULL) - , fDisplay(NULL) - , fPixmap(0) - , fGlxPixmap(0) { -} - -SkNativeGLContext::~SkNativeGLContext() { - this->destroyGLContext(); -} - -void SkNativeGLContext::destroyGLContext() { - if (fDisplay) { - glXMakeCurrent(fDisplay, 0, 0); - - if (fContext) { - glXDestroyContext(fDisplay, fContext); - fContext = NULL; - } - - if (fGlxPixmap) { - glXDestroyGLXPixmap(fDisplay, fGlxPixmap); - fGlxPixmap = 0; - } - - if (fPixmap) { - XFreePixmap(fDisplay, fPixmap); - fPixmap = 0; - } - - XCloseDisplay(fDisplay); - fDisplay = NULL; - } -} - -const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { - fDisplay = XOpenDisplay(0); - - if (!fDisplay) { - SkDebugf("Failed to open X display.\n"); - this->destroyGLContext(); - return NULL; - } - - // Get a matching FB config - static int visual_attribs[] = { - GLX_X_RENDERABLE , True, - GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT, - None - }; - - int glx_major, glx_minor; - - // FBConfigs were added in GLX version 1.3. - if (!glXQueryVersion(fDisplay, &glx_major, &glx_minor) || - ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) { - SkDebugf("GLX version 1.3 or higher required.\n"); - this->destroyGLContext(); - return NULL; - } - - //SkDebugf("Getting matching framebuffer configs.\n"); - int fbcount; - GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay), - visual_attribs, &fbcount); - if (!fbc) { - SkDebugf("Failed to retrieve a framebuffer config.\n"); - this->destroyGLContext(); - return NULL; - } - //SkDebugf("Found %d matching FB configs.\n", fbcount); - - // Pick the FB config/visual with the most samples per pixel - //SkDebugf("Getting XVisualInfos.\n"); - int best_fbc = -1, best_num_samp = -1; - - int i; - for (i = 0; i < fbcount; ++i) { - XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, fbc[i]); - if (vi) { - int samp_buf, samples; - glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); - glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLES, &samples); - - //SkDebugf(" Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d," - // " SAMPLES = %d\n", - // i, (unsigned int)vi->visualid, samp_buf, samples); - - if (best_fbc < 0 || (samp_buf && samples > best_num_samp)) - best_fbc = i, best_num_samp = samples; - } - XFree(vi); - } - - GLXFBConfig bestFbc = fbc[best_fbc]; - - // Be sure to free the FBConfig list allocated by glXChooseFBConfig() - XFree(fbc); - - // Get a visual - XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc); - //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid); - - fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10, vi->depth); - - if (!fPixmap) { - SkDebugf("Failed to create pixmap.\n"); - this->destroyGLContext(); - return NULL; - } - - fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap); - - // Done with the visual info data - XFree(vi); - - // Create the context - - // Install an X error handler so the application won't exit if GL 3.0 - // context allocation fails. - // - // Note this error handler is global. - // All display connections in all threads of a process use the same - // error handler, so be sure to guard against other threads issuing - // X commands while this code is running. - ctxErrorOccurred = false; - int (*oldHandler)(Display*, XErrorEvent*) = - XSetErrorHandler(&ctxErrorHandler); - - // Get the default screen's GLX extension list - const char *glxExts = glXQueryExtensionsString( - fDisplay, DefaultScreen(fDisplay) - ); - - - // Check for the GLX_ARB_create_context extension string and the function. - // If either is not present, use GLX 1.3 context creation method. - if (!gluCheckExtension(reinterpret_cast("GLX_ARB_create_context"), - reinterpret_cast(glxExts))) { - if (kGLES_GrGLStandard != forcedGpuAPI) { - fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True); - } - } else { - //SkDebugf("Creating context.\n"); - PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = - (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((GrGLubyte*)"glXCreateContextAttribsARB"); - - if (kGLES_GrGLStandard == forcedGpuAPI) { - if (gluCheckExtension( - reinterpret_cast("GLX_EXT_create_context_es2_profile"), - reinterpret_cast(glxExts))) { - static const int context_attribs_gles[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 0, - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, - None - }; - fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, - context_attribs_gles); - } - } else { - // Well, unfortunately GLX will not just give us the highest context so instead we have - // to do this nastiness - for (i = NUM_GL_VERSIONS - 2; i > 0 ; i--) { - /* don't bother below GL 3.0 */ - if (gl_versions[i].major == 3 && gl_versions[i].minor == 0) { - break; - } - // On Nvidia GPUs, to use Nv Path rendering we need a compatibility profile for the - // time being. - // TODO when Nvidia implements NVPR on Core profiles, we should start requesting - // core here - static const int context_attribs_gl[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, gl_versions[i].major, - GLX_CONTEXT_MINOR_VERSION_ARB, gl_versions[i].minor, - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - None - }; - fContext = - glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, context_attribs_gl); - - // Sync to ensure any errors generated are processed. - XSync(fDisplay, False); - - if (!ctxErrorOccurred && fContext) { - break; - } - // try again - ctxErrorOccurred = false; - } - - // Couldn't create GL 3.0 context. - // Fall back to old-style 2.x context. - // When a context version below 3.0 is requested, - // implementations will return the newest context version - // compatible with OpenGL versions less than version 3.0. - if (ctxErrorOccurred || !fContext) { - static const int context_attribs_gl_fallback[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 1, - GLX_CONTEXT_MINOR_VERSION_ARB, 0, - None - }; - - ctxErrorOccurred = false; - - fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, - context_attribs_gl_fallback); - } - } - } - - // Sync to ensure any errors generated are processed. - XSync(fDisplay, False); - - // Restore the original error handler - XSetErrorHandler(oldHandler); - - if (ctxErrorOccurred || !fContext) { - SkDebugf("Failed to create an OpenGL context.\n"); - this->destroyGLContext(); - return NULL; - } - - // Verify that context is a direct context - if (!glXIsDirect(fDisplay, fContext)) { - //SkDebugf("Indirect GLX rendering context obtained.\n"); - } else { - //SkDebugf("Direct GLX rendering context obtained.\n"); - } - - //SkDebugf("Making context current.\n"); - if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { - SkDebugf("Could not set the context.\n"); - this->destroyGLContext(); - return NULL; - } - - const GrGLInterface* interface = GrGLCreateNativeInterface(); - if (!interface) { - SkDebugf("Failed to create gl interface"); - this->destroyGLContext(); - return NULL; - } - return interface; -} - -void SkNativeGLContext::makeCurrent() const { - if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { - SkDebugf("Could not set the context.\n"); - } -} - -void SkNativeGLContext::swapBuffers() const { - glXSwapBuffers(fDisplay, fGlxPixmap); -} -- cgit v1.2.3