| /* | |
| * 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() { | |
| 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 | |
| }, | |
| }; | |
| const GrGLInterface* interface = NULL; | |
| for (size_t api = 0; NULL == interface && api < SK_ARRAY_COUNT(kAPIs); ++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"); | |
| } | |
| } |