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
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 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 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 = SkTMax(fSampleCount, 1);
119
120 return GrGLMakeNativeInterface();
121 }
122
onDestroyContext()123 void GLWindowContext_android::onDestroyContext() {
124 if (!fDisplay || !fEGLContext || !fSurfaceAndroid) {
125 return;
126 }
127 eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
128 SkAssertResult(eglDestroySurface(fDisplay, fSurfaceAndroid));
129 SkAssertResult(eglDestroyContext(fDisplay, fEGLContext));
130 fEGLContext = EGL_NO_CONTEXT;
131 fSurfaceAndroid = EGL_NO_SURFACE;
132 }
133
onSwapBuffers()134 void GLWindowContext_android::onSwapBuffers() {
135 if (fDisplay && fEGLContext && fSurfaceAndroid) {
136 eglSwapBuffers(fDisplay, fSurfaceAndroid);
137 }
138 }
139
140 } // anonymous namespace
141
142 namespace sk_app {
143 namespace window_context_factory {
144
NewGLForAndroid(ANativeWindow * window,const DisplayParams & params)145 WindowContext* NewGLForAndroid(ANativeWindow* window, const DisplayParams& params) {
146 WindowContext* ctx = new GLWindowContext_android(window, params);
147 if (!ctx->isValid()) {
148 delete ctx;
149 return nullptr;
150 }
151 return ctx;
152 }
153
154 } // namespace window_context_factory
155 } // namespace sk_app
156