Home | History | Annotate | Download | only in android
      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 "../GLWindowContext.h"
     12 #include "WindowContextFactory_android.h"
     13 #include "gl/GrGLInterface.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     sk_sp<const GrGLInterface> 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 sk_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     // These values are the same as the corresponding VG colorspace attributes,
    105     // which were accepted starting in EGL 1.2. For some reason in 1.4, sRGB
    106     // became hidden behind an extension, but it looks like devices aren't
    107     // advertising that extension (including Nexus 5X). So just check version?
    108     const EGLint srgbWindowAttribs[] = {
    109         /*EGL_GL_COLORSPACE_KHR*/ 0x309D, /*EGL_GL_COLORSPACE_SRGB_KHR*/ 0x3089,
    110         EGL_NONE,
    111     };
    112     const EGLint* windowAttribs = nullptr;
    113     auto srgbColorSpace = SkColorSpace::MakeSRGB();
    114     if (srgbColorSpace == fDisplayParams.fColorSpace && majorVersion == 1 && minorVersion >= 2) {
    115         windowAttribs = srgbWindowAttribs;
    116     }
    117 
    118     fSurfaceAndroid = eglCreateWindowSurface(fDisplay, surfaceConfig, fNativeWindow, windowAttribs);
    119     if (EGL_NO_SURFACE == fSurfaceAndroid && windowAttribs) {
    120         // Try again without sRGB
    121         fSurfaceAndroid = eglCreateWindowSurface(fDisplay, surfaceConfig, fNativeWindow, nullptr);
    122     }
    123     SkASSERT(EGL_NO_SURFACE != fSurfaceAndroid);
    124 
    125     SkAssertResult(eglMakeCurrent(fDisplay, fSurfaceAndroid, fSurfaceAndroid, fEGLContext));
    126     // GLWindowContext::initializeContext will call GrGLMakeNativeInterface so we
    127     // won't call it here.
    128 
    129     glClearStencil(0);
    130     glClearColor(0, 0, 0, 0);
    131     glStencilMask(0xffffffff);
    132     glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    133 
    134     eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_STENCIL_SIZE, &fStencilBits);
    135     eglGetConfigAttrib(fDisplay, surfaceConfig, EGL_SAMPLES, &fSampleCount);
    136     fSampleCount = SkTMax(fSampleCount, 1);
    137 
    138     return GrGLMakeNativeInterface();
    139 }
    140 
    141 void GLWindowContext_android::onDestroyContext() {
    142     if (!fDisplay || !fEGLContext || !fSurfaceAndroid) {
    143         return;
    144     }
    145     eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    146     SkAssertResult(eglDestroySurface(fDisplay, fSurfaceAndroid));
    147     SkAssertResult(eglDestroyContext(fDisplay, fEGLContext));
    148     fEGLContext = EGL_NO_CONTEXT;
    149     fSurfaceAndroid = EGL_NO_SURFACE;
    150 }
    151 
    152 void GLWindowContext_android::onSwapBuffers() {
    153     if (fDisplay && fEGLContext && fSurfaceAndroid) {
    154         eglSwapBuffers(fDisplay, fSurfaceAndroid);
    155     }
    156 }
    157 
    158 }  // anonymous namespace
    159 
    160 namespace sk_app {
    161 namespace window_context_factory {
    162 
    163 WindowContext* NewGLForAndroid(ANativeWindow* window, const DisplayParams& params) {
    164     WindowContext* ctx = new GLWindowContext_android(window, params);
    165     if (!ctx->isValid()) {
    166         delete ctx;
    167         return nullptr;
    168     }
    169     return ctx;
    170 }
    171 
    172 }  // namespace window_context_factory
    173 }  // namespace sk_app
    174