/* * 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 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 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