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#include "device_gles.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <algorithm>
198bf80f4bSopenharmony_ci
208bf80f4bSopenharmony_ci#include <base/containers/string.h>
218bf80f4bSopenharmony_ci#include <base/math/vector.h>
228bf80f4bSopenharmony_ci#include <base/util/compile_time_hashes.h>
238bf80f4bSopenharmony_ci#include <render/namespace.h>
248bf80f4bSopenharmony_ci
258bf80f4bSopenharmony_ci#include "device/gpu_program_util.h"
268bf80f4bSopenharmony_ci#include "device/gpu_resource_manager.h"
278bf80f4bSopenharmony_ci#include "device/shader_manager.h"
288bf80f4bSopenharmony_ci#include "device/shader_module.h"
298bf80f4bSopenharmony_ci#include "gles/gl_functions.h"
308bf80f4bSopenharmony_ci#include "gles/gpu_buffer_gles.h"
318bf80f4bSopenharmony_ci#include "gles/gpu_image_gles.h"
328bf80f4bSopenharmony_ci#include "gles/gpu_program_gles.h"
338bf80f4bSopenharmony_ci#include "gles/gpu_sampler_gles.h"
348bf80f4bSopenharmony_ci#include "gles/gpu_semaphore_gles.h"
358bf80f4bSopenharmony_ci#include "gles/node_context_descriptor_set_manager_gles.h"
368bf80f4bSopenharmony_ci#include "gles/node_context_pool_manager_gles.h"
378bf80f4bSopenharmony_ci#include "gles/pipeline_state_object_gles.h"
388bf80f4bSopenharmony_ci#include "gles/render_backend_gles.h"
398bf80f4bSopenharmony_ci#include "gles/render_frame_sync_gles.h"
408bf80f4bSopenharmony_ci#include "gles/shader_module_gles.h"
418bf80f4bSopenharmony_ci#include "gles/swapchain_gles.h"
428bf80f4bSopenharmony_ci#include "util/log.h"
438bf80f4bSopenharmony_ci
448bf80f4bSopenharmony_ciusing namespace BASE_NS;
458bf80f4bSopenharmony_ci
468bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE()
478bf80f4bSopenharmony_cinamespace {
488bf80f4bSopenharmony_ci// Make all temporary binds to unit GL_TEXTURE15. (should use the last available unit, so as to least affect actual
498bf80f4bSopenharmony_ci// usage) "The number of texture units is implementation-dependent, but must be at least 32. texture must be one of
508bf80f4bSopenharmony_ci// GL_TEXTUREi, where i ranges from zero to the value of GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS minus one." Currently our
518bf80f4bSopenharmony_ci// there is an implementation limit in our resource caching which limits it to 16... (this is why we use 16 instead of
528bf80f4bSopenharmony_ci// 32)
538bf80f4bSopenharmony_ciconstexpr const uint32_t TEMP_BIND_UNIT = 15;
548bf80f4bSopenharmony_ciconstexpr const string_view EXT_BUFFER_STORAGE = "GL_EXT_buffer_storage";
558bf80f4bSopenharmony_ci#if RENDER_GL_DEBUG
568bf80f4bSopenharmony_ci#define DUMP(a)                       \
578bf80f4bSopenharmony_ci    {                                 \
588bf80f4bSopenharmony_ci        GLint val;                    \
598bf80f4bSopenharmony_ci        glGetIntegerv(a, &val);       \
608bf80f4bSopenharmony_ci        PLUGIN_LOG_V(#a ": %d", val); \
618bf80f4bSopenharmony_ci    }
628bf80f4bSopenharmony_ci
638bf80f4bSopenharmony_ci#define DUMP_INDEX(a, index)                     \
648bf80f4bSopenharmony_ci    {                                            \
658bf80f4bSopenharmony_ci        GLint val;                               \
668bf80f4bSopenharmony_ci        glGetIntegeri_v(a, index, &val);         \
678bf80f4bSopenharmony_ci        PLUGIN_LOG_V(#a "[%d]: %d", index, val); \
688bf80f4bSopenharmony_ci    }
698bf80f4bSopenharmony_ci
708bf80f4bSopenharmony_cistatic bool (*filterErrorFunc)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
718bf80f4bSopenharmony_ci    const string_view message, const void* userParam) noexcept = nullptr;
728bf80f4bSopenharmony_ci
738bf80f4bSopenharmony_cistatic auto SourceName(GLenum source)
748bf80f4bSopenharmony_ci{
758bf80f4bSopenharmony_ci    switch (source) {
768bf80f4bSopenharmony_ci        case GL_DEBUG_SOURCE_API:
778bf80f4bSopenharmony_ci            return "GL_DEBUG_SOURCE_API";
788bf80f4bSopenharmony_ci        case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
798bf80f4bSopenharmony_ci            return "GL_DEBUG_SOURCE_WINDOW_SYSTEM";
808bf80f4bSopenharmony_ci        case GL_DEBUG_SOURCE_SHADER_COMPILER:
818bf80f4bSopenharmony_ci            return "GL_DEBUG_SOURCE_SHADER_COMPILER";
828bf80f4bSopenharmony_ci        case GL_DEBUG_SOURCE_THIRD_PARTY:
838bf80f4bSopenharmony_ci            return "GL_DEBUG_SOURCE_THIRD_PARTY";
848bf80f4bSopenharmony_ci        case GL_DEBUG_SOURCE_APPLICATION:
858bf80f4bSopenharmony_ci            return "GL_DEBUG_SOURCE_APPLICATION";
868bf80f4bSopenharmony_ci        case GL_DEBUG_SOURCE_OTHER:
878bf80f4bSopenharmony_ci            return "GL_DEBUG_SOURCE_OTHER";
888bf80f4bSopenharmony_ci
898bf80f4bSopenharmony_ci        default:
908bf80f4bSopenharmony_ci            break;
918bf80f4bSopenharmony_ci    }
928bf80f4bSopenharmony_ci    return "UNKNOWN";
938bf80f4bSopenharmony_ci}
948bf80f4bSopenharmony_ci
958bf80f4bSopenharmony_cistatic auto TypeName(GLenum type)
968bf80f4bSopenharmony_ci{
978bf80f4bSopenharmony_ci    switch (type) {
988bf80f4bSopenharmony_ci        case GL_DEBUG_TYPE_ERROR:
998bf80f4bSopenharmony_ci            return "GL_DEBUG_TYPE_ERROR";
1008bf80f4bSopenharmony_ci        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1018bf80f4bSopenharmony_ci            return "GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR";
1028bf80f4bSopenharmony_ci        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1038bf80f4bSopenharmony_ci            return "GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR";
1048bf80f4bSopenharmony_ci        case GL_DEBUG_TYPE_PORTABILITY:
1058bf80f4bSopenharmony_ci            return "GL_DEBUG_TYPE_PORTABILITY";
1068bf80f4bSopenharmony_ci        case GL_DEBUG_TYPE_PERFORMANCE:
1078bf80f4bSopenharmony_ci            return "GL_DEBUG_TYPE_PERFORMANCE";
1088bf80f4bSopenharmony_ci        case GL_DEBUG_TYPE_MARKER:
1098bf80f4bSopenharmony_ci            return "GL_DEBUG_TYPE_MARKER";
1108bf80f4bSopenharmony_ci        case GL_DEBUG_TYPE_PUSH_GROUP:
1118bf80f4bSopenharmony_ci            return "GL_DEBUG_TYPE_PUSH_GROUP";
1128bf80f4bSopenharmony_ci        case GL_DEBUG_TYPE_POP_GROUP:
1138bf80f4bSopenharmony_ci            return "GL_DEBUG_TYPE_POP_GROUP";
1148bf80f4bSopenharmony_ci        case GL_DEBUG_TYPE_OTHER:
1158bf80f4bSopenharmony_ci            return "GL_DEBUG_TYPE_OTHER";
1168bf80f4bSopenharmony_ci
1178bf80f4bSopenharmony_ci        default:
1188bf80f4bSopenharmony_ci            break;
1198bf80f4bSopenharmony_ci    }
1208bf80f4bSopenharmony_ci    return "UNKNOWN";
1218bf80f4bSopenharmony_ci}
1228bf80f4bSopenharmony_ci
1238bf80f4bSopenharmony_cistatic auto SeverityName(GLenum severity)
1248bf80f4bSopenharmony_ci{
1258bf80f4bSopenharmony_ci    switch (severity) {
1268bf80f4bSopenharmony_ci        case GL_DEBUG_SEVERITY_LOW:
1278bf80f4bSopenharmony_ci            return "GL_DEBUG_SEVERITY_LOW";
1288bf80f4bSopenharmony_ci        case GL_DEBUG_SEVERITY_MEDIUM:
1298bf80f4bSopenharmony_ci            return "GL_DEBUG_SEVERITY_MEDIUM";
1308bf80f4bSopenharmony_ci        case GL_DEBUG_SEVERITY_HIGH:
1318bf80f4bSopenharmony_ci            return "GL_DEBUG_SEVERITY_HIGH";
1328bf80f4bSopenharmony_ci        case GL_DEBUG_SEVERITY_NOTIFICATION:
1338bf80f4bSopenharmony_ci            return "GL_DEBUG_SEVERITY_NOTIFICATION";
1348bf80f4bSopenharmony_ci
1358bf80f4bSopenharmony_ci        default:
1368bf80f4bSopenharmony_ci            break;
1378bf80f4bSopenharmony_ci    }
1388bf80f4bSopenharmony_ci    return "UNKNOWN";
1398bf80f4bSopenharmony_ci}
1408bf80f4bSopenharmony_ci
1418bf80f4bSopenharmony_ci#ifndef APIENTRY
1428bf80f4bSopenharmony_ci#define APIENTRY
1438bf80f4bSopenharmony_ci#endif
1448bf80f4bSopenharmony_cistatic void APIENTRY OnGlError(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
1458bf80f4bSopenharmony_ci    const GLchar* message, const void* userParam) noexcept
1468bf80f4bSopenharmony_ci{
1478bf80f4bSopenharmony_ci    if (type == GL_DEBUG_TYPE_PUSH_GROUP) {
1488bf80f4bSopenharmony_ci        return;
1498bf80f4bSopenharmony_ci    } else if (type == GL_DEBUG_TYPE_POP_GROUP) {
1508bf80f4bSopenharmony_ci        return;
1518bf80f4bSopenharmony_ci    } else if ((filterErrorFunc) && (filterErrorFunc(source, type, id, severity, length, message, userParam))) {
1528bf80f4bSopenharmony_ci        return;
1538bf80f4bSopenharmony_ci    } else if (type == GL_DEBUG_TYPE_ERROR) {
1548bf80f4bSopenharmony_ci        PLUGIN_LOG_E("---------------------opengl-callback-start------------\n"
1558bf80f4bSopenharmony_ci                     "source: %s\n"
1568bf80f4bSopenharmony_ci                     "type: %s\n"
1578bf80f4bSopenharmony_ci                     "id: %u\n"
1588bf80f4bSopenharmony_ci                     "severity: %s\n"
1598bf80f4bSopenharmony_ci                     "message: %s\n"
1608bf80f4bSopenharmony_ci                     "---------------------opengl-callback-end--------------\n",
1618bf80f4bSopenharmony_ci            SourceName(source), TypeName(type), id, SeverityName(severity), message);
1628bf80f4bSopenharmony_ci    } else {
1638bf80f4bSopenharmony_ci        PLUGIN_LOG_D("---------------------opengl-callback-start------------\n"
1648bf80f4bSopenharmony_ci                     "source: %s\n"
1658bf80f4bSopenharmony_ci                     "type: %s\n"
1668bf80f4bSopenharmony_ci                     "id: %u\n"
1678bf80f4bSopenharmony_ci                     "severity: %s\n"
1688bf80f4bSopenharmony_ci                     "message: %s\n"
1698bf80f4bSopenharmony_ci                     "---------------------opengl-callback-end--------------\n",
1708bf80f4bSopenharmony_ci            SourceName(source), TypeName(type), id, SeverityName(severity), message);
1718bf80f4bSopenharmony_ci    }
1728bf80f4bSopenharmony_ci}
1738bf80f4bSopenharmony_ci#else
1748bf80f4bSopenharmony_ci#define DUMP(a)
1758bf80f4bSopenharmony_ci#define DUMP_INDEX(a, index)
1768bf80f4bSopenharmony_ci#endif
1778bf80f4bSopenharmony_ci
1788bf80f4bSopenharmony_cistruct FormatFeatures {
1798bf80f4bSopenharmony_ci    GLenum internalFormat;
1808bf80f4bSopenharmony_ci    FormatFeatureFlags flags;
1818bf80f4bSopenharmony_ci};
1828bf80f4bSopenharmony_ci
1838bf80f4bSopenharmony_ci// image store and atomic operations seem to go hand in hand
1848bf80f4bSopenharmony_cistatic constexpr const FormatFeatureFlags ATOMIC_STORE =
1858bf80f4bSopenharmony_ci    CORE_FORMAT_FEATURE_STORAGE_IMAGE_BIT | CORE_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
1868bf80f4bSopenharmony_ci// no writable texture buffers in gl?
1878bf80f4bSopenharmony_cistatic constexpr const FormatFeatureFlags TEXEL_BUF = CORE_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
1888bf80f4bSopenharmony_ci// color renderable
1898bf80f4bSopenharmony_cistatic constexpr const FormatFeatureFlags CR = CORE_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1908bf80f4bSopenharmony_ci// texture filterable
1918bf80f4bSopenharmony_cistatic constexpr const FormatFeatureFlags TF = CORE_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
1928bf80f4bSopenharmony_ci//  required texture formats. assume can be sampled, and transfered to/from
1938bf80f4bSopenharmony_cistatic constexpr const FormatFeatureFlags TEX =
1948bf80f4bSopenharmony_ci    CORE_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | CORE_FORMAT_FEATURE_TRANSFER_SRC_BIT | CORE_FORMAT_FEATURE_TRANSFER_SRC_BIT;
1958bf80f4bSopenharmony_ci// required depth format
1968bf80f4bSopenharmony_cistatic constexpr const FormatFeatureFlags DS = CORE_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | TEX | TF;
1978bf80f4bSopenharmony_ci
1988bf80f4bSopenharmony_cistatic constexpr const FormatFeatureFlags TF_TEX = TF | TEX;
1998bf80f4bSopenharmony_ci#if RENDER_HAS_GL_BACKEND
2008bf80f4bSopenharmony_cistatic constexpr const FormatFeatureFlags CR_TEX = CR | TEX; // color renderable, texture format
2018bf80f4bSopenharmony_ci#endif
2028bf80f4bSopenharmony_cistatic constexpr const FormatFeatureFlags CR_REND_TEX = CR | TEX; // color renderable, renderbuffer, texture format
2038bf80f4bSopenharmony_ci#if RENDER_HAS_GLES_BACKEND
2048bf80f4bSopenharmony_cistatic constexpr const FormatFeatureFlags CR_TF_REND_TEX = CR | TF | TEX;
2058bf80f4bSopenharmony_ci#endif
2068bf80f4bSopenharmony_ci
2078bf80f4bSopenharmony_cistatic constexpr const FormatFeatures IMAGE_FORMAT_FEATURES[] = {
2088bf80f4bSopenharmony_ci#if RENDER_HAS_GL_BACKEND
2098bf80f4bSopenharmony_ci    { GL_R8, CR_TEX | ATOMIC_STORE | TEXEL_BUF },
2108bf80f4bSopenharmony_ci    { GL_R8_SNORM, CR_TEX | ATOMIC_STORE },
2118bf80f4bSopenharmony_ci    { GL_R16, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2128bf80f4bSopenharmony_ci    { GL_R16_SNORM, CR_TEX | ATOMIC_STORE },
2138bf80f4bSopenharmony_ci    { GL_RG8, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2148bf80f4bSopenharmony_ci    { GL_RG8_SNORM, CR_TEX | ATOMIC_STORE },
2158bf80f4bSopenharmony_ci    { GL_RG16, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2168bf80f4bSopenharmony_ci    { GL_RG16_SNORM, CR_TEX | ATOMIC_STORE },
2178bf80f4bSopenharmony_ci    // R3_G3_B2 not in base format
2188bf80f4bSopenharmony_ci    { GL_RGB4, CR_TEX },
2198bf80f4bSopenharmony_ci    // RGB5 not in base format
2208bf80f4bSopenharmony_ci    { GL_RGB565, CR_REND_TEX },
2218bf80f4bSopenharmony_ci    { GL_RGB8, CR_TEX },
2228bf80f4bSopenharmony_ci    { GL_RGB8_SNORM, CR_TEX },
2238bf80f4bSopenharmony_ci    { GL_RGB10, CR_TEX },
2248bf80f4bSopenharmony_ci    { GL_RGB12, CR_TEX },
2258bf80f4bSopenharmony_ci    { GL_RGB16, CR_TEX },
2268bf80f4bSopenharmony_ci    { GL_RGB16_SNORM, CR_TEX },
2278bf80f4bSopenharmony_ci    // RGBA2 not in base format
2288bf80f4bSopenharmony_ci    { GL_RGBA4, CR_REND_TEX },
2298bf80f4bSopenharmony_ci    { GL_RGB5_A1, CR_REND_TEX },
2308bf80f4bSopenharmony_ci    { GL_RGBA8, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2318bf80f4bSopenharmony_ci    { GL_RGBA8_SNORM, CR_TEX | ATOMIC_STORE },
2328bf80f4bSopenharmony_ci    { GL_RGB10_A2, CR_REND_TEX | ATOMIC_STORE },
2338bf80f4bSopenharmony_ci    { GL_RGB10_A2UI, CR_REND_TEX | ATOMIC_STORE },
2348bf80f4bSopenharmony_ci    { GL_RGBA12, CR_TEX },
2358bf80f4bSopenharmony_ci    { GL_RGBA16, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2368bf80f4bSopenharmony_ci    { GL_RGBA16_SNORM, CR_TEX | ATOMIC_STORE },
2378bf80f4bSopenharmony_ci    { GL_SRGB8, CR_TEX },
2388bf80f4bSopenharmony_ci    { GL_SRGB8_ALPHA8, CR_REND_TEX },
2398bf80f4bSopenharmony_ci    { GL_R16F, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2408bf80f4bSopenharmony_ci    { GL_RG16F, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2418bf80f4bSopenharmony_ci    { GL_RGB16F, CR_TEX },
2428bf80f4bSopenharmony_ci    { GL_RGBA16F, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2438bf80f4bSopenharmony_ci    { GL_R32F, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2448bf80f4bSopenharmony_ci    { GL_RG32F, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2458bf80f4bSopenharmony_ci    { GL_RGB32F, CR_TEX | TEXEL_BUF | TEXEL_BUF },
2468bf80f4bSopenharmony_ci    { GL_RGBA32F, CR_REND_TEX | ATOMIC_STORE },
2478bf80f4bSopenharmony_ci    { GL_R11F_G11F_B10F, CR_REND_TEX | ATOMIC_STORE },
2488bf80f4bSopenharmony_ci    { GL_RGB9_E5, TEX },
2498bf80f4bSopenharmony_ci    { GL_R8I, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2508bf80f4bSopenharmony_ci    { GL_R8UI, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2518bf80f4bSopenharmony_ci    { GL_R16I, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2528bf80f4bSopenharmony_ci    { GL_R16UI, CR_REND_TEX | TEXEL_BUF },
2538bf80f4bSopenharmony_ci    { GL_R32I, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2548bf80f4bSopenharmony_ci    { GL_R32UI, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2558bf80f4bSopenharmony_ci    { GL_RG8I, CR_REND_TEX | TEXEL_BUF },
2568bf80f4bSopenharmony_ci    { GL_RG8UI, CR_REND_TEX | TEXEL_BUF },
2578bf80f4bSopenharmony_ci    { GL_RG16I, CR_REND_TEX | TEXEL_BUF },
2588bf80f4bSopenharmony_ci    { GL_RG16UI, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2598bf80f4bSopenharmony_ci    { GL_RG32I, CR_REND_TEX | TEXEL_BUF },
2608bf80f4bSopenharmony_ci    { GL_RG32UI, CR_REND_TEX | TEXEL_BUF },
2618bf80f4bSopenharmony_ci    { GL_RGB8I, CR_TEX },
2628bf80f4bSopenharmony_ci    { GL_RGB8UI, CR_TEX },
2638bf80f4bSopenharmony_ci    { GL_RGB16I, CR_TEX },
2648bf80f4bSopenharmony_ci    { GL_RGB16UI, CR_TEX },
2658bf80f4bSopenharmony_ci    { GL_RGB32I, CR_TEX | TEXEL_BUF },
2668bf80f4bSopenharmony_ci    { GL_RGB32UI, CR_TEX | ATOMIC_STORE | TEXEL_BUF },
2678bf80f4bSopenharmony_ci    { GL_RGBA8I, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2688bf80f4bSopenharmony_ci    { GL_RGBA8UI, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2698bf80f4bSopenharmony_ci    { GL_RGBA16I, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2708bf80f4bSopenharmony_ci    { GL_RGBA16UI, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2718bf80f4bSopenharmony_ci    { GL_RGBA32I, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2728bf80f4bSopenharmony_ci    { GL_RGBA32UI, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2738bf80f4bSopenharmony_ci#elif RENDER_HAS_GLES_BACKEND
2748bf80f4bSopenharmony_ci    { GL_R8, CR_TF_REND_TEX | TEXEL_BUF },
2758bf80f4bSopenharmony_ci    { GL_R8_SNORM, TF_TEX },
2768bf80f4bSopenharmony_ci    { GL_RG8, CR_TF_REND_TEX | TEXEL_BUF },
2778bf80f4bSopenharmony_ci    { GL_RG8_SNORM, TF_TEX },
2788bf80f4bSopenharmony_ci    { GL_RGB8, CR_TF_REND_TEX },
2798bf80f4bSopenharmony_ci    { GL_RGB8_SNORM, TF_TEX },
2808bf80f4bSopenharmony_ci    { GL_RGB565, CR_TF_REND_TEX },
2818bf80f4bSopenharmony_ci    { GL_RGBA4, CR_TF_REND_TEX },
2828bf80f4bSopenharmony_ci    { GL_RGB5_A1, CR_TF_REND_TEX },
2838bf80f4bSopenharmony_ci    { GL_RGBA8, CR_TF_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2848bf80f4bSopenharmony_ci    { GL_RGBA8_SNORM, TF_TEX | ATOMIC_STORE },
2858bf80f4bSopenharmony_ci    { GL_RGB10_A2, CR_TF_REND_TEX },
2868bf80f4bSopenharmony_ci    { GL_RGB10_A2UI, CR_REND_TEX },
2878bf80f4bSopenharmony_ci    { GL_SRGB8, TF_TEX },
2888bf80f4bSopenharmony_ci    { GL_SRGB8_ALPHA8, CR_TF_REND_TEX },
2898bf80f4bSopenharmony_ci    { GL_R16F, CR_TF_REND_TEX | TEXEL_BUF },
2908bf80f4bSopenharmony_ci    { GL_RG16F, CR_TF_REND_TEX | TEXEL_BUF },
2918bf80f4bSopenharmony_ci    { GL_RGB16F, TF_TEX },
2928bf80f4bSopenharmony_ci    { GL_RGBA16F, CR_TF_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2938bf80f4bSopenharmony_ci    { GL_R32F, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2948bf80f4bSopenharmony_ci    { GL_RG32F, CR_REND_TEX | TEXEL_BUF },
2958bf80f4bSopenharmony_ci    { GL_RGB32F, TEX | TEXEL_BUF },
2968bf80f4bSopenharmony_ci    { GL_RGBA32F, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
2978bf80f4bSopenharmony_ci    { GL_R11F_G11F_B10F, CR_TF_REND_TEX },
2988bf80f4bSopenharmony_ci    { GL_RGB9_E5, TF_TEX },
2998bf80f4bSopenharmony_ci    { GL_R8I, CR_REND_TEX | TEXEL_BUF },
3008bf80f4bSopenharmony_ci    { GL_R8UI, CR_REND_TEX | TEXEL_BUF },
3018bf80f4bSopenharmony_ci    { GL_R16I, CR_REND_TEX | TEXEL_BUF },
3028bf80f4bSopenharmony_ci    { GL_R16UI, CR_REND_TEX | TEXEL_BUF },
3038bf80f4bSopenharmony_ci    { GL_R32I, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
3048bf80f4bSopenharmony_ci    { GL_R32UI, CR_REND_TEX | TEXEL_BUF },
3058bf80f4bSopenharmony_ci    { GL_RG8I, CR_REND_TEX | TEXEL_BUF },
3068bf80f4bSopenharmony_ci    { GL_RG8UI, CR_REND_TEX | TEXEL_BUF },
3078bf80f4bSopenharmony_ci    { GL_RG16I, CR_REND_TEX | TEXEL_BUF },
3088bf80f4bSopenharmony_ci    { GL_RG16UI, CR_REND_TEX | TEXEL_BUF },
3098bf80f4bSopenharmony_ci    { GL_RG32I, CR_REND_TEX | TEXEL_BUF },
3108bf80f4bSopenharmony_ci    { GL_RG32UI, CR_REND_TEX | TEXEL_BUF },
3118bf80f4bSopenharmony_ci    { GL_RGB8I, TEX },
3128bf80f4bSopenharmony_ci    { GL_RGB8UI, TEX },
3138bf80f4bSopenharmony_ci    { GL_RGB16I, TEX },
3148bf80f4bSopenharmony_ci    { GL_RGB16UI, TEX },
3158bf80f4bSopenharmony_ci    { GL_RGB32I, TEX | TEXEL_BUF },
3168bf80f4bSopenharmony_ci    { GL_RGB32UI, TEX | TEXEL_BUF },
3178bf80f4bSopenharmony_ci    { GL_RGBA8I, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
3188bf80f4bSopenharmony_ci    { GL_RGBA8UI, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
3198bf80f4bSopenharmony_ci    { GL_RGBA16I, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
3208bf80f4bSopenharmony_ci    { GL_RGBA16UI, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
3218bf80f4bSopenharmony_ci    { GL_RGBA32I, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
3228bf80f4bSopenharmony_ci    { GL_RGBA32UI, CR_REND_TEX | ATOMIC_STORE | TEXEL_BUF },
3238bf80f4bSopenharmony_ci#endif
3248bf80f4bSopenharmony_ci    { GL_DEPTH_COMPONENT16, DS },
3258bf80f4bSopenharmony_ci    { GL_DEPTH_COMPONENT24, DS },
3268bf80f4bSopenharmony_ci    { GL_DEPTH_COMPONENT32F, DS },
3278bf80f4bSopenharmony_ci    { GL_DEPTH24_STENCIL8, DS },
3288bf80f4bSopenharmony_ci    { GL_DEPTH32F_STENCIL8, DS },
3298bf80f4bSopenharmony_ci    { GL_STENCIL_INDEX8, DS },
3308bf80f4bSopenharmony_ci
3318bf80f4bSopenharmony_ci#if (defined(GL_EXT_texture_sRGB_R8) && (GL_EXT_texture_sRGB_R8))
3328bf80f4bSopenharmony_ci    { GL_SR8_EXT, TF_TEX },
3338bf80f4bSopenharmony_ci#endif
3348bf80f4bSopenharmony_ci
3358bf80f4bSopenharmony_ci#if (defined(GL_EXT_texture_sRGB_RG8) && (GL_EXT_texture_sRGB_RG8))
3368bf80f4bSopenharmony_ci    { GL_SRG8_EXT, TF_TEX },
3378bf80f4bSopenharmony_ci#endif
3388bf80f4bSopenharmony_ci
3398bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_format_BGRA8888) && (GL_EXT_texture_format_BGRA8888)
3408bf80f4bSopenharmony_ci    { GL_BGRA_EXT, CR_REND_TEX },
3418bf80f4bSopenharmony_ci#endif
3428bf80f4bSopenharmony_ci
3438bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_norm16) && (GL_EXT_texture_norm16)
3448bf80f4bSopenharmony_ci    { GL_R16_EXT, CR_TF_REND_TEX },
3458bf80f4bSopenharmony_ci    { GL_RG16_EXT, CR_TF_REND_TEX },
3468bf80f4bSopenharmony_ci    { GL_RGB16_EXT, TF_TEX },
3478bf80f4bSopenharmony_ci    { GL_RGBA16_EXT, CR_TF_REND_TEX },
3488bf80f4bSopenharmony_ci    { GL_R16_SNORM_EXT, TF_TEX },
3498bf80f4bSopenharmony_ci    { GL_RG16_SNORM_EXT, TF_TEX },
3508bf80f4bSopenharmony_ci    { GL_RGB16_SNORM_EXT, TF_TEX },
3518bf80f4bSopenharmony_ci    { GL_RGBA16_SNORM_EXT, TF_TEX },
3528bf80f4bSopenharmony_ci#endif
3538bf80f4bSopenharmony_ci
3548bf80f4bSopenharmony_ci    { GL_COMPRESSED_R11_EAC, TF_TEX },
3558bf80f4bSopenharmony_ci    { GL_COMPRESSED_SIGNED_R11_EAC, TF_TEX },
3568bf80f4bSopenharmony_ci    { GL_COMPRESSED_RG11_EAC, TF_TEX },
3578bf80f4bSopenharmony_ci    { GL_COMPRESSED_SIGNED_RG11_EAC, TF_TEX },
3588bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGB8_ETC2, TF_TEX },
3598bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ETC2, TF_TEX },
3608bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, TF_TEX },
3618bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, TF_TEX },
3628bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA8_ETC2_EAC, TF_TEX },
3638bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, TF_TEX },
3648bf80f4bSopenharmony_ci#if RENDER_HAS_GLES_BACKEND
3658bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_4x4, TF_TEX },
3668bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_5x4, TF_TEX },
3678bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_5x5, TF_TEX },
3688bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_6x5, TF_TEX },
3698bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_6x6, TF_TEX },
3708bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_8x5, TF_TEX },
3718bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_8x6, TF_TEX },
3728bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_8x8, TF_TEX },
3738bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_10x5, TF_TEX },
3748bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_10x6, TF_TEX },
3758bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_10x8, TF_TEX },
3768bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_10x10, TF_TEX },
3778bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_12x10, TF_TEX },
3788bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_ASTC_12x12, TF_TEX },
3798bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4, TF_TEX },
3808bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4, TF_TEX },
3818bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5, TF_TEX },
3828bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5, TF_TEX },
3838bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6, TF_TEX },
3848bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5, TF_TEX },
3858bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6, TF_TEX },
3868bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8, TF_TEX },
3878bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5, TF_TEX },
3888bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6, TF_TEX },
3898bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8, TF_TEX },
3908bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10, TF_TEX },
3918bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10, TF_TEX },
3928bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12, TF_TEX },
3938bf80f4bSopenharmony_ci#endif
3948bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_compression_s3tc) && (GL_EXT_texture_compression_s3tc)
3958bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGB_S3TC_DXT1_EXT, TF_TEX },
3968bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, TF_TEX },
3978bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, TF_TEX },
3988bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, TF_TEX },
3998bf80f4bSopenharmony_ci#endif
4008bf80f4bSopenharmony_ci#if defined(GL_ARB_texture_compression_bptc) && (GL_ARB_texture_compression_bptc)
4018bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, TF_TEX },
4028bf80f4bSopenharmony_ci    { GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, TF_TEX },
4038bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, TF_TEX },
4048bf80f4bSopenharmony_ci    { GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB, TF_TEX },
4058bf80f4bSopenharmony_ci#endif
4068bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_compression_rgtc) && (GL_EXT_texture_compression_rgtc)
4078bf80f4bSopenharmony_ci    { GL_COMPRESSED_RED_RGTC1_EXT, TF_TEX },
4088bf80f4bSopenharmony_ci    { GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, TF_TEX },
4098bf80f4bSopenharmony_ci    { GL_COMPRESSED_RED_GREEN_RGTC2_EXT, TF_TEX },
4108bf80f4bSopenharmony_ci    { GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, TF_TEX },
4118bf80f4bSopenharmony_ci#endif
4128bf80f4bSopenharmony_ci};
4138bf80f4bSopenharmony_ci
4148bf80f4bSopenharmony_ci// Dont allow SRGB_R8 and SRGB_R8G8 internal formats, instead use the GL_SRGB8 with swizzle as workaround.
4158bf80f4bSopenharmony_ci#define USE_EXTENSION_FORMATS
4168bf80f4bSopenharmony_ci
4178bf80f4bSopenharmony_ci#define BLOCK_BITS_8 1
4188bf80f4bSopenharmony_ci#define BLOCK_BITS_16 2
4198bf80f4bSopenharmony_ci#define BLOCK_BITS_32 4
4208bf80f4bSopenharmony_ci#define BLOCK_BITS_64 8
4218bf80f4bSopenharmony_ci#define BLOCK_BITS_128 16
4228bf80f4bSopenharmony_ci
4238bf80f4bSopenharmony_ci// GL_EXT_texture_sRGB_R8 extension
4248bf80f4bSopenharmony_ci#if (defined(GL_EXT_texture_sRGB_R8) && (GL_EXT_texture_sRGB_R8))
4258bf80f4bSopenharmony_cistatic constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_SRGB_R8[] = {
4268bf80f4bSopenharmony_ci    { BASE_FORMAT_R8_SRGB, GL_RED, GL_SR8_EXT, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
4278bf80f4bSopenharmony_ci        { GL_RED, GL_ZERO, GL_ZERO, GL_ONE } },
4288bf80f4bSopenharmony_ci};
4298bf80f4bSopenharmony_ci#endif
4308bf80f4bSopenharmony_ci
4318bf80f4bSopenharmony_ci// GL_EXT_texture_sRGB_RG8 extension
4328bf80f4bSopenharmony_ci#if (defined(GL_EXT_texture_sRGB_RG8) && (GL_EXT_texture_sRGB_RG8))
4338bf80f4bSopenharmony_cistatic constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_SRGB_RG8[] = {
4348bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8_SRGB, GL_RG, GL_SRG8_EXT, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
4358bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_ZERO, GL_ONE } },
4368bf80f4bSopenharmony_ci};
4378bf80f4bSopenharmony_ci#endif
4388bf80f4bSopenharmony_ci
4398bf80f4bSopenharmony_ci// GL_EXT_texture_sRGB extension
4408bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_sRGB) && (GL_EXT_texture_sRGB)
4418bf80f4bSopenharmony_cistatic constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_SRGB[] = {
4428bf80f4bSopenharmony_ci    { BASE_FORMAT_BC1_RGB_SRGB_BLOCK, GL_RGB, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, 0,
4438bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4448bf80f4bSopenharmony_ci    { BASE_FORMAT_BC1_RGBA_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, 0,
4458bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4468bf80f4bSopenharmony_ci    { BASE_FORMAT_BC2_SRGB_BLOCK, GL_RGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_UNSIGNED_BYTE, 0,
4478bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4488bf80f4bSopenharmony_ci    { BASE_FORMAT_BC3_SRGB_BLOCK, GL_RGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_UNSIGNED_BYTE, 0,
4498bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4508bf80f4bSopenharmony_ci};
4518bf80f4bSopenharmony_ci#endif
4528bf80f4bSopenharmony_ci
4538bf80f4bSopenharmony_ci// GL_EXT_texture_format_BGRA8888 extension
4548bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_format_BGRA8888) && (GL_EXT_texture_format_BGRA8888)
4558bf80f4bSopenharmony_cistatic constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_BGRA[] = {
4568bf80f4bSopenharmony_ci    { BASE_FORMAT_B8G8R8A8_UNORM, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 4, { false, 0, 0, 0 },
4578bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4588bf80f4bSopenharmony_ci};
4598bf80f4bSopenharmony_ci#endif
4608bf80f4bSopenharmony_ci
4618bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_norm16) && (GL_EXT_texture_norm16)
4628bf80f4bSopenharmony_cistatic constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_NORM16[] = {
4638bf80f4bSopenharmony_ci    { BASE_FORMAT_R16_UNORM, GL_RED, GL_R16_EXT, GL_UNSIGNED_SHORT, 2, { false, 0, 0, 0 },
4648bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4658bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16_UNORM, GL_RG, GL_RG16_EXT, GL_UNSIGNED_SHORT, 4, { false, 0, 0, 0 },
4668bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4678bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16_UNORM, GL_RGB, GL_RGB16_EXT, GL_UNSIGNED_SHORT, 6, { false, 0, 0, 0 },
4688bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4698bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16A16_UNORM, GL_RGBA, GL_RGBA16_EXT, GL_UNSIGNED_SHORT, 8, { false, 0, 0, 0 },
4708bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4718bf80f4bSopenharmony_ci    { BASE_FORMAT_R16_SNORM, GL_RED, GL_R16_SNORM_EXT, GL_SHORT, 2, { false, 0, 0, 0 },
4728bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4738bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16_SNORM, GL_RG, GL_RG16_SNORM_EXT, GL_SHORT, 4, { false, 0, 0, 0 },
4748bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4758bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16_SNORM, GL_RGB, GL_RGB16_SNORM_EXT, GL_SHORT, 6, { false, 0, 0, 0 },
4768bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4778bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16A16_SNORM, GL_RGBA, GL_RGBA16_SNORM_EXT, GL_SHORT, 8, { false, 0, 0, 0 },
4788bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4798bf80f4bSopenharmony_ci};
4808bf80f4bSopenharmony_ci#endif
4818bf80f4bSopenharmony_ci
4828bf80f4bSopenharmony_ci// GL_EXT_texture_compression_s3tc extension
4838bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_compression_s3tc) && (GL_EXT_texture_compression_s3tc)
4848bf80f4bSopenharmony_cistatic constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_S3TC[] = {
4858bf80f4bSopenharmony_ci    { BASE_FORMAT_BC1_RGB_UNORM_BLOCK, GL_RGB, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, 0,
4868bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4878bf80f4bSopenharmony_ci    { BASE_FORMAT_BC1_RGBA_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, 0,
4888bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4898bf80f4bSopenharmony_ci    { BASE_FORMAT_BC2_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_UNSIGNED_BYTE, 0,
4908bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4918bf80f4bSopenharmony_ci    { BASE_FORMAT_BC3_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_UNSIGNED_BYTE, 0,
4928bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
4938bf80f4bSopenharmony_ci};
4948bf80f4bSopenharmony_ci#endif
4958bf80f4bSopenharmony_ci
4968bf80f4bSopenharmony_ci// GL_ARB_texture_compression_bptc extension
4978bf80f4bSopenharmony_ci#if defined(GL_ARB_texture_compression_bptc) && (GL_ARB_texture_compression_bptc)
4988bf80f4bSopenharmony_cistatic constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_BPTC[] = {
4998bf80f4bSopenharmony_ci    { BASE_FORMAT_BC7_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_UNSIGNED_BYTE, 0,
5008bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5018bf80f4bSopenharmony_ci    { BASE_FORMAT_BC7_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, GL_UNSIGNED_BYTE, 0,
5028bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5038bf80f4bSopenharmony_ci    { BASE_FORMAT_BC6H_SFLOAT_BLOCK, GL_RGB, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_FLOAT, 0,
5048bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5058bf80f4bSopenharmony_ci    { BASE_FORMAT_BC6H_UFLOAT_BLOCK, GL_RGB, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB, GL_FLOAT, 0,
5068bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5078bf80f4bSopenharmony_ci};
5088bf80f4bSopenharmony_ci#endif
5098bf80f4bSopenharmony_ci
5108bf80f4bSopenharmony_ci// GL_EXT_texture_norm16 extension
5118bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_compression_rgtc) && (GL_EXT_texture_compression_rgtc)
5128bf80f4bSopenharmony_cistatic constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_RGTC[] = {
5138bf80f4bSopenharmony_ci    { BASE_FORMAT_BC4_UNORM_BLOCK, GL_RED, GL_COMPRESSED_RED_RGTC1_EXT, GL_UNSIGNED_BYTE, 0,
5148bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5158bf80f4bSopenharmony_ci    { BASE_FORMAT_BC4_SNORM_BLOCK, GL_RED, GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, GL_UNSIGNED_BYTE, 0,
5168bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5178bf80f4bSopenharmony_ci    { BASE_FORMAT_BC5_UNORM_BLOCK, GL_RG, GL_COMPRESSED_RED_GREEN_RGTC2_EXT, GL_UNSIGNED_BYTE, 0,
5188bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5198bf80f4bSopenharmony_ci    { BASE_FORMAT_BC5_SNORM_BLOCK, GL_RG, GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, GL_UNSIGNED_BYTE, 0,
5208bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5218bf80f4bSopenharmony_ci};
5228bf80f4bSopenharmony_ci#endif
5238bf80f4bSopenharmony_ci
5248bf80f4bSopenharmony_cistatic constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_FALLBACK[] = {
5258bf80f4bSopenharmony_ci    { BASE_FORMAT_R4G4_UNORM_PACK8, GL_RG, GL_RGBA4, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
5268bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_ZERO, GL_ONE } },
5278bf80f4bSopenharmony_ci    { BASE_FORMAT_B4G4R4A4_UNORM_PACK16, GL_RGBA, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, 2, { false, 0, 0, 0 },
5288bf80f4bSopenharmony_ci        { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA } },
5298bf80f4bSopenharmony_ci    { BASE_FORMAT_B5G6R5_UNORM_PACK16, GL_RGB, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, 2, { false, 0, 0, 0 },
5308bf80f4bSopenharmony_ci        { GL_BLUE, GL_GREEN, GL_RED, GL_ONE } },
5318bf80f4bSopenharmony_ci    { BASE_FORMAT_B5G5R5A1_UNORM_PACK16, GL_RGBA, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, 2, { false, 0, 0, 0 },
5328bf80f4bSopenharmony_ci        { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA } },
5338bf80f4bSopenharmony_ci    { BASE_FORMAT_A1R5G5B5_UNORM_PACK16, GL_RGBA, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, 2, { false, 0, 0, 0 },
5348bf80f4bSopenharmony_ci        { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA } },
5358bf80f4bSopenharmony_ci
5368bf80f4bSopenharmony_ci    // not available in desktop, available as an extension in opengles. "GL_EXT_texture_sRGB_RG8"
5378bf80f4bSopenharmony_ci    { BASE_FORMAT_R8_SRGB, GL_RED, GL_SRGB8, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
5388bf80f4bSopenharmony_ci        { GL_RED, GL_ZERO, GL_ZERO, GL_ONE } },
5398bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8_SRGB, GL_RG, GL_SRGB8, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
5408bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_ZERO, GL_ONE } },
5418bf80f4bSopenharmony_ci
5428bf80f4bSopenharmony_ci    { BASE_FORMAT_A2R10G10B10_UNORM_PACK32, GL_RGBA, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, 4, { false, 0, 0, 0 },
5438bf80f4bSopenharmony_ci        { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA } },
5448bf80f4bSopenharmony_ci    { BASE_FORMAT_A2R10G10B10_UINT_PACK32, GL_RGBA, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, 4,
5458bf80f4bSopenharmony_ci        { false, 0, 0, 0 }, { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA } },
5468bf80f4bSopenharmony_ci
5478bf80f4bSopenharmony_ci    // available as an extension in opengles. "GL_EXT_texture_norm16" -> fallback to half float
5488bf80f4bSopenharmony_ci    { BASE_FORMAT_R16_UNORM, GL_RED, GL_R16F, GL_HALF_FLOAT, 2, { false, 0, 0, 0 },
5498bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5508bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16_UNORM, GL_RG, GL_RG16F, GL_HALF_FLOAT, 4, { false, 0, 0, 0 },
5518bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5528bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16_UNORM, GL_RGB, GL_RGB16F, GL_HALF_FLOAT, 6, { false, 0, 0, 0 },
5538bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5548bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16A16_UNORM, GL_RGBA, GL_RGBA16F, GL_HALF_FLOAT, 8, { false, 0, 0, 0 },
5558bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5568bf80f4bSopenharmony_ci};
5578bf80f4bSopenharmony_ci
5588bf80f4bSopenharmony_ci// NOTE: verify this table. add missing formats.
5598bf80f4bSopenharmony_cistatic constexpr DeviceGLES::ImageFormat IMAGE_FORMATS[] = {
5608bf80f4bSopenharmony_ci    { BASE_FORMAT_UNDEFINED, GL_NONE, GL_NONE, GL_NONE, 0, { false, 0, 0, 0 },
5618bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5628bf80f4bSopenharmony_ci    // These are required in GL and GLES
5638bf80f4bSopenharmony_ci    { BASE_FORMAT_R8_UNORM, GL_RED, GL_R8, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
5648bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5658bf80f4bSopenharmony_ci    { BASE_FORMAT_R8_SNORM, GL_RED, GL_R8_SNORM, GL_BYTE, 1, { false, 0, 0, 0 },
5668bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5678bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8_UNORM, GL_RG, GL_RG8, GL_UNSIGNED_BYTE, 2, { false, 0, 0, 0 },
5688bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5698bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8_SNORM, GL_RG, GL_RG8, GL_BYTE, 2, { false, 0, 0, 0 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5708bf80f4bSopenharmony_ci    { BASE_FORMAT_R5G6B5_UNORM_PACK16, GL_RGB, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, 2, { false, 0, 0, 0 },
5718bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5728bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8B8_UNORM, GL_RGB, GL_RGB8, GL_UNSIGNED_BYTE, 3, { false, 0, 0, 0 },
5738bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5748bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8B8_SNORM, GL_RGB, GL_RGB8, GL_BYTE, 3, { false, 0, 0, 0 },
5758bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5768bf80f4bSopenharmony_ci    { BASE_FORMAT_R4G4B4A4_UNORM_PACK16, GL_RGBA, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, 2, { false, 0, 0, 0 },
5778bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5788bf80f4bSopenharmony_ci    { BASE_FORMAT_R5G5B5A1_UNORM_PACK16, GL_RGBA, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, 2, { false, 0, 0, 0 },
5798bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5808bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8B8A8_UNORM, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE, 4, { false, 0, 0, 0 },
5818bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5828bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8B8A8_SNORM, GL_RGBA, GL_RGBA8, GL_BYTE, 4, { false, 0, 0, 0 },
5838bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5848bf80f4bSopenharmony_ci    { BASE_FORMAT_A2B10G10R10_UNORM_PACK32, GL_RGBA, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, 4, { false, 0, 0, 0 },
5858bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5868bf80f4bSopenharmony_ci    { BASE_FORMAT_A2B10G10R10_UINT_PACK32, GL_RGBA, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, 4,
5878bf80f4bSopenharmony_ci        { false, 0, 0, 0 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5888bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8B8_SRGB, GL_RGB, GL_SRGB8, GL_UNSIGNED_BYTE, 3, { false, 0, 0, 0 },
5898bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5908bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8B8A8_SRGB, GL_RGBA, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE, 4, { false, 0, 0, 0 },
5918bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5928bf80f4bSopenharmony_ci    { BASE_FORMAT_R16_SFLOAT, GL_RED, GL_R16F, GL_HALF_FLOAT, 2, { false, 0, 0, 0 },
5938bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5948bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16_SFLOAT, GL_RG, GL_RG16F, GL_HALF_FLOAT, 4, { false, 0, 0, 0 },
5958bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5968bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16_SFLOAT, GL_RGB, GL_RGB16F, GL_HALF_FLOAT, 6, { false, 0, 0, 0 },
5978bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
5988bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16A16_SFLOAT, GL_RGBA, GL_RGBA16F, GL_HALF_FLOAT, 8, { false, 0, 0, 0 },
5998bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6008bf80f4bSopenharmony_ci    { BASE_FORMAT_R32_SFLOAT, GL_RED, GL_R32F, GL_FLOAT, 4, { false, 0, 0, 0 },
6018bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6028bf80f4bSopenharmony_ci    { BASE_FORMAT_R32G32_SFLOAT, GL_RG, GL_RG32F, GL_FLOAT, 8, { false, 0, 0, 0 },
6038bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6048bf80f4bSopenharmony_ci    { BASE_FORMAT_R32G32B32_SFLOAT, GL_RGB, GL_RGB32F, GL_FLOAT, 12, { false, 0, 0, 0 },
6058bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6068bf80f4bSopenharmony_ci    { BASE_FORMAT_R32G32B32A32_SFLOAT, GL_RGBA, GL_RGBA32F, GL_FLOAT, 16, { false, 0, 0, 0 },
6078bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6088bf80f4bSopenharmony_ci    // Special R11 G11 B10 float format. This format does not work with compute on GLES, but works as a texture. (this
6098bf80f4bSopenharmony_ci    // is handled elsewhere)
6108bf80f4bSopenharmony_ci    { BASE_FORMAT_B10G11R11_UFLOAT_PACK32, GL_RGB, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV, 4,
6118bf80f4bSopenharmony_ci        { false, 0, 0, 0 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6128bf80f4bSopenharmony_ci    { BASE_FORMAT_E5B9G9R9_UFLOAT_PACK32, GL_RGB, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV, 4, { false, 0, 0, 0 },
6138bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6148bf80f4bSopenharmony_ci    { BASE_FORMAT_R8_SINT, GL_RED_INTEGER, GL_R8I, GL_BYTE, 1, { false, 0, 0, 0 },
6158bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6168bf80f4bSopenharmony_ci    { BASE_FORMAT_R8_UINT, GL_RED_INTEGER, GL_R8UI, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
6178bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6188bf80f4bSopenharmony_ci    { BASE_FORMAT_R16_SINT, GL_RED_INTEGER, GL_R16I, GL_SHORT, 2, { false, 0, 0, 0 },
6198bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6208bf80f4bSopenharmony_ci    { BASE_FORMAT_R16_UINT, GL_RED_INTEGER, GL_R16UI, GL_UNSIGNED_SHORT, 2, { false, 0, 0, 0 },
6218bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6228bf80f4bSopenharmony_ci    { BASE_FORMAT_R32_SINT, GL_RED_INTEGER, GL_R32I, GL_INT, 4, { false, 0, 0, 0 },
6238bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6248bf80f4bSopenharmony_ci    { BASE_FORMAT_R32_UINT, GL_RED_INTEGER, GL_R32UI, GL_UNSIGNED_INT, 4, { false, 0, 0, 0 },
6258bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6268bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8_SINT, GL_RG_INTEGER, GL_RG8I, GL_BYTE, 2, { false, 0, 0, 0 },
6278bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6288bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8_UINT, GL_RG_INTEGER, GL_R8UI, GL_UNSIGNED_BYTE, 2, { false, 0, 0, 0 },
6298bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6308bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16_SINT, GL_RG_INTEGER, GL_RG16I, GL_SHORT, 4, { false, 0, 0, 0 },
6318bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6328bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16_UINT, GL_RG_INTEGER, GL_RG16UI, GL_UNSIGNED_SHORT, 4, { false, 0, 0, 0 },
6338bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6348bf80f4bSopenharmony_ci    { BASE_FORMAT_R32G32_SINT, GL_RG_INTEGER, GL_RG32I, GL_INT, 8, { false, 0, 0, 0 },
6358bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6368bf80f4bSopenharmony_ci    { BASE_FORMAT_R32G32_UINT, GL_RG_INTEGER, GL_RG32UI, GL_UNSIGNED_INT, 8, { false, 0, 0, 0 },
6378bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6388bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8B8_SINT, GL_RGB_INTEGER, GL_RGB8I, GL_BYTE, 3, { false, 0, 0, 0 },
6398bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6408bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8B8_UINT, GL_RGB_INTEGER, GL_RGB8UI, GL_UNSIGNED_BYTE, 3, { false, 0, 0, 0 },
6418bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6428bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16_SINT, GL_RGB_INTEGER, GL_RGB16I, GL_SHORT, 6, { false, 0, 0, 0 },
6438bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6448bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16_UINT, GL_RGB_INTEGER, GL_RGB16UI, GL_UNSIGNED_SHORT, 6, { false, 0, 0, 0 },
6458bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6468bf80f4bSopenharmony_ci    { BASE_FORMAT_R32G32B32_SINT, GL_RGB_INTEGER, GL_RGB32I, GL_INT, 12, { false, 0, 0, 0 },
6478bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6488bf80f4bSopenharmony_ci    { BASE_FORMAT_R32G32B32_UINT, GL_RGB_INTEGER, GL_RGB32UI, GL_UNSIGNED_INT, 12, { false, 0, 0, 0 },
6498bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6508bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8B8A8_SINT, GL_RGBA_INTEGER, GL_RGBA8I, GL_BYTE, 4, { false, 0, 0, 0 },
6518bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6528bf80f4bSopenharmony_ci    { BASE_FORMAT_R8G8B8A8_UINT, GL_RGBA_INTEGER, GL_RGBA8UI, GL_UNSIGNED_BYTE, 4, { false, 0, 0, 0 },
6538bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6548bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16A16_SINT, GL_RGBA_INTEGER, GL_RGBA16I, GL_SHORT, 8, { false, 0, 0, 0 },
6558bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6568bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16A16_UINT, GL_RGBA_INTEGER, GL_RGBA16UI, GL_UNSIGNED_SHORT, 8, { false, 0, 0, 0 },
6578bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6588bf80f4bSopenharmony_ci    { BASE_FORMAT_R32G32B32A32_SINT, GL_RGBA_INTEGER, GL_RGBA32I, GL_INT, 16, { false, 0, 0, 0 },
6598bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6608bf80f4bSopenharmony_ci    { BASE_FORMAT_R32G32B32A32_UINT, GL_RGBA_INTEGER, GL_RGBA32UI, GL_UNSIGNED_INT, 16, { false, 0, 0, 0 },
6618bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6628bf80f4bSopenharmony_ci    { BASE_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, 2, { false, 0, 0, 0 },
6638bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6648bf80f4bSopenharmony_ci    { BASE_FORMAT_X8_D24_UNORM_PACK32, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, 4, { false, 0, 0, 0 },
6658bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6668bf80f4bSopenharmony_ci    { BASE_FORMAT_D32_SFLOAT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT32F, GL_FLOAT, 4, { false, 0, 0, 0 },
6678bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6688bf80f4bSopenharmony_ci    { BASE_FORMAT_S8_UINT, GL_STENCIL_INDEX, GL_STENCIL_INDEX8, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
6698bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6708bf80f4bSopenharmony_ci    { BASE_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH_STENCIL, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, 4, { false, 0, 0, 0 },
6718bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6728bf80f4bSopenharmony_ci    { BASE_FORMAT_D32_SFLOAT_S8_UINT, GL_DEPTH_STENCIL, GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8,
6738bf80f4bSopenharmony_ci        { false, 0, 0, 0 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6748bf80f4bSopenharmony_ci    // EAC
6758bf80f4bSopenharmony_ci    { BASE_FORMAT_EAC_R11_UNORM_BLOCK, GL_RED, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, 0,
6768bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6778bf80f4bSopenharmony_ci    { BASE_FORMAT_EAC_R11_SNORM_BLOCK, GL_RED, GL_COMPRESSED_SIGNED_R11_EAC, GL_BYTE, 0, { true, 4, 4, BLOCK_BITS_64 },
6788bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6798bf80f4bSopenharmony_ci    { BASE_FORMAT_EAC_R11G11_UNORM_BLOCK, GL_RG, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, 0,
6808bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6818bf80f4bSopenharmony_ci    { BASE_FORMAT_EAC_R11G11_SNORM_BLOCK, GL_RG, GL_COMPRESSED_SIGNED_RG11_EAC, GL_BYTE, 0,
6828bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6838bf80f4bSopenharmony_ci    // ETC
6848bf80f4bSopenharmony_ci    { BASE_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, GL_RGB, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, 0,
6858bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6868bf80f4bSopenharmony_ci    { BASE_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, GL_RGB, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, 0,
6878bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6888bf80f4bSopenharmony_ci    { BASE_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, 0,
6898bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6908bf80f4bSopenharmony_ci    { BASE_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, 0,
6918bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6928bf80f4bSopenharmony_ci    { BASE_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, 0,
6938bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6948bf80f4bSopenharmony_ci    { BASE_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, 0,
6958bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
6968bf80f4bSopenharmony_ci#if RENDER_HAS_GL_BACKEND
6978bf80f4bSopenharmony_ci    // required by GL
6988bf80f4bSopenharmony_ci    { BASE_FORMAT_R16_UNORM, GL_RED, GL_R16, GL_UNSIGNED_SHORT, 2, { false, 0, 0, 0 },
6998bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7008bf80f4bSopenharmony_ci    { BASE_FORMAT_R16_SNORM, GL_RED, GL_R16, GL_SHORT, 2, { false, 0, 0, 0 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7018bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16_UNORM, GL_RG, GL_RG16, GL_UNSIGNED_SHORT, 4, { false, 0, 0, 0 },
7028bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7038bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16_SNORM, GL_RG, GL_RG16, GL_SHORT, 4, { false, 0, 0, 0 },
7048bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7058bf80f4bSopenharmony_ci    // GL_R3_G3_B2, RGB4, RGB5, RGB10, RGB12 not in base formats
7068bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16_UNORM, GL_RGB, GL_RGB16, GL_UNSIGNED_SHORT, 6, { false, 0, 0, 0 },
7078bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7088bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16_SNORM, GL_RGB, GL_RGB16, GL_SHORT, 6, { false, 0, 0, 0 },
7098bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7108bf80f4bSopenharmony_ci    // RGBA2, RGBA12 not in base formats
7118bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16A16_UNORM, GL_RGBA, GL_RGBA16, GL_UNSIGNED_SHORT, 8, { false, 0, 0, 0 },
7128bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7138bf80f4bSopenharmony_ci    { BASE_FORMAT_R16G16B16A16_SNORM, GL_RGBA, GL_RGBA16, GL_SHORT, 8, { false, 0, 0, 0 },
7148bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7158bf80f4bSopenharmony_ci    // STENCIL_INDEX1, STENCIL_INDEX4, STENCIL_INDEX16 not in base formats
7168bf80f4bSopenharmony_ci    { BASE_FORMAT_B4G4R4A4_UNORM_PACK16, GL_BGRA, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4_REV, 2, { false, 0, 0, 0 },
7178bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7188bf80f4bSopenharmony_ci    { BASE_FORMAT_A1R5G5B5_UNORM_PACK16, GL_BGRA, GL_RGB5_A1, GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, { false, 0, 0, 0 },
7198bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7208bf80f4bSopenharmony_ci    { BASE_FORMAT_B5G6R5_UNORM_PACK16, GL_BGR, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5_REV, 2, { false, 0, 0, 0 },
7218bf80f4bSopenharmony_ci        { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7228bf80f4bSopenharmony_ci#elif RENDER_HAS_GLES_BACKEND
7238bf80f4bSopenharmony_ci    // required by GLES
7248bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_4x4_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_UNSIGNED_BYTE, 0,
7258bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7268bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_5x4_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_UNSIGNED_BYTE, 0,
7278bf80f4bSopenharmony_ci        { true, 5, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7288bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_5x5_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_UNSIGNED_BYTE, 0,
7298bf80f4bSopenharmony_ci        { true, 5, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7308bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_6x5_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_UNSIGNED_BYTE, 0,
7318bf80f4bSopenharmony_ci        { true, 6, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7328bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_6x6_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_UNSIGNED_BYTE, 0,
7338bf80f4bSopenharmony_ci        { true, 6, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7348bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_8x5_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_UNSIGNED_BYTE, 0,
7358bf80f4bSopenharmony_ci        { true, 8, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7368bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_8x6_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_UNSIGNED_BYTE, 0,
7378bf80f4bSopenharmony_ci        { true, 8, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7388bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_8x8_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_UNSIGNED_BYTE, 0,
7398bf80f4bSopenharmony_ci        { true, 8, 8, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7408bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_10x5_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_UNSIGNED_BYTE, 0,
7418bf80f4bSopenharmony_ci        { true, 10, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7428bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_10x6_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_UNSIGNED_BYTE, 0,
7438bf80f4bSopenharmony_ci        { true, 10, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7448bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_10x8_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_UNSIGNED_BYTE, 0,
7458bf80f4bSopenharmony_ci        { true, 10, 8, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7468bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_10x10_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_UNSIGNED_BYTE, 0,
7478bf80f4bSopenharmony_ci        { true, 10, 10, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7488bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_12x10_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_UNSIGNED_BYTE, 0,
7498bf80f4bSopenharmony_ci        { true, 12, 10, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7508bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_12x12_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_UNSIGNED_BYTE, 0,
7518bf80f4bSopenharmony_ci        { true, 12, 12, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7528bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_4x4_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_UNSIGNED_BYTE, 0,
7538bf80f4bSopenharmony_ci        { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7548bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_5x4_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_UNSIGNED_BYTE, 0,
7558bf80f4bSopenharmony_ci        { true, 5, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7568bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_5x5_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_UNSIGNED_BYTE, 0,
7578bf80f4bSopenharmony_ci        { true, 5, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7588bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_6x5_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_UNSIGNED_BYTE, 0,
7598bf80f4bSopenharmony_ci        { true, 6, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7608bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_6x6_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_UNSIGNED_BYTE, 0,
7618bf80f4bSopenharmony_ci        { true, 6, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7628bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_8x5_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_UNSIGNED_BYTE, 0,
7638bf80f4bSopenharmony_ci        { true, 8, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7648bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_8x6_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_UNSIGNED_BYTE, 0,
7658bf80f4bSopenharmony_ci        { true, 8, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7668bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_8x8_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_UNSIGNED_BYTE, 0,
7678bf80f4bSopenharmony_ci        { true, 8, 8, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7688bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_10x5_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_UNSIGNED_BYTE, 0,
7698bf80f4bSopenharmony_ci        { true, 10, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7708bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_10x6_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_UNSIGNED_BYTE, 0,
7718bf80f4bSopenharmony_ci        { true, 10, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7728bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_10x8_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_UNSIGNED_BYTE, 0,
7738bf80f4bSopenharmony_ci        { true, 10, 8, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7748bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_10x10_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_UNSIGNED_BYTE, 0,
7758bf80f4bSopenharmony_ci        { true, 10, 10, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7768bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_12x10_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_UNSIGNED_BYTE, 0,
7778bf80f4bSopenharmony_ci        { true, 12, 10, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7788bf80f4bSopenharmony_ci    { BASE_FORMAT_ASTC_12x12_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_UNSIGNED_BYTE, 0,
7798bf80f4bSopenharmony_ci        { true, 12, 12, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
7808bf80f4bSopenharmony_ci#endif
7818bf80f4bSopenharmony_ci};
7828bf80f4bSopenharmony_ci
7838bf80f4bSopenharmony_civoid FillExtensionFormats(const DeviceGLES& device, BASE_NS::vector<DeviceGLES::ImageFormat>& sf)
7848bf80f4bSopenharmony_ci{
7858bf80f4bSopenharmony_ci#if (defined(GL_EXT_texture_sRGB_R8) && (GL_EXT_texture_sRGB_R8))
7868bf80f4bSopenharmony_ci    if (device.HasExtension("GL_EXT_texture_sRGB_R8")) {
7878bf80f4bSopenharmony_ci        sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_SRGB_R8), std::end(IMAGE_FORMATS_EXT_SRGB_R8));
7888bf80f4bSopenharmony_ci    }
7898bf80f4bSopenharmony_ci#endif
7908bf80f4bSopenharmony_ci
7918bf80f4bSopenharmony_ci#if (defined(GL_EXT_texture_sRGB_RG8) && (GL_EXT_texture_sRGB_RG8))
7928bf80f4bSopenharmony_ci    if (device.HasExtension("GL_EXT_texture_sRGB_RG8")) {
7938bf80f4bSopenharmony_ci        sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_SRGB_RG8), std::end(IMAGE_FORMATS_EXT_SRGB_RG8));
7948bf80f4bSopenharmony_ci    }
7958bf80f4bSopenharmony_ci#endif
7968bf80f4bSopenharmony_ci
7978bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_sRGB) && (GL_EXT_texture_sRGB)
7988bf80f4bSopenharmony_ci    if (device.HasExtension("GL_EXT_texture_sRGB")) {
7998bf80f4bSopenharmony_ci        sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_SRGB), std::end(IMAGE_FORMATS_EXT_SRGB));
8008bf80f4bSopenharmony_ci    }
8018bf80f4bSopenharmony_ci#endif
8028bf80f4bSopenharmony_ci
8038bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_format_BGRA8888) && (GL_EXT_texture_format_BGRA8888)
8048bf80f4bSopenharmony_ci    if (device.HasExtension("GL_EXT_texture_format_BGRA8888")) {
8058bf80f4bSopenharmony_ci        sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_BGRA), std::end(IMAGE_FORMATS_EXT_BGRA));
8068bf80f4bSopenharmony_ci    }
8078bf80f4bSopenharmony_ci#endif
8088bf80f4bSopenharmony_ci
8098bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_norm16) && (GL_EXT_texture_norm16)
8108bf80f4bSopenharmony_ci    if (device.HasExtension("GL_EXT_texture_norm16")) {
8118bf80f4bSopenharmony_ci        sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_NORM16), std::end(IMAGE_FORMATS_EXT_NORM16));
8128bf80f4bSopenharmony_ci    }
8138bf80f4bSopenharmony_ci#endif
8148bf80f4bSopenharmony_ci
8158bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_compression_s3tc) && (GL_EXT_texture_compression_s3tc)
8168bf80f4bSopenharmony_ci    if (device.HasExtension("GL_EXT_texture_compression_s3tc")) {
8178bf80f4bSopenharmony_ci        sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_S3TC), std::end(IMAGE_FORMATS_EXT_S3TC));
8188bf80f4bSopenharmony_ci    }
8198bf80f4bSopenharmony_ci#endif
8208bf80f4bSopenharmony_ci
8218bf80f4bSopenharmony_ci#if defined(GL_ARB_texture_compression_bptc) && (GL_ARB_texture_compression_bptc)
8228bf80f4bSopenharmony_ci    if (device.HasExtension("GL_ARB_texture_compression_bptc")) {
8238bf80f4bSopenharmony_ci        sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_BPTC), std::end(IMAGE_FORMATS_EXT_BPTC));
8248bf80f4bSopenharmony_ci    }
8258bf80f4bSopenharmony_ci#endif
8268bf80f4bSopenharmony_ci
8278bf80f4bSopenharmony_ci#if defined(GL_EXT_texture_compression_rgtc) && (GL_EXT_texture_compression_rgtc)
8288bf80f4bSopenharmony_ci    if (device.HasExtension("GL_EXT_texture_compression_rgtc")) {
8298bf80f4bSopenharmony_ci        sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_RGTC), std::end(IMAGE_FORMATS_EXT_RGTC));
8308bf80f4bSopenharmony_ci    }
8318bf80f4bSopenharmony_ci#endif
8328bf80f4bSopenharmony_ci}
8338bf80f4bSopenharmony_ci} // namespace
8348bf80f4bSopenharmony_ci
8358bf80f4bSopenharmony_ci// Some OpenGL/ES features are supported and using them will lead to an assertion unless
8368bf80f4bSopenharmony_ci// the following define is added locally or as part of the build command: #define HANDLE_UNSUPPORTED_ENUMS
8378bf80f4bSopenharmony_ciinline uint32_t DeviceGLES::TargetToBinding(uint32_t target)
8388bf80f4bSopenharmony_ci{
8398bf80f4bSopenharmony_ci    if (target == GL_UNIFORM_BUFFER) {
8408bf80f4bSopenharmony_ci        return GL_UNIFORM_BUFFER_BINDING;
8418bf80f4bSopenharmony_ci    } else if (target == GL_SHADER_STORAGE_BUFFER) {
8428bf80f4bSopenharmony_ci        return GL_SHADER_STORAGE_BUFFER_BINDING;
8438bf80f4bSopenharmony_ci    } else if (target == GL_PIXEL_UNPACK_BUFFER) {
8448bf80f4bSopenharmony_ci        return GL_PIXEL_UNPACK_BUFFER_BINDING;
8458bf80f4bSopenharmony_ci    } else if (target == GL_COPY_READ_BUFFER) {
8468bf80f4bSopenharmony_ci        return GL_COPY_READ_BUFFER_BINDING;
8478bf80f4bSopenharmony_ci    } else if (target == GL_COPY_WRITE_BUFFER) {
8488bf80f4bSopenharmony_ci        return GL_COPY_WRITE_BUFFER_BINDING;
8498bf80f4bSopenharmony_ci#ifdef HANDLE_UNSUPPORTED_ENUMS
8508bf80f4bSopenharmony_ci    } else if (target == GL_ATOMIC_COUNTER_BUFFER) {
8518bf80f4bSopenharmony_ci        return GL_ATOMIC_COUNTER_BUFFER_BINDING;
8528bf80f4bSopenharmony_ci    } else if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
8538bf80f4bSopenharmony_ci        return GL_TRANSFORM_FEEDBACK_BUFFER_BINDING;
8548bf80f4bSopenharmony_ci    } else if (target == GL_PIXEL_PACK_BUFFER) {
8558bf80f4bSopenharmony_ci        return GL_PIXEL_PACK_BUFFER_BINDING;
8568bf80f4bSopenharmony_ci    } else if (target == GL_QUERY_BUFFER) {
8578bf80f4bSopenharmony_ci        return GL_QUERY_BUFFER_BINDING;
8588bf80f4bSopenharmony_ci    } else if (target == GL_ARRAY_BUFFER) {
8598bf80f4bSopenharmony_ci        return GL_ARRAY_BUFFER_BINDING;
8608bf80f4bSopenharmony_ci    } else if (target == GL_DISPATCH_INDIRECT_BUFFER) {
8618bf80f4bSopenharmony_ci        return GL_DISPATCH_INDIRECT_BUFFER_BINDING;
8628bf80f4bSopenharmony_ci    } else if (target == GL_DRAW_INDIRECT_BUFFER) {
8638bf80f4bSopenharmony_ci        return GL_DRAW_INDIRECT_BUFFER_BINDING;
8648bf80f4bSopenharmony_ci    } else if (target == GL_ELEMENT_ARRAY_BUFFER) { // stored in VAO state...
8658bf80f4bSopenharmony_ci        return GL_ELEMENT_ARRAY_BUFFER_BINDING;
8668bf80f4bSopenharmony_ci    } else if (target == GL_TEXTURE_BUFFER) {
8678bf80f4bSopenharmony_ci        return GL_TEXTURE_BUFFER_BINDING;
8688bf80f4bSopenharmony_ci#endif
8698bf80f4bSopenharmony_ci    }
8708bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(false, "UNHANDLED BUFFER BIND TARGET UNIT");
8718bf80f4bSopenharmony_ci    return GL_NONE;
8728bf80f4bSopenharmony_ci}
8738bf80f4bSopenharmony_ci
8748bf80f4bSopenharmony_ciinline DeviceGLES::BufferBindId DeviceGLES::IndexedTargetToTargetId(uint32_t target)
8758bf80f4bSopenharmony_ci{
8768bf80f4bSopenharmony_ci    if (target == GL_UNIFORM_BUFFER) {
8778bf80f4bSopenharmony_ci        return BufferBindId::UNIFORM_BUFFER_BIND;
8788bf80f4bSopenharmony_ci    } else if (target == GL_SHADER_STORAGE_BUFFER) {
8798bf80f4bSopenharmony_ci        return BufferBindId::SHADER_STORAGE_BUFFER_BIND;
8808bf80f4bSopenharmony_ci#ifdef HANDLE_UNSUPPORTED_ENUMS
8818bf80f4bSopenharmony_ci    } else if (target == GL_ATOMIC_COUNTER_BUFFER) {
8828bf80f4bSopenharmony_ci        return BufferBindId::ATOMIC_COUNTER_BUFFER;
8838bf80f4bSopenharmony_ci    } else if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
8848bf80f4bSopenharmony_ci        return BufferBindId::TRANSFORM_FEEDBACK_BUFFER;
8858bf80f4bSopenharmony_ci#endif
8868bf80f4bSopenharmony_ci    }
8878bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(false, "UNHANDLED BUFFER BIND TARGET UNIT");
8888bf80f4bSopenharmony_ci    return BufferBindId::MAX_BUFFER_BIND_ID;
8898bf80f4bSopenharmony_ci}
8908bf80f4bSopenharmony_ci
8918bf80f4bSopenharmony_ciinline uint32_t DeviceGLES::IndexedTargetIdToTarget(DeviceGLES::BufferBindId target)
8928bf80f4bSopenharmony_ci{
8938bf80f4bSopenharmony_ci    if (target == BufferBindId::UNIFORM_BUFFER_BIND) {
8948bf80f4bSopenharmony_ci        return GL_UNIFORM_BUFFER;
8958bf80f4bSopenharmony_ci    } else if (target == BufferBindId::SHADER_STORAGE_BUFFER_BIND) {
8968bf80f4bSopenharmony_ci        return GL_SHADER_STORAGE_BUFFER;
8978bf80f4bSopenharmony_ci#ifdef HANDLE_UNSUPPORTED_ENUMS
8988bf80f4bSopenharmony_ci    } else if (target == BufferBindId::ATOMIC_COUNTER_BUFFER_BIND) {
8998bf80f4bSopenharmony_ci        return GL_ATOMIC_COUNTER_BUFFER;
9008bf80f4bSopenharmony_ci    } else if (target == BufferBindId::TRANSFORM_FEEDBACK_BUFFER_BIND) {
9018bf80f4bSopenharmony_ci        return GL_TRANSFORM_FEEDBACK_BUFFER;
9028bf80f4bSopenharmony_ci#endif
9038bf80f4bSopenharmony_ci    }
9048bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(false, "UNHANDLED BUFFER BIND TARGET UNIT");
9058bf80f4bSopenharmony_ci    return 0;
9068bf80f4bSopenharmony_ci}
9078bf80f4bSopenharmony_ci
9088bf80f4bSopenharmony_ciinline DeviceGLES::BufferTargetId DeviceGLES::GenericTargetToTargetId(uint32_t target)
9098bf80f4bSopenharmony_ci{
9108bf80f4bSopenharmony_ci    if (target == GL_PIXEL_UNPACK_BUFFER) {
9118bf80f4bSopenharmony_ci        return BufferTargetId::PIXEL_UNPACK_BUFFER;
9128bf80f4bSopenharmony_ci    } else if (target == GL_PIXEL_PACK_BUFFER) {
9138bf80f4bSopenharmony_ci        return BufferTargetId::PIXEL_PACK_BUFFER;
9148bf80f4bSopenharmony_ci    } else if (target == GL_COPY_READ_BUFFER) {
9158bf80f4bSopenharmony_ci        return BufferTargetId::COPY_READ_BUFFER;
9168bf80f4bSopenharmony_ci    } else if (target == GL_COPY_WRITE_BUFFER) {
9178bf80f4bSopenharmony_ci        return BufferTargetId::COPY_WRITE_BUFFER;
9188bf80f4bSopenharmony_ci    } else if (target == GL_UNIFORM_BUFFER) {
9198bf80f4bSopenharmony_ci        return BufferTargetId::UNIFORM_BUFFER;
9208bf80f4bSopenharmony_ci    } else if (target == GL_SHADER_STORAGE_BUFFER) {
9218bf80f4bSopenharmony_ci        return BufferTargetId::SHADER_STORAGE_BUFFER;
9228bf80f4bSopenharmony_ci    } else if (target == GL_DISPATCH_INDIRECT_BUFFER) {
9238bf80f4bSopenharmony_ci        return BufferTargetId::DISPATCH_INDIRECT_BUFFER;
9248bf80f4bSopenharmony_ci    } else if (target == GL_DRAW_INDIRECT_BUFFER) {
9258bf80f4bSopenharmony_ci        return BufferTargetId::DRAW_INDIRECT_BUFFER;
9268bf80f4bSopenharmony_ci#ifdef HANDLE_UNSUPPORTED_ENUMS
9278bf80f4bSopenharmony_ci    } else if (target == GL_ATOMIC_COUNTER_BUFFER) {
9288bf80f4bSopenharmony_ci        return BufferTargetId::ATOMIC_COUNTER_BUFFER;
9298bf80f4bSopenharmony_ci    } else if (target == GL_QUERY_BUFFER) {
9308bf80f4bSopenharmony_ci        return BufferTargetId::QUERY_BUFFER;
9318bf80f4bSopenharmony_ci    } else if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
9328bf80f4bSopenharmony_ci        return BufferTargetId::TRANSFORM_FEEDBACK_BUFFER;
9338bf80f4bSopenharmony_ci    } else if (target == GL_ARRAY_BUFFER) {
9348bf80f4bSopenharmony_ci        return BufferTargetId::ARRAY_BUFFER;
9358bf80f4bSopenharmony_ci    } else if (target == GL_ELEMENT_ARRAY_BUFFER) { // stored in VAO state...
9368bf80f4bSopenharmony_ci        return BufferTargetId::ELEMENT_ARRAY_BUFFER;
9378bf80f4bSopenharmony_ci    } else if (target == GL_TEXTURE_BUFFER) {
9388bf80f4bSopenharmony_ci        return BufferTargetId::TEXTURE_BUFFER;
9398bf80f4bSopenharmony_ci#endif
9408bf80f4bSopenharmony_ci    }
9418bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(false, "UNHANDLED BUFFER BIND TARGET");
9428bf80f4bSopenharmony_ci    return BufferTargetId::MAX_BUFFER_TARGET_ID;
9438bf80f4bSopenharmony_ci}
9448bf80f4bSopenharmony_ci
9458bf80f4bSopenharmony_ciinline uint32_t DeviceGLES::GenericTargetIdToTarget(BufferTargetId target)
9468bf80f4bSopenharmony_ci{
9478bf80f4bSopenharmony_ci    if (target == BufferTargetId::PIXEL_UNPACK_BUFFER) {
9488bf80f4bSopenharmony_ci        return GL_PIXEL_UNPACK_BUFFER;
9498bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::PIXEL_PACK_BUFFER) {
9508bf80f4bSopenharmony_ci        return GL_PIXEL_PACK_BUFFER;
9518bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::COPY_READ_BUFFER) {
9528bf80f4bSopenharmony_ci        return GL_COPY_READ_BUFFER;
9538bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::COPY_WRITE_BUFFER) {
9548bf80f4bSopenharmony_ci        return GL_COPY_WRITE_BUFFER;
9558bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::UNIFORM_BUFFER) {
9568bf80f4bSopenharmony_ci        return GL_UNIFORM_BUFFER;
9578bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::SHADER_STORAGE_BUFFER) {
9588bf80f4bSopenharmony_ci        return GL_SHADER_STORAGE_BUFFER;
9598bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::DISPATCH_INDIRECT_BUFFER) {
9608bf80f4bSopenharmony_ci        return GL_DISPATCH_INDIRECT_BUFFER;
9618bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::DRAW_INDIRECT_BUFFER) {
9628bf80f4bSopenharmony_ci        return GL_DRAW_INDIRECT_BUFFER;
9638bf80f4bSopenharmony_ci#ifdef HANDLE_UNSUPPORTED_ENUMS
9648bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::ATOMIC_COUNTER_BUFFER) {
9658bf80f4bSopenharmony_ci        return GL_ATOMIC_COUNTER_BUFFER;
9668bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::QUERY_BUFFER) {
9678bf80f4bSopenharmony_ci        return GL_QUERY_BUFFER;
9688bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::TRANSFORM_FEEDBACK_BUFFER) {
9698bf80f4bSopenharmony_ci        return GL_TRANSFORM_FEEDBACK_BUFFER;
9708bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::ARRAY_BUFFER) {
9718bf80f4bSopenharmony_ci        return GL_ARRAY_BUFFER;
9728bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::ELEMENT_ARRAY_BUFFER) { // stored in VAO state...
9738bf80f4bSopenharmony_ci        return GL_ELEMENT_ARRAY_BUFFER;
9748bf80f4bSopenharmony_ci    } else if (target == BufferTargetId::TEXTURE_BUFFER) {
9758bf80f4bSopenharmony_ci        return GL_TEXTURE_BUFFER;
9768bf80f4bSopenharmony_ci#endif
9778bf80f4bSopenharmony_ci    }
9788bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(false, "UNHANDLED BUFFER BIND TARGET");
9798bf80f4bSopenharmony_ci    return 0;
9808bf80f4bSopenharmony_ci}
9818bf80f4bSopenharmony_ci
9828bf80f4bSopenharmony_ciinline DeviceGLES::TextureTargetId DeviceGLES::TextureTargetToTargetId(uint32_t target)
9838bf80f4bSopenharmony_ci{
9848bf80f4bSopenharmony_ci    if (target == GL_TEXTURE_2D) {
9858bf80f4bSopenharmony_ci        return TextureTargetId::TEXTURE_2D;
9868bf80f4bSopenharmony_ci    } else if ((target == GL_TEXTURE_CUBE_MAP_POSITIVE_X) || (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X) ||
9878bf80f4bSopenharmony_ci               (target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y) || (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ||
9888bf80f4bSopenharmony_ci               (target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z) || (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ||
9898bf80f4bSopenharmony_ci               (target == GL_TEXTURE_CUBE_MAP)) {
9908bf80f4bSopenharmony_ci        return TextureTargetId::TEXTURE_CUBE_MAP;
9918bf80f4bSopenharmony_ci#if RENDER_HAS_GLES_BACKEND
9928bf80f4bSopenharmony_ci    } else if (target == GL_TEXTURE_EXTERNAL_OES) {
9938bf80f4bSopenharmony_ci        return TextureTargetId::TEXTURE_EXTERNAL_OES;
9948bf80f4bSopenharmony_ci#endif
9958bf80f4bSopenharmony_ci    } else if (target == GL_TEXTURE_2D_MULTISAMPLE) {
9968bf80f4bSopenharmony_ci        return TextureTargetId::TEXTURE_2D_MULTISAMPLE;
9978bf80f4bSopenharmony_ci    } else if (target == GL_TEXTURE_2D_ARRAY) {
9988bf80f4bSopenharmony_ci        return TextureTargetId::TEXTURE_2D_ARRAY;
9998bf80f4bSopenharmony_ci    } else if (target == GL_TEXTURE_3D) {
10008bf80f4bSopenharmony_ci        return TextureTargetId::TEXTURE_3D;
10018bf80f4bSopenharmony_ci    }
10028bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(false, "UNHANDLED TEXTURE TARGET UNIT");
10038bf80f4bSopenharmony_ci    return TextureTargetId::MAX_TEXTURE_TARGET_ID;
10048bf80f4bSopenharmony_ci}
10058bf80f4bSopenharmony_ci
10068bf80f4bSopenharmony_ciinline uint32_t DeviceGLES::TextureTargetIdToTarget(DeviceGLES::TextureTargetId target)
10078bf80f4bSopenharmony_ci{
10088bf80f4bSopenharmony_ci    if (target == TextureTargetId::TEXTURE_2D) {
10098bf80f4bSopenharmony_ci        return GL_TEXTURE_2D;
10108bf80f4bSopenharmony_ci    } else if (target == TextureTargetId::TEXTURE_CUBE_MAP) {
10118bf80f4bSopenharmony_ci        return GL_TEXTURE_CUBE_MAP;
10128bf80f4bSopenharmony_ci#if RENDER_HAS_GLES_BACKEND
10138bf80f4bSopenharmony_ci    } else if (target == TextureTargetId::TEXTURE_EXTERNAL_OES) {
10148bf80f4bSopenharmony_ci        return GL_TEXTURE_EXTERNAL_OES;
10158bf80f4bSopenharmony_ci#endif
10168bf80f4bSopenharmony_ci    } else if (target == TextureTargetId::TEXTURE_2D_MULTISAMPLE) {
10178bf80f4bSopenharmony_ci        return GL_TEXTURE_2D_MULTISAMPLE;
10188bf80f4bSopenharmony_ci    } else if (target == TextureTargetId::TEXTURE_2D_ARRAY) {
10198bf80f4bSopenharmony_ci        return GL_TEXTURE_2D_ARRAY;
10208bf80f4bSopenharmony_ci    } else if (target == TextureTargetId::TEXTURE_3D) {
10218bf80f4bSopenharmony_ci        return GL_TEXTURE_3D;
10228bf80f4bSopenharmony_ci    }
10238bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(false, "UNHANDLED TEXTURE TARGET UNIT");
10248bf80f4bSopenharmony_ci    return 0;
10258bf80f4bSopenharmony_ci}
10268bf80f4bSopenharmony_ci
10278bf80f4bSopenharmony_civoid DeviceGLES::Activate(RenderHandle swapchain)
10288bf80f4bSopenharmony_ci{
10298bf80f4bSopenharmony_ci    if (HasSwapchain()) {
10308bf80f4bSopenharmony_ci        eglState_.SetContext(static_cast<const SwapchainGLES*>(GetSwapchain(swapchain)));
10318bf80f4bSopenharmony_ci    } else {
10328bf80f4bSopenharmony_ci        // bind the dummy surface as there is no swapchain.
10338bf80f4bSopenharmony_ci        eglState_.SetContext(nullptr);
10348bf80f4bSopenharmony_ci    }
10358bf80f4bSopenharmony_ci}
10368bf80f4bSopenharmony_ci
10378bf80f4bSopenharmony_civoid DeviceGLES::SwapBuffers(const SwapchainGLES& swapchain)
10388bf80f4bSopenharmony_ci{
10398bf80f4bSopenharmony_ci    eglState_.SwapBuffers(swapchain);
10408bf80f4bSopenharmony_ci}
10418bf80f4bSopenharmony_ci
10428bf80f4bSopenharmony_ci#if RENDER_HAS_GL_BACKEND
10438bf80f4bSopenharmony_ciconst WGLHelpers::WGLState& DeviceGLES::GetEglState()
10448bf80f4bSopenharmony_ci#endif
10458bf80f4bSopenharmony_ci#if RENDER_HAS_GLES_BACKEND
10468bf80f4bSopenharmony_ci    const EGLHelpers::EGLState& DeviceGLES::GetEglState()
10478bf80f4bSopenharmony_ci#endif
10488bf80f4bSopenharmony_ci{
10498bf80f4bSopenharmony_ci    return eglState_;
10508bf80f4bSopenharmony_ci}
10518bf80f4bSopenharmony_ci
10528bf80f4bSopenharmony_ci#if RENDER_HAS_GLES_BACKEND
10538bf80f4bSopenharmony_cibool DeviceGLES::IsDepthResolveSupported() const
10548bf80f4bSopenharmony_ci{
10558bf80f4bSopenharmony_ci    return backendConfig_.allowDepthResolve;
10568bf80f4bSopenharmony_ci}
10578bf80f4bSopenharmony_ci#endif
10588bf80f4bSopenharmony_ci
10598bf80f4bSopenharmony_ciDeviceGLES::DeviceGLES(RenderContext& renderContext, DeviceCreateInfo const& createInfo)
10608bf80f4bSopenharmony_ci    : Device(renderContext, createInfo)
10618bf80f4bSopenharmony_ci{
10628bf80f4bSopenharmony_ci    eglState_.CreateContext(createInfo);
10638bf80f4bSopenharmony_ci    if (!eglState_.IsValid()) {
10648bf80f4bSopenharmony_ci        PLUGIN_LOG_F("Failed to create a context");
10658bf80f4bSopenharmony_ci        return;
10668bf80f4bSopenharmony_ci    }
10678bf80f4bSopenharmony_ci    eglState_.GlInitialize();
10688bf80f4bSopenharmony_ci#if RENDER_GL_DEBUG
10698bf80f4bSopenharmony_ci    filterErrorFunc = (decltype(filterErrorFunc))eglState_.ErrorFilter();
10708bf80f4bSopenharmony_ci    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
10718bf80f4bSopenharmony_ci    glDebugMessageCallback(OnGlError, NULL);
10728bf80f4bSopenharmony_ci    GLuint unusedIds = 0;
10738bf80f4bSopenharmony_ci    glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, &unusedIds, true);
10748bf80f4bSopenharmony_ci#endif
10758bf80f4bSopenharmony_ci    PLUGIN_LOG_I("GL_VENDOR: %s", glGetString(GL_VENDOR));
10768bf80f4bSopenharmony_ci    PLUGIN_LOG_I("GL_RENDERER: %s", glGetString(GL_RENDERER));
10778bf80f4bSopenharmony_ci    PLUGIN_LOG_I("GL_VERSION: %s", glGetString(GL_VERSION));
10788bf80f4bSopenharmony_ci    PLUGIN_LOG_I("GL_SHADING_LANGUAGE_VERSION: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
10798bf80f4bSopenharmony_ci    GLint n = 0;
10808bf80f4bSopenharmony_ci    glGetIntegerv(GL_NUM_EXTENSIONS, &n);
10818bf80f4bSopenharmony_ci    extensions_.reserve(n + 1U);
10828bf80f4bSopenharmony_ci    for (GLuint i = 0U; i < static_cast<GLuint>(n); ++i) {
10838bf80f4bSopenharmony_ci        const auto ext = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i));
10848bf80f4bSopenharmony_ci        PLUGIN_LOG_V("  GL_EXTENSION: %s", ext);
10858bf80f4bSopenharmony_ci        extensions_.emplace_back(ext);
10868bf80f4bSopenharmony_ci    }
10878bf80f4bSopenharmony_ci    std::sort(extensions_.begin(), extensions_.end(),
10888bf80f4bSopenharmony_ci        [](const string_view& lhs, const string_view& rhs) { return lhs < rhs; });
10898bf80f4bSopenharmony_ci
10908bf80f4bSopenharmony_ci#if RENDER_HAS_GL_BACKEND
10918bf80f4bSopenharmony_ci    // Extension in OpenGL ES, but part of core in OpenGL.
10928bf80f4bSopenharmony_ci    if (const auto pos = std::lower_bound(extensions_.cbegin(), extensions_.cend(), EXT_BUFFER_STORAGE,
10938bf80f4bSopenharmony_ci            [](const string_view& element, const string_view& value) { return element < value; });
10948bf80f4bSopenharmony_ci        (pos == extensions_.cend()) || (*pos != EXT_BUFFER_STORAGE)) {
10958bf80f4bSopenharmony_ci        extensions_.insert(pos, EXT_BUFFER_STORAGE);
10968bf80f4bSopenharmony_ci    }
10978bf80f4bSopenharmony_ci    // Seamless cubemaps are always on in vulkan and gles 3.0..
10988bf80f4bSopenharmony_ci    // (3.0 made it required, not supported prior to 3.0 es)
10998bf80f4bSopenharmony_ci    // on desktop gl, it's optional.
11008bf80f4bSopenharmony_ci    // (but must be supported since 3.2)
11018bf80f4bSopenharmony_ci    // So just enable it always, so that desktop GL works as vulkan and GLES.
11028bf80f4bSopenharmony_ci    glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
11038bf80f4bSopenharmony_ci#endif
11048bf80f4bSopenharmony_ci#if RENDER_GL_DEBUG
11058bf80f4bSopenharmony_ci    // Dump interesting constants.
11068bf80f4bSopenharmony_ci    DUMP(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
11078bf80f4bSopenharmony_ci    DUMP(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS);
11088bf80f4bSopenharmony_ci    DUMP(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
11098bf80f4bSopenharmony_ci    DUMP(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
11108bf80f4bSopenharmony_ci    DUMP(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS);
11118bf80f4bSopenharmony_ci    DUMP(GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
11128bf80f4bSopenharmony_ci#endif
11138bf80f4bSopenharmony_ci    boundReadFbo_ = boundWriteFbo_ = 0;
11148bf80f4bSopenharmony_ci    eglState_.RestoreContext();
11158bf80f4bSopenharmony_ci#ifdef RENDER_OPTIMIZE_FOR_INTEGRATED_GPU
11168bf80f4bSopenharmony_ci    // NOTE: we expect e.g. mobile devices to have integrated memory, where we can bypass staging and write directly to
11178bf80f4bSopenharmony_ci    // linear gpu buffers without additional copies and performance decrease
11188bf80f4bSopenharmony_ci    deviceSharedMemoryPropertyFlags_ = CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
11198bf80f4bSopenharmony_ci#endif
11208bf80f4bSopenharmony_ci    SetDeviceStatus(true);
11218bf80f4bSopenharmony_ci
11228bf80f4bSopenharmony_ci    // First dump required formats and then add based on supported extensions
11238bf80f4bSopenharmony_ci    supportedFormats_.insert(supportedFormats_.end(), std::begin(IMAGE_FORMATS), std::end(IMAGE_FORMATS));
11248bf80f4bSopenharmony_ci
11258bf80f4bSopenharmony_ci    FillExtensionFormats(*this, supportedFormats_);
11268bf80f4bSopenharmony_ci
11278bf80f4bSopenharmony_ci    // Keep the list sorted for faster lookup
11288bf80f4bSopenharmony_ci    std::sort(supportedFormats_.begin(), supportedFormats_.end(),
11298bf80f4bSopenharmony_ci        [](const ImageFormat& lhs, const ImageFormat& rhs) { return lhs.coreFormat < rhs.coreFormat; });
11308bf80f4bSopenharmony_ci
11318bf80f4bSopenharmony_ci    const GpuResourceManager::CreateInfo grmCreateInfo {
11328bf80f4bSopenharmony_ci        GpuResourceManager::GPU_RESOURCE_MANAGER_OPTIMIZE_STAGING_MEMORY,
11338bf80f4bSopenharmony_ci    };
11348bf80f4bSopenharmony_ci    gpuResourceMgr_ = make_unique<GpuResourceManager>(*this, grmCreateInfo);
11358bf80f4bSopenharmony_ci    shaderMgr_ = make_unique<ShaderManager>(*this);
11368bf80f4bSopenharmony_ci
11378bf80f4bSopenharmony_ci    lowLevelDevice_ = make_unique<LowLevelDeviceGLES>(*this);
11388bf80f4bSopenharmony_ci}
11398bf80f4bSopenharmony_ci
11408bf80f4bSopenharmony_ciDeviceGLES::~DeviceGLES()
11418bf80f4bSopenharmony_ci{
11428bf80f4bSopenharmony_ci    if (eglState_.IsValid()) {
11438bf80f4bSopenharmony_ci        Activate(); // make sure we are active during teardown..
11448bf80f4bSopenharmony_ci        WaitForIdle();
11458bf80f4bSopenharmony_ci
11468bf80f4bSopenharmony_ci        // must release handles before taking down gpu resource manager.
11478bf80f4bSopenharmony_ci        swapchains_.clear();
11488bf80f4bSopenharmony_ci
11498bf80f4bSopenharmony_ci        gpuResourceMgr_.reset();
11508bf80f4bSopenharmony_ci        shaderMgr_.reset();
11518bf80f4bSopenharmony_ci        eglState_.DestroyContext();
11528bf80f4bSopenharmony_ci        Deactivate(); // make sure the previous context is still active..
11538bf80f4bSopenharmony_ci    }
11548bf80f4bSopenharmony_ci}
11558bf80f4bSopenharmony_ci
11568bf80f4bSopenharmony_cibool DeviceGLES::HasExtension(const string_view extension) const
11578bf80f4bSopenharmony_ci{
11588bf80f4bSopenharmony_ci    return std::binary_search(extensions_.begin(), extensions_.end(), extension,
11598bf80f4bSopenharmony_ci        [](const string_view& element, const string_view value) { return element < value; });
11608bf80f4bSopenharmony_ci}
11618bf80f4bSopenharmony_ci
11628bf80f4bSopenharmony_ciDeviceBackendType DeviceGLES::GetBackendType() const
11638bf80f4bSopenharmony_ci{
11648bf80f4bSopenharmony_ci    return backendType_;
11658bf80f4bSopenharmony_ci}
11668bf80f4bSopenharmony_ci
11678bf80f4bSopenharmony_ciconst DevicePlatformData& DeviceGLES::GetPlatformData() const
11688bf80f4bSopenharmony_ci{
11698bf80f4bSopenharmony_ci    return eglState_.GetPlatformData();
11708bf80f4bSopenharmony_ci}
11718bf80f4bSopenharmony_ci
11728bf80f4bSopenharmony_ciILowLevelDevice& DeviceGLES::GetLowLevelDevice() const
11738bf80f4bSopenharmony_ci{
11748bf80f4bSopenharmony_ci    return *lowLevelDevice_;
11758bf80f4bSopenharmony_ci}
11768bf80f4bSopenharmony_ci
11778bf80f4bSopenharmony_ciFormatProperties DeviceGLES::GetFormatProperties(const Format format) const
11788bf80f4bSopenharmony_ci{
11798bf80f4bSopenharmony_ci    FormatProperties properties;
11808bf80f4bSopenharmony_ci    auto& glFormat = GetGlImageFormat(format);
11818bf80f4bSopenharmony_ci    if (glFormat.internalFormat != GL_NONE) {
11828bf80f4bSopenharmony_ci        if (auto pos = std::find_if(std::begin(IMAGE_FORMAT_FEATURES), std::end(IMAGE_FORMAT_FEATURES),
11838bf80f4bSopenharmony_ci                [internalFormat = glFormat.internalFormat](
11848bf80f4bSopenharmony_ci                    const FormatFeatures& features) { return features.internalFormat == internalFormat; });
11858bf80f4bSopenharmony_ci            pos != std::end(IMAGE_FORMAT_FEATURES)) {
11868bf80f4bSopenharmony_ci            // split texel buffer support to bufferFeatures
11878bf80f4bSopenharmony_ci            properties.linearTilingFeatures = properties.optimalTilingFeatures =
11888bf80f4bSopenharmony_ci                pos->flags & ~CORE_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
11898bf80f4bSopenharmony_ci            // assume if the format can be sampled it can be used as a vertex buffer.
11908bf80f4bSopenharmony_ci            properties.bufferFeatures =
11918bf80f4bSopenharmony_ci                ((pos->flags & CORE_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? CORE_FORMAT_FEATURE_VERTEX_BUFFER_BIT : 0U) |
11928bf80f4bSopenharmony_ci                (pos->flags & CORE_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT);
11938bf80f4bSopenharmony_ci#if RENDER_HAS_GL_BACKEND
11948bf80f4bSopenharmony_ci            // desktop GL can filter anything
11958bf80f4bSopenharmony_ci            properties.linearTilingFeatures |= TF;
11968bf80f4bSopenharmony_ci            properties.optimalTilingFeatures |= TF;
11978bf80f4bSopenharmony_ci#endif
11988bf80f4bSopenharmony_ci            // can probably blit if not compressed
11998bf80f4bSopenharmony_ci            if (!glFormat.compression.compressed) {
12008bf80f4bSopenharmony_ci                properties.linearTilingFeatures |= CORE_FORMAT_FEATURE_BLIT_DST_BIT | CORE_FORMAT_FEATURE_BLIT_SRC_BIT;
12018bf80f4bSopenharmony_ci                properties.optimalTilingFeatures |= CORE_FORMAT_FEATURE_BLIT_DST_BIT | CORE_FORMAT_FEATURE_BLIT_SRC_BIT;
12028bf80f4bSopenharmony_ci            }
12038bf80f4bSopenharmony_ci            properties.bytesPerPixel = glFormat.bytesperpixel;
12048bf80f4bSopenharmony_ci        }
12058bf80f4bSopenharmony_ci    }
12068bf80f4bSopenharmony_ci    return properties;
12078bf80f4bSopenharmony_ci}
12088bf80f4bSopenharmony_ci
12098bf80f4bSopenharmony_ciAccelerationStructureBuildSizes DeviceGLES::GetAccelerationStructureBuildSizes(
12108bf80f4bSopenharmony_ci    const AccelerationStructureBuildGeometryInfo& geometry,
12118bf80f4bSopenharmony_ci    BASE_NS::array_view<const AccelerationStructureGeometryTrianglesInfo> triangles,
12128bf80f4bSopenharmony_ci    BASE_NS::array_view<const AccelerationStructureGeometryAabbsInfo> aabbs,
12138bf80f4bSopenharmony_ci    BASE_NS::array_view<const AccelerationStructureGeometryInstancesInfo> instances) const
12148bf80f4bSopenharmony_ci{
12158bf80f4bSopenharmony_ci    return {};
12168bf80f4bSopenharmony_ci}
12178bf80f4bSopenharmony_ci
12188bf80f4bSopenharmony_ciPlatformGpuMemoryAllocator* DeviceGLES::GetPlatformGpuMemoryAllocator()
12198bf80f4bSopenharmony_ci{
12208bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(false, "DeviceGLES::GetPlatformGpuMemoryAllocator called!");
12218bf80f4bSopenharmony_ci    return nullptr;
12228bf80f4bSopenharmony_ci}
12238bf80f4bSopenharmony_ci
12248bf80f4bSopenharmony_ci// (re-)create swapchain
12258bf80f4bSopenharmony_ciunique_ptr<Swapchain> DeviceGLES::CreateDeviceSwapchain(const SwapchainCreateInfo& swapchainCreateInfo)
12268bf80f4bSopenharmony_ci{
12278bf80f4bSopenharmony_ci    PLUGIN_ASSERT(IsActive());
12288bf80f4bSopenharmony_ci    auto swapchain = make_unique<SwapchainGLES>(*this, swapchainCreateInfo);
12298bf80f4bSopenharmony_ci    // Switch to the new swapchain.
12308bf80f4bSopenharmony_ci    eglState_.SetContext(swapchain.get());
12318bf80f4bSopenharmony_ci    return swapchain;
12328bf80f4bSopenharmony_ci}
12338bf80f4bSopenharmony_ci
12348bf80f4bSopenharmony_civoid DeviceGLES::DestroyDeviceSwapchain()
12358bf80f4bSopenharmony_ci{
12368bf80f4bSopenharmony_ci    PLUGIN_ASSERT(IsActive());
12378bf80f4bSopenharmony_ci    // TODO:
12388bf80f4bSopenharmony_ci    // Drop to dummycontext (ie. 1x1 surface etc...)
12398bf80f4bSopenharmony_ci    eglState_.SetContext(nullptr);
12408bf80f4bSopenharmony_ci}
12418bf80f4bSopenharmony_ci
12428bf80f4bSopenharmony_cibool DeviceGLES::IsActive() const
12438bf80f4bSopenharmony_ci{
12448bf80f4bSopenharmony_ci    return isActive_ > 0;
12458bf80f4bSopenharmony_ci}
12468bf80f4bSopenharmony_ci
12478bf80f4bSopenharmony_civoid DeviceGLES::Activate()
12488bf80f4bSopenharmony_ci{
12498bf80f4bSopenharmony_ci    activeMutex_.lock();
12508bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(isActive_ == 0, "Activate called while already inactive");
12518bf80f4bSopenharmony_ci    if (isActive_ == 0) {
12528bf80f4bSopenharmony_ci        eglState_.SaveContext();
12538bf80f4bSopenharmony_ci
12548bf80f4bSopenharmony_ci        constexpr RenderHandle defaultSwapchain {};
12558bf80f4bSopenharmony_ci        Activate(defaultSwapchain);
12568bf80f4bSopenharmony_ci    }
12578bf80f4bSopenharmony_ci    isActive_++;
12588bf80f4bSopenharmony_ci}
12598bf80f4bSopenharmony_ci
12608bf80f4bSopenharmony_civoid DeviceGLES::Deactivate()
12618bf80f4bSopenharmony_ci{
12628bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(isActive_ > 0, "Deactivate called while already inactive");
12638bf80f4bSopenharmony_ci    if (isActive_ > 0) {
12648bf80f4bSopenharmony_ci        isActive_--;
12658bf80f4bSopenharmony_ci    }
12668bf80f4bSopenharmony_ci    if (isActive_ == 0) {
12678bf80f4bSopenharmony_ci        eglState_.RestoreContext();
12688bf80f4bSopenharmony_ci        isActive_ = false;
12698bf80f4bSopenharmony_ci    }
12708bf80f4bSopenharmony_ci    activeMutex_.unlock();
12718bf80f4bSopenharmony_ci}
12728bf80f4bSopenharmony_ci
12738bf80f4bSopenharmony_ciGpuQueue DeviceGLES::GetValidGpuQueue(const GpuQueue& gpuQueue) const
12748bf80f4bSopenharmony_ci{
12758bf80f4bSopenharmony_ci    return { GpuQueue::QueueType::GRAPHICS, 0 }; // no queues -> graphics
12768bf80f4bSopenharmony_ci}
12778bf80f4bSopenharmony_ci
12788bf80f4bSopenharmony_ciuint32_t DeviceGLES::GetGpuQueueCount() const
12798bf80f4bSopenharmony_ci{
12808bf80f4bSopenharmony_ci    return 1;
12818bf80f4bSopenharmony_ci}
12828bf80f4bSopenharmony_ci
12838bf80f4bSopenharmony_civoid DeviceGLES::InitializePipelineCache(array_view<const uint8_t> initialData)
12848bf80f4bSopenharmony_ci{
12858bf80f4bSopenharmony_ci    // NOTE: not implemented.
12868bf80f4bSopenharmony_ci}
12878bf80f4bSopenharmony_ci
12888bf80f4bSopenharmony_civector<uint8_t> DeviceGLES::GetPipelineCache() const
12898bf80f4bSopenharmony_ci{
12908bf80f4bSopenharmony_ci    // NOTE: not implemented. could probably be done by gathering glGetProgramBinary results together.
12918bf80f4bSopenharmony_ci    return {};
12928bf80f4bSopenharmony_ci}
12938bf80f4bSopenharmony_ci
12948bf80f4bSopenharmony_civoid DeviceGLES::WaitForIdle()
12958bf80f4bSopenharmony_ci{
12968bf80f4bSopenharmony_ci    const bool activeState = IsActive();
12978bf80f4bSopenharmony_ci    if (!activeState) {
12988bf80f4bSopenharmony_ci        Activate();
12998bf80f4bSopenharmony_ci    }
13008bf80f4bSopenharmony_ci    if (!isRenderbackendRunning_) {
13018bf80f4bSopenharmony_ci        PLUGIN_LOG_D("Device - WaitForIdle");
13028bf80f4bSopenharmony_ci        glFinish();
13038bf80f4bSopenharmony_ci    } else {
13048bf80f4bSopenharmony_ci        PLUGIN_LOG_E("Device WaitForIdle can only called when render backend is not running");
13058bf80f4bSopenharmony_ci    }
13068bf80f4bSopenharmony_ci    if (!activeState) {
13078bf80f4bSopenharmony_ci        Deactivate();
13088bf80f4bSopenharmony_ci    }
13098bf80f4bSopenharmony_ci}
13108bf80f4bSopenharmony_ci
13118bf80f4bSopenharmony_ci#if (RENDER_HAS_GL_BACKEND)
13128bf80f4bSopenharmony_ciunique_ptr<Device> CreateDeviceGL(RenderContext& renderContext, DeviceCreateInfo const& createInfo)
13138bf80f4bSopenharmony_ci{
13148bf80f4bSopenharmony_ci    if (auto device = make_unique<DeviceGLES>(renderContext, createInfo); device) {
13158bf80f4bSopenharmony_ci        const auto& plat = static_cast<const DevicePlatformDataGL&>(device->GetPlatformData());
13168bf80f4bSopenharmony_ci        if (plat.context != nullptr) {
13178bf80f4bSopenharmony_ci            return device;
13188bf80f4bSopenharmony_ci        }
13198bf80f4bSopenharmony_ci    }
13208bf80f4bSopenharmony_ci    return nullptr;
13218bf80f4bSopenharmony_ci}
13228bf80f4bSopenharmony_ci#endif
13238bf80f4bSopenharmony_ci#if (RENDER_HAS_GLES_BACKEND)
13248bf80f4bSopenharmony_ciunique_ptr<Device> CreateDeviceGLES(RenderContext& renderContext, DeviceCreateInfo const& createInfo)
13258bf80f4bSopenharmony_ci{
13268bf80f4bSopenharmony_ci    if (auto device = make_unique<DeviceGLES>(renderContext, createInfo); device) {
13278bf80f4bSopenharmony_ci        const auto& plat = static_cast<const DevicePlatformDataGLES&>(device->GetPlatformData());
13288bf80f4bSopenharmony_ci        if (plat.context != EGL_NO_CONTEXT) {
13298bf80f4bSopenharmony_ci            return device;
13308bf80f4bSopenharmony_ci        }
13318bf80f4bSopenharmony_ci    }
13328bf80f4bSopenharmony_ci    return nullptr;
13338bf80f4bSopenharmony_ci}
13348bf80f4bSopenharmony_ci#endif
13358bf80f4bSopenharmony_ci
13368bf80f4bSopenharmony_civoid DeviceGLES::ReleaseShader(uint32_t type, uint32_t shader)
13378bf80f4bSopenharmony_ci{
13388bf80f4bSopenharmony_ci    vector<ShaderCache::Entry>* cache = nullptr;
13398bf80f4bSopenharmony_ci    if (type == GL_FRAGMENT_SHADER) {
13408bf80f4bSopenharmony_ci        cache = &caches[DeviceGLES::FRAGMENT_CACHE].cache;
13418bf80f4bSopenharmony_ci    } else if (type == GL_VERTEX_SHADER) {
13428bf80f4bSopenharmony_ci        cache = &caches[DeviceGLES::VERTEX_CACHE].cache;
13438bf80f4bSopenharmony_ci    } else if (type == GL_COMPUTE_SHADER) {
13448bf80f4bSopenharmony_ci        cache = &caches[DeviceGLES::COMPUTE_CACHE].cache;
13458bf80f4bSopenharmony_ci    } else {
13468bf80f4bSopenharmony_ci        return;
13478bf80f4bSopenharmony_ci    }
13488bf80f4bSopenharmony_ci
13498bf80f4bSopenharmony_ci    const auto pos = std::find_if(
13508bf80f4bSopenharmony_ci        cache->begin(), cache->end(), [shader](const ShaderCache::Entry& entry) { return entry.shader == shader; });
13518bf80f4bSopenharmony_ci    if (pos != cache->end()) {
13528bf80f4bSopenharmony_ci        ShaderCache::Entry& entry = *pos;
13538bf80f4bSopenharmony_ci        entry.refCount--;
13548bf80f4bSopenharmony_ci        if (entry.refCount == 0) {
13558bf80f4bSopenharmony_ci            glDeleteShader(entry.shader);
13568bf80f4bSopenharmony_ci            cache->erase(pos);
13578bf80f4bSopenharmony_ci        }
13588bf80f4bSopenharmony_ci        return;
13598bf80f4bSopenharmony_ci    }
13608bf80f4bSopenharmony_ci
13618bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(false, "Tried to release a non-existant shader?");
13628bf80f4bSopenharmony_ci}
13638bf80f4bSopenharmony_ci
13648bf80f4bSopenharmony_civoid DeviceGLES::ReleaseProgram(uint32_t program)
13658bf80f4bSopenharmony_ci{
13668bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(isActive_, "Device not active when releasing shaders");
13678bf80f4bSopenharmony_ci    for (auto it = programs_.begin(); it != programs_.end(); it++) {
13688bf80f4bSopenharmony_ci        auto& t = *it;
13698bf80f4bSopenharmony_ci        if (t.program == program) {
13708bf80f4bSopenharmony_ci            t.refCount--;
13718bf80f4bSopenharmony_ci            if (t.refCount == 0) {
13728bf80f4bSopenharmony_ci                if (t.fragShader) {
13738bf80f4bSopenharmony_ci                    ReleaseShader(GL_FRAGMENT_SHADER, t.fragShader);
13748bf80f4bSopenharmony_ci                }
13758bf80f4bSopenharmony_ci                if (t.vertShader) {
13768bf80f4bSopenharmony_ci                    ReleaseShader(GL_VERTEX_SHADER, t.vertShader);
13778bf80f4bSopenharmony_ci                }
13788bf80f4bSopenharmony_ci                if (t.compShader) {
13798bf80f4bSopenharmony_ci                    ReleaseShader(GL_COMPUTE_SHADER, t.compShader);
13808bf80f4bSopenharmony_ci                }
13818bf80f4bSopenharmony_ci                glDeleteProgram(t.program);
13828bf80f4bSopenharmony_ci                programs_.erase(it);
13838bf80f4bSopenharmony_ci            }
13848bf80f4bSopenharmony_ci            return;
13858bf80f4bSopenharmony_ci        }
13868bf80f4bSopenharmony_ci    }
13878bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(false, "Tried to release a non-existant program?");
13888bf80f4bSopenharmony_ci}
13898bf80f4bSopenharmony_ci
13908bf80f4bSopenharmony_ciconst DeviceGLES::ShaderCache::Entry& DeviceGLES::CacheShader(int type, const string_view source)
13918bf80f4bSopenharmony_ci{
13928bf80f4bSopenharmony_ci    PLUGIN_ASSERT(type < MAX_CACHES);
13938bf80f4bSopenharmony_ci    if (source.empty()) {
13948bf80f4bSopenharmony_ci        static constexpr DeviceGLES::ShaderCache::Entry invalid {};
13958bf80f4bSopenharmony_ci        return invalid;
13968bf80f4bSopenharmony_ci    }
13978bf80f4bSopenharmony_ci    constexpr GLenum types[] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, GL_COMPUTE_SHADER };
13988bf80f4bSopenharmony_ci    // NOTE: check other hash functions, also i guess verify (strcmp) on collision would be prudent.
13998bf80f4bSopenharmony_ci    const uint64_t hash = FNV1aHash(source.data(), source.size());
14008bf80f4bSopenharmony_ci    PLUGIN_ASSERT(hash != 0);
14018bf80f4bSopenharmony_ci    for (auto& t : caches[type].cache) {
14028bf80f4bSopenharmony_ci        if (t.hash == hash) {
14038bf80f4bSopenharmony_ci            caches[type].hit++;
14048bf80f4bSopenharmony_ci            t.refCount++;
14058bf80f4bSopenharmony_ci            return t;
14068bf80f4bSopenharmony_ci        }
14078bf80f4bSopenharmony_ci    }
14088bf80f4bSopenharmony_ci    caches[type].miss++;
14098bf80f4bSopenharmony_ci    DeviceGLES::ShaderCache::Entry entry;
14108bf80f4bSopenharmony_ci    entry.hash = hash;
14118bf80f4bSopenharmony_ci    entry.shader = glCreateShader(types[type]);
14128bf80f4bSopenharmony_ci    entry.refCount = 1;
14138bf80f4bSopenharmony_ci    const GLint len = static_cast<GLint>(source.length());
14148bf80f4bSopenharmony_ci    const auto data = source.data();
14158bf80f4bSopenharmony_ci    glShaderSource(entry.shader, 1, &data, &len);
14168bf80f4bSopenharmony_ci    glCompileShader(entry.shader);
14178bf80f4bSopenharmony_ci    GLint result = GL_FALSE;
14188bf80f4bSopenharmony_ci    glGetShaderiv(entry.shader, GL_COMPILE_STATUS, &result);
14198bf80f4bSopenharmony_ci    if (result == GL_FALSE) {
14208bf80f4bSopenharmony_ci        GLint logLength = 0;
14218bf80f4bSopenharmony_ci        glGetShaderiv(entry.shader, GL_INFO_LOG_LENGTH, &logLength);
14228bf80f4bSopenharmony_ci        string messages;
14238bf80f4bSopenharmony_ci        messages.resize(static_cast<size_t>(logLength));
14248bf80f4bSopenharmony_ci        glGetShaderInfoLog(entry.shader, logLength, 0, messages.data());
14258bf80f4bSopenharmony_ci        PLUGIN_LOG_F("Shader compilation error: %s", messages.c_str());
14268bf80f4bSopenharmony_ci        glDeleteShader(entry.shader);
14278bf80f4bSopenharmony_ci        entry.shader = 0U;
14288bf80f4bSopenharmony_ci    }
14298bf80f4bSopenharmony_ci    caches[type].cache.push_back(entry);
14308bf80f4bSopenharmony_ci    return caches[type].cache.back();
14318bf80f4bSopenharmony_ci}
14328bf80f4bSopenharmony_ci
14338bf80f4bSopenharmony_ciuint32_t DeviceGLES::CacheProgram(
14348bf80f4bSopenharmony_ci    const string_view vertSource, const string_view fragSource, const string_view compSource)
14358bf80f4bSopenharmony_ci{
14368bf80f4bSopenharmony_ci    PLUGIN_ASSERT_MSG(isActive_, "Device not active when building shaders");
14378bf80f4bSopenharmony_ci    // Hash and cache shader sources.
14388bf80f4bSopenharmony_ci    const auto& vEntry = CacheShader(DeviceGLES::VERTEX_CACHE, vertSource);
14398bf80f4bSopenharmony_ci    const auto& fEntry = CacheShader(DeviceGLES::FRAGMENT_CACHE, fragSource);
14408bf80f4bSopenharmony_ci    const auto& cEntry = CacheShader(DeviceGLES::COMPUTE_CACHE, compSource);
14418bf80f4bSopenharmony_ci    // Then check if we have the program already cached (ie. matching shaders linked)
14428bf80f4bSopenharmony_ci    for (ProgramCache& t : programs_) {
14438bf80f4bSopenharmony_ci        if ((t.hashVert != vEntry.hash) || (t.hashFrag != fEntry.hash) || (t.hashComp != cEntry.hash)) {
14448bf80f4bSopenharmony_ci            continue;
14458bf80f4bSopenharmony_ci        }
14468bf80f4bSopenharmony_ci        pCacheHit_++;
14478bf80f4bSopenharmony_ci        t.refCount++;
14488bf80f4bSopenharmony_ci        return t.program;
14498bf80f4bSopenharmony_ci    }
14508bf80f4bSopenharmony_ci    // Create new program
14518bf80f4bSopenharmony_ci    pCacheMiss_++;
14528bf80f4bSopenharmony_ci    const GLuint program = glCreateProgram();
14538bf80f4bSopenharmony_ci#if defined(CORE_USE_SEPARATE_SHADER_OBJECTS) && (CORE_USE_SEPARATE_SHADER_OBJECTS == 1)
14548bf80f4bSopenharmony_ci    // enable separable programs.
14558bf80f4bSopenharmony_ci    glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
14568bf80f4bSopenharmony_ci#endif
14578bf80f4bSopenharmony_ci    // Attach and link
14588bf80f4bSopenharmony_ci    if (vEntry.shader) {
14598bf80f4bSopenharmony_ci        glAttachShader(program, vEntry.shader);
14608bf80f4bSopenharmony_ci    }
14618bf80f4bSopenharmony_ci    if (fEntry.shader) {
14628bf80f4bSopenharmony_ci        glAttachShader(program, fEntry.shader);
14638bf80f4bSopenharmony_ci    }
14648bf80f4bSopenharmony_ci    if (cEntry.shader) {
14658bf80f4bSopenharmony_ci        glAttachShader(program, cEntry.shader);
14668bf80f4bSopenharmony_ci    }
14678bf80f4bSopenharmony_ci    glLinkProgram(program);
14688bf80f4bSopenharmony_ci    GLint result = GL_FALSE;
14698bf80f4bSopenharmony_ci    glGetProgramiv(program, GL_LINK_STATUS, &result);
14708bf80f4bSopenharmony_ci    if (result == GL_FALSE) {
14718bf80f4bSopenharmony_ci        GLint logLength = 0;
14728bf80f4bSopenharmony_ci        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
14738bf80f4bSopenharmony_ci        string messages;
14748bf80f4bSopenharmony_ci        messages.resize(static_cast<size_t>(logLength));
14758bf80f4bSopenharmony_ci        glGetProgramInfoLog(program, logLength, 0, messages.data());
14768bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
14778bf80f4bSopenharmony_ci        PLUGIN_LOG_ONCE_E("gl_shader_linking_error_" + to_string(program),
14788bf80f4bSopenharmony_ci            "RENDER_VALIDATION: Shader linking error: %s", messages.c_str());
14798bf80f4bSopenharmony_ci#endif
14808bf80f4bSopenharmony_ci        glDeleteProgram(program);
14818bf80f4bSopenharmony_ci        return 0U;
14828bf80f4bSopenharmony_ci    }
14838bf80f4bSopenharmony_ci    // Add the program to cache
14848bf80f4bSopenharmony_ci    programs_.push_back(
14858bf80f4bSopenharmony_ci        { program, vEntry.shader, fEntry.shader, cEntry.shader, vEntry.hash, fEntry.hash, cEntry.hash, 1 });
14868bf80f4bSopenharmony_ci    return program;
14878bf80f4bSopenharmony_ci}
14888bf80f4bSopenharmony_ci
14898bf80f4bSopenharmony_civoid DeviceGLES::UseProgram(uint32_t program)
14908bf80f4bSopenharmony_ci{
14918bf80f4bSopenharmony_ci    if (boundProgram_ != program) {
14928bf80f4bSopenharmony_ci        boundProgram_ = program;
14938bf80f4bSopenharmony_ci        glUseProgram(static_cast<GLuint>(program));
14948bf80f4bSopenharmony_ci    }
14958bf80f4bSopenharmony_ci}
14968bf80f4bSopenharmony_ci
14978bf80f4bSopenharmony_civoid DeviceGLES::BindBuffer(uint32_t target, uint32_t buffer)
14988bf80f4bSopenharmony_ci{
14998bf80f4bSopenharmony_ci    const uint32_t targetId = GenericTargetToTargetId(target);
15008bf80f4bSopenharmony_ci    auto& state = bufferBound_[targetId];
15018bf80f4bSopenharmony_ci    if ((!state.bound) || (state.buffer != buffer)) {
15028bf80f4bSopenharmony_ci        state.bound = true;
15038bf80f4bSopenharmony_ci        state.buffer = buffer;
15048bf80f4bSopenharmony_ci        glBindBuffer(target, static_cast<GLuint>(buffer));
15058bf80f4bSopenharmony_ci    }
15068bf80f4bSopenharmony_ci}
15078bf80f4bSopenharmony_ci
15088bf80f4bSopenharmony_civoid DeviceGLES::BindBufferRange(uint32_t target, uint32_t binding, uint32_t buffer, uint64_t offset, uint64_t size)
15098bf80f4bSopenharmony_ci{
15108bf80f4bSopenharmony_ci    const uint32_t targetId = IndexedTargetToTargetId(target);
15118bf80f4bSopenharmony_ci    auto& slot = boundBuffers_[targetId][binding];
15128bf80f4bSopenharmony_ci
15138bf80f4bSopenharmony_ci    if ((slot.cached == false) || (slot.buffer != buffer) || (slot.offset != offset) || (slot.size != size)) {
15148bf80f4bSopenharmony_ci        slot.cached = true;
15158bf80f4bSopenharmony_ci        slot.buffer = buffer;
15168bf80f4bSopenharmony_ci        slot.offset = offset;
15178bf80f4bSopenharmony_ci        slot.size = size;
15188bf80f4bSopenharmony_ci        glBindBufferRange(target, binding, buffer, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
15198bf80f4bSopenharmony_ci        // BindBufferRange sets the "generic" binding too. so make sure cache state is correct.
15208bf80f4bSopenharmony_ci        const uint32_t targetId2 = GenericTargetToTargetId(target);
15218bf80f4bSopenharmony_ci        auto& state = bufferBound_[targetId2];
15228bf80f4bSopenharmony_ci        state.bound = true;
15238bf80f4bSopenharmony_ci        state.buffer = buffer;
15248bf80f4bSopenharmony_ci    }
15258bf80f4bSopenharmony_ci    // NOTE: we are not forcing the generic bind point here. use BindBuffer to set the generic one if needed!
15268bf80f4bSopenharmony_ci}
15278bf80f4bSopenharmony_ci
15288bf80f4bSopenharmony_civoid DeviceGLES::BindSampler(uint32_t textureUnit, uint32_t sampler)
15298bf80f4bSopenharmony_ci{
15308bf80f4bSopenharmony_ci    if ((sampler + 1) != boundSampler_[textureUnit]) {
15318bf80f4bSopenharmony_ci        boundSampler_[textureUnit] = sampler + 1;
15328bf80f4bSopenharmony_ci        glBindSampler(textureUnit, sampler);
15338bf80f4bSopenharmony_ci    }
15348bf80f4bSopenharmony_ci}
15358bf80f4bSopenharmony_ci
15368bf80f4bSopenharmony_ciuint32_t DeviceGLES::BoundReadFrameBuffer() const
15378bf80f4bSopenharmony_ci{
15388bf80f4bSopenharmony_ci    return boundReadFbo_;
15398bf80f4bSopenharmony_ci}
15408bf80f4bSopenharmony_ci
15418bf80f4bSopenharmony_ciuint32_t DeviceGLES::BoundWriteFrameBuffer() const
15428bf80f4bSopenharmony_ci{
15438bf80f4bSopenharmony_ci    return boundWriteFbo_;
15448bf80f4bSopenharmony_ci}
15458bf80f4bSopenharmony_ci
15468bf80f4bSopenharmony_ciuint32_t DeviceGLES::BoundProgram() const
15478bf80f4bSopenharmony_ci{
15488bf80f4bSopenharmony_ci    return boundProgram_;
15498bf80f4bSopenharmony_ci}
15508bf80f4bSopenharmony_ci
15518bf80f4bSopenharmony_ciuint32_t DeviceGLES::BoundBuffer(uint32_t target) const
15528bf80f4bSopenharmony_ci{
15538bf80f4bSopenharmony_ci    const uint32_t targetId = GenericTargetToTargetId(target);
15548bf80f4bSopenharmony_ci    if (targetId >= MAX_BUFFER_BIND_ID) {
15558bf80f4bSopenharmony_ci        return 0;
15568bf80f4bSopenharmony_ci    }
15578bf80f4bSopenharmony_ci    const auto& slot = bufferBound_[targetId];
15588bf80f4bSopenharmony_ci    if (!slot.bound) {
15598bf80f4bSopenharmony_ci        return 0;
15608bf80f4bSopenharmony_ci    }
15618bf80f4bSopenharmony_ci    return slot.buffer;
15628bf80f4bSopenharmony_ci}
15638bf80f4bSopenharmony_ci
15648bf80f4bSopenharmony_ciuint32_t DeviceGLES::BoundBuffer(uint32_t target, uint32_t binding) const
15658bf80f4bSopenharmony_ci{
15668bf80f4bSopenharmony_ci    const uint32_t targetId = IndexedTargetToTargetId(target);
15678bf80f4bSopenharmony_ci    if (targetId >= MAX_BUFFER_BIND_ID || binding >= MAX_BINDING_VALUE) {
15688bf80f4bSopenharmony_ci        return 0;
15698bf80f4bSopenharmony_ci    }
15708bf80f4bSopenharmony_ci    const auto& slot = boundBuffers_[targetId][binding];
15718bf80f4bSopenharmony_ci    if (!slot.cached) {
15728bf80f4bSopenharmony_ci        return 0;
15738bf80f4bSopenharmony_ci    }
15748bf80f4bSopenharmony_ci    return slot.buffer;
15758bf80f4bSopenharmony_ci}
15768bf80f4bSopenharmony_ci
15778bf80f4bSopenharmony_ciuint32_t DeviceGLES::BoundSampler(uint32_t textureUnit) const
15788bf80f4bSopenharmony_ci{
15798bf80f4bSopenharmony_ci    if (textureUnit >= MAX_SAMPLERS) {
15808bf80f4bSopenharmony_ci        return 0;
15818bf80f4bSopenharmony_ci    }
15828bf80f4bSopenharmony_ci    const uint32_t bound = boundSampler_[textureUnit];
15838bf80f4bSopenharmony_ci    return bound ? (bound - 1) : bound;
15848bf80f4bSopenharmony_ci}
15858bf80f4bSopenharmony_ci
15868bf80f4bSopenharmony_ciuint32_t DeviceGLES::BoundTexture(uint32_t textureUnit, uint32_t target) const
15878bf80f4bSopenharmony_ci{
15888bf80f4bSopenharmony_ci    const uint32_t targetId = TextureTargetToTargetId(target);
15898bf80f4bSopenharmony_ci    if (textureUnit >= MAX_TEXTURE_UNITS || targetId >= MAX_TEXTURE_TARGET_ID) {
15908bf80f4bSopenharmony_ci        return 0;
15918bf80f4bSopenharmony_ci    }
15928bf80f4bSopenharmony_ci    const uint32_t bound = boundTexture_[textureUnit][targetId];
15938bf80f4bSopenharmony_ci    if (bound == 0) {
15948bf80f4bSopenharmony_ci        return 0; // bound 0 == nothing has been bound via cache yet.
15958bf80f4bSopenharmony_ci    }
15968bf80f4bSopenharmony_ci    return bound - 1;
15978bf80f4bSopenharmony_ci}
15988bf80f4bSopenharmony_ci
15998bf80f4bSopenharmony_civoid DeviceGLES::BindImageTexture(
16008bf80f4bSopenharmony_ci    uint32_t unit, uint32_t texture, uint32_t level, bool layered, uint32_t layer, uint32_t access, uint32_t format)
16018bf80f4bSopenharmony_ci{
16028bf80f4bSopenharmony_ci    auto& image = boundImage_[unit];
16038bf80f4bSopenharmony_ci    if ((!image.bound) || (image.texture != texture) || (image.level != level) || (image.layered != layered) ||
16048bf80f4bSopenharmony_ci        (image.access != access) || (image.format != format)) {
16058bf80f4bSopenharmony_ci        image.bound = true;
16068bf80f4bSopenharmony_ci        image.texture = texture;
16078bf80f4bSopenharmony_ci        image.level = level;
16088bf80f4bSopenharmony_ci        image.layered = layered;
16098bf80f4bSopenharmony_ci        image.access = access;
16108bf80f4bSopenharmony_ci        image.format = format;
16118bf80f4bSopenharmony_ci        glBindImageTexture(static_cast<GLuint>(unit), static_cast<GLuint>(texture), static_cast<GLint>(level),
16128bf80f4bSopenharmony_ci            static_cast<GLboolean>(layered), static_cast<GLint>(layer), static_cast<GLenum>(access),
16138bf80f4bSopenharmony_ci            static_cast<GLenum>(format));
16148bf80f4bSopenharmony_ci    }
16158bf80f4bSopenharmony_ci}
16168bf80f4bSopenharmony_ci
16178bf80f4bSopenharmony_civoid DeviceGLES::SetActiveTextureUnit(uint32_t textureUnit)
16188bf80f4bSopenharmony_ci{
16198bf80f4bSopenharmony_ci    if ((textureUnit + 1) != activeTextureUnit_) {
16208bf80f4bSopenharmony_ci        activeTextureUnit_ = textureUnit + 1;
16218bf80f4bSopenharmony_ci        glActiveTexture(GL_TEXTURE0 + textureUnit);
16228bf80f4bSopenharmony_ci    }
16238bf80f4bSopenharmony_ci}
16248bf80f4bSopenharmony_ci
16258bf80f4bSopenharmony_civoid DeviceGLES::BindTexture(uint32_t textureUnit, uint32_t target, uint32_t texture)
16268bf80f4bSopenharmony_ci{
16278bf80f4bSopenharmony_ci    const uint32_t targetId = TextureTargetToTargetId(target);
16288bf80f4bSopenharmony_ci#if RENDER_HAS_GLES_BACKEND
16298bf80f4bSopenharmony_ci    if (target == GL_TEXTURE_EXTERNAL_OES) {
16308bf80f4bSopenharmony_ci        // Work around for oes textures needing a bind to zero to update.
16318bf80f4bSopenharmony_ci        SetActiveTextureUnit(textureUnit);
16328bf80f4bSopenharmony_ci        glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
16338bf80f4bSopenharmony_ci        boundTexture_[textureUnit][targetId] = 0;
16348bf80f4bSopenharmony_ci        // Force the default sampler for OES textures.
16358bf80f4bSopenharmony_ci        BindSampler(textureUnit, 0);
16368bf80f4bSopenharmony_ci    }
16378bf80f4bSopenharmony_ci#endif
16388bf80f4bSopenharmony_ci    if ((texture + 1) != boundTexture_[textureUnit][targetId]) {
16398bf80f4bSopenharmony_ci        SetActiveTextureUnit(textureUnit);
16408bf80f4bSopenharmony_ci        boundTexture_[textureUnit][targetId] = texture + 1;
16418bf80f4bSopenharmony_ci        // remap the cubemap layer ids...
16428bf80f4bSopenharmony_ci        switch (target) {
16438bf80f4bSopenharmony_ci            case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
16448bf80f4bSopenharmony_ci            case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
16458bf80f4bSopenharmony_ci            case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
16468bf80f4bSopenharmony_ci            case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
16478bf80f4bSopenharmony_ci            case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
16488bf80f4bSopenharmony_ci            case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
16498bf80f4bSopenharmony_ci                glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
16508bf80f4bSopenharmony_ci                break;
16518bf80f4bSopenharmony_ci            default:
16528bf80f4bSopenharmony_ci                glBindTexture(target, texture);
16538bf80f4bSopenharmony_ci                break;
16548bf80f4bSopenharmony_ci        }
16558bf80f4bSopenharmony_ci    }
16568bf80f4bSopenharmony_ci}
16578bf80f4bSopenharmony_ci
16588bf80f4bSopenharmony_civoid DeviceGLES::TexSwizzle(uint32_t image, uint32_t target, const Math::UVec4& swizzle)
16598bf80f4bSopenharmony_ci{
16608bf80f4bSopenharmony_ci    // set only if not default..
16618bf80f4bSopenharmony_ci    if ((swizzle.x != GL_RED) || (swizzle.y != GL_GREEN) || (swizzle.z != GL_BLUE) || (swizzle.w != GL_ALPHA)) {
16628bf80f4bSopenharmony_ci        SetActiveTextureUnit(TEMP_BIND_UNIT);
16638bf80f4bSopenharmony_ci        BindTexture(TEMP_BIND_UNIT, target, image);
16648bf80f4bSopenharmony_ci        glTexParameteri(static_cast<GLenum>(target), GL_TEXTURE_SWIZZLE_R, static_cast<GLint>(swizzle.x));
16658bf80f4bSopenharmony_ci        glTexParameteri(static_cast<GLenum>(target), GL_TEXTURE_SWIZZLE_G, static_cast<GLint>(swizzle.y));
16668bf80f4bSopenharmony_ci        glTexParameteri(static_cast<GLenum>(target), GL_TEXTURE_SWIZZLE_B, static_cast<GLint>(swizzle.z));
16678bf80f4bSopenharmony_ci        glTexParameteri(static_cast<GLenum>(target), GL_TEXTURE_SWIZZLE_A, static_cast<GLint>(swizzle.w));
16688bf80f4bSopenharmony_ci    }
16698bf80f4bSopenharmony_ci}
16708bf80f4bSopenharmony_ci
16718bf80f4bSopenharmony_civoid DeviceGLES::TexStorage2D(
16728bf80f4bSopenharmony_ci    uint32_t image, uint32_t target, uint32_t levels, uint32_t internalformat, const Math::UVec2& extent)
16738bf80f4bSopenharmony_ci{
16748bf80f4bSopenharmony_ci    SetActiveTextureUnit(TEMP_BIND_UNIT);
16758bf80f4bSopenharmony_ci    BindTexture(TEMP_BIND_UNIT, target, image);
16768bf80f4bSopenharmony_ci    glTexStorage2D(static_cast<GLenum>(target), static_cast<GLsizei>(levels), static_cast<GLenum>(internalformat),
16778bf80f4bSopenharmony_ci        static_cast<GLsizei>(extent.x), static_cast<GLsizei>(extent.y));
16788bf80f4bSopenharmony_ci}
16798bf80f4bSopenharmony_ci
16808bf80f4bSopenharmony_civoid DeviceGLES::TexStorage2DMultisample(uint32_t image, uint32_t target, uint32_t samples, uint32_t internalformat,
16818bf80f4bSopenharmony_ci    const Math::UVec2& extent, bool fixedsamplelocations)
16828bf80f4bSopenharmony_ci{
16838bf80f4bSopenharmony_ci    SetActiveTextureUnit(TEMP_BIND_UNIT);
16848bf80f4bSopenharmony_ci    BindTexture(TEMP_BIND_UNIT, target, image);
16858bf80f4bSopenharmony_ci    glTexStorage2DMultisample(static_cast<GLenum>(target), static_cast<GLsizei>(samples),
16868bf80f4bSopenharmony_ci        static_cast<GLenum>(internalformat), static_cast<GLsizei>(extent.x), static_cast<GLsizei>(extent.y),
16878bf80f4bSopenharmony_ci        fixedsamplelocations);
16888bf80f4bSopenharmony_ci}
16898bf80f4bSopenharmony_ci
16908bf80f4bSopenharmony_civoid DeviceGLES::TexStorage3D(
16918bf80f4bSopenharmony_ci    uint32_t image, uint32_t target, uint32_t levels, uint32_t internalformat, const Math::UVec3& extent)
16928bf80f4bSopenharmony_ci{
16938bf80f4bSopenharmony_ci    SetActiveTextureUnit(TEMP_BIND_UNIT);
16948bf80f4bSopenharmony_ci    BindTexture(TEMP_BIND_UNIT, target, image);
16958bf80f4bSopenharmony_ci    glTexStorage3D((GLenum)target, (GLsizei)levels, (GLenum)internalformat, (GLsizei)extent.x, (GLsizei)extent.y,
16968bf80f4bSopenharmony_ci        (GLsizei)extent.z);
16978bf80f4bSopenharmony_ci}
16988bf80f4bSopenharmony_ci
16998bf80f4bSopenharmony_civoid DeviceGLES::TexSubImage2D(uint32_t image, uint32_t target, uint32_t level, const Math::UVec2& offset,
17008bf80f4bSopenharmony_ci    const Math::UVec2& extent, uint32_t format, uint32_t type, const void* pixels)
17018bf80f4bSopenharmony_ci{
17028bf80f4bSopenharmony_ci    SetActiveTextureUnit(TEMP_BIND_UNIT);
17038bf80f4bSopenharmony_ci    BindTexture(TEMP_BIND_UNIT, target, image);
17048bf80f4bSopenharmony_ci    glTexSubImage2D((GLenum)target, (GLint)level, (GLint)offset.x, (GLint)offset.y, (GLsizei)extent.x,
17058bf80f4bSopenharmony_ci        (GLsizei)extent.y, (GLenum)format, (GLenum)type, pixels);
17068bf80f4bSopenharmony_ci}
17078bf80f4bSopenharmony_ci
17088bf80f4bSopenharmony_civoid DeviceGLES::TexSubImage3D(uint32_t image, uint32_t target, uint32_t level, const Math::UVec3& offset,
17098bf80f4bSopenharmony_ci    const Math::UVec3& extent, uint32_t format, uint32_t type, const void* pixels)
17108bf80f4bSopenharmony_ci{
17118bf80f4bSopenharmony_ci    SetActiveTextureUnit(TEMP_BIND_UNIT);
17128bf80f4bSopenharmony_ci    BindTexture(TEMP_BIND_UNIT, target, image);
17138bf80f4bSopenharmony_ci    glTexSubImage3D((GLenum)target, (GLint)level, (GLint)offset.x, (GLint)offset.y, (GLint)offset.z, (GLsizei)extent.x,
17148bf80f4bSopenharmony_ci        (GLsizei)extent.y, (GLsizei)extent.z, (GLenum)format, (GLenum)type, pixels);
17158bf80f4bSopenharmony_ci}
17168bf80f4bSopenharmony_ci
17178bf80f4bSopenharmony_civoid DeviceGLES::CompressedTexSubImage2D(uint32_t image, uint32_t target, uint32_t level, const Math::UVec2& offset,
17188bf80f4bSopenharmony_ci    const Math::UVec2& extent, uint32_t format, uint32_t imageSize, const void* data)
17198bf80f4bSopenharmony_ci{
17208bf80f4bSopenharmony_ci    SetActiveTextureUnit(TEMP_BIND_UNIT);
17218bf80f4bSopenharmony_ci    BindTexture(TEMP_BIND_UNIT, target, image);
17228bf80f4bSopenharmony_ci    glCompressedTexSubImage2D((GLenum)target, (GLint)level, (GLint)offset.x, (GLint)offset.y, (GLsizei)extent.x,
17238bf80f4bSopenharmony_ci        (GLsizei)extent.y, (GLenum)format, (GLint)imageSize, data);
17248bf80f4bSopenharmony_ci}
17258bf80f4bSopenharmony_ci
17268bf80f4bSopenharmony_civoid DeviceGLES::CompressedTexSubImage3D(uint32_t image, uint32_t target, uint32_t level, const Math::UVec3& offset,
17278bf80f4bSopenharmony_ci    const Math::UVec3& extent, uint32_t format, uint32_t imageSize, const void* data)
17288bf80f4bSopenharmony_ci{
17298bf80f4bSopenharmony_ci    SetActiveTextureUnit(TEMP_BIND_UNIT);
17308bf80f4bSopenharmony_ci    BindTexture(TEMP_BIND_UNIT, target, image);
17318bf80f4bSopenharmony_ci    glCompressedTexSubImage3D((GLenum)target, (GLint)level, (GLint)offset.x, (GLint)offset.y, (GLint)offset.z,
17328bf80f4bSopenharmony_ci        (GLsizei)extent.x, (GLsizei)extent.y, (GLsizei)extent.z, (GLenum)format, (GLint)imageSize, data);
17338bf80f4bSopenharmony_ci}
17348bf80f4bSopenharmony_ci
17358bf80f4bSopenharmony_ciconst DeviceGLES::ImageFormat& DeviceGLES::GetGlImageFormat(const Format format) const
17368bf80f4bSopenharmony_ci{
17378bf80f4bSopenharmony_ci    if (const auto pos = std::lower_bound(supportedFormats_.begin(), supportedFormats_.end(), format,
17388bf80f4bSopenharmony_ci            [](const ImageFormat& element, const Format value) { return element.coreFormat < value; });
17398bf80f4bSopenharmony_ci        (pos != supportedFormats_.end()) && (pos->coreFormat == format)) {
17408bf80f4bSopenharmony_ci        return *pos;
17418bf80f4bSopenharmony_ci    }
17428bf80f4bSopenharmony_ci    if (const auto pos = std::lower_bound(std::begin(IMAGE_FORMATS_FALLBACK), std::end(IMAGE_FORMATS_FALLBACK), format,
17438bf80f4bSopenharmony_ci            [](const ImageFormat& element, const Format value) { return element.coreFormat < value; });
17448bf80f4bSopenharmony_ci        (pos != std::end(IMAGE_FORMATS_FALLBACK)) && (pos->coreFormat == format)) {
17458bf80f4bSopenharmony_ci        PLUGIN_LOG_I("using fallback for format %u", format);
17468bf80f4bSopenharmony_ci        return *pos;
17478bf80f4bSopenharmony_ci    }
17488bf80f4bSopenharmony_ci    PLUGIN_LOG_I("asking for unsupported format %u", format);
17498bf80f4bSopenharmony_ci    return supportedFormats_[0];
17508bf80f4bSopenharmony_ci}
17518bf80f4bSopenharmony_ci
17528bf80f4bSopenharmony_civoid DeviceGLES::DeleteTexture(uint32_t texture)
17538bf80f4bSopenharmony_ci{
17548bf80f4bSopenharmony_ci    UnBindTexture(texture);
17558bf80f4bSopenharmony_ci    glDeleteTextures(1, &texture);
17568bf80f4bSopenharmony_ci}
17578bf80f4bSopenharmony_ci
17588bf80f4bSopenharmony_civoid DeviceGLES::DeleteBuffer(uint32_t buffer)
17598bf80f4bSopenharmony_ci{
17608bf80f4bSopenharmony_ci    UnBindBuffer(buffer);
17618bf80f4bSopenharmony_ci    glDeleteBuffers(1, &buffer);
17628bf80f4bSopenharmony_ci}
17638bf80f4bSopenharmony_ci
17648bf80f4bSopenharmony_civoid DeviceGLES::DeleteSampler(uint32_t sampler)
17658bf80f4bSopenharmony_ci{
17668bf80f4bSopenharmony_ci    UnBindSampler(sampler);
17678bf80f4bSopenharmony_ci    glDeleteSamplers(1, &sampler);
17688bf80f4bSopenharmony_ci}
17698bf80f4bSopenharmony_ci
17708bf80f4bSopenharmony_ciuint32_t DeviceGLES::CreateVertexArray()
17718bf80f4bSopenharmony_ci{
17728bf80f4bSopenharmony_ci    GLuint vao;
17738bf80f4bSopenharmony_ci    glGenVertexArrays(1, &vao);
17748bf80f4bSopenharmony_ci    if (vaoStatesInUse_ == vaoStates_.size()) {
17758bf80f4bSopenharmony_ci        for (auto it = vaoStates_.begin(); it != vaoStates_.end(); it++) {
17768bf80f4bSopenharmony_ci            if (it->vao == 0) {
17778bf80f4bSopenharmony_ci                // re-use old "object"
17788bf80f4bSopenharmony_ci                it->vao = vao;
17798bf80f4bSopenharmony_ci                vaoStatesInUse_++;
17808bf80f4bSopenharmony_ci                return static_cast<uint32_t>(1 + (it - vaoStates_.begin()));
17818bf80f4bSopenharmony_ci            }
17828bf80f4bSopenharmony_ci        }
17838bf80f4bSopenharmony_ci    }
17848bf80f4bSopenharmony_ci    VAOState v;
17858bf80f4bSopenharmony_ci    v.vao = vao;
17868bf80f4bSopenharmony_ci    vaoStates_.push_back(v);
17878bf80f4bSopenharmony_ci    vaoStatesInUse_++;
17888bf80f4bSopenharmony_ci    return static_cast<uint32_t>(vaoStates_.size());
17898bf80f4bSopenharmony_ci}
17908bf80f4bSopenharmony_ci
17918bf80f4bSopenharmony_civoid DeviceGLES::DeleteVertexArray(uint32_t vao)
17928bf80f4bSopenharmony_ci{
17938bf80f4bSopenharmony_ci    PLUGIN_ASSERT(!vaoStates_.empty());
17948bf80f4bSopenharmony_ci    if (vao > 0) {
17958bf80f4bSopenharmony_ci        UnBindVertexArray(vao);
17968bf80f4bSopenharmony_ci        auto& state = vaoStates_[vao - 1];
17978bf80f4bSopenharmony_ci        glDeleteVertexArrays(1, &state.vao);
17988bf80f4bSopenharmony_ci        state = {}; // clear the object.
17998bf80f4bSopenharmony_ci        vaoStatesInUse_--;
18008bf80f4bSopenharmony_ci    }
18018bf80f4bSopenharmony_ci}
18028bf80f4bSopenharmony_ci
18038bf80f4bSopenharmony_civoid DeviceGLES::DeleteFrameBuffer(uint32_t fbo)
18048bf80f4bSopenharmony_ci{
18058bf80f4bSopenharmony_ci    PLUGIN_ASSERT(IsActive());
18068bf80f4bSopenharmony_ci    UnBindFrameBuffer(fbo);
18078bf80f4bSopenharmony_ci    glDeleteFramebuffers(1, &fbo);
18088bf80f4bSopenharmony_ci#if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
18098bf80f4bSopenharmony_ci    PLUGIN_LOG_D("fbo id <: %u", fbo);
18108bf80f4bSopenharmony_ci#endif
18118bf80f4bSopenharmony_ci}
18128bf80f4bSopenharmony_ci
18138bf80f4bSopenharmony_civoid DeviceGLES::UnBindTexture(uint32_t texture)
18148bf80f4bSopenharmony_ci{
18158bf80f4bSopenharmony_ci    uint32_t unit = 0;
18168bf80f4bSopenharmony_ci    for (auto& textureUnit : boundTexture_) {
18178bf80f4bSopenharmony_ci        uint32_t targetId = 0;
18188bf80f4bSopenharmony_ci        for (uint32_t& typeBinding : textureUnit) {
18198bf80f4bSopenharmony_ci            if (typeBinding == texture + 1) {
18208bf80f4bSopenharmony_ci                SetActiveTextureUnit(unit);
18218bf80f4bSopenharmony_ci                const uint32_t target = TextureTargetIdToTarget(TextureTargetId { targetId });
18228bf80f4bSopenharmony_ci                glBindTexture(target, 0);
18238bf80f4bSopenharmony_ci                typeBinding = 0;
18248bf80f4bSopenharmony_ci            }
18258bf80f4bSopenharmony_ci            targetId++;
18268bf80f4bSopenharmony_ci        }
18278bf80f4bSopenharmony_ci        unit++;
18288bf80f4bSopenharmony_ci    }
18298bf80f4bSopenharmony_ci
18308bf80f4bSopenharmony_ci    unit = 0;
18318bf80f4bSopenharmony_ci    for (auto& image : boundImage_) {
18328bf80f4bSopenharmony_ci        if ((image.bound) && (image.texture == texture)) {
18338bf80f4bSopenharmony_ci            glBindImageTexture(static_cast<GLuint>(unit), 0, 0, false, 0, GL_READ_ONLY, GL_R32UI);
18348bf80f4bSopenharmony_ci            // set default state...
18358bf80f4bSopenharmony_ci            image.bound = false;
18368bf80f4bSopenharmony_ci            image.texture = 0;
18378bf80f4bSopenharmony_ci            image.level = 0;
18388bf80f4bSopenharmony_ci            image.layered = false;
18398bf80f4bSopenharmony_ci            image.access = GL_READ_ONLY;
18408bf80f4bSopenharmony_ci            image.format = GL_R32UI;
18418bf80f4bSopenharmony_ci        }
18428bf80f4bSopenharmony_ci        unit++;
18438bf80f4bSopenharmony_ci    }
18448bf80f4bSopenharmony_ci}
18458bf80f4bSopenharmony_ci
18468bf80f4bSopenharmony_civoid DeviceGLES::UnBindBuffer(uint32_t buffer)
18478bf80f4bSopenharmony_ci{
18488bf80f4bSopenharmony_ci    uint32_t tid = 0;
18498bf80f4bSopenharmony_ci    for (auto& buffers : boundBuffers_) {
18508bf80f4bSopenharmony_ci        const uint32_t targetId = IndexedTargetIdToTarget(BufferBindId { tid });
18518bf80f4bSopenharmony_ci        uint32_t bid = 0;
18528bf80f4bSopenharmony_ci        for (auto& slot : buffers) {
18538bf80f4bSopenharmony_ci            if (slot.buffer == buffer) {
18548bf80f4bSopenharmony_ci                glBindBufferRange(targetId, bid, 0, 0, 0);
18558bf80f4bSopenharmony_ci                // nothing bound
18568bf80f4bSopenharmony_ci                slot.cached = false;
18578bf80f4bSopenharmony_ci                slot.buffer = 0;
18588bf80f4bSopenharmony_ci                slot.offset = 0;
18598bf80f4bSopenharmony_ci                slot.size = 0;
18608bf80f4bSopenharmony_ci            }
18618bf80f4bSopenharmony_ci            bid++;
18628bf80f4bSopenharmony_ci        }
18638bf80f4bSopenharmony_ci        tid++;
18648bf80f4bSopenharmony_ci    }
18658bf80f4bSopenharmony_ci
18668bf80f4bSopenharmony_ci    tid = 0;
18678bf80f4bSopenharmony_ci    for (auto& slot : bufferBound_) {
18688bf80f4bSopenharmony_ci        if (slot.buffer == buffer) {
18698bf80f4bSopenharmony_ci            const uint32_t targetId = GenericTargetIdToTarget(BufferTargetId { tid });
18708bf80f4bSopenharmony_ci            glBindBuffer(targetId, 0);
18718bf80f4bSopenharmony_ci            // nothing bound
18728bf80f4bSopenharmony_ci            slot.bound = false;
18738bf80f4bSopenharmony_ci            slot.buffer = 0;
18748bf80f4bSopenharmony_ci        }
18758bf80f4bSopenharmony_ci        tid++;
18768bf80f4bSopenharmony_ci    }
18778bf80f4bSopenharmony_ci
18788bf80f4bSopenharmony_ci    // scan VAOs also..
18798bf80f4bSopenharmony_ci    UnBindBufferFromVertexArray(buffer);
18808bf80f4bSopenharmony_ci}
18818bf80f4bSopenharmony_ci
18828bf80f4bSopenharmony_civoid DeviceGLES::UnBindBufferFromVertexArray(uint32_t buffer)
18838bf80f4bSopenharmony_ci{
18848bf80f4bSopenharmony_ci    uint32_t vao = 1;
18858bf80f4bSopenharmony_ci    uint32_t wasbound = BoundVertexArray();
18868bf80f4bSopenharmony_ci    for (auto& state : vaoStates_) {
18878bf80f4bSopenharmony_ci        if (state.vao > 0) {
18888bf80f4bSopenharmony_ci            auto& elementBuffer = state.elementBuffer;
18898bf80f4bSopenharmony_ci            auto& vertexBufferBinds = state.vertexBufferBinds;
18908bf80f4bSopenharmony_ci            int slot = 0;
18918bf80f4bSopenharmony_ci            for (auto& t : vertexBufferBinds) {
18928bf80f4bSopenharmony_ci                if ((t.bound) && (t.buffer == buffer)) {
18938bf80f4bSopenharmony_ci                    // detach the buffer from vao.
18948bf80f4bSopenharmony_ci                    BindVertexArray(vao);
18958bf80f4bSopenharmony_ci                    glBindVertexBuffer((GLuint)slot, 0, 0, 0);
18968bf80f4bSopenharmony_ci                    t.bound = false;
18978bf80f4bSopenharmony_ci                    t.buffer = 0;
18988bf80f4bSopenharmony_ci                    t.offset = 0;
18998bf80f4bSopenharmony_ci                    t.stride = 0;
19008bf80f4bSopenharmony_ci                }
19018bf80f4bSopenharmony_ci                slot++;
19028bf80f4bSopenharmony_ci            }
19038bf80f4bSopenharmony_ci            if ((elementBuffer.bound) && (elementBuffer.buffer == buffer)) {
19048bf80f4bSopenharmony_ci                // detach the buffer from vao.
19058bf80f4bSopenharmony_ci                BindVertexArray(vao);
19068bf80f4bSopenharmony_ci                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
19078bf80f4bSopenharmony_ci                elementBuffer.bound = false;
19088bf80f4bSopenharmony_ci                elementBuffer.buffer = 0;
19098bf80f4bSopenharmony_ci            }
19108bf80f4bSopenharmony_ci        }
19118bf80f4bSopenharmony_ci        vao++;
19128bf80f4bSopenharmony_ci    }
19138bf80f4bSopenharmony_ci    BindVertexArray(wasbound);
19148bf80f4bSopenharmony_ci}
19158bf80f4bSopenharmony_ci
19168bf80f4bSopenharmony_civoid DeviceGLES::UnBindSampler(uint32_t sampler)
19178bf80f4bSopenharmony_ci{
19188bf80f4bSopenharmony_ci    for (uint32_t& boundSampler : boundSampler_) {
19198bf80f4bSopenharmony_ci        if ((sampler + 1) == boundSampler) {
19208bf80f4bSopenharmony_ci            glBindSampler((sampler + 1), 0);
19218bf80f4bSopenharmony_ci            boundSampler = 0;
19228bf80f4bSopenharmony_ci        }
19238bf80f4bSopenharmony_ci    }
19248bf80f4bSopenharmony_ci}
19258bf80f4bSopenharmony_ci
19268bf80f4bSopenharmony_civoid DeviceGLES::UnBindVertexArray(uint32_t vao)
19278bf80f4bSopenharmony_ci{
19288bf80f4bSopenharmony_ci    if (boundVao_ == vao) {
19298bf80f4bSopenharmony_ci        glBindVertexArray(0);
19308bf80f4bSopenharmony_ci        boundVao_ = 0;
19318bf80f4bSopenharmony_ci    }
19328bf80f4bSopenharmony_ci}
19338bf80f4bSopenharmony_ci
19348bf80f4bSopenharmony_civoid DeviceGLES::UnBindFrameBuffer(uint32_t fbo)
19358bf80f4bSopenharmony_ci{
19368bf80f4bSopenharmony_ci    if ((fbo == boundReadFbo_) && (fbo == boundWriteFbo_)) {
19378bf80f4bSopenharmony_ci        boundReadFbo_ = 0;
19388bf80f4bSopenharmony_ci        boundWriteFbo_ = 0;
19398bf80f4bSopenharmony_ci        glBindFramebuffer(GL_FRAMEBUFFER, 0);
19408bf80f4bSopenharmony_ci    } else if (boundWriteFbo_ == fbo) {
19418bf80f4bSopenharmony_ci        boundWriteFbo_ = 0;
19428bf80f4bSopenharmony_ci        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
19438bf80f4bSopenharmony_ci    } else if (boundReadFbo_ == fbo) {
19448bf80f4bSopenharmony_ci        boundReadFbo_ = 0;
19458bf80f4bSopenharmony_ci        glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
19468bf80f4bSopenharmony_ci    }
19478bf80f4bSopenharmony_ci}
19488bf80f4bSopenharmony_ci
19498bf80f4bSopenharmony_ciuint32_t DeviceGLES::BoundVertexArray() const
19508bf80f4bSopenharmony_ci{
19518bf80f4bSopenharmony_ci    return boundVao_;
19528bf80f4bSopenharmony_ci}
19538bf80f4bSopenharmony_ci
19548bf80f4bSopenharmony_civoid DeviceGLES::BindFrameBuffer(uint32_t fbo)
19558bf80f4bSopenharmony_ci{
19568bf80f4bSopenharmony_ci    if ((boundReadFbo_ != fbo) && (boundWriteFbo_ != fbo)) {
19578bf80f4bSopenharmony_ci        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
19588bf80f4bSopenharmony_ci        boundReadFbo_ = boundWriteFbo_ = fbo;
19598bf80f4bSopenharmony_ci    } else if (boundWriteFbo_ != fbo) {
19608bf80f4bSopenharmony_ci        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
19618bf80f4bSopenharmony_ci        boundWriteFbo_ = fbo;
19628bf80f4bSopenharmony_ci    } else if (boundReadFbo_ != fbo) {
19638bf80f4bSopenharmony_ci        glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
19648bf80f4bSopenharmony_ci        boundReadFbo_ = fbo;
19658bf80f4bSopenharmony_ci    }
19668bf80f4bSopenharmony_ci}
19678bf80f4bSopenharmony_ci
19688bf80f4bSopenharmony_civoid DeviceGLES::BindReadFrameBuffer(uint32_t fbo)
19698bf80f4bSopenharmony_ci{
19708bf80f4bSopenharmony_ci    if (boundReadFbo_ != fbo) {
19718bf80f4bSopenharmony_ci        glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
19728bf80f4bSopenharmony_ci        boundReadFbo_ = fbo;
19738bf80f4bSopenharmony_ci    }
19748bf80f4bSopenharmony_ci}
19758bf80f4bSopenharmony_ci
19768bf80f4bSopenharmony_civoid DeviceGLES::BindWriteFrameBuffer(uint32_t fbo)
19778bf80f4bSopenharmony_ci{
19788bf80f4bSopenharmony_ci    if (boundWriteFbo_ != fbo) {
19798bf80f4bSopenharmony_ci        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
19808bf80f4bSopenharmony_ci        boundWriteFbo_ = fbo;
19818bf80f4bSopenharmony_ci    }
19828bf80f4bSopenharmony_ci}
19838bf80f4bSopenharmony_ci
19848bf80f4bSopenharmony_civoid DeviceGLES::BindVertexArray(uint32_t vao)
19858bf80f4bSopenharmony_ci{
19868bf80f4bSopenharmony_ci    if (boundVao_ != vao) {
19878bf80f4bSopenharmony_ci        PLUGIN_ASSERT(vao <= vaoStates_.size());
19888bf80f4bSopenharmony_ci        if (vao > 0) {
19898bf80f4bSopenharmony_ci            glBindVertexArray(vaoStates_[vao - 1].vao);
19908bf80f4bSopenharmony_ci        } else {
19918bf80f4bSopenharmony_ci            glBindVertexArray(0);
19928bf80f4bSopenharmony_ci        }
19938bf80f4bSopenharmony_ci        boundVao_ = vao;
19948bf80f4bSopenharmony_ci    }
19958bf80f4bSopenharmony_ci}
19968bf80f4bSopenharmony_ci
19978bf80f4bSopenharmony_civoid DeviceGLES::BindVertexBuffer(uint32_t slot, uint32_t buffer, intptr_t offset, intptr_t stride)
19988bf80f4bSopenharmony_ci{
19998bf80f4bSopenharmony_ci    PLUGIN_ASSERT(boundVao_ > 0);
20008bf80f4bSopenharmony_ci    PLUGIN_ASSERT(boundVao_ <= vaoStates_.size());
20018bf80f4bSopenharmony_ci    auto& vertexBufferBinds = vaoStates_[boundVao_ - 1].vertexBufferBinds;
20028bf80f4bSopenharmony_ci    bool bind = true;
20038bf80f4bSopenharmony_ci    if (vertexBufferBinds[slot].bound) {
20048bf80f4bSopenharmony_ci        bind = (vertexBufferBinds[slot].buffer != buffer) || (vertexBufferBinds[slot].offset != offset) ||
20058bf80f4bSopenharmony_ci               (vertexBufferBinds[slot].stride != stride);
20068bf80f4bSopenharmony_ci    }
20078bf80f4bSopenharmony_ci    if (bind) {
20088bf80f4bSopenharmony_ci        vertexBufferBinds[slot].bound = true;
20098bf80f4bSopenharmony_ci        vertexBufferBinds[slot].buffer = buffer;
20108bf80f4bSopenharmony_ci        vertexBufferBinds[slot].offset = offset;
20118bf80f4bSopenharmony_ci        vertexBufferBinds[slot].stride = stride;
20128bf80f4bSopenharmony_ci        glBindVertexBuffer((GLuint)slot, (GLuint)buffer, (GLintptr)offset, (GLsizei)stride);
20138bf80f4bSopenharmony_ci    }
20148bf80f4bSopenharmony_ci}
20158bf80f4bSopenharmony_ci
20168bf80f4bSopenharmony_civoid DeviceGLES::VertexBindingDivisor(uint32_t slot, uint32_t divisor)
20178bf80f4bSopenharmony_ci{
20188bf80f4bSopenharmony_ci    PLUGIN_ASSERT(boundVao_ > 0);
20198bf80f4bSopenharmony_ci    PLUGIN_ASSERT(boundVao_ <= vaoStates_.size());
20208bf80f4bSopenharmony_ci    auto& vertexBufferBinds = vaoStates_[boundVao_ - 1].vertexBufferBinds;
20218bf80f4bSopenharmony_ci    if (vertexBufferBinds[slot].divisor != divisor) {
20228bf80f4bSopenharmony_ci        vertexBufferBinds[slot].divisor = divisor;
20238bf80f4bSopenharmony_ci        glVertexBindingDivisor(slot, divisor);
20248bf80f4bSopenharmony_ci    }
20258bf80f4bSopenharmony_ci}
20268bf80f4bSopenharmony_ci
20278bf80f4bSopenharmony_civoid DeviceGLES::BindElementBuffer(uint32_t buffer)
20288bf80f4bSopenharmony_ci{
20298bf80f4bSopenharmony_ci    PLUGIN_ASSERT(boundVao_ > 0);
20308bf80f4bSopenharmony_ci    PLUGIN_ASSERT(boundVao_ <= vaoStates_.size());
20318bf80f4bSopenharmony_ci    auto& elementBuffer = vaoStates_[boundVao_ - 1].elementBuffer;
20328bf80f4bSopenharmony_ci    bool bind = true;
20338bf80f4bSopenharmony_ci    if (elementBuffer.bound) {
20348bf80f4bSopenharmony_ci        bind = (buffer != elementBuffer.buffer);
20358bf80f4bSopenharmony_ci    }
20368bf80f4bSopenharmony_ci    if (bind) {
20378bf80f4bSopenharmony_ci        elementBuffer.bound = true;
20388bf80f4bSopenharmony_ci        elementBuffer.buffer = buffer;
20398bf80f4bSopenharmony_ci        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
20408bf80f4bSopenharmony_ci    }
20418bf80f4bSopenharmony_ci}
20428bf80f4bSopenharmony_ci
20438bf80f4bSopenharmony_cibool DeviceGLES::AllowThreadedProcessing() const
20448bf80f4bSopenharmony_ci{
20458bf80f4bSopenharmony_ci    return HasExtension(EXT_BUFFER_STORAGE);
20468bf80f4bSopenharmony_ci}
20478bf80f4bSopenharmony_ci
20488bf80f4bSopenharmony_ciunique_ptr<GpuBuffer> DeviceGLES::CreateGpuBuffer(const GpuBufferDesc& desc)
20498bf80f4bSopenharmony_ci{
20508bf80f4bSopenharmony_ci    return make_unique<GpuBufferGLES>(*this, desc);
20518bf80f4bSopenharmony_ci}
20528bf80f4bSopenharmony_ci
20538bf80f4bSopenharmony_ciunique_ptr<GpuBuffer> DeviceGLES::CreateGpuBuffer(const GpuAccelerationStructureDesc& desc)
20548bf80f4bSopenharmony_ci{
20558bf80f4bSopenharmony_ci    return make_unique<GpuBufferGLES>(*this, desc.bufferDesc);
20568bf80f4bSopenharmony_ci}
20578bf80f4bSopenharmony_ci
20588bf80f4bSopenharmony_ciunique_ptr<GpuImage> DeviceGLES::CreateGpuImage(const GpuImageDesc& desc)
20598bf80f4bSopenharmony_ci{
20608bf80f4bSopenharmony_ci    return make_unique<GpuImageGLES>(*this, desc);
20618bf80f4bSopenharmony_ci}
20628bf80f4bSopenharmony_ci
20638bf80f4bSopenharmony_ciunique_ptr<GpuImage> DeviceGLES::CreateGpuImageView(const GpuImageDesc& desc, const GpuImagePlatformData& platformData)
20648bf80f4bSopenharmony_ci{
20658bf80f4bSopenharmony_ci    PLUGIN_ASSERT(IsActive());
20668bf80f4bSopenharmony_ci    return make_unique<GpuImageGLES>(*this, desc, platformData);
20678bf80f4bSopenharmony_ci}
20688bf80f4bSopenharmony_ci
20698bf80f4bSopenharmony_civector<unique_ptr<GpuImage>> DeviceGLES::CreateGpuImageViews(const Swapchain& platformSwapchain)
20708bf80f4bSopenharmony_ci{
20718bf80f4bSopenharmony_ci    vector<unique_ptr<GpuImage>> gpuImages;
20728bf80f4bSopenharmony_ci    const SwapchainGLES& swapchain = (const SwapchainGLES&)platformSwapchain;
20738bf80f4bSopenharmony_ci    const GpuImageDesc& desc = swapchain.GetDesc();
20748bf80f4bSopenharmony_ci    const auto& swapchainPlat = swapchain.GetPlatformData();
20758bf80f4bSopenharmony_ci
20768bf80f4bSopenharmony_ci    gpuImages.resize(swapchainPlat.swapchainImages.images.size());
20778bf80f4bSopenharmony_ci
20788bf80f4bSopenharmony_ci    PLUGIN_ASSERT(IsActive());
20798bf80f4bSopenharmony_ci    for (size_t idx = 0; idx < gpuImages.size(); ++idx) {
20808bf80f4bSopenharmony_ci        GpuImagePlatformDataGL gpuImagePlat {};
20818bf80f4bSopenharmony_ci        gpuImagePlat.image = swapchainPlat.swapchainImages.images[idx];
20828bf80f4bSopenharmony_ci        gpuImagePlat.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
20838bf80f4bSopenharmony_ci        gpuImages[idx] = CreateGpuImageView(desc, gpuImagePlat);
20848bf80f4bSopenharmony_ci    }
20858bf80f4bSopenharmony_ci    return gpuImages;
20868bf80f4bSopenharmony_ci}
20878bf80f4bSopenharmony_ci
20888bf80f4bSopenharmony_ciunique_ptr<GpuSampler> DeviceGLES::CreateGpuSampler(const GpuSamplerDesc& desc)
20898bf80f4bSopenharmony_ci{
20908bf80f4bSopenharmony_ci    return make_unique<GpuSamplerGLES>(*this, desc);
20918bf80f4bSopenharmony_ci}
20928bf80f4bSopenharmony_ci
20938bf80f4bSopenharmony_ciunique_ptr<RenderFrameSync> DeviceGLES::CreateRenderFrameSync()
20948bf80f4bSopenharmony_ci{
20958bf80f4bSopenharmony_ci    return make_unique<RenderFrameSyncGLES>(*this);
20968bf80f4bSopenharmony_ci}
20978bf80f4bSopenharmony_ci
20988bf80f4bSopenharmony_ciunique_ptr<RenderBackend> DeviceGLES::CreateRenderBackend(
20998bf80f4bSopenharmony_ci    GpuResourceManager& gpuResourceMgr, const CORE_NS::IParallelTaskQueue::Ptr&)
21008bf80f4bSopenharmony_ci{
21018bf80f4bSopenharmony_ci    return make_unique<RenderBackendGLES>(*this, gpuResourceMgr);
21028bf80f4bSopenharmony_ci}
21038bf80f4bSopenharmony_ci
21048bf80f4bSopenharmony_ciunique_ptr<ShaderModule> DeviceGLES::CreateShaderModule(const ShaderModuleCreateInfo& data)
21058bf80f4bSopenharmony_ci{
21068bf80f4bSopenharmony_ci    return make_unique<ShaderModuleGLES>(*this, data);
21078bf80f4bSopenharmony_ci}
21088bf80f4bSopenharmony_ci
21098bf80f4bSopenharmony_ciunique_ptr<ShaderModule> DeviceGLES::CreateComputeShaderModule(const ShaderModuleCreateInfo& data)
21108bf80f4bSopenharmony_ci{
21118bf80f4bSopenharmony_ci    return make_unique<ShaderModuleGLES>(*this, data);
21128bf80f4bSopenharmony_ci}
21138bf80f4bSopenharmony_ci
21148bf80f4bSopenharmony_ciunique_ptr<GpuShaderProgram> DeviceGLES::CreateGpuShaderProgram(const GpuShaderProgramCreateData& data)
21158bf80f4bSopenharmony_ci{
21168bf80f4bSopenharmony_ci    return make_unique<GpuShaderProgramGLES>(*this, data);
21178bf80f4bSopenharmony_ci}
21188bf80f4bSopenharmony_ci
21198bf80f4bSopenharmony_ciunique_ptr<GpuComputeProgram> DeviceGLES::CreateGpuComputeProgram(const GpuComputeProgramCreateData& data)
21208bf80f4bSopenharmony_ci{
21218bf80f4bSopenharmony_ci    return make_unique<GpuComputeProgramGLES>(*this, data);
21228bf80f4bSopenharmony_ci}
21238bf80f4bSopenharmony_ci
21248bf80f4bSopenharmony_ciunique_ptr<NodeContextDescriptorSetManager> DeviceGLES::CreateNodeContextDescriptorSetManager()
21258bf80f4bSopenharmony_ci{
21268bf80f4bSopenharmony_ci    return make_unique<NodeContextDescriptorSetManagerGLES>(*this);
21278bf80f4bSopenharmony_ci}
21288bf80f4bSopenharmony_ci
21298bf80f4bSopenharmony_ciunique_ptr<NodeContextPoolManager> DeviceGLES::CreateNodeContextPoolManager(
21308bf80f4bSopenharmony_ci    GpuResourceManager& gpuResourceMgr, const GpuQueue& gpuQueue)
21318bf80f4bSopenharmony_ci{
21328bf80f4bSopenharmony_ci    return make_unique<NodeContextPoolManagerGLES>(*this, gpuResourceMgr);
21338bf80f4bSopenharmony_ci}
21348bf80f4bSopenharmony_ci
21358bf80f4bSopenharmony_ciunique_ptr<GraphicsPipelineStateObject> DeviceGLES::CreateGraphicsPipelineStateObject(
21368bf80f4bSopenharmony_ci    const GpuShaderProgram& gpuProgram, const GraphicsState& graphicsState, const PipelineLayout& pipelineLayout,
21378bf80f4bSopenharmony_ci    const VertexInputDeclarationView& vertexInputDeclaration,
21388bf80f4bSopenharmony_ci    const ShaderSpecializationConstantDataView& specializationConstants,
21398bf80f4bSopenharmony_ci    const array_view<const DynamicStateEnum> dynamicStates, const RenderPassDesc& renderPassDesc,
21408bf80f4bSopenharmony_ci    const array_view<const RenderPassSubpassDesc>& renderPassSubpassDescs, const uint32_t subpassIndex,
21418bf80f4bSopenharmony_ci    const LowLevelRenderPassData* renderPassData, const LowLevelPipelineLayoutData* pipelineLayoutData)
21428bf80f4bSopenharmony_ci{
21438bf80f4bSopenharmony_ci    PLUGIN_ASSERT(!renderPassData);
21448bf80f4bSopenharmony_ci    PLUGIN_ASSERT(!pipelineLayoutData);
21458bf80f4bSopenharmony_ci    auto pipeline = make_unique<GraphicsPipelineStateObjectGLES>(*this, gpuProgram, graphicsState, pipelineLayout,
21468bf80f4bSopenharmony_ci        vertexInputDeclaration, specializationConstants, dynamicStates, renderPassDesc, renderPassSubpassDescs,
21478bf80f4bSopenharmony_ci        subpassIndex);
21488bf80f4bSopenharmony_ci    return unique_ptr<GraphicsPipelineStateObject> { pipeline->GetPlatformData().graphicsShader ? pipeline.release()
21498bf80f4bSopenharmony_ci                                                                                                : nullptr };
21508bf80f4bSopenharmony_ci}
21518bf80f4bSopenharmony_ci
21528bf80f4bSopenharmony_ciunique_ptr<ComputePipelineStateObject> DeviceGLES::CreateComputePipelineStateObject(const GpuComputeProgram& gpuProgram,
21538bf80f4bSopenharmony_ci    const PipelineLayout& pipelineLayout, const ShaderSpecializationConstantDataView& specializationConstants,
21548bf80f4bSopenharmony_ci    const LowLevelPipelineLayoutData* pipelineLayoutData)
21558bf80f4bSopenharmony_ci{
21568bf80f4bSopenharmony_ci    PLUGIN_ASSERT(!pipelineLayoutData);
21578bf80f4bSopenharmony_ci    auto pipeline =
21588bf80f4bSopenharmony_ci        make_unique<ComputePipelineStateObjectGLES>(*this, gpuProgram, pipelineLayout, specializationConstants);
21598bf80f4bSopenharmony_ci    return unique_ptr<ComputePipelineStateObject> { pipeline->GetPlatformData().computeShader ? pipeline.release()
21608bf80f4bSopenharmony_ci                                                                                              : nullptr };
21618bf80f4bSopenharmony_ci}
21628bf80f4bSopenharmony_ci
21638bf80f4bSopenharmony_ciunique_ptr<GpuSemaphore> DeviceGLES::CreateGpuSemaphore()
21648bf80f4bSopenharmony_ci{
21658bf80f4bSopenharmony_ci    return make_unique<GpuSemaphoreGles>(*this);
21668bf80f4bSopenharmony_ci}
21678bf80f4bSopenharmony_ci
21688bf80f4bSopenharmony_ciunique_ptr<GpuSemaphore> DeviceGLES::CreateGpuSemaphoreView(const uint64_t handle)
21698bf80f4bSopenharmony_ci{
21708bf80f4bSopenharmony_ci    return make_unique<GpuSemaphoreGles>(*this, handle);
21718bf80f4bSopenharmony_ci}
21728bf80f4bSopenharmony_ci
21738bf80f4bSopenharmony_civoid DeviceGLES::SetBackendConfig(const BackendConfig& config)
21748bf80f4bSopenharmony_ci{
21758bf80f4bSopenharmony_ci#if RENDER_HAS_GLES_BACKEND
21768bf80f4bSopenharmony_ci    backendConfig_.allowDepthResolve = static_cast<const BackendConfigGLES&>(config).allowDepthResolve &&
21778bf80f4bSopenharmony_ci                                       HasExtension("GL_EXT_multisampled_render_to_texture2");
21788bf80f4bSopenharmony_ci#endif
21798bf80f4bSopenharmony_ci}
21808bf80f4bSopenharmony_ci
21818bf80f4bSopenharmony_ciLowLevelDeviceGLES::LowLevelDeviceGLES(DeviceGLES& deviceGLES)
21828bf80f4bSopenharmony_ci    : deviceGLES_(deviceGLES), gpuResourceMgr_(static_cast<GpuResourceManager&>(deviceGLES.GetGpuResourceManager()))
21838bf80f4bSopenharmony_ci{}
21848bf80f4bSopenharmony_ci
21858bf80f4bSopenharmony_ciDeviceBackendType LowLevelDeviceGLES::GetBackendType() const
21868bf80f4bSopenharmony_ci{
21878bf80f4bSopenharmony_ci    return deviceGLES_.GetBackendType();
21888bf80f4bSopenharmony_ci}
21898bf80f4bSopenharmony_ci
21908bf80f4bSopenharmony_ci#if RENDER_HAS_EXPERIMENTAL
21918bf80f4bSopenharmony_civoid LowLevelDeviceGLES::Activate()
21928bf80f4bSopenharmony_ci{
21938bf80f4bSopenharmony_ci    deviceGLES_.Activate();
21948bf80f4bSopenharmony_ci}
21958bf80f4bSopenharmony_ci
21968bf80f4bSopenharmony_civoid LowLevelDeviceGLES::Deactivate()
21978bf80f4bSopenharmony_ci{
21988bf80f4bSopenharmony_ci    deviceGLES_.Deactivate();
21998bf80f4bSopenharmony_ci}
22008bf80f4bSopenharmony_ci
22018bf80f4bSopenharmony_civoid LowLevelDeviceGLES::SwapBuffers()
22028bf80f4bSopenharmony_ci{
22038bf80f4bSopenharmony_ci    if (deviceGLES_.IsActive() && deviceGLES_.HasSwapchain()) {
22048bf80f4bSopenharmony_ci        RenderHandle defaultSwapChain {};
22058bf80f4bSopenharmony_ci        auto sc = static_cast<const SwapchainGLES*>(deviceGLES_.GetSwapchain(defaultSwapChain));
22068bf80f4bSopenharmony_ci        deviceGLES_.SwapBuffers(*sc);
22078bf80f4bSopenharmony_ci    }
22088bf80f4bSopenharmony_ci}
22098bf80f4bSopenharmony_ci#endif
22108bf80f4bSopenharmony_ci
22118bf80f4bSopenharmony_ciRENDER_END_NAMESPACE()
2212