18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#if RENDER_HAS_GL_BACKEND
178bf80f4bSopenharmony_ci#include "gles/wgl_state.h"
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include <base/containers/fixed_string.h>
208bf80f4bSopenharmony_ci#include <render/namespace.h>
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ci#include "util/log.h"
238bf80f4bSopenharmony_ci
248bf80f4bSopenharmony_ci// NOTE: intentional double include of gl_functions.h
258bf80f4bSopenharmony_ci#include "gles/gl_functions.h"
268bf80f4bSopenharmony_ci#define declare(a, b) a b = nullptr;
278bf80f4bSopenharmony_ci#include <gl/wgl.h>
288bf80f4bSopenharmony_ci
298bf80f4bSopenharmony_ci#include "gles/gl_functions.h"
308bf80f4bSopenharmony_ci#include "gles/surface_information.h"
318bf80f4bSopenharmony_ci#include "gles/swapchain_gles.h"
328bf80f4bSopenharmony_ci
338bf80f4bSopenharmony_ciusing BASE_NS::string_view;
348bf80f4bSopenharmony_ciusing BASE_NS::vector;
358bf80f4bSopenharmony_ci
368bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE()
378bf80f4bSopenharmony_cinamespace WGLHelpers {
388bf80f4bSopenharmony_cinamespace {
398bf80f4bSopenharmony_ci#define WGLFUNCS                                                                   \
408bf80f4bSopenharmony_ci    declareWGL(PFNWGLGETPROCADDRESSPROC, wglGetProcAddress);                       \
418bf80f4bSopenharmony_ci    declareWGL(PFNWGLCREATECONTEXTPROC, wglCreateContext);                         \
428bf80f4bSopenharmony_ci    declareWGL(PFNWGLDELETECONTEXTPROC, wglDeleteContext);                         \
438bf80f4bSopenharmony_ci    declareWGL(PFNWGLMAKECURRENTPROC, wglMakeCurrent);                             \
448bf80f4bSopenharmony_ci    declareWGL(PFNWGLGETCURRENTCONTEXTPROC, wglGetCurrentContext);                 \
458bf80f4bSopenharmony_ci    declareWGL(PFNWGLGETCURRENTDCPROC, wglGetCurrentDC);                           \
468bf80f4bSopenharmony_ci    declareWGL(PFNWGLCREATECONTEXTATTRIBSARBPROC, wglCreateContextAttribsARB);     \
478bf80f4bSopenharmony_ci    declareWGL(PFNWGLGETPIXELFORMATATTRIBIVARBPROC, wglGetPixelFormatAttribivARB); \
488bf80f4bSopenharmony_ci    declareWGL(PFNWGLGETPIXELFORMATATTRIBFVARBPROC, wglGetPixelFormatAttribfvARB); \
498bf80f4bSopenharmony_ci    declareWGL(PFNWGLCHOOSEPIXELFORMATARBPROC, wglChoosePixelFormatARB);           \
508bf80f4bSopenharmony_ci    declareWGL(PFNWGLSWAPINTERVALEXTPROC, wglSwapIntervalEXT);                     \
518bf80f4bSopenharmony_ci    declareWGL(PFNWGLGETEXTENSIONSSTRINGARBPROC, wglGetExtensionsStringARB);
528bf80f4bSopenharmony_ci
538bf80f4bSopenharmony_ci#define declareWGL(a, b) a b = nullptr;
548bf80f4bSopenharmony_ciWGLFUNCS;
558bf80f4bSopenharmony_ci#undef declareWGL
568bf80f4bSopenharmony_ci
578bf80f4bSopenharmony_ciconstexpr int WGL_ATTRIBS[] = {
588bf80f4bSopenharmony_ci#if defined(CORE_CREATE_GLES_CONTEXT_WITH_WGL) && (CORE_CREATE_GLES_CONTEXT_WITH_WGL == 1)
598bf80f4bSopenharmony_ci    WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 2,
608bf80f4bSopenharmony_ci#if RENDER_GL_DEBUG
618bf80f4bSopenharmony_ci    WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
628bf80f4bSopenharmony_ci#endif
638bf80f4bSopenharmony_ci    WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_ES2_PROFILE_BIT_EXT, 0
648bf80f4bSopenharmony_ci#else
658bf80f4bSopenharmony_ci    WGL_CONTEXT_MAJOR_VERSION_ARB, 4, WGL_CONTEXT_MINOR_VERSION_ARB, 5,
668bf80f4bSopenharmony_ci#if RENDER_GL_DEBUG
678bf80f4bSopenharmony_ci    WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
688bf80f4bSopenharmony_ci#endif
698bf80f4bSopenharmony_ci    WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 0
708bf80f4bSopenharmony_ci#endif
718bf80f4bSopenharmony_ci};
728bf80f4bSopenharmony_ci
738bf80f4bSopenharmony_cistatic bool FilterError(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
748bf80f4bSopenharmony_ci    const string_view message, const void* userParam) noexcept
758bf80f4bSopenharmony_ci{
768bf80f4bSopenharmony_ci    if (source == GL_DEBUG_SOURCE_API) {
778bf80f4bSopenharmony_ci        if (type == GL_DEBUG_TYPE_OTHER) {
788bf80f4bSopenharmony_ci            if ((id == 11) && (severity == GL_DEBUG_SEVERITY_LOW)) {
798bf80f4bSopenharmony_ci                /*  Ignore the following warning that Intel drivers seem to spam. (no problems on nvidia or mali...)
808bf80f4bSopenharmony_ci                source: GL_DEBUG_SOURCE_API
818bf80f4bSopenharmony_ci                type: GL_DEBUG_TYPE_OTHER
828bf80f4bSopenharmony_ci                severity: GL_DEBUG_SEVERITY_LOW
838bf80f4bSopenharmony_ci                message: API_ID_SYNC_FLUSH other warning has been generated. ClientWait flush in different gc for sync
848bf80f4bSopenharmony_ci                object 2, "" will be ineffective.
858bf80f4bSopenharmony_ci                */
868bf80f4bSopenharmony_ci                return true;
878bf80f4bSopenharmony_ci            }
888bf80f4bSopenharmony_ci
898bf80f4bSopenharmony_ci            if ((id == 131185) && (severity == GL_DEBUG_SEVERITY_NOTIFICATION)) {
908bf80f4bSopenharmony_ci                /* Ignore this warning that Nvidia sends.
918bf80f4bSopenharmony_ci                source:      GL_DEBUG_SOURCE_API
928bf80f4bSopenharmony_ci                type:        GL_DEBUG_TYPE_OTHER
938bf80f4bSopenharmony_ci                severity:    GL_DEBUG_SEVERITY_NOTIFICATION
948bf80f4bSopenharmony_ci                message:     Buffer detailed info: Buffer object X (bound to GL_COPY_WRITE_BUFFER_BINDING_EXT, usage
958bf80f4bSopenharmony_ci                hint is GL_DYNAMIC_DRAW) will use SYSTEM HEAP memory as the source for buffer object operations. *OR*
968bf80f4bSopenharmony_ci                message:     Buffer detailed info: Buffer object X (bound to GL_COPY_WRITE_BUFFER_BINDING_EXT, usage
978bf80f4bSopenharmony_ci                hint is GL_DYNAMIC_DRAW) has been mapped WRITE_ONLY in SYSTEM HEAP memory (fast).
988bf80f4bSopenharmony_ci                */
998bf80f4bSopenharmony_ci                return true;
1008bf80f4bSopenharmony_ci            }
1018bf80f4bSopenharmony_ci        }
1028bf80f4bSopenharmony_ci        if (type == GL_DEBUG_TYPE_PERFORMANCE) {
1038bf80f4bSopenharmony_ci            if ((id == 131154) && (severity == GL_DEBUG_SEVERITY_MEDIUM)) {
1048bf80f4bSopenharmony_ci                /*
1058bf80f4bSopenharmony_ci                source: GL_DEBUG_SOURCE_API
1068bf80f4bSopenharmony_ci                type: GL_DEBUG_TYPE_PERFORMANCE
1078bf80f4bSopenharmony_ci                id: 131154
1088bf80f4bSopenharmony_ci                severity: GL_DEBUG_SEVERITY_MEDIUM
1098bf80f4bSopenharmony_ci                message: Pixel-path performance warning: Pixel transfer is synchronized with 3D rendering.
1108bf80f4bSopenharmony_ci                */
1118bf80f4bSopenharmony_ci                return true;
1128bf80f4bSopenharmony_ci            }
1138bf80f4bSopenharmony_ci            if ((id == 131186) && (severity == GL_DEBUG_SEVERITY_MEDIUM)) {
1148bf80f4bSopenharmony_ci                /* Ignore this warning that Nvidia sends.
1158bf80f4bSopenharmony_ci                source: GL_DEBUG_SOURCE_API
1168bf80f4bSopenharmony_ci                type: GL_DEBUG_TYPE_PERFORMANCE
1178bf80f4bSopenharmony_ci                id: 131186
1188bf80f4bSopenharmony_ci                severity: GL_DEBUG_SEVERITY_MEDIUM
1198bf80f4bSopenharmony_ci                message: Buffer performance warning: Buffer object X (bound to GL_ELEMENT_ARRAY_BUFFER_ARB, usage hint
1208bf80f4bSopenharmony_ci                is GL_DYNAMIC_DRAW) is being copied/moved from VIDEO memory to HOST memory.
1218bf80f4bSopenharmony_ci                */
1228bf80f4bSopenharmony_ci                return true;
1238bf80f4bSopenharmony_ci            }
1248bf80f4bSopenharmony_ci            if ((id == 131202) && (severity == GL_DEBUG_SEVERITY_MEDIUM)) {
1258bf80f4bSopenharmony_ci                /* Ignore this warning that Nvidia sends.
1268bf80f4bSopenharmony_ci                source: GL_DEBUG_SOURCE_API
1278bf80f4bSopenharmony_ci                type: GL_DEBUG_TYPE_PERFORMANCE
1288bf80f4bSopenharmony_ci                id: 131202
1298bf80f4bSopenharmony_ci                severity: GL_DEBUG_SEVERITY_MEDIUM
1308bf80f4bSopenharmony_ci                message: Texture state performance warning: emulating compressed format not supported in hardware with
1318bf80f4bSopenharmony_ci                decompressed images
1328bf80f4bSopenharmony_ci                */
1338bf80f4bSopenharmony_ci                return true;
1348bf80f4bSopenharmony_ci            }
1358bf80f4bSopenharmony_ci        }
1368bf80f4bSopenharmony_ci    }
1378bf80f4bSopenharmony_ci    return false;
1388bf80f4bSopenharmony_ci}
1398bf80f4bSopenharmony_ci
1408bf80f4bSopenharmony_cistatic void DoDummy()
1418bf80f4bSopenharmony_ci{
1428bf80f4bSopenharmony_ci    WNDCLASS wc = { 0 };
1438bf80f4bSopenharmony_ci    wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
1448bf80f4bSopenharmony_ci    wc.lpfnWndProc = DefWindowProc; // WindowProc;
1458bf80f4bSopenharmony_ci    wc.hInstance = GetModuleHandle(nullptr);
1468bf80f4bSopenharmony_ci    wc.lpszClassName = TEXT("PureGL_WGL_Dummy");
1478bf80f4bSopenharmony_ci    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
1488bf80f4bSopenharmony_ci    RegisterClass(&wc);
1498bf80f4bSopenharmony_ci    const HWND dummyhWnd = CreateWindowEx(0, wc.lpszClassName, wc.lpszClassName, WS_OVERLAPPED, CW_USEDEFAULT,
1508bf80f4bSopenharmony_ci        CW_USEDEFAULT, 1, 1, nullptr, nullptr, wc.hInstance, nullptr);
1518bf80f4bSopenharmony_ci    const HDC dummyhDC = GetDC(dummyhWnd);
1528bf80f4bSopenharmony_ci    PIXELFORMATDESCRIPTOR pfd = { 0 };
1538bf80f4bSopenharmony_ci    pfd.nSize = sizeof(pfd);
1548bf80f4bSopenharmony_ci    pfd.nVersion = 1;
1558bf80f4bSopenharmony_ci    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED | PFD_DOUBLEBUFFER;
1568bf80f4bSopenharmony_ci    pfd.iPixelType = PFD_TYPE_RGBA;
1578bf80f4bSopenharmony_ci    pfd.cColorBits = 32;
1588bf80f4bSopenharmony_ci    pfd.iLayerType = PFD_MAIN_PLANE;
1598bf80f4bSopenharmony_ci    SetPixelFormat(dummyhDC, ChoosePixelFormat(dummyhDC, &pfd), &pfd);
1608bf80f4bSopenharmony_ci    const HGLRC dummy = wglCreateContext(dummyhDC);
1618bf80f4bSopenharmony_ci    wglMakeCurrent(dummyhDC, dummy);
1628bf80f4bSopenharmony_ci#define declareWGL(a, b)                                                                    \
1638bf80f4bSopenharmony_ci    if ((b) == nullptr) {                                                                   \
1648bf80f4bSopenharmony_ci        *(reinterpret_cast<void**>(&(b))) = reinterpret_cast<void*>(wglGetProcAddress(#b)); \
1658bf80f4bSopenharmony_ci    }
1668bf80f4bSopenharmony_ci    WGLFUNCS
1678bf80f4bSopenharmony_ci#undef declareWGL
1688bf80f4bSopenharmony_ci    wglMakeCurrent(dummyhDC, nullptr);
1698bf80f4bSopenharmony_ci    wglMakeCurrent(nullptr, nullptr);
1708bf80f4bSopenharmony_ci    wglDeleteContext(dummy);
1718bf80f4bSopenharmony_ci    ReleaseDC(dummyhWnd, dummyhDC);
1728bf80f4bSopenharmony_ci    DestroyWindow(dummyhWnd);
1738bf80f4bSopenharmony_ci    UnregisterClass(wc.lpszClassName, wc.hInstance);
1748bf80f4bSopenharmony_ci}
1758bf80f4bSopenharmony_ci
1768bf80f4bSopenharmony_civoid ParseExtensions(const string_view extensions, vector<string_view>& extensionList)
1778bf80f4bSopenharmony_ci{
1788bf80f4bSopenharmony_ci    size_t start = 0;
1798bf80f4bSopenharmony_ci    for (auto end = extensions.find(' '); end != BASE_NS::string::npos; end = extensions.find(' ', start)) {
1808bf80f4bSopenharmony_ci        extensionList.emplace_back(extensions.data() + start, end - start);
1818bf80f4bSopenharmony_ci        start = end + 1;
1828bf80f4bSopenharmony_ci    }
1838bf80f4bSopenharmony_ci    if (start < extensions.size()) {
1848bf80f4bSopenharmony_ci        extensionList.emplace_back(extensions.data() + start);
1858bf80f4bSopenharmony_ci    }
1868bf80f4bSopenharmony_ci}
1878bf80f4bSopenharmony_ci
1888bf80f4bSopenharmony_civoid FillProperties(DevicePropertiesGL& properties)
1898bf80f4bSopenharmony_ci{
1908bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &properties.max3DTextureSize);
1918bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &properties.maxTextureSize);
1928bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &properties.maxArrayTextureLayers);
1938bf80f4bSopenharmony_ci    glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &properties.maxTextureLodBias);
1948bf80f4bSopenharmony_ci    glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &properties.maxTextureMaxAnisotropy);
1958bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &properties.maxCubeMapTextureSize);
1968bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &properties.maxRenderbufferSize);
1978bf80f4bSopenharmony_ci    glGetFloati_v(GL_MAX_VIEWPORT_DIMS, 0, properties.maxViewportDims);
1988bf80f4bSopenharmony_ci    glGetFloati_v(GL_MAX_VIEWPORT_DIMS, 1, properties.maxViewportDims + 1);
1998bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VIEWPORTS, &properties.maxViewports);
2008bf80f4bSopenharmony_ci    glGetIntegerv(GL_VIEWPORT_SUBPIXEL_BITS, &properties.viewportSubpixelBits);
2018bf80f4bSopenharmony_ci    glGetIntegerv(GL_VIEWPORT_BOUNDS_RANGE, &properties.viewportBoundsRange);
2028bf80f4bSopenharmony_ci
2038bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAJOR_VERSION, &properties.majorVersion);
2048bf80f4bSopenharmony_ci    glGetIntegerv(GL_MINOR_VERSION, &properties.minorVersion);
2058bf80f4bSopenharmony_ci    glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &properties.numProgramBinaryFormats);
2068bf80f4bSopenharmony_ci    glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &properties.numShaderBinaryFormats);
2078bf80f4bSopenharmony_ci
2088bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &properties.maxVertexAttribs);
2098bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &properties.maxVertexUniformComponents);
2108bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &properties.maxVertexUniformVectors);
2118bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &properties.maxVertexUniformBlocks);
2128bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &properties.maxVertexImageUniforms);
2138bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &properties.maxVertexOutputComponents);
2148bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &properties.maxVertexTextureImageUnits);
2158bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &properties.maxVertexAtomicCounterBuffers);
2168bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &properties.maxVertexAtomicCounters);
2178bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &properties.maxVertexShaderStorageBlocks);
2188bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, &properties.maxCombinedVertexUniformComponents);
2198bf80f4bSopenharmony_ci
2208bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &properties.maxFragmentUniformComponents);
2218bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &properties.maxFragmentUniformVectors);
2228bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &properties.maxFragmentUniformBlocks);
2238bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &properties.maxFragmentImageUniforms);
2248bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &properties.maxFragmentInputComponents);
2258bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &properties.maxFragmentImageUnits);
2268bf80f4bSopenharmony_ci    glGetIntegerv(GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET, &properties.minProgramTextureGatherOffset);
2278bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET, &properties.maxProgramTextureGatherOffset);
2288bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &properties.maxFragmentAtomicCounterBuffers);
2298bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &properties.maxFragmentAtomicCounters);
2308bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &properties.maxFragmentShaderStorageBlocks);
2318bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, &properties.maxCombinedFragmentUniformComponents);
2328bf80f4bSopenharmony_ci
2338bf80f4bSopenharmony_ci    glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, properties.maxComputeWorkGroupCount);
2348bf80f4bSopenharmony_ci    glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, properties.maxComputeWorkGroupCount + 1);
2358bf80f4bSopenharmony_ci    glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, properties.maxComputeWorkGroupCount + 2);
2368bf80f4bSopenharmony_ci    glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, properties.maxComputeWorkGroupSize);
2378bf80f4bSopenharmony_ci    glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, properties.maxComputeWorkGroupSize + 1);
2388bf80f4bSopenharmony_ci    glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, properties.maxComputeWorkGroupSize + 2);
2398bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &properties.maxComputeWorkGroupInvocations);
2408bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &properties.maxComputeUniformBlocks);
2418bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &properties.maxComputeImageUniforms);
2428bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &properties.maxComputeTextureImageUnits);
2438bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &properties.maxComputeAtomicCounterBuffers);
2448bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &properties.maxComputeAtomicCounters);
2458bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &properties.maxComputeSharedMemorySize);
2468bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_COMPONENTS, &properties.maxComputeUniformComponents);
2478bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &properties.maxComputeShaderStorageBlocks);
2488bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS, &properties.maxCombinedComputeUniformComponents);
2498bf80f4bSopenharmony_ci
2508bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &properties.maxTextureBufferSize);
2518bf80f4bSopenharmony_ci    glGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &properties.minProgramTexelOffset);
2528bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &properties.maxProgramTexelOffset);
2538bf80f4bSopenharmony_ci    glGetIntegerv(GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET, &properties.minProgramTextureGatherOffset);
2548bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET, &properties.maxProgramTextureGatherOffset);
2558bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &properties.maxUniformBufferBindings);
2568bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &properties.maxUniformBlockSize);
2578bf80f4bSopenharmony_ci    glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &properties.uniformBufferOffsetAlignment);
2588bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &properties.maxCombinedUniformBlocks);
2598bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &properties.maxUniformLocations);
2608bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &properties.maxVaryingComponents);
2618bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VARYING_FLOATS, &properties.maxVaryingFloats);
2628bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VARYING_VECTORS, &properties.maxVaryingVectors);
2638bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &properties.maxCombinedTextureImageUnits);
2648bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &properties.maxAtomicCounterBufferBindings);
2658bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, &properties.maxAtomicCounterBufferSize);
2668bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMBINED_ATOMIC_COUNTERS, &properties.maxCombinedAtomicCounters);
2678bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS, &properties.maxCombinedAtomicCounterBuffers);
2688bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &properties.maxShaderStorageBufferBindings);
2698bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &properties.maxShaderStorageBlockSize);
2708bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &properties.maxCombinedShaderStorageBlocks);
2718bf80f4bSopenharmony_ci    glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &properties.shaderStorageBufferOffsetAlignment);
2728bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_IMAGE_UNITS, &properties.maxImageUnits);
2738bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &properties.maxCombinedShaderOutputResources);
2748bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &properties.maxCombinedImageUniforms);
2758bf80f4bSopenharmony_ci
2768bf80f4bSopenharmony_ci    glGetIntegerv(GL_MIN_MAP_BUFFER_ALIGNMENT, &properties.minMapBufferAlignment);
2778bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &properties.maxVertexAttribRelativeOffset);
2788bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &properties.maxVertexAttribBindings);
2798bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &properties.maxVertexAttribStride);
2808bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &properties.maxElementsIndices);
2818bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &properties.maxElementsVertices);
2828bf80f4bSopenharmony_ci    glGetInteger64v(GL_MAX_ELEMENT_INDEX, &properties.maxElementIndex);
2838bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_CLIP_DISTANCES, &properties.maxClipDistances);
2848bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &properties.maxColorAttachments);
2858bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAMEBUFFER_WIDTH, &properties.maxFramebufferWidth);
2868bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAMEBUFFER_HEIGHT, &properties.maxFramebufferHeight);
2878bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAMEBUFFER_LAYERS, &properties.maxFramebufferLayers);
2888bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_FRAMEBUFFER_SAMPLES, &properties.maxFramebufferSamples);
2898bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &properties.maxSampleMaskWords);
2908bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_SAMPLES, &properties.maxSamples);
2918bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &properties.maxColorTextureSamples);
2928bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &properties.maxDepthTextureSamples);
2938bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &properties.maxIntegerSamples);
2948bf80f4bSopenharmony_ci    glGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &properties.maxServerWaitTimeout);
2958bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_DRAW_BUFFERS, &properties.maxDrawBuffers);
2968bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS, &properties.maxDualSourceDrawBuffers);
2978bf80f4bSopenharmony_ci    glGetIntegerv(GL_MAX_LABEL_LENGTH, &properties.maxLabelLength);
2988bf80f4bSopenharmony_ci}
2998bf80f4bSopenharmony_ci} // namespace
3008bf80f4bSopenharmony_ci
3018bf80f4bSopenharmony_ciuintptr_t WGLState::CreateSurface(uintptr_t window, uintptr_t instance) const noexcept
3028bf80f4bSopenharmony_ci{
3038bf80f4bSopenharmony_ci    return reinterpret_cast<uintptr_t>(GetDC(reinterpret_cast<HWND>(window)));
3048bf80f4bSopenharmony_ci}
3058bf80f4bSopenharmony_ci
3068bf80f4bSopenharmony_civoid WGLState::DestroySurface(uintptr_t surface) const noexcept
3078bf80f4bSopenharmony_ci{
3088bf80f4bSopenharmony_ci    auto deviceContext = reinterpret_cast<HDC>(surface);
3098bf80f4bSopenharmony_ci    HWND window = WindowFromDC(deviceContext);
3108bf80f4bSopenharmony_ci    ReleaseDC(window, deviceContext);
3118bf80f4bSopenharmony_ci}
3128bf80f4bSopenharmony_ci
3138bf80f4bSopenharmony_cibool WGLState::GetInformation(HDC surface, int32_t configId, GlesImplementation::SurfaceInfo& res) const
3148bf80f4bSopenharmony_ci{
3158bf80f4bSopenharmony_ci    if (configId > 0) {
3168bf80f4bSopenharmony_ci        int attribList[16] = { WGL_RED_BITS_ARB, /* 0 */
3178bf80f4bSopenharmony_ci            WGL_GREEN_BITS_ARB,                  /* 1 */
3188bf80f4bSopenharmony_ci            WGL_BLUE_BITS_ARB,                   /* 2 */
3198bf80f4bSopenharmony_ci            WGL_ALPHA_BITS_ARB,                  /* 3 */
3208bf80f4bSopenharmony_ci            WGL_DEPTH_BITS_ARB,                  /* 4 */
3218bf80f4bSopenharmony_ci            WGL_STENCIL_BITS_ARB,                /* 5 */
3228bf80f4bSopenharmony_ci            WGL_SAMPLES_ARB };                   /* 6 */
3238bf80f4bSopenharmony_ci        int32_t attribCnt = 7;
3248bf80f4bSopenharmony_ci        int32_t colorspaceIndex = 0;
3258bf80f4bSopenharmony_ci        int32_t srgbIndex = 0;
3268bf80f4bSopenharmony_ci        if (hasColorSpace_) {
3278bf80f4bSopenharmony_ci            colorspaceIndex = attribCnt;
3288bf80f4bSopenharmony_ci            attribList[attribCnt] = WGL_COLORSPACE_EXT;
3298bf80f4bSopenharmony_ci            attribCnt++;
3308bf80f4bSopenharmony_ci        }
3318bf80f4bSopenharmony_ci        if (hasSRGBFB_) {
3328bf80f4bSopenharmony_ci            srgbIndex = attribCnt;
3338bf80f4bSopenharmony_ci            attribList[attribCnt] = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
3348bf80f4bSopenharmony_ci            attribCnt++;
3358bf80f4bSopenharmony_ci        }
3368bf80f4bSopenharmony_ci        int values[16] {};
3378bf80f4bSopenharmony_ci        const bool ret =
3388bf80f4bSopenharmony_ci            wglGetPixelFormatAttribivARB(surface, configId, 0, static_cast<UINT>(attribCnt), attribList, values);
3398bf80f4bSopenharmony_ci        if (ret) {
3408bf80f4bSopenharmony_ci            res.configId = static_cast<uint32_t>(configId);
3418bf80f4bSopenharmony_ci            res.red_size = static_cast<uint32_t>(values[0]);
3428bf80f4bSopenharmony_ci            res.green_size = static_cast<uint32_t>(values[1]);
3438bf80f4bSopenharmony_ci            res.blue_size = static_cast<uint32_t>(values[2]);
3448bf80f4bSopenharmony_ci            res.alpha_size = static_cast<uint32_t>(values[3]);
3458bf80f4bSopenharmony_ci            res.depth_size = static_cast<uint32_t>(values[4]);
3468bf80f4bSopenharmony_ci            res.stencil_size = static_cast<uint32_t>(values[5]);
3478bf80f4bSopenharmony_ci            res.samples = static_cast<uint32_t>(values[6]);
3488bf80f4bSopenharmony_ci            res.srgb = false; // default to linear framebuffer
3498bf80f4bSopenharmony_ci            if (hasSRGBFB_) {
3508bf80f4bSopenharmony_ci                // is framebuffer srgb capable?
3518bf80f4bSopenharmony_ci                res.srgb = (values[srgbIndex] != 0) ? true : false;
3528bf80f4bSopenharmony_ci            }
3538bf80f4bSopenharmony_ci            if (hasColorSpace_) {
3548bf80f4bSopenharmony_ci                // has srgb colorspace?
3558bf80f4bSopenharmony_ci                res.srgb = static_cast<uint32_t>(values[colorspaceIndex]) == WGL_COLORSPACE_SRGB_EXT;
3568bf80f4bSopenharmony_ci            }
3578bf80f4bSopenharmony_ci            return true;
3588bf80f4bSopenharmony_ci        }
3598bf80f4bSopenharmony_ci    }
3608bf80f4bSopenharmony_ci    return false;
3618bf80f4bSopenharmony_ci}
3628bf80f4bSopenharmony_ci
3638bf80f4bSopenharmony_cibool WGLState::GetSurfaceInformation(HDC surface, GlesImplementation::SurfaceInfo& res) const
3648bf80f4bSopenharmony_ci{
3658bf80f4bSopenharmony_ci    RECT rcCli;
3668bf80f4bSopenharmony_ci    GetClientRect(WindowFromDC(surface), &rcCli);
3678bf80f4bSopenharmony_ci    // then you might have:
3688bf80f4bSopenharmony_ci    res.width = static_cast<uint32_t>(rcCli.right - rcCli.left);
3698bf80f4bSopenharmony_ci    res.height = static_cast<uint32_t>(rcCli.bottom - rcCli.top);
3708bf80f4bSopenharmony_ci    int32_t configId = GetPixelFormat(surface);
3718bf80f4bSopenharmony_ci    if (!configId) {
3728bf80f4bSopenharmony_ci        configId = GetPixelFormat(plat_.display);
3738bf80f4bSopenharmony_ci        if (configId) {
3748bf80f4bSopenharmony_ci            PIXELFORMATDESCRIPTOR pfd = { 0 };
3758bf80f4bSopenharmony_ci            DescribePixelFormat(plat_.display, configId, sizeof(pfd), &pfd);
3768bf80f4bSopenharmony_ci            SetPixelFormat(surface, configId, &pfd);
3778bf80f4bSopenharmony_ci        }
3788bf80f4bSopenharmony_ci    }
3798bf80f4bSopenharmony_ci    return GetInformation(surface, configId, res);
3808bf80f4bSopenharmony_ci}
3818bf80f4bSopenharmony_ci
3828bf80f4bSopenharmony_civoid WGLState::SwapBuffers(const SwapchainGLES& swapChain)
3838bf80f4bSopenharmony_ci{
3848bf80f4bSopenharmony_ci    auto& plat = swapChain.GetPlatformData();
3858bf80f4bSopenharmony_ci    ::SwapBuffers(reinterpret_cast<HDC>(plat.surface));
3868bf80f4bSopenharmony_ci}
3878bf80f4bSopenharmony_ci
3888bf80f4bSopenharmony_cibool WGLState::HasExtension(const string_view extension) const
3898bf80f4bSopenharmony_ci{
3908bf80f4bSopenharmony_ci    for (const auto& e : extensionList_) {
3918bf80f4bSopenharmony_ci        if (extension == e)
3928bf80f4bSopenharmony_ci            return true;
3938bf80f4bSopenharmony_ci    }
3948bf80f4bSopenharmony_ci    return false;
3958bf80f4bSopenharmony_ci}
3968bf80f4bSopenharmony_ci
3978bf80f4bSopenharmony_ciint WGLState::ChoosePixelFormat(HDC dc, const vector<int>& attributes)
3988bf80f4bSopenharmony_ci{
3998bf80f4bSopenharmony_ci    /*
4008bf80f4bSopenharmony_ci    Create a custom algorithm for choosing a best match, it seems wglChoosePixelFormatARB ignores some attributes.
4018bf80f4bSopenharmony_ci    Seems to completely ignore WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB for example */
4028bf80f4bSopenharmony_ci    int pixelFormats[64] = { -1 };
4038bf80f4bSopenharmony_ci    UINT numFormats = 0;
4048bf80f4bSopenharmony_ci    wglChoosePixelFormatARB(dc, attributes.data(), nullptr, 64, pixelFormats, &numFormats);
4058bf80f4bSopenharmony_ci    return pixelFormats[0];
4068bf80f4bSopenharmony_ci}
4078bf80f4bSopenharmony_ci
4088bf80f4bSopenharmony_cibool WGLState::IsValid()
4098bf80f4bSopenharmony_ci{
4108bf80f4bSopenharmony_ci    return plat_.context != nullptr;
4118bf80f4bSopenharmony_ci}
4128bf80f4bSopenharmony_ci
4138bf80f4bSopenharmony_civoid WGLState::CreateContext(DeviceCreateInfo const& createInfo)
4148bf80f4bSopenharmony_ci{
4158bf80f4bSopenharmony_ci    glModule_ = LoadLibrary("opengl32.dll");
4168bf80f4bSopenharmony_ci#define declareWGL(a, b)                                                                          \
4178bf80f4bSopenharmony_ci    if (b == nullptr) {                                                                           \
4188bf80f4bSopenharmony_ci        *(reinterpret_cast<void**>(&b)) = reinterpret_cast<void*>(GetProcAddress(glModule_, #b)); \
4198bf80f4bSopenharmony_ci    }
4208bf80f4bSopenharmony_ci    WGLFUNCS
4218bf80f4bSopenharmony_ci#undef declareWGL
4228bf80f4bSopenharmony_ci    auto backendConfig = static_cast<const BackendExtraGL*>(createInfo.backendConfiguration);
4238bf80f4bSopenharmony_ci
4248bf80f4bSopenharmony_ci    HGLRC sharedContext = nullptr;
4258bf80f4bSopenharmony_ci    if (backendConfig) {
4268bf80f4bSopenharmony_ci        plat_.mhWnd = backendConfig->window;
4278bf80f4bSopenharmony_ci        sharedContext = backendConfig->sharedContext;
4288bf80f4bSopenharmony_ci    }
4298bf80f4bSopenharmony_ci
4308bf80f4bSopenharmony_ci    DoDummy();
4318bf80f4bSopenharmony_ci
4328bf80f4bSopenharmony_ci    if (!plat_.mhWnd) {
4338bf80f4bSopenharmony_ci        plat_.mhWnd = GetActiveWindow();
4348bf80f4bSopenharmony_ci    }
4358bf80f4bSopenharmony_ci    plat_.display = GetDC(plat_.mhWnd);
4368bf80f4bSopenharmony_ci    if (wglGetExtensionsStringARB) {
4378bf80f4bSopenharmony_ci        extensions_ = wglGetExtensionsStringARB(plat_.display);
4388bf80f4bSopenharmony_ci    }
4398bf80f4bSopenharmony_ci
4408bf80f4bSopenharmony_ci    PLUGIN_LOG_V("WGL_EXTENSIONS: %s", extensions_.c_str());
4418bf80f4bSopenharmony_ci
4428bf80f4bSopenharmony_ci    ParseExtensions(extensions_, extensionList_);
4438bf80f4bSopenharmony_ci
4448bf80f4bSopenharmony_ci    hasSRGBFB_ = HasExtension("WGL_ARB_framebuffer_sRGB");
4458bf80f4bSopenharmony_ci    hasColorSpace_ = HasExtension("WGL_EXT_colorspace");
4468bf80f4bSopenharmony_ci
4478bf80f4bSopenharmony_ci    // construct attribute list dynamically
4488bf80f4bSopenharmony_ci    vector<int> attributes;
4498bf80f4bSopenharmony_ci    const size_t ATTRIBUTE_RESERVE = 20;       // reserve 20 attributes
4508bf80f4bSopenharmony_ci    attributes.reserve(ATTRIBUTE_RESERVE * 2); // 2 EGLints per attribute
4518bf80f4bSopenharmony_ci    const auto addAttribute = [&attributes](int a, int b) {
4528bf80f4bSopenharmony_ci        attributes.push_back(a);
4538bf80f4bSopenharmony_ci        attributes.push_back(b);
4548bf80f4bSopenharmony_ci    };
4558bf80f4bSopenharmony_ci    addAttribute(WGL_STEREO_ARB, GL_FALSE);
4568bf80f4bSopenharmony_ci    addAttribute(WGL_AUX_BUFFERS_ARB, 0);
4578bf80f4bSopenharmony_ci    addAttribute(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_EXT);
4588bf80f4bSopenharmony_ci    addAttribute(WGL_DRAW_TO_WINDOW_ARB, GL_TRUE);
4598bf80f4bSopenharmony_ci    addAttribute(WGL_SUPPORT_OPENGL_ARB, GL_TRUE);
4608bf80f4bSopenharmony_ci    addAttribute(WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB);
4618bf80f4bSopenharmony_ci    addAttribute(WGL_DOUBLE_BUFFER_ARB, GL_TRUE);
4628bf80f4bSopenharmony_ci    addAttribute(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB);
4638bf80f4bSopenharmony_ci    addAttribute(WGL_RED_BITS_ARB, 8);
4648bf80f4bSopenharmony_ci    addAttribute(WGL_GREEN_BITS_ARB, 8);
4658bf80f4bSopenharmony_ci    addAttribute(WGL_BLUE_BITS_ARB, 8);
4668bf80f4bSopenharmony_ci    if (hasSRGBFB_) {
4678bf80f4bSopenharmony_ci        addAttribute(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GL_TRUE); // srgb capable framebuffers only..
4688bf80f4bSopenharmony_ci    }
4698bf80f4bSopenharmony_ci    if (hasColorSpace_) {
4708bf80f4bSopenharmony_ci        addAttribute(WGL_COLORSPACE_EXT, WGL_COLORSPACE_SRGB_EXT); // prefer srgb..
4718bf80f4bSopenharmony_ci    }
4728bf80f4bSopenharmony_ci    if (backendConfig) {
4738bf80f4bSopenharmony_ci        if (backendConfig->MSAASamples > 1) {
4748bf80f4bSopenharmony_ci            addAttribute(WGL_SAMPLE_BUFFERS_ARB, 1);
4758bf80f4bSopenharmony_ci            addAttribute(WGL_SAMPLES_ARB, static_cast<int>(backendConfig->MSAASamples));
4768bf80f4bSopenharmony_ci        }
4778bf80f4bSopenharmony_ci        addAttribute(WGL_DEPTH_BITS_ARB, static_cast<int>(backendConfig->depthBits));
4788bf80f4bSopenharmony_ci        addAttribute(WGL_STENCIL_BITS_ARB, static_cast<int>(backendConfig->stencilBits));
4798bf80f4bSopenharmony_ci        addAttribute(WGL_ALPHA_BITS_ARB, static_cast<int>(backendConfig->alphaBits));
4808bf80f4bSopenharmony_ci    }
4818bf80f4bSopenharmony_ci    addAttribute(0, 0); // Terminate the list
4828bf80f4bSopenharmony_ci    const int pixelFormat = ChoosePixelFormat(plat_.display, attributes);
4838bf80f4bSopenharmony_ci    PIXELFORMATDESCRIPTOR pfd = { 0 };
4848bf80f4bSopenharmony_ci    DescribePixelFormat(plat_.display, pixelFormat, sizeof(pfd), &pfd);
4858bf80f4bSopenharmony_ci    SetPixelFormat(plat_.display, pixelFormat, &pfd);
4868bf80f4bSopenharmony_ci
4878bf80f4bSopenharmony_ci    plat_.context = wglCreateContextAttribsARB(plat_.display, sharedContext, WGL_ATTRIBS);
4888bf80f4bSopenharmony_ci
4898bf80f4bSopenharmony_ci    SaveContext();
4908bf80f4bSopenharmony_ci    SetContext(nullptr); // activate the context with the dummy PBuffer.
4918bf80f4bSopenharmony_ci}
4928bf80f4bSopenharmony_ci
4938bf80f4bSopenharmony_civoid WGLState::DestroyContext()
4948bf80f4bSopenharmony_ci{
4958bf80f4bSopenharmony_ci    wglMakeCurrent(nullptr, nullptr);
4968bf80f4bSopenharmony_ci    if (plat_.context) {
4978bf80f4bSopenharmony_ci        wglDeleteContext(plat_.context);
4988bf80f4bSopenharmony_ci    }
4998bf80f4bSopenharmony_ci    if (plat_.mhWnd && plat_.display) {
5008bf80f4bSopenharmony_ci        ReleaseDC(plat_.mhWnd, plat_.display);
5018bf80f4bSopenharmony_ci    }
5028bf80f4bSopenharmony_ci    FreeLibrary(glModule_);
5038bf80f4bSopenharmony_ci}
5048bf80f4bSopenharmony_ci
5058bf80f4bSopenharmony_civoid WGLState::GlInitialize()
5068bf80f4bSopenharmony_ci{
5078bf80f4bSopenharmony_ci#define declare(a, b)                                                                             \
5088bf80f4bSopenharmony_ci    if (b == nullptr) {                                                                           \
5098bf80f4bSopenharmony_ci        *(reinterpret_cast<void**>(&b)) = reinterpret_cast<void*>(wglGetProcAddress(#b));         \
5108bf80f4bSopenharmony_ci    }                                                                                             \
5118bf80f4bSopenharmony_ci    if (b == nullptr) {                                                                           \
5128bf80f4bSopenharmony_ci        *(reinterpret_cast<void**>(&b)) = reinterpret_cast<void*>(GetProcAddress(glModule_, #b)); \
5138bf80f4bSopenharmony_ci    }                                                                                             \
5148bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(b, "Missing %s\n", #b)
5158bf80f4bSopenharmony_ci
5168bf80f4bSopenharmony_ci#include "gles/gl_functions.h"
5178bf80f4bSopenharmony_ci#undef declare
5188bf80f4bSopenharmony_ci
5198bf80f4bSopenharmony_ci    plat_.deviceName = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
5208bf80f4bSopenharmony_ci    plat_.driverVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
5218bf80f4bSopenharmony_ci    BASE_NS::ClearToValue(
5228bf80f4bSopenharmony_ci        &plat_.deviceProperties, sizeof(plat_.deviceProperties), 0x00, sizeof(plat_.deviceProperties));
5238bf80f4bSopenharmony_ci    FillProperties(plat_.deviceProperties);
5248bf80f4bSopenharmony_ci
5258bf80f4bSopenharmony_ci    SetSwapInterval(1); // default to vsync enabled.
5268bf80f4bSopenharmony_ci
5278bf80f4bSopenharmony_ci    glEnable(GL_FRAMEBUFFER_SRGB);
5288bf80f4bSopenharmony_ci}
5298bf80f4bSopenharmony_ci
5308bf80f4bSopenharmony_civoid WGLState::SetSwapInterval(uint32_t aInterval)
5318bf80f4bSopenharmony_ci{
5328bf80f4bSopenharmony_ci    if (wglSwapIntervalEXT) {
5338bf80f4bSopenharmony_ci        wglSwapIntervalEXT(static_cast<int>(aInterval));
5348bf80f4bSopenharmony_ci    }
5358bf80f4bSopenharmony_ci}
5368bf80f4bSopenharmony_ci
5378bf80f4bSopenharmony_civoid* WGLState::ErrorFilter() const
5388bf80f4bSopenharmony_ci{
5398bf80f4bSopenharmony_ci    return reinterpret_cast<void*>(FilterError);
5408bf80f4bSopenharmony_ci}
5418bf80f4bSopenharmony_ci
5428bf80f4bSopenharmony_civoid WGLState::SaveContext()
5438bf80f4bSopenharmony_ci{
5448bf80f4bSopenharmony_ci    PLUGIN_ASSERT(!oldIsSet_);
5458bf80f4bSopenharmony_ci    oldIsSet_ = true;
5468bf80f4bSopenharmony_ci    oldContext_.context = wglGetCurrentContext();
5478bf80f4bSopenharmony_ci    oldContext_.display = wglGetCurrentDC();
5488bf80f4bSopenharmony_ci}
5498bf80f4bSopenharmony_ci
5508bf80f4bSopenharmony_civoid WGLState::SetContext(const SwapchainGLES* swapChain)
5518bf80f4bSopenharmony_ci{
5528bf80f4bSopenharmony_ci    if (swapChain == nullptr) {
5538bf80f4bSopenharmony_ci        wglMakeCurrent(plat_.display, plat_.context);
5548bf80f4bSopenharmony_ci    } else {
5558bf80f4bSopenharmony_ci        const auto& plat = swapChain->GetPlatformData();
5568bf80f4bSopenharmony_ci        if (plat.surface == 0) {
5578bf80f4bSopenharmony_ci            const uint64_t swapLoc = reinterpret_cast<uint64_t>(swapChain);
5588bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
5598bf80f4bSopenharmony_ci            PLUGIN_LOG_ONCE_E(
5608bf80f4bSopenharmony_ci                "gl_invalid_surface" + BASE_NS::to_string(swapLoc),
5618bf80f4bSopenharmony_ci                    "Invalid swapchain surface for MakeCurrent using default");
5628bf80f4bSopenharmony_ci#endif
5638bf80f4bSopenharmony_ci            wglMakeCurrent(plat_.display, plat_.context);
5648bf80f4bSopenharmony_ci        } else {
5658bf80f4bSopenharmony_ci            auto display = reinterpret_cast<HDC>(plat.surface);
5668bf80f4bSopenharmony_ci            auto context = plat_.context;
5678bf80f4bSopenharmony_ci            if (plat_.context == 0) {
5688bf80f4bSopenharmony_ci                PLUGIN_LOG_E("Invalid context for MakeCurrent");
5698bf80f4bSopenharmony_ci            }
5708bf80f4bSopenharmony_ci            wglMakeCurrent(display, context);
5718bf80f4bSopenharmony_ci        }
5728bf80f4bSopenharmony_ci
5738bf80f4bSopenharmony_ci        if (vSync_ != plat.vsync) {
5748bf80f4bSopenharmony_ci            vSync_ = plat.vsync;
5758bf80f4bSopenharmony_ci            SetSwapInterval(plat.vsync ? 1u : 0u);
5768bf80f4bSopenharmony_ci        }
5778bf80f4bSopenharmony_ci    }
5788bf80f4bSopenharmony_ci}
5798bf80f4bSopenharmony_ci
5808bf80f4bSopenharmony_civoid WGLState::RestoreContext()
5818bf80f4bSopenharmony_ci{
5828bf80f4bSopenharmony_ci    PLUGIN_ASSERT(oldIsSet_);
5838bf80f4bSopenharmony_ci    wglMakeCurrent(oldContext_.display, oldContext_.context);
5848bf80f4bSopenharmony_ci    oldIsSet_ = false;
5858bf80f4bSopenharmony_ci}
5868bf80f4bSopenharmony_ci
5878bf80f4bSopenharmony_ciconst DevicePlatformData& WGLState::GetPlatformData() const
5888bf80f4bSopenharmony_ci{
5898bf80f4bSopenharmony_ci    return plat_;
5908bf80f4bSopenharmony_ci}
5918bf80f4bSopenharmony_ci
5928bf80f4bSopenharmony_ci} // namespace WGLHelpers
5938bf80f4bSopenharmony_ciRENDER_END_NAMESPACE()
5948bf80f4bSopenharmony_ci#endif