michael@0: michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: #include "gl/SkNativeGLContext.h" michael@0: michael@0: SkNativeGLContext::AutoContextRestore::AutoContextRestore() { michael@0: fOldEGLContext = eglGetCurrentContext(); michael@0: fOldDisplay = eglGetCurrentDisplay(); michael@0: fOldSurface = eglGetCurrentSurface(EGL_DRAW); michael@0: michael@0: } michael@0: michael@0: SkNativeGLContext::AutoContextRestore::~AutoContextRestore() { michael@0: if (NULL != fOldDisplay) { michael@0: eglMakeCurrent(fOldDisplay, fOldSurface, fOldSurface, fOldEGLContext); michael@0: } michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkNativeGLContext::SkNativeGLContext() michael@0: : fContext(EGL_NO_CONTEXT) michael@0: , fDisplay(EGL_NO_DISPLAY) michael@0: , fSurface(EGL_NO_SURFACE) { michael@0: } michael@0: michael@0: SkNativeGLContext::~SkNativeGLContext() { michael@0: this->destroyGLContext(); michael@0: } michael@0: michael@0: void SkNativeGLContext::destroyGLContext() { michael@0: if (fDisplay) { michael@0: eglMakeCurrent(fDisplay, 0, 0, 0); michael@0: michael@0: if (fContext) { michael@0: eglDestroyContext(fDisplay, fContext); michael@0: fContext = EGL_NO_CONTEXT; michael@0: } michael@0: michael@0: if (fSurface) { michael@0: eglDestroySurface(fDisplay, fSurface); michael@0: fSurface = EGL_NO_SURFACE; michael@0: } michael@0: michael@0: //TODO should we close the display? michael@0: fDisplay = EGL_NO_DISPLAY; michael@0: } michael@0: } michael@0: michael@0: const GrGLInterface* SkNativeGLContext::createGLContext() { michael@0: static const EGLint kEGLContextAttribsForOpenGL[] = { michael@0: EGL_NONE michael@0: }; michael@0: michael@0: static const EGLint kEGLContextAttribsForOpenGLES[] = { michael@0: EGL_CONTEXT_CLIENT_VERSION, 2, michael@0: EGL_NONE michael@0: }; michael@0: michael@0: static const struct { michael@0: const EGLint* fContextAttribs; michael@0: EGLenum fAPI; michael@0: EGLint fRenderableTypeBit; michael@0: GrGLStandard fStandard; michael@0: } kAPIs[] = { michael@0: { // OpenGL michael@0: kEGLContextAttribsForOpenGL, michael@0: EGL_OPENGL_API, michael@0: EGL_OPENGL_BIT, michael@0: kGL_GrGLStandard michael@0: }, michael@0: { // OpenGL ES. This seems to work for both ES2 and 3 (when available). michael@0: kEGLContextAttribsForOpenGLES, michael@0: EGL_OPENGL_ES_API, michael@0: EGL_OPENGL_ES2_BIT, michael@0: kGLES_GrGLStandard michael@0: }, michael@0: }; michael@0: michael@0: const GrGLInterface* interface = NULL; michael@0: michael@0: for (size_t api = 0; NULL == interface && api < SK_ARRAY_COUNT(kAPIs); ++api) { michael@0: fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); michael@0: michael@0: EGLint majorVersion; michael@0: EGLint minorVersion; michael@0: eglInitialize(fDisplay, &majorVersion, &minorVersion); michael@0: michael@0: #if 0 michael@0: SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR)); michael@0: SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS)); michael@0: SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION)); michael@0: SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS)); michael@0: #endif michael@0: michael@0: if (!eglBindAPI(kAPIs[api].fAPI)) { michael@0: continue; michael@0: } michael@0: michael@0: EGLint numConfigs; michael@0: const EGLint configAttribs[] = { michael@0: EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, michael@0: EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit, michael@0: EGL_RED_SIZE, 8, michael@0: EGL_GREEN_SIZE, 8, michael@0: EGL_BLUE_SIZE, 8, michael@0: EGL_ALPHA_SIZE, 8, michael@0: EGL_NONE michael@0: }; michael@0: michael@0: EGLConfig surfaceConfig; michael@0: if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) { michael@0: SkDebugf("eglChooseConfig failed. EGL Error: 0x%08x\n", eglGetError()); michael@0: continue; michael@0: } michael@0: michael@0: fContext = eglCreateContext(fDisplay, surfaceConfig, NULL, kAPIs[api].fContextAttribs); michael@0: if (EGL_NO_CONTEXT == fContext) { michael@0: SkDebugf("eglCreateContext failed. EGL Error: 0x%08x\n", eglGetError()); michael@0: continue; michael@0: } michael@0: michael@0: static const EGLint kSurfaceAttribs[] = { michael@0: EGL_WIDTH, 1, michael@0: EGL_HEIGHT, 1, michael@0: EGL_NONE michael@0: }; michael@0: michael@0: fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, kSurfaceAttribs); michael@0: if (EGL_NO_SURFACE == fSurface) { michael@0: SkDebugf("eglCreatePbufferSurface failed. EGL Error: 0x%08x\n", eglGetError()); michael@0: this->destroyGLContext(); michael@0: continue; michael@0: } michael@0: michael@0: if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { michael@0: SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError()); michael@0: this->destroyGLContext(); michael@0: continue; michael@0: } michael@0: michael@0: interface = GrGLCreateNativeInterface(); michael@0: if (NULL == interface) { michael@0: SkDebugf("Failed to create gl interface.\n"); michael@0: this->destroyGLContext(); michael@0: continue; michael@0: } michael@0: michael@0: if (!interface->validate()) { michael@0: interface->unref(); michael@0: interface = NULL; michael@0: this->destroyGLContext(); michael@0: } michael@0: } michael@0: michael@0: return interface; michael@0: } michael@0: michael@0: void SkNativeGLContext::makeCurrent() const { michael@0: if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { michael@0: SkDebugf("Could not set the context.\n"); michael@0: } michael@0: } michael@0: michael@0: void SkNativeGLContext::swapBuffers() const { michael@0: if (!eglSwapBuffers(fDisplay, fSurface)) { michael@0: SkDebugf("Could not complete eglSwapBuffers.\n"); michael@0: } michael@0: }