1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "gl/SkNativeGLContext.h" 9 10 SkNativeGLContext::AutoContextRestore::AutoContextRestore() { 11 fOldEGLContext = eglGetCurrentContext(); 12 fOldDisplay = eglGetCurrentDisplay(); 13 fOldSurface = eglGetCurrentSurface(EGL_DRAW); 14 15 } 16 17 SkNativeGLContext::AutoContextRestore::~AutoContextRestore() { 18 if (fOldDisplay) { 19 eglMakeCurrent(fOldDisplay, fOldSurface, fOldSurface, fOldEGLContext); 20 } 21 } 22 23 /////////////////////////////////////////////////////////////////////////////// 24 25 SkNativeGLContext::SkNativeGLContext() 26 : fContext(EGL_NO_CONTEXT) 27 , fDisplay(EGL_NO_DISPLAY) 28 , fSurface(EGL_NO_SURFACE) { 29 } 30 31 SkNativeGLContext::~SkNativeGLContext() { 32 this->destroyGLContext(); 33 } 34 35 void SkNativeGLContext::destroyGLContext() { 36 if (fDisplay) { 37 eglMakeCurrent(fDisplay, 0, 0, 0); 38 39 if (fContext) { 40 eglDestroyContext(fDisplay, fContext); 41 fContext = EGL_NO_CONTEXT; 42 } 43 44 if (fSurface) { 45 eglDestroySurface(fDisplay, fSurface); 46 fSurface = EGL_NO_SURFACE; 47 } 48 49 //TODO should we close the display? 50 fDisplay = EGL_NO_DISPLAY; 51 } 52 } 53 54 const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { 55 static const EGLint kEGLContextAttribsForOpenGL[] = { 56 EGL_NONE 57 }; 58 59 static const EGLint kEGLContextAttribsForOpenGLES[] = { 60 EGL_CONTEXT_CLIENT_VERSION, 2, 61 EGL_NONE 62 }; 63 64 static const struct { 65 const EGLint* fContextAttribs; 66 EGLenum fAPI; 67 EGLint fRenderableTypeBit; 68 GrGLStandard fStandard; 69 } kAPIs[] = { 70 { // OpenGL 71 kEGLContextAttribsForOpenGL, 72 EGL_OPENGL_API, 73 EGL_OPENGL_BIT, 74 kGL_GrGLStandard 75 }, 76 { // OpenGL ES. This seems to work for both ES2 and 3 (when available). 77 kEGLContextAttribsForOpenGLES, 78 EGL_OPENGL_ES_API, 79 EGL_OPENGL_ES2_BIT, 80 kGLES_GrGLStandard 81 }, 82 }; 83 84 size_t apiLimit = SK_ARRAY_COUNT(kAPIs); 85 size_t api = 0; 86 if (forcedGpuAPI == kGL_GrGLStandard) { 87 apiLimit = 1; 88 } else if (forcedGpuAPI == kGLES_GrGLStandard) { 89 api = 1; 90 } 91 SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kAPIs[api].fStandard == forcedGpuAPI); 92 93 const GrGLInterface* interface = NULL; 94 95 for (; NULL == interface && api < apiLimit; ++api) { 96 fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 97 98 EGLint majorVersion; 99 EGLint minorVersion; 100 eglInitialize(fDisplay, &majorVersion, &minorVersion); 101 102 #if 0 103 SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR)); 104 SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS)); 105 SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION)); 106 SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS)); 107 #endif 108 109 if (!eglBindAPI(kAPIs[api].fAPI)) { 110 continue; 111 } 112 113 EGLint numConfigs; 114 const EGLint configAttribs[] = { 115 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 116 EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit, 117 EGL_RED_SIZE, 8, 118 EGL_GREEN_SIZE, 8, 119 EGL_BLUE_SIZE, 8, 120 EGL_ALPHA_SIZE, 8, 121 EGL_NONE 122 }; 123 124 EGLConfig surfaceConfig; 125 if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) { 126 SkDebugf("eglChooseConfig failed. EGL Error: 0x%08x\n", eglGetError()); 127 continue; 128 } 129 130 fContext = eglCreateContext(fDisplay, surfaceConfig, NULL, kAPIs[api].fContextAttribs); 131 if (EGL_NO_CONTEXT == fContext) { 132 SkDebugf("eglCreateContext failed. EGL Error: 0x%08x\n", eglGetError()); 133 continue; 134 } 135 136 static const EGLint kSurfaceAttribs[] = { 137 EGL_WIDTH, 1, 138 EGL_HEIGHT, 1, 139 EGL_NONE 140 }; 141 142 fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, kSurfaceAttribs); 143 if (EGL_NO_SURFACE == fSurface) { 144 SkDebugf("eglCreatePbufferSurface failed. EGL Error: 0x%08x\n", eglGetError()); 145 this->destroyGLContext(); 146 continue; 147 } 148 149 if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { 150 SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError()); 151 this->destroyGLContext(); 152 continue; 153 } 154 155 interface = GrGLCreateNativeInterface(); 156 if (NULL == interface) { 157 SkDebugf("Failed to create gl interface.\n"); 158 this->destroyGLContext(); 159 continue; 160 } 161 162 if (!interface->validate()) { 163 interface->unref(); 164 interface = NULL; 165 this->destroyGLContext(); 166 } 167 } 168 169 return interface; 170 } 171 172 void SkNativeGLContext::makeCurrent() const { 173 if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { 174 SkDebugf("Could not set the context.\n"); 175 } 176 } 177 178 void SkNativeGLContext::swapBuffers() const { 179 if (!eglSwapBuffers(fDisplay, fSurface)) { 180 SkDebugf("Could not complete eglSwapBuffers.\n"); 181 } 182 } 183