xref: /aosp_15_r20/external/skia/tools/window/ANGLEWindowContext.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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