1 2 /* 3 * Copyright 2016 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 9 #include <GLES/gl.h> 10 11 #include "WindowContextFactory_android.h" 12 #include "../GLWindowContext.h" 13 #include <EGL/egl.h> 14 15 using sk_app::GLWindowContext; 16 using sk_app::DisplayParams; 17 18 namespace { 19 class GLWindowContext_android : public GLWindowContext { 20 public: 21 22 GLWindowContext_android(ANativeWindow*, const DisplayParams&); 23 24 ~GLWindowContext_android() override; 25 26 void onSwapBuffers() override; 27 28 void onInitializeContext() override; 29 void onDestroyContext() override; 30 31 private: 32 33 EGLDisplay fDisplay; 34 EGLContext fEGLContext; 35 EGLSurface fSurfaceAndroid; 36 37 // For setDisplayParams and resize which call onInitializeContext with null platformData 38 ANativeWindow* fNativeWindow = nullptr; 39 40 typedef GLWindowContext INHERITED; 41 }; 42 43 GLWindowContext_android::GLWindowContext_android(ANativeWindow* window, 44 const DisplayParams& params) 45 : INHERITED(params) 46 , fDisplay(EGL_NO_DISPLAY) 47 , fEGLContext(EGL_NO_CONTEXT) 48 , fSurfaceAndroid(EGL_NO_SURFACE) 49 , fNativeWindow(window) { 50 51 // any config code here (particularly for msaa)? 52 53 this->initializeContext(); 54 } 55 56 GLWindowContext_android::~GLWindowContext_android() { 57 this->destroyContext(); 58 } 59 60 void GLWindowContext_android::onInitializeContext() { 61 fWidth = ANativeWindow_getWidth(fNativeWindow); 62 fHeight = ANativeWindow_getHeight(fNativeWindow); 63 64 fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 65 66 EGLint majorVersion; 67 EGLint minorVersion; 68 eglInitialize(fDisplay, &majorVersion, &minorVersion); 69 70 SkAssertResult(eglBindAPI(EGL_OPENGL_ES_API)); 71 72 EGLint numConfigs = 0; 73 const EGLint configAttribs[] = { 74 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 75 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 76 EGL_RED_SIZE, 8, 77 EGL_GREEN_SIZE, 8, 78 EGL_BLUE_SIZE, 8, 79 EGL_ALPHA_SIZE, 8, 80 EGL_STENCIL_SIZE, 8, 81 EGL_SAMPLE_BUFFERS, fDisplayParams.fMSAASampleCount ? 1 : 0, 82 EGL_SAMPLES, fDisplayParams.fMSAASampleCount, 83 EGL_NONE 84 }; 85 86 EGLConfig surfaceConfig; 87 SkAssertResult(eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)); 88 SkASSERT(numConfigs > 0); 89 90 static const EGLint kEGLContextAttribsForOpenGLES[] = { 91 EGL_CONTEXT_CLIENT_VERSION, 2, 92 EGL_NONE 93 }; 94 fEGLContext = eglCreateContext( 95 fDisplay, surfaceConfig, nullptr, kEGLContextAttribsForOpenGLES); 96 SkASSERT(EGL_NO_CONTEXT != fEGLContext); 97 98 // SkDebugf("EGL: %d.%d", majorVersion, minorVersion); 99 // SkDebugf("Vendor: %s", eglQueryString(fDisplay, EGL_VENDOR)); 100 // SkDebugf("Extensions: %s", eglQueryString(fDisplay, EGL_EXTENSIONS)); 101 102 // These values are the same as the corresponding VG colorspace attributes, 103 // which were accepted starting in EGL 1.2. For some reason in 1.4, sRGB 104 // became hidden behind an extension, but it looks like devices aren't 105 // advertising that extension (including Nexus 5X). So just check version? 106 const EGLint srgbWindowAttribs[] = { 107 /*EGL_GL_COLORSPACE_KHR*/ 0x309D, /*EGL_GL_COLORSPACE_SRGB_KHR*/ 0x3089, 108 EGL_NONE, 109 }; 110 const EGLint* windowAttribs = nullptr; 111 auto srgbColorSpace = SkColorSpace::MakeSRGB(); 112 if (srgbColorSpace == fDisplayParams.fColorSpace && majorVersion == 1 && minorVersion >= 2) { 113 windowAttribs = srgbWindowAttribs; 114 } 115 116 fSurfaceAndroid = eglCreateWindowSurface(fDisplay, surfaceConfig, fNativeWindow, windowAttribs); 117 if (EGL_NO_SURFACE == fSurfaceAndroid && windowAttribs) { 118 // Try again without sRGB 119 fSurfaceAndroid = eglCreateWindowSurface(fDisplay, surfaceConfig, fNativeWindow, nullptr); 120 } 121 SkASSERT(EGL_NO_SURFACE != fSurfaceAndroid); 122 123 SkAssertResult(eglMakeCurrent(fDisplay, fSurfaceAndroid, fSurfaceAndroid, fEGLContext)); 124 // GLWindowContext::initializeContext will call GrGLCreateNativeInterface so we 125 // won't call it here. 126 127 glClearStencil(0); 128 glClearColor(0, 0, 0, 0); 129 glStencilMask(0xffffffff); 130 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 131 132 eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_STENCIL_SIZE, &fStencilBits); 133 eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_SAMPLES, &fSampleCount); 134 } 135 136 void GLWindowContext_android::onDestroyContext() { 137 if (!fDisplay || !fEGLContext || !fSurfaceAndroid) { 138 return; 139 } 140 eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 141 SkAssertResult(eglDestroySurface(fDisplay, fSurfaceAndroid)); 142 SkAssertResult(eglDestroyContext(fDisplay, fEGLContext)); 143 fEGLContext = EGL_NO_CONTEXT; 144 fSurfaceAndroid = EGL_NO_SURFACE; 145 } 146 147 void GLWindowContext_android::onSwapBuffers() { 148 if (fDisplay && fEGLContext && fSurfaceAndroid) { 149 eglSwapBuffers(fDisplay, fSurfaceAndroid); 150 } 151 } 152 153 } // anonymous namespace 154 155 namespace sk_app { 156 namespace window_context_factory { 157 158 WindowContext* NewGLForAndroid(ANativeWindow* window, const DisplayParams& params) { 159 WindowContext* ctx = new GLWindowContext_android(window, params); 160 if (!ctx->isValid()) { 161 delete ctx; 162 return nullptr; 163 } 164 return ctx; 165 } 166 167 } // namespace window_context_factory 168 } // namespace sk_app 169