| |
| /* |
| * 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 (NULL != 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 (size_t i = 0; NULL == interface && i < 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"); |
| } |
| } |