| /* | |
| * Copyright 2023 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "tools/window/ANGLEWindowContext.h" | |
| #include "include/gpu/ganesh/gl/GrGLAssembleInterface.h" | |
| #include "src/gpu/ganesh/gl/GrGLDefines.h" | |
| #include "tools/window/DisplayParams.h" | |
| namespace skwindow::internal { | |
| ANGLEWindowContext::~ANGLEWindowContext() { this->destroyContext(); } | |
| sk_sp<const GrGLInterface> ANGLEWindowContext::onInitializeContext() { | |
| PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = | |
| (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); | |
| // We expect ANGLE to support this extension | |
| if (!eglGetPlatformDisplayEXT) { | |
| return nullptr; | |
| } | |
| fDisplay = this->onGetEGLDisplay(eglGetPlatformDisplayEXT); | |
| if (EGL_NO_DISPLAY == fDisplay) { | |
| return nullptr; | |
| } | |
| EGLint majorVersion; | |
| EGLint minorVersion; | |
| if (!eglInitialize(fDisplay, &majorVersion, &minorVersion)) { | |
| SkDebugf("Could not initialize display!\n"); | |
| return nullptr; | |
| } | |
| EGLint numConfigs; | |
| fSampleCount = this->getDisplayParams()->msaaSampleCount(); | |
| const int sampleBuffers = fSampleCount > 1 ? 1 : 0; | |
| const int eglSampleCnt = fSampleCount > 1 ? fSampleCount : 0; | |
| const EGLint configAttribs[] = {EGL_RENDERABLE_TYPE, | |
| // We currently only support ES3. | |
| EGL_OPENGL_ES3_BIT, | |
| EGL_RED_SIZE, | |
| 8, | |
| EGL_GREEN_SIZE, | |
| 8, | |
| EGL_BLUE_SIZE, | |
| 8, | |
| EGL_ALPHA_SIZE, | |
| 8, | |
| EGL_SAMPLE_BUFFERS, | |
| sampleBuffers, | |
| EGL_SAMPLES, | |
| eglSampleCnt, | |
| EGL_NONE}; | |
| EGLConfig surfaceConfig; | |
| if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) { | |
| SkDebugf("Could not create choose config!\n"); | |
| return nullptr; | |
| } | |
| // We currently only support ES3. | |
| const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; | |
| fEGLContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, contextAttribs); | |
| if (EGL_NO_CONTEXT == fEGLContext) { | |
| SkDebugf("Could not create context!\n"); | |
| return nullptr; | |
| } | |
| fEGLSurface = | |
| eglCreateWindowSurface(fDisplay, surfaceConfig, this->onGetNativeWindow(), nullptr); | |
| if (EGL_NO_SURFACE == fEGLSurface) { | |
| SkDebugf("Could not create surface!\n"); | |
| return nullptr; | |
| } | |
| if (!eglMakeCurrent(fDisplay, fEGLSurface, fEGLSurface, fEGLContext)) { | |
| SkDebugf("Could not make context current!\n"); | |
| return nullptr; | |
| } | |
| sk_sp<const GrGLInterface> interface(GrGLMakeAssembledInterface( | |
| nullptr, | |
| [](void* ctx, const char name[]) -> GrGLFuncPtr { return eglGetProcAddress(name); })); | |
| if (interface) { | |
| interface->fFunctions.fClearStencil(0); | |
| interface->fFunctions.fClearColor(0, 0, 0, 0); | |
| interface->fFunctions.fStencilMask(0xffffffff); | |
| interface->fFunctions.fClear(GR_GL_STENCIL_BUFFER_BIT | GR_GL_COLOR_BUFFER_BIT); | |
| fStencilBits = this->onGetStencilBits(); | |
| SkISize size = this->onGetSize(); | |
| fWidth = size.width(); | |
| fHeight = size.height(); | |
| interface->fFunctions.fViewport(0, 0, fWidth, fHeight); | |
| } | |
| return interface; | |
| } | |
| void ANGLEWindowContext::onDestroyContext() { | |
| eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | |
| if (EGL_NO_CONTEXT != fEGLContext) { | |
| eglDestroyContext(fDisplay, fEGLContext); | |
| } | |
| if (EGL_NO_SURFACE != fEGLSurface) { | |
| eglDestroySurface(fDisplay, fEGLSurface); | |
| } | |
| if (EGL_NO_DISPLAY != fDisplay) { | |
| eglTerminate(fDisplay); | |
| } | |
| } | |
| void ANGLEWindowContext::onSwapBuffers() { | |
| if (!eglSwapBuffers(fDisplay, fEGLSurface)) { | |
| SkDebugf("Could not complete eglSwapBuffers.\n"); | |
| } | |
| } | |
| } // namespace skwindow::internal |