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 <EGL/egl.h> 10#include <GLES/gl.h> 11#include "include/gpu/gl/GrGLInterface.h" 12#include "tools/sk_app/GLWindowContext.h" 13#include "tools/sk_app/android/WindowContextFactory_android.h" 14 15using sk_app::GLWindowContext; 16using sk_app::DisplayParams; 17 18namespace { 19class GLWindowContext_android : public GLWindowContext { 20public: 21 22 GLWindowContext_android(ANativeWindow*, const DisplayParams&); 23 24 ~GLWindowContext_android() override; 25 26 void onSwapBuffers() override; 27 28 sk_sp<const GrGLInterface> onInitializeContext() override; 29 void onDestroyContext() override; 30 31private: 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 using INHERITED = GLWindowContext; 41}; 42 43GLWindowContext_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 56GLWindowContext_android::~GLWindowContext_android() { 57 this->destroyContext(); 58} 59 60sk_sp<const GrGLInterface> 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 EGLint eglSampleCnt = fDisplayParams.fMSAASampleCount > 1 ? fDisplayParams.fMSAASampleCount > 1 74 : 0; 75 const EGLint configAttribs[] = { 76 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 77 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 78 EGL_RED_SIZE, 8, 79 EGL_GREEN_SIZE, 8, 80 EGL_BLUE_SIZE, 8, 81 EGL_ALPHA_SIZE, 8, 82 EGL_STENCIL_SIZE, 8, 83 EGL_SAMPLE_BUFFERS, eglSampleCnt ? 1 : 0, 84 EGL_SAMPLES, eglSampleCnt, 85 EGL_NONE 86 }; 87 88 EGLConfig surfaceConfig; 89 SkAssertResult(eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)); 90 SkASSERT(numConfigs > 0); 91 92 static const EGLint kEGLContextAttribsForOpenGLES[] = { 93 EGL_CONTEXT_CLIENT_VERSION, 2, 94 EGL_NONE 95 }; 96 fEGLContext = eglCreateContext( 97 fDisplay, surfaceConfig, nullptr, kEGLContextAttribsForOpenGLES); 98 SkASSERT(EGL_NO_CONTEXT != fEGLContext); 99 100// SkDebugf("EGL: %d.%d", majorVersion, minorVersion); 101// SkDebugf("Vendor: %s", eglQueryString(fDisplay, EGL_VENDOR)); 102// SkDebugf("Extensions: %s", eglQueryString(fDisplay, EGL_EXTENSIONS)); 103 104 fSurfaceAndroid = eglCreateWindowSurface(fDisplay, surfaceConfig, fNativeWindow, nullptr); 105 SkASSERT(EGL_NO_SURFACE != fSurfaceAndroid); 106 107 SkAssertResult(eglMakeCurrent(fDisplay, fSurfaceAndroid, fSurfaceAndroid, fEGLContext)); 108 // GLWindowContext::initializeContext will call GrGLMakeNativeInterface so we 109 // won't call it here. 110 111 glClearStencil(0); 112 glClearColor(0, 0, 0, 0); 113 glStencilMask(0xffffffff); 114 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 115 116 eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_STENCIL_SIZE, &fStencilBits); 117 eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_SAMPLES, &fSampleCount); 118 fSampleCount = std::max(fSampleCount, 1); 119 120 eglSwapInterval(fDisplay, fDisplayParams.fDisableVsync ? 0 : 1); 121 122 return GrGLMakeNativeInterface(); 123} 124 125void GLWindowContext_android::onDestroyContext() { 126 if (!fDisplay || !fEGLContext || !fSurfaceAndroid) { 127 return; 128 } 129 eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 130 SkAssertResult(eglDestroySurface(fDisplay, fSurfaceAndroid)); 131 SkAssertResult(eglDestroyContext(fDisplay, fEGLContext)); 132 fEGLContext = EGL_NO_CONTEXT; 133 fSurfaceAndroid = EGL_NO_SURFACE; 134} 135 136void GLWindowContext_android::onSwapBuffers() { 137 if (fDisplay && fEGLContext && fSurfaceAndroid) { 138 eglSwapBuffers(fDisplay, fSurfaceAndroid); 139 } 140} 141 142} // anonymous namespace 143 144namespace sk_app { 145namespace window_context_factory { 146 147std::unique_ptr<WindowContext> MakeGLForAndroid(ANativeWindow* window, 148 const DisplayParams& params) { 149 std::unique_ptr<WindowContext> ctx(new GLWindowContext_android(window, params)); 150 if (!ctx->isValid()) { 151 return nullptr; 152 } 153 return ctx; 154} 155 156} // namespace window_context_factory 157} // namespace sk_app 158