Index: src/gpu/gl/egl/SkNativeGLContext_egl.cpp |
diff --git a/src/gpu/gl/egl/SkNativeGLContext_egl.cpp b/src/gpu/gl/egl/SkNativeGLContext_egl.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d4d7219b5bbbf7a3799e367d7102288cfa382abc |
--- /dev/null |
+++ b/src/gpu/gl/egl/SkNativeGLContext_egl.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"); |
+ } |
+} |