diff options
Diffstat (limited to 'src/gpu/gl/android/SkNativeGLContext_android.cpp')
-rw-r--r-- | src/gpu/gl/android/SkNativeGLContext_android.cpp | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/gpu/gl/android/SkNativeGLContext_android.cpp b/src/gpu/gl/android/SkNativeGLContext_android.cpp new file mode 100644 index 0000000000..d4d7219b5b --- /dev/null +++ b/src/gpu/gl/android/SkNativeGLContext_android.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"); + } +} |