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
GLWindowContext_android(ANativeWindow * window,const DisplayParams & params)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
~GLWindowContext_android()56 GLWindowContext_android::~GLWindowContext_android() {
57 this->destroyContext();
58 }
59
onInitializeContext()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
onDestroyContext()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
onSwapBuffers()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
NewGLForAndroid(ANativeWindow * window,const DisplayParams & params)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