/* * 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"); } }