1 /*
2 * Copyright 2023 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "tools/window/ANGLEWindowContext.h"
9
10 #include "include/gpu/ganesh/gl/GrGLAssembleInterface.h"
11 #include "src/gpu/ganesh/gl/GrGLDefines.h"
12 #include "tools/window/DisplayParams.h"
13
14 namespace skwindow::internal {
15
~ANGLEWindowContext()16 ANGLEWindowContext::~ANGLEWindowContext() { this->destroyContext(); }
17
onInitializeContext()18 sk_sp<const GrGLInterface> ANGLEWindowContext::onInitializeContext() {
19 PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
20 (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
21
22 // We expect ANGLE to support this extension
23 if (!eglGetPlatformDisplayEXT) {
24 return nullptr;
25 }
26
27 fDisplay = this->onGetEGLDisplay(eglGetPlatformDisplayEXT);
28 if (EGL_NO_DISPLAY == fDisplay) {
29 return nullptr;
30 }
31
32 EGLint majorVersion;
33 EGLint minorVersion;
34 if (!eglInitialize(fDisplay, &majorVersion, &minorVersion)) {
35 SkDebugf("Could not initialize display!\n");
36 return nullptr;
37 }
38 EGLint numConfigs;
39 fSampleCount = this->getDisplayParams()->msaaSampleCount();
40 const int sampleBuffers = fSampleCount > 1 ? 1 : 0;
41 const int eglSampleCnt = fSampleCount > 1 ? fSampleCount : 0;
42 const EGLint configAttribs[] = {EGL_RENDERABLE_TYPE,
43 // We currently only support ES3.
44 EGL_OPENGL_ES3_BIT,
45 EGL_RED_SIZE,
46 8,
47 EGL_GREEN_SIZE,
48 8,
49 EGL_BLUE_SIZE,
50 8,
51 EGL_ALPHA_SIZE,
52 8,
53 EGL_SAMPLE_BUFFERS,
54 sampleBuffers,
55 EGL_SAMPLES,
56 eglSampleCnt,
57 EGL_NONE};
58
59 EGLConfig surfaceConfig;
60 if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) {
61 SkDebugf("Could not create choose config!\n");
62 return nullptr;
63 }
64 // We currently only support ES3.
65 const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
66 fEGLContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, contextAttribs);
67 if (EGL_NO_CONTEXT == fEGLContext) {
68 SkDebugf("Could not create context!\n");
69 return nullptr;
70 }
71 fEGLSurface =
72 eglCreateWindowSurface(fDisplay, surfaceConfig, this->onGetNativeWindow(), nullptr);
73 if (EGL_NO_SURFACE == fEGLSurface) {
74 SkDebugf("Could not create surface!\n");
75 return nullptr;
76 }
77 if (!eglMakeCurrent(fDisplay, fEGLSurface, fEGLSurface, fEGLContext)) {
78 SkDebugf("Could not make context current!\n");
79 return nullptr;
80 }
81
82 sk_sp<const GrGLInterface> interface(GrGLMakeAssembledInterface(
83 nullptr,
84 [](void* ctx, const char name[]) -> GrGLFuncPtr { return eglGetProcAddress(name); }));
85 if (interface) {
86 interface->fFunctions.fClearStencil(0);
87 interface->fFunctions.fClearColor(0, 0, 0, 0);
88 interface->fFunctions.fStencilMask(0xffffffff);
89 interface->fFunctions.fClear(GR_GL_STENCIL_BUFFER_BIT | GR_GL_COLOR_BUFFER_BIT);
90
91 fStencilBits = this->onGetStencilBits();
92
93 SkISize size = this->onGetSize();
94 fWidth = size.width();
95 fHeight = size.height();
96 interface->fFunctions.fViewport(0, 0, fWidth, fHeight);
97 }
98 return interface;
99 }
100
onDestroyContext()101 void ANGLEWindowContext::onDestroyContext() {
102 eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
103 if (EGL_NO_CONTEXT != fEGLContext) {
104 eglDestroyContext(fDisplay, fEGLContext);
105 }
106 if (EGL_NO_SURFACE != fEGLSurface) {
107 eglDestroySurface(fDisplay, fEGLSurface);
108 }
109 if (EGL_NO_DISPLAY != fDisplay) {
110 eglTerminate(fDisplay);
111 }
112 }
113
onSwapBuffers()114 void ANGLEWindowContext::onSwapBuffers() {
115 if (!eglSwapBuffers(fDisplay, fEGLSurface)) {
116 SkDebugf("Could not complete eglSwapBuffers.\n");
117 }
118 }
119
120 } // namespace skwindow::internal
121