158629291bc145edca8fb303e465c8537bed65314djsollen@google.com 258629291bc145edca8fb303e465c8537bed65314djsollen@google.com/* 358629291bc145edca8fb303e465c8537bed65314djsollen@google.com * Copyright 2011 Google Inc. 458629291bc145edca8fb303e465c8537bed65314djsollen@google.com * 558629291bc145edca8fb303e465c8537bed65314djsollen@google.com * Use of this source code is governed by a BSD-style license that can be 658629291bc145edca8fb303e465c8537bed65314djsollen@google.com * found in the LICENSE file. 758629291bc145edca8fb303e465c8537bed65314djsollen@google.com */ 89e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen#include "gl/SkGLContext.h" 958629291bc145edca8fb303e465c8537bed65314djsollen@google.com 109e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen#include <GLES2/gl2.h> 119e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen#include <EGL/egl.h> 1258629291bc145edca8fb303e465c8537bed65314djsollen@google.com 139e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunennamespace { 14a90ed4e83897b45d6331ee4c54e1edd4054de9a8kkinnunen 159e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunenclass EGLGLContext : public SkGLContext { 169e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunenpublic: 1730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen EGLGLContext(GrGLStandard forcedGpuAPI); 1836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein ~EGLGLContext() override; 1936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void makeCurrent() const override; 2036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void swapBuffers() const override; 2158629291bc145edca8fb303e465c8537bed65314djsollen@google.com 229e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunenprivate: 2330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen void destroyGLContext(); 2430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen 259e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen EGLContext fContext; 269e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen EGLDisplay fDisplay; 279e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen EGLSurface fSurface; 289e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen}; 2958629291bc145edca8fb303e465c8537bed65314djsollen@google.com 3030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunenEGLGLContext::EGLGLContext(GrGLStandard forcedGpuAPI) 3158629291bc145edca8fb303e465c8537bed65314djsollen@google.com : fContext(EGL_NO_CONTEXT) 3258629291bc145edca8fb303e465c8537bed65314djsollen@google.com , fDisplay(EGL_NO_DISPLAY) 3358629291bc145edca8fb303e465c8537bed65314djsollen@google.com , fSurface(EGL_NO_SURFACE) { 34f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org static const EGLint kEGLContextAttribsForOpenGL[] = { 35f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org EGL_NONE 36f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org }; 37f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org 38f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org static const EGLint kEGLContextAttribsForOpenGLES[] = { 39f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org EGL_CONTEXT_CLIENT_VERSION, 2, 40f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org EGL_NONE 41f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org }; 42f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org 431e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org static const struct { 441e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org const EGLint* fContextAttribs; 451e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGLenum fAPI; 461e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGLint fRenderableTypeBit; 479e90aed5de82732cc9921f01388d3063a41a053bcommit-bot@chromium.org GrGLStandard fStandard; 481e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org } kAPIs[] = { 491e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org { // OpenGL 501e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org kEGLContextAttribsForOpenGL, 511e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_OPENGL_API, 521e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_OPENGL_BIT, 539e90aed5de82732cc9921f01388d3063a41a053bcommit-bot@chromium.org kGL_GrGLStandard 541e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org }, 551e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org { // OpenGL ES. This seems to work for both ES2 and 3 (when available). 561e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org kEGLContextAttribsForOpenGLES, 571e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_OPENGL_ES_API, 581e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_OPENGL_ES2_BIT, 599e90aed5de82732cc9921f01388d3063a41a053bcommit-bot@chromium.org kGLES_GrGLStandard 601e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org }, 611e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org }; 62f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org 6380549fcdd50269d7e069d6db02b395fca128056ckkinnunen size_t apiLimit = SK_ARRAY_COUNT(kAPIs); 6480549fcdd50269d7e069d6db02b395fca128056ckkinnunen size_t api = 0; 6580549fcdd50269d7e069d6db02b395fca128056ckkinnunen if (forcedGpuAPI == kGL_GrGLStandard) { 6680549fcdd50269d7e069d6db02b395fca128056ckkinnunen apiLimit = 1; 6780549fcdd50269d7e069d6db02b395fca128056ckkinnunen } else if (forcedGpuAPI == kGLES_GrGLStandard) { 6880549fcdd50269d7e069d6db02b395fca128056ckkinnunen api = 1; 6980549fcdd50269d7e069d6db02b395fca128056ckkinnunen } 7080549fcdd50269d7e069d6db02b395fca128056ckkinnunen SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kAPIs[api].fStandard == forcedGpuAPI); 7180549fcdd50269d7e069d6db02b395fca128056ckkinnunen 7230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen for (; NULL == fGL.get() && api < apiLimit; ++api) { 731e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 7458629291bc145edca8fb303e465c8537bed65314djsollen@google.com 751e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGLint majorVersion; 761e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGLint minorVersion; 771e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org eglInitialize(fDisplay, &majorVersion, &minorVersion); 78dabdd9e71df4619db0260b9091c9bcc0d57b0a34borenet@google.com 791e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org#if 0 801e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR)); 811e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS)); 821e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION)); 831e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS)); 841e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org#endif 8558629291bc145edca8fb303e465c8537bed65314djsollen@google.com 861e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org if (!eglBindAPI(kAPIs[api].fAPI)) { 871e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org continue; 881e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org } 8958629291bc145edca8fb303e465c8537bed65314djsollen@google.com 90bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg EGLint numConfigs = 0; 911e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org const EGLint configAttribs[] = { 921e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 931e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit, 941e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_RED_SIZE, 8, 951e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_GREEN_SIZE, 8, 961e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_BLUE_SIZE, 8, 971e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_ALPHA_SIZE, 8, 981e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_NONE 991e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org }; 1001e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org 1011e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGLConfig surfaceConfig; 1021e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) { 1031e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org SkDebugf("eglChooseConfig failed. EGL Error: 0x%08x\n", eglGetError()); 1041e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org continue; 1051e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org } 10658629291bc145edca8fb303e465c8537bed65314djsollen@google.com 107bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg if (0 == numConfigs) { 108bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg SkDebugf("No suitable EGL config found.\n"); 109bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg continue; 110bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg } 111bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg 1121e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org fContext = eglCreateContext(fDisplay, surfaceConfig, NULL, kAPIs[api].fContextAttribs); 1131e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org if (EGL_NO_CONTEXT == fContext) { 1141e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org SkDebugf("eglCreateContext failed. EGL Error: 0x%08x\n", eglGetError()); 1151e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org continue; 1161e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org } 11758629291bc145edca8fb303e465c8537bed65314djsollen@google.com 1181e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org static const EGLint kSurfaceAttribs[] = { 1191e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_WIDTH, 1, 1201e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_HEIGHT, 1, 1211e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org EGL_NONE 1221e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org }; 1231e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org 1241e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, kSurfaceAttribs); 1251e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org if (EGL_NO_SURFACE == fSurface) { 1261e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org SkDebugf("eglCreatePbufferSurface failed. EGL Error: 0x%08x\n", eglGetError()); 1271e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org this->destroyGLContext(); 1281e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org continue; 1291e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org } 13058629291bc145edca8fb303e465c8537bed65314djsollen@google.com 1311e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { 1321e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError()); 1331e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org this->destroyGLContext(); 1341e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org continue; 1351e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org } 13658629291bc145edca8fb303e465c8537bed65314djsollen@google.com 13730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen fGL.reset(GrGLCreateNativeInterface()); 13830bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen if (NULL == fGL.get()) { 1391e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org SkDebugf("Failed to create gl interface.\n"); 1401e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org this->destroyGLContext(); 1411e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org continue; 1421e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org } 1431e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org 14430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen if (!fGL->validate()) { 14530bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen SkDebugf("Failed to validate gl interface.\n"); 1461e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org this->destroyGLContext(); 14730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen continue; 1481e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org } 14958629291bc145edca8fb303e465c8537bed65314djsollen@google.com } 15030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen} 151f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org 15230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunenEGLGLContext::~EGLGLContext() { 15330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen this->destroyGLContext(); 15458629291bc145edca8fb303e465c8537bed65314djsollen@google.com} 15558629291bc145edca8fb303e465c8537bed65314djsollen@google.com 15630bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunenvoid EGLGLContext::destroyGLContext() { 15730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen fGL.reset(NULL); 15830bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen if (fDisplay) { 15930bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen eglMakeCurrent(fDisplay, 0, 0, 0); 16030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen 16130bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen if (fContext) { 16230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen eglDestroyContext(fDisplay, fContext); 16330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen fContext = EGL_NO_CONTEXT; 16430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen } 16530bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen 16630bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen if (fSurface) { 16730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen eglDestroySurface(fDisplay, fSurface); 16830bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen fSurface = EGL_NO_SURFACE; 16930bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen } 17030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen 17130bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen //TODO should we close the display? 17230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen fDisplay = EGL_NO_DISPLAY; 17330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen } 17430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen} 17530bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen 17630bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen 1779e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunenvoid EGLGLContext::makeCurrent() const { 17858629291bc145edca8fb303e465c8537bed65314djsollen@google.com if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { 17958629291bc145edca8fb303e465c8537bed65314djsollen@google.com SkDebugf("Could not set the context.\n"); 18058629291bc145edca8fb303e465c8537bed65314djsollen@google.com } 18158629291bc145edca8fb303e465c8537bed65314djsollen@google.com} 182c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com 1839e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunenvoid EGLGLContext::swapBuffers() const { 184c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com if (!eglSwapBuffers(fDisplay, fSurface)) { 185c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com SkDebugf("Could not complete eglSwapBuffers.\n"); 186c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com } 187c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com} 1889e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen 1899e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen} // anonymous namespace 1909e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen 19130bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunenSkGLContext* SkCreatePlatformGLContext(GrGLStandard forcedGpuAPI) { 19230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen EGLGLContext* ctx = SkNEW_ARGS(EGLGLContext, (forcedGpuAPI)); 19330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen if (!ctx->isValid()) { 19430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen SkDELETE(ctx); 19530bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen return NULL; 19630bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen } 19730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen return ctx; 1989e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen} 1999e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen 200