[Refactor] (...): Optimize code file structure.

This commit is contained in:
BZLZHH
2025-05-01 09:22:50 +08:00
parent 8ab90e8e60
commit 04976daa9f
35 changed files with 65 additions and 66 deletions
@@ -0,0 +1,179 @@
//
// Created by BZLZHH on 2025/4/26.
//
#include "EGL_WRAP.h"
#if BACKEND_TYPE == BACKEND_GLES
MG_EXPORT EGLint eglGetError(void) {
LOAD_EGL(eglGetError)
return egl_eglGetError();
}
MG_EXPORT EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id) {
LOAD_EGL(eglGetDisplay)
return egl_eglGetDisplay(display_id);
}
MG_EXPORT EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) {
LOAD_EGL(eglInitialize)
return egl_eglInitialize(dpy, major, minor);
}
MG_EXPORT EGLBoolean eglTerminate(EGLDisplay dpy) {
LOAD_EGL(eglTerminate)
return egl_eglTerminate(dpy);
}
MG_EXPORT const char *eglQueryString(EGLDisplay dpy, EGLint name) {
LOAD_EGL(eglQueryString)
return egl_eglQueryString(dpy, name);
}
MG_EXPORT EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) {
LOAD_EGL(eglGetConfigs)
return egl_eglGetConfigs(dpy, configs, config_size, num_config);
}
MG_EXPORT EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) {
LOAD_EGL(eglChooseConfig)
return egl_eglChooseConfig(dpy, attrib_list, configs, config_size, num_config);
}
MG_EXPORT EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) {
LOAD_EGL(eglGetConfigAttrib)
return egl_eglGetConfigAttrib(dpy, config, attribute, value);
}
MG_EXPORT EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) {
LOAD_EGL(eglCreateWindowSurface)
return egl_eglCreateWindowSurface(dpy, config, win, attrib_list);
}
MG_EXPORT EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) {
LOAD_EGL(eglCreatePbufferSurface)
return egl_eglCreatePbufferSurface(dpy, config, attrib_list);
}
MG_EXPORT EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) {
LOAD_EGL(eglCreatePixmapSurface)
return egl_eglCreatePixmapSurface(dpy, config, pixmap, attrib_list);
}
MG_EXPORT EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) {
LOAD_EGL(eglDestroySurface)
return egl_eglDestroySurface(dpy, surface);
}
MG_EXPORT EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) {
LOAD_EGL(eglQuerySurface)
return egl_eglQuerySurface(dpy, surface, attribute, value);
}
MG_EXPORT EGLBoolean eglBindAPI(EGLenum api) {
LOAD_EGL(eglBindAPI)
return egl_eglBindAPI(api);
}
MG_EXPORT EGLenum eglQueryAPI(void) {
LOAD_EGL(eglQueryAPI)
return egl_eglQueryAPI();
}
MG_EXPORT EGLBoolean eglWaitClient(void) {
LOAD_EGL(eglWaitClient)
return egl_eglWaitClient();
}
MG_EXPORT EGLBoolean eglReleaseThread(void) {
LOAD_EGL(eglReleaseThread)
return egl_eglReleaseThread();
}
MG_EXPORT EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) {
LOAD_EGL(eglCreatePbufferFromClientBuffer)
return egl_eglCreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list);
}
MG_EXPORT EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) {
LOAD_EGL(eglSurfaceAttrib)
return egl_eglSurfaceAttrib(dpy, surface, attribute, value);
}
MG_EXPORT EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
LOAD_EGL(eglBindTexImage)
return egl_eglBindTexImage(dpy, surface, buffer);
}
MG_EXPORT EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
LOAD_EGL(eglReleaseTexImage)
return egl_eglReleaseTexImage(dpy, surface, buffer);
}
MG_EXPORT EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) {
LOAD_EGL(eglSwapInterval)
return egl_eglSwapInterval(dpy, interval);
}
MG_EXPORT EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) {
LOAD_EGL(eglCreateContext)
return egl_eglCreateContext(dpy, config, share_context, attrib_list);
}
MG_EXPORT EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) {
LOAD_EGL(eglDestroyContext)
return egl_eglDestroyContext(dpy, ctx);
}
MG_EXPORT EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
LOAD_EGL(eglMakeCurrent)
return egl_eglMakeCurrent(dpy, draw, read, ctx);
}
MG_EXPORT EGLContext eglGetCurrentContext(void) {
LOAD_EGL(eglGetCurrentContext)
return egl_eglGetCurrentContext();
}
MG_EXPORT EGLSurface eglGetCurrentSurface(EGLint readdraw) {
LOAD_EGL(eglGetCurrentSurface)
return egl_eglGetCurrentSurface(readdraw);
}
MG_EXPORT EGLDisplay eglGetCurrentDisplay(void) {
LOAD_EGL(eglGetCurrentDisplay)
return egl_eglGetCurrentDisplay();
}
MG_EXPORT EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) {
LOAD_EGL(eglQueryContext)
return egl_eglQueryContext(dpy, ctx, attribute, value);
}
MG_EXPORT EGLBoolean eglWaitGL(void) {
LOAD_EGL(eglWaitGL)
return egl_eglWaitGL();
}
MG_EXPORT EGLBoolean eglWaitNative(EGLint engine) {
LOAD_EGL(eglWaitNative)
return egl_eglWaitNative(engine);
}
MG_EXPORT EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
LOAD_EGL(eglSwapBuffers)
return egl_eglSwapBuffers(dpy, surface);
}
MG_EXPORT EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) {
LOAD_EGL(eglCopyBuffers)
return egl_eglCopyBuffers(dpy, surface, target);
}
MG_EXPORT EGLDisplay eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list) {
LOAD_EGL(eglGetPlatformDisplay)
return egl_eglGetPlatformDisplay(platform, native_display, (const EGLint *)attrib_list);
}
#endif
@@ -0,0 +1,14 @@
//
// Created by BZLZHH on 2025/4/26.
//
#ifndef MOBILEGL_EGL_GLES_EGL_WRAP_H
#define MOBILEGL_EGL_GLES_EGL_WRAP_H
#include "../../../../Includes.h"
#if BACKEND_TYPE == BACKEND_GLES
#endif
#endif //MOBILEGL_EGL_GLES_EGL_WRAP_H
+551
View File
@@ -0,0 +1,551 @@
//
// Created by BZLZHH on 2025/3/30.
//
#include "EGL_EMU.h"
#if BACKEND_TYPE == BACKEND_VULKAN
std::atomic<uintptr_t> g_nextContextId{1};
std::atomic<uintptr_t> g_nextSurfaceId{1};
EGLenum g_currentAPI = EGL_OPENGL_ES_API;
std::mutex g_globalMutex;
std::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
std::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
std::unordered_map<EGLContext, VulkanContext> g_contexts;
EGLint g_lastError = EGL_SUCCESS;
thread_local EGLContext tls_currentContext = EGL_NO_CONTEXT;
thread_local EGLSurface tls_drawSurface = EGL_NO_SURFACE;
thread_local EGLSurface tls_readSurface = EGL_NO_SURFACE;
static VkResult CreateRenderPass(VulkanDisplay& display, VulkanContext& ctx) {
VkAttachmentDescription colorAttachment{};
colorAttachment.format = VK_FORMAT_B8G8R8A8_SRGB;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference colorRef{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorRef;
VkRenderPassCreateInfo rpInfo{};
rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
rpInfo.subpassCount = 1;
rpInfo.pSubpasses = &subpass;
rpInfo.attachmentCount = 1;
rpInfo.pAttachments = &colorAttachment;
return vkCreateRenderPass(display.device, &rpInfo, nullptr, &ctx.renderPass);
}
EGLDisplay eglGetDisplay(NativeDisplayType display) {
std::lock_guard<std::mutex> lock(g_globalMutex);
static uintptr_t nextDisplayId = 1;
EGLDisplay newDisplay = (EGLDisplay)nextDisplayId++;
g_displays[newDisplay].initialized = false;
return newDisplay;
}
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) {
VulkanDisplay& vkDpy = g_displays[dpy];
if (vkDpy.initialized) return EGL_TRUE;
VkInstanceCreateInfo instInfo{};
instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
const char* extensions[] = {
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
};
instInfo.enabledExtensionCount = 2;
instInfo.ppEnabledExtensionNames = extensions;
if (vkCreateInstance(&instInfo, nullptr, &vkDpy.instance) != VK_SUCCESS) {
g_lastError = EGL_NOT_INITIALIZED;
return EGL_FALSE;
}
uint32_t devCount = 0;
vkEnumeratePhysicalDevices(vkDpy.instance, &devCount, nullptr);
std::vector<VkPhysicalDevice> devices(devCount);
vkEnumeratePhysicalDevices(vkDpy.instance, &devCount, devices.data());
vkDpy.physicalDevice = devices[0];
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(vkDpy.physicalDevice, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(vkDpy.physicalDevice, &queueFamilyCount, queueFamilies.data());
// 寻找支持图形和呈现的队列家族
bool foundQueue = false;
for (uint32_t i = 0; i < queueFamilyCount; ++i) {
VkBool32 presentSupport = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(vkDpy.physicalDevice, i, VK_NULL_HANDLE, &presentSupport);
if ((queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && presentSupport) {
vkDpy.graphicsQueueFamily = i;
foundQueue = true;
break;
}
}
if (!foundQueue) {
g_lastError = EGL_NOT_INITIALIZED;
return EGL_FALSE;
}
// 创建逻辑设备时请求队列
float queuePriority = 1.0f;
VkDeviceQueueCreateInfo queueInfo{};
queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueInfo.queueFamilyIndex = vkDpy.graphicsQueueFamily;
queueInfo.queueCount = 1;
queueInfo.pQueuePriorities = &queuePriority;
const char* devExtensions[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
VkDeviceCreateInfo devInfo{};
devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
devInfo.pQueueCreateInfos = &queueInfo;
devInfo.queueCreateInfoCount = 1;
devInfo.ppEnabledExtensionNames = devExtensions;
devInfo.enabledExtensionCount = 1;
if (vkCreateDevice(vkDpy.physicalDevice, &devInfo, nullptr, &vkDpy.device) != VK_SUCCESS) {
g_lastError = EGL_NOT_INITIALIZED;
return EGL_FALSE;
}
vkDpy.vkCreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)vkGetDeviceProcAddr(vkDpy.device, "vkCreateSwapchainKHR");
vkDpy.vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)vkGetDeviceProcAddr(vkDpy.device, "vkDestroySwapchainKHR");
vkDpy.vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)vkGetDeviceProcAddr(vkDpy.device, "vkGetSwapchainImagesKHR");
vkDpy.vkAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)vkGetDeviceProcAddr(vkDpy.device, "vkAcquireNextImageKHR");
vkDpy.vkQueuePresentKHR = (PFN_vkQueuePresentKHR)vkGetDeviceProcAddr(vkDpy.device, "vkQueuePresentKHR");
vkGetDeviceQueue(vkDpy.device, vkDpy.graphicsQueueFamily, 0, &vkDpy.graphicsQueue);
vkDpy.presentQueue = vkDpy.graphicsQueue;
vkDpy.initialized = true;
if (major) *major = 1;
if (minor) *minor = 5;
return EGL_TRUE;
}
EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config) {
VulkanDisplay& vkDpy = g_displays[dpy];
EGLInternalConfig defaultConfig{ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, 1 };
vkDpy.configs = {defaultConfig};
EGLint returnCount = 1;
if (configs && config_size > 0) {
configs[0] = (EGLConfig)0;
}
if (num_config) *num_config = returnCount;
return EGL_TRUE;
}
EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint* attrib_list) {
VulkanDisplay& disp = g_displays[dpy];
static uintptr_t nextSurfId = 1;
ANativeWindow* nativeWindow = static_cast<ANativeWindow*>(window);
if (!nativeWindow || ANativeWindow_getWidth(nativeWindow) <= 0 || ANativeWindow_getHeight(nativeWindow) <= 0) {
g_lastError = EGL_BAD_NATIVE_WINDOW;
return EGL_NO_SURFACE;
}
auto vkCreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(
disp.instance, "vkCreateAndroidSurfaceKHR");
if (!vkCreateAndroidSurfaceKHR) {
g_lastError = EGL_BAD_ALLOC;
return EGL_NO_SURFACE;
}
VulkanSurface surface{};
surface.type = VulkanSurface::WINDOW;
VkAndroidSurfaceCreateInfoKHR createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
createInfo.window = nativeWindow;
VkResult result = vkCreateAndroidSurfaceKHR(disp.instance, &createInfo, nullptr, &surface.surface);
if (result != VK_SUCCESS) {
g_lastError = (result == VK_ERROR_NATIVE_WINDOW_IN_USE_KHR) ?
EGL_BAD_NATIVE_WINDOW : EGL_BAD_ALLOC;
return EGL_NO_SURFACE;
}
VkBool32 supported = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(disp.physicalDevice,
disp.graphicsQueueFamily,
surface.surface,
&supported);
if (!supported) {
vkDestroySurfaceKHR(disp.instance, surface.surface, nullptr);
g_lastError = EGL_BAD_MATCH;
return EGL_NO_SURFACE;
}
VkSurfaceCapabilitiesKHR caps;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(disp.physicalDevice, surface.surface, &caps);
const VkExtent2D swapchainExtent = {
(std::max)(caps.minImageExtent.width, (uint32_t)ANativeWindow_getWidth(nativeWindow)),
(std::max)(caps.minImageExtent.height, (uint32_t)ANativeWindow_getHeight(nativeWindow))
};
VkSwapchainCreateInfoKHR swapInfo{};
swapInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapInfo.surface = surface.surface;
swapInfo.minImageCount = 3;
swapInfo.imageFormat = VK_FORMAT_R8G8B8A8_SRGB;
swapInfo.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
swapInfo.imageExtent = swapchainExtent;
swapInfo.imageArrayLayers = 1;
swapInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapInfo.preTransform = caps.currentTransform;
swapInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
swapInfo.presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
if (disp.vkCreateSwapchainKHR(disp.device, &swapInfo, nullptr, &surface.swapchain) != VK_SUCCESS) {
vkDestroySurfaceKHR(disp.instance, surface.surface, nullptr);
g_lastError = EGL_BAD_ALLOC;
return EGL_NO_SURFACE;
}
uint32_t imageCount = 0;
disp.vkGetSwapchainImagesKHR(disp.device, surface.swapchain, &imageCount, nullptr);
surface.images.resize(imageCount);
disp.vkGetSwapchainImagesKHR(disp.device, surface.swapchain, &imageCount, surface.images.data());
surface.imageViews.resize(imageCount);
for (uint32_t i = 0; i < imageCount; ++i) {
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = surface.images[i];
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = swapInfo.imageFormat;
viewInfo.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
if (vkCreateImageView(disp.device, &viewInfo, nullptr, &surface.imageViews[i]) != VK_SUCCESS) {
// Handle error
}
}
ANativeWindow_acquire(nativeWindow);
ANativeWindow_setBuffersGeometry(nativeWindow,
swapchainExtent.width,
swapchainExtent.height,
AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM);
EGLSurface surfId = (EGLSurface)nextSurfId++;
g_surfaces[surfId] = std::move(surface);
return surfId;
}
EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext shareCtx, const EGLint* attrib_list) {
static uintptr_t nextCtxId = 1;
VulkanDisplay &disp = g_displays[dpy];
VulkanContext ctx{};
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = 0;
if (vkCreateCommandPool(disp.device, &poolInfo, nullptr, &ctx.cmdPool) != VK_SUCCESS) {
g_lastError = EGL_BAD_ALLOC;
return EGL_NO_CONTEXT;
}
ctx.frameFences.resize(2);
ctx.acquireSemaphores.resize(2);
ctx.presentSemaphores.resize(2);
for (uint32_t i = 0; i < 2; ++i) {
VkFenceCreateInfo fenceInfo{VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr,
VK_FENCE_CREATE_SIGNALED_BIT};
vkCreateFence(disp.device, &fenceInfo, nullptr, &ctx.frameFences[i]);
VkSemaphoreCreateInfo semInfo{VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
vkCreateSemaphore(disp.device, &semInfo, nullptr, &ctx.acquireSemaphores[i]);
vkCreateSemaphore(disp.device, &semInfo, nullptr, &ctx.presentSemaphores[i]);
}
if (CreateRenderPass(disp, ctx) != VK_SUCCESS) {
g_lastError = EGL_BAD_CONFIG;
return EGL_NO_CONTEXT;
}
EGLContext ctxId = (EGLContext)nextCtxId++;
g_contexts[ctxId] = std::move(ctx);
return ctxId;
}
EGLint eglGetError() {
return EGL_SUCCESS;
}
EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
std::lock_guard<std::mutex> lock(g_globalMutex);
if (dpy == EGL_NO_DISPLAY || (ctx != EGL_NO_CONTEXT && !g_contexts.count(ctx)) ||
(draw != EGL_NO_SURFACE && !g_surfaces.count(draw)) ||
(read != EGL_NO_SURFACE && !g_surfaces.count(read))) {
g_lastError = EGL_BAD_PARAMETER;
return EGL_FALSE;
}
if (tls_currentContext != EGL_NO_CONTEXT) {
VulkanContext& oldCtx = g_contexts[tls_currentContext];
if (oldCtx.currentCmdBuffer) {
vkEndCommandBuffer(oldCtx.currentCmdBuffer);
oldCtx.currentCmdBuffer = VK_NULL_HANDLE;
}
}
if (ctx != EGL_NO_CONTEXT) {
VulkanContext& newCtx = g_contexts[ctx];
VulkanDisplay& disp = g_displays[dpy];
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = newCtx.cmdPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1;
if (vkAllocateCommandBuffers(disp.device, &allocInfo, &newCtx.currentCmdBuffer) != VK_SUCCESS) {
g_lastError = EGL_BAD_ALLOC;
return EGL_FALSE;
}
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(newCtx.currentCmdBuffer, &beginInfo);
}
tls_currentContext = ctx;
tls_drawSurface = draw;
tls_readSurface = read;
return EGL_TRUE;
}
EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) {
std::lock_guard<std::mutex> lock(g_globalMutex);
if (!g_contexts.count(ctx)) {
g_lastError = EGL_BAD_CONTEXT;
return EGL_FALSE;
}
VulkanContext& vkCtx = g_contexts[ctx];
VulkanDisplay& disp = g_displays[dpy];
vkDeviceWaitIdle(disp.device);
vkDestroyCommandPool(disp.device, vkCtx.cmdPool, nullptr);
vkDestroyRenderPass(disp.device, vkCtx.renderPass, nullptr);
for (auto& fence : vkCtx.frameFences)
vkDestroyFence(disp.device, fence, nullptr);
for (auto& sem : vkCtx.acquireSemaphores)
vkDestroySemaphore(disp.device, sem, nullptr);
for (auto& sem : vkCtx.presentSemaphores)
vkDestroySemaphore(disp.device, sem, nullptr);
g_contexts.erase(ctx);
if (tls_currentContext == ctx)
tls_currentContext = EGL_NO_CONTEXT;
return EGL_TRUE;
}
EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) {
std::lock_guard<std::mutex> lock(g_globalMutex);
if (!g_surfaces.count(surface)) {
g_lastError = EGL_BAD_SURFACE;
return EGL_FALSE;
}
VulkanSurface& surf = g_surfaces[surface];
VulkanDisplay& disp = g_displays[dpy];
vkDeviceWaitIdle(disp.device);
if (surf.type == VulkanSurface::WINDOW) {
disp.vkDestroySwapchainKHR(disp.device, surf.swapchain, nullptr);
vkDestroySurfaceKHR(disp.instance, surf.surface, nullptr);
for (auto& view : surf.imageViews)
vkDestroyImageView(disp.device, view, nullptr);
} else {
vkDestroyImageView(disp.device, surf.pbufferImageView, nullptr);
vkDestroyImage(disp.device, surf.pbufferImage, nullptr);
}
g_surfaces.erase(surface);
return EGL_TRUE;
}
EGLBoolean eglTerminate(EGLDisplay dpy) {
std::lock_guard<std::mutex> lock(g_globalMutex);
if (!g_displays.count(dpy)) {
g_lastError = EGL_BAD_DISPLAY;
return EGL_FALSE;
}
VulkanDisplay& disp = g_displays[dpy];
for (auto& [ctxId, ctx] : g_contexts)
eglDestroyContext(dpy, ctxId);
for (auto& [surfId, surf] : g_surfaces)
eglDestroySurface(dpy, surfId);
vkDestroyDevice(disp.device, nullptr);
vkDestroyInstance(disp.instance, nullptr);
g_displays.erase(dpy);
return EGL_TRUE;
}
EGLBoolean eglReleaseThread(void) {
tls_currentContext = EGL_NO_CONTEXT;
tls_drawSurface = EGL_NO_SURFACE;
tls_readSurface = EGL_NO_SURFACE;
return EGL_TRUE;
}
EGLContext eglGetCurrentContext(void) {
return tls_currentContext;
}
EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) {
VulkanDisplay& disp = g_displays[dpy];
if (!disp.configs.empty() && config == (EGLConfig)0) {
switch (attribute) {
case EGL_BUFFER_SIZE: *value = 32; break;
case EGL_RED_SIZE: *value = 8; break;
case EGL_GREEN_SIZE: *value = 8; break;
case EGL_BLUE_SIZE: *value = 8; break;
case EGL_ALPHA_SIZE: *value = 8; break;
case EGL_CONFIG_ID: *value = 1; break;
default: return EGL_FALSE;
}
return EGL_TRUE;
}
return EGL_FALSE;
}
EGLBoolean eglBindAPI(EGLenum api) {
if (api == EGL_OPENGL_ES_API) {
g_currentAPI = api;
return EGL_TRUE;
}
return EGL_FALSE;
}
EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) {
VulkanDisplay& disp = g_displays[dpy];
VulkanSurface surface{};
surface.type = VulkanSurface::PBUFFER;
VkImageCreateInfo imgInfo{};
imgInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imgInfo.imageType = VK_IMAGE_TYPE_2D;
imgInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
imgInfo.extent = {512, 512, 1};
imgInfo.mipLevels = 1;
imgInfo.arrayLayers = 1;
imgInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imgInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imgInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
imgInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
if (vkCreateImage(disp.device, &imgInfo, nullptr, &surface.pbufferImage) != VK_SUCCESS) {
g_lastError = EGL_BAD_ALLOC;
return EGL_NO_SURFACE;
}
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = surface.pbufferImage;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = imgInfo.format;
viewInfo.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
if (vkCreateImageView(disp.device, &viewInfo, nullptr, &surface.pbufferImageView) != VK_SUCCESS) {
vkDestroyImage(disp.device, surface.pbufferImage, nullptr);
g_lastError = EGL_BAD_ALLOC;
return EGL_NO_SURFACE;
}
EGLSurface surfId = (EGLSurface)g_nextSurfaceId++;
g_surfaces[surfId] = surface;
return surfId;
}
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) {
VulkanSurface& surf = g_surfaces[draw];
VulkanDisplay& disp = g_displays[dpy];
VulkanContext& ctx = g_contexts[tls_currentContext];
if (!disp.presentQueue) {
g_lastError = EGL_BAD_DISPLAY;
return EGL_FALSE;
}
if (surf.type != VulkanSurface::WINDOW) {
g_lastError = EGL_BAD_SURFACE;
return EGL_FALSE;
}
vkEndCommandBuffer(ctx.currentCmdBuffer);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &ctx.currentCmdBuffer;
vkQueueSubmit(disp.graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &surf.swapchain;
presentInfo.pImageIndices = &ctx.frameIndex;
VkResult result = disp.vkQueuePresentKHR(disp.presentQueue, &presentInfo);
if (result != VK_SUCCESS) {
g_lastError = EGL_BAD_ALLOC;
return EGL_FALSE;
}
ctx.frameIndex = (ctx.frameIndex + 1) % surf.images.size();
return EGL_TRUE;
}
EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) {
// TODO
return EGL_TRUE;
}
EGLSurface eglGetCurrentSurface(EGLint readdraw) {
return (readdraw == EGL_READ) ? tls_readSurface : tls_drawSurface;
}
EGLBoolean eglQuerySurface(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint *value) {
VulkanSurface& surf = g_surfaces[surface];
switch (attribute) {
case EGL_WIDTH: *value = surf.extent.width; break;
case EGL_HEIGHT: *value = surf.extent.height; break;
case EGL_CONFIG_ID: *value = 1; break;
default: return EGL_FALSE;
}
return EGL_TRUE;
}
#endif
+103
View File
@@ -0,0 +1,103 @@
//
// Created by BZLZHH on 2025/3/30.
//
#ifndef MOBILEGL_EGL_VK_EMU_H
#define MOBILEGL_EGL_VK_EMU_H
#include "../../../../Includes.h"
#if BACKEND_TYPE == BACKEND_VULKAN
struct EGLInternalConfig {
VkFormat format;
VkColorSpaceKHR colorSpace;
uint32_t samples;
};
struct VulkanDisplay {
VkInstance instance;
VkPhysicalDevice physicalDevice;
VkDevice device;
uint32_t graphicsQueueFamily;
VkQueue graphicsQueue;
std::vector<EGLInternalConfig> configs;
bool initialized = false;
PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR;
PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
PFN_vkQueuePresentKHR vkQueuePresentKHR;
VkRenderPass defaultRenderPass;
VkQueue presentQueue = VK_NULL_HANDLE;
};
struct VulkanSurface {
enum Type { WINDOW, PBUFFER } type;
VkSurfaceKHR surface;
VkSwapchainKHR swapchain;
std::vector<VkImage> images;
std::vector<VkImageView> imageViews;
VkExtent2D extent;
VkFormat format;
VkImage pbImage;
VkImageView pbImageView;
VkDeviceMemory pbMemory;
VkFramebuffer framebuffer;
VkImage pbufferImage;
VkImageView pbufferImageView;
};
struct VulkanContext {
VkCommandPool cmdPool;
std::vector<VkCommandBuffer> cmdBuffers;
uint32_t currentFrame = 0;
VkRenderPass renderPass;
VkPipelineLayout pipelineLayout;
VkPipeline graphicsPipeline;
std::vector<VkFence> frameFences;
std::vector<VkSemaphore> acquireSemaphores;
std::vector<VkSemaphore> presentSemaphores;
VulkanSurface* boundSurface = nullptr;
VkCommandBuffer currentCmdBuffer;
uint32_t frameIndex;
VkClearColorValue clearColor;
};
extern std::atomic<uintptr_t> g_nextContextId;
extern std::atomic<uintptr_t> g_nextSurfaceId;
extern EGLenum g_currentAPI;
extern std::mutex g_globalMutex;
extern std::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
extern std::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
extern std::unordered_map<EGLContext, VulkanContext> g_contexts;
extern EGLint g_lastError;
extern thread_local EGLContext tls_currentContext;
extern thread_local EGLSurface tls_drawSurface;
extern thread_local EGLSurface tls_readSurface;
MG_EXPORT EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint* attrib_list);
MG_EXPORT EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config);
MG_EXPORT EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext shareCtx, const EGLint* attrib_list);
MG_EXPORT EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor);
MG_EXPORT EGLDisplay eglGetDisplay(NativeDisplayType display);
MG_EXPORT EGLint eglGetError();
MG_EXPORT EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
MG_EXPORT EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
MG_EXPORT EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
MG_EXPORT EGLBoolean eglTerminate(EGLDisplay dpy);
MG_EXPORT EGLBoolean eglReleaseThread(void);
MG_EXPORT EGLContext eglGetCurrentContext(void);
MG_EXPORT EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
MG_EXPORT EGLBoolean eglBindAPI(EGLenum api);
MG_EXPORT EGLSurface eglGetCurrentSurface(EGLint readdraw);
MG_EXPORT EGLBoolean eglQuerySurface(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint *value);
MG_EXPORT EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval);
MG_EXPORT EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
MG_EXPORT EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
#endif
#endif //MOBILEGL_EGL_VK_EMU_H
@@ -0,0 +1,9 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "GL_Buffer.h"
namespace MG_GL::GL {
}
@@ -0,0 +1,14 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_GL_BUFFER_H
#define MOBILEGL_GL_BUFFER_H
#include "../../../../Includes.h"
namespace MG_GL::GL {
}
#endif //MOBILEGL_GL_BUFFER_H
@@ -0,0 +1,28 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "GL_Common.h"
namespace MG_GL::GL {
void ClearDepth(GLdouble depth) {
}
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
}
void Clear(GLbitfield mask) {
}
void PixelStorei(GLenum pname, GLint param) {
MG_Util::Debug::LogD("glPixelStorei, pname: %d, param: %d", pname, param);
GLenum result = MG_State::SetPixelStoreInt(pname,param);
if (result == GL_NO_ERROR)
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
}
@@ -0,0 +1,17 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_GL_COMMON_H
#define MOBILEGL_GL_COMMON_H
#include "../../../../Includes.h"
namespace MG_GL::GL {
void ClearDepth(::GLdouble depth);
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void Clear(GLbitfield mask);
void PixelStorei(GLenum pname, GLint param);
}
#endif //MOBILEGL_GL_COMMON_H
@@ -0,0 +1,17 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "GL_Drawing.h"
namespace MG_GL::GL {
// This is a test function that directly draws textures.
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) {
::GLES::glViewport(0,0,3200,1440);
MG_RHI::GLES::Test::DrawAllTextures();
};
void DrawArrays(GLenum mode, GLint first, GLsizei count) {
::GLES::glViewport(0,0,3200,1440);
MG_RHI::GLES::Test::DrawAllTextures();
};
}
@@ -0,0 +1,15 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_GL_DRAWING_H
#define MOBILEGL_GL_DRAWING_H
#include "../../../../Includes.h"
namespace MG_GL::GL {
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
void DrawArrays(GLenum mode, GLint first, GLsizei count);
}
#endif //MOBILEGL_GL_DRAWING_H
@@ -0,0 +1,11 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "GL_Framebuffer.h"
namespace MG_GL::GL {
GLenum CheckFramebufferStatus(GLenum target) {
return GL_FRAMEBUFFER_COMPLETE;
}
}
@@ -0,0 +1,14 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_GL_FRAMEBUFFER_H
#define MOBILEGL_GL_FRAMEBUFFER_H
#include "../../../../Includes.h"
namespace MG_GL::GL {
GLenum CheckFramebufferStatus(GLenum target);
}
#endif //MOBILEGL_GL_FRAMEBUFFER_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,10 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_GL_FUNCS_DEFINITIONS_H
#define MOBILEGL_GL_FUNCS_DEFINITIONS_H
#include "../../../../Includes.h"
#endif //MOBILEGL_GL_FUNCS_DEFINITIONS_H
@@ -0,0 +1,93 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "BackendInfo.h"
namespace MG_GL::Getter {
const std::string GetBackendName() {
#if BACKEND_TYPE == BACKEND_VULKAN
return "Vulkan";
#elif BACKEND_TYPE == BACKEND_METAL
return "Metal";
#elif BACKEND_TYPE == BACKEND_GLES
return "OpenGL ES";
#else
return "<Unknown Backend>";
#endif
}
const std::string GetMGName() {
#if BACKEND_TYPE == BACKEND_VULKAN
return "MobileGluvk";
#elif BACKEND_TYPE == BACKEND_METAL
return "MobileGlumtl";
#elif BACKEND_TYPE == BACKEND_GLES
return "MobileGlues";
#else
return "<Unknown MobileGL Version>";
#endif
}
void LogMGInfo() {
std::string MGName = MG_GL::Getter::GetMGName() + " (MobileGL Core)";
std::string MGVersion = std::to_string(MG_Global::MG::VersionMajor) + "."
+ std::to_string(MG_Global::MG::VersionMinor) + "."
+ std::to_string(MG_Global::MG::VersionRevision);
if (MG_Global::MG::VersionPatch != 0)
MGVersion += "." + std::to_string(MG_Global::MG::VersionPatch);
MGVersion += MG_Global::MG::VersionSuffix;
std::string GLVersion = std::to_string(MG_Global::GL::GLVersionMajor) + "."
+ std::to_string(MG_Global::GL::GLVersionMinor) + "."
+ std::to_string(MG_Global::GL::GLVersionRevision);
std::string backendName = MG_GL::Getter::GetBackendName();
std::string backendVersion;
#if BACKEND_TYPE == BACKEND_VULKAN
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Vulkan Version Query";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
VkInstance instance;
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
throw std::runtime_error("Failed to create Vulkan instance!");
}
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
if (deviceCount == 0) {
throw std::runtime_error("No Vulkan devices found!");
}
VkPhysicalDevice physicalDevice;
vkEnumeratePhysicalDevices(instance, &deviceCount, &physicalDevice);
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
uint32_t major = VK_VERSION_MAJOR(deviceProperties.apiVersion);
uint32_t minor = VK_VERSION_MINOR(deviceProperties.apiVersion);
uint32_t patch = VK_VERSION_PATCH(deviceProperties.apiVersion);
vkDestroyInstance(instance, nullptr);
backendVersion = "Vulkan " + std::to_string(major) + "." +
std::to_string(minor)+"." + std::to_string(patch);
#elif BACKEND_TYPE == BACKEND_GLES
backendVersion = std::string((const char*)::GLES::glGetString(GL_VERSION));
#else
backendVersion = "<Unknown Backend>";
#endif
MG_Util::Debug::LogI("MobileGL Renderer Info:");
MG_Util::Debug::LogI("----%s:", MGName.c_str());
MG_Util::Debug::LogI("--------MobileGL Version: %s", MGVersion.c_str());
MG_Util::Debug::LogI("--------Target OpenGL Implementation Version: %s", GLVersion.c_str());
MG_Util::Debug::LogI("--------Backend: %s", backendName.c_str());
MG_Util::Debug::LogI("--------Backend Version: %s", backendVersion.c_str());
}
}
@@ -0,0 +1,16 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_BACKENDINFO_H
#define MOBILEGL_BACKENDINFO_H
#include "../../../../Includes.h"
namespace MG_GL::Getter {
const std::string GetBackendName();
const std::string GetMGName();
void LogMGInfo();
}
#endif //MOBILEGL_BACKENDINFO_H
@@ -0,0 +1,157 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "GL_Getter.h"
namespace MG_GL::GL {
static std::string rendererString;
static bool loggedMGInfo;
const GLubyte* GetString(GLenum name) {
if (!loggedMGInfo) {
loggedMGInfo = true;
MG_GL::Getter::LogMGInfo();
}
MG_Util::Debug::LogD("glGetString, name: %s", MG_Util::Debug::GLEnumToString(name));
switch (name) {
case GL_VENDOR:
return (const GLubyte *)"MobileGL-Dev";
case GL_VERSION: {
static std::string versionStr;
if (versionStr.empty()) {
versionStr == std::to_string(MG_Global::GL::GLVersionMajor) + "."
+ std::to_string(MG_Global::GL::GLVersionMinor) + "."
+ std::to_string(MG_Global::GL::GLVersionRevision)
+ " "+ MG_GL::Getter::GetMGName() +
", MobileGL Core, " + MG_GL::Getter::GetBackendName() + " Backend";
versionStr += std::to_string(MG_Global::MG::VersionMajor) + "."
+ std::to_string(MG_Global::MG::VersionMinor) + "."
+ std::to_string(MG_Global::MG::VersionRevision);
if (MG_Global::MG::VersionPatch != 0)
versionStr += "." + std::to_string(MG_Global::MG::VersionPatch);
versionStr += MG_Global::MG::VersionSuffix;
}
return (const GLubyte *)versionStr.c_str();
}
case GL_RENDERER:
{
/*
if (rendererString == std::string("")) {
const char* gpuName = getGpuName();
const char* glesName = getGLESName();
rendererString = std::string(gpuName) + " | " + std::string(glesName);
}
return (const GLubyte *)rendererString.c_str();
*/
return (const GLubyte *)(MG_GL::Getter::GetMGName() + "(MobileGL Core) Renderer").c_str();
}
case GL_SHADING_LANGUAGE_VERSION:
return (const GLubyte *) "4.50 MobileGL with glslang";
case GL_EXTENSIONS:
return (const GLubyte *) "OpenGL11 "
"OpenGL12 "
"OpenGL13 "
"OpenGL14 "
"OpenGL15 "
"OpenGL20 "
"OpenGL21 "
"OpenGL30 ";
default:
return (const GLubyte *) "Unknown enum";
}
}
const GLubyte* GetStringi(GLenum name, GLuint index) {
MG_Util::Debug::LogD("glGetStringi, name: %s, index: %d", MG_Util::Debug::GLEnumToString(name), index);
if (name != GL_EXTENSIONS)
return (const GLubyte*)"";
typedef struct {
GLenum name;
const char** parts;
GLuint count;
} StringCache;
static StringCache caches[] = {
{GL_EXTENSIONS, nullptr, 0},
{GL_VENDOR, nullptr, 0},
{GL_VERSION, nullptr, 0},
{GL_SHADING_LANGUAGE_VERSION, nullptr, 0}
};
static int initialized = 0;
if (!initialized) {
for (auto & cache : caches) {
GLenum target = cache.name;
const GLubyte* str = nullptr;
const char* delimiter = " ";
str = GetString(GL_EXTENSIONS);
char* copy = strdup((const char*)str);
char* token = strtok(copy, delimiter);
while (token) {
cache.parts = (const char**)realloc(cache.parts, (cache.count + 1) * sizeof(char*));
cache.parts[cache.count++] = strdup(token);
token = strtok(nullptr, delimiter);
}
free(copy);
}
initialized = 1;
}
for (auto & cache : caches) {
if (cache.name == name) {
if (index >= cache.count) {
return nullptr;
}
return (const GLubyte*)cache.parts[index];
}
}
return nullptr;
}
GLenum GetError() {
GLenum error = MG_State::GetError();
MG_Util::Debug::LogD("glGetError -> %s", MG_Util::Debug::GLEnumToString(error));
return error;
}
void GetIntegerv(GLenum pname, GLint *params) {
MG_Util::Debug::LogD("glGetIntegerv, pname: %s", MG_Util::Debug::GLEnumToString(pname));
switch (pname) {
case GL_CONTEXT_PROFILE_MASK:
(*params) = GL_CONTEXT_CORE_PROFILE_BIT;
break;
case GL_NUM_EXTENSIONS:
static GLint num_extensions = -1;
if (num_extensions == -1) {
const GLubyte* ext_str = glGetString(GL_EXTENSIONS);
if (ext_str) {
char* copy = strdup((const char*)ext_str);
char* token = strtok(copy, " ");
num_extensions = 0;
while (token) {
num_extensions++;
token = strtok(nullptr, " ");
}
free(copy);
} else {
num_extensions = 0;
}
}
(*params) = num_extensions;
break;
case GL_MAJOR_VERSION:
(*params) = MG_Global::GL::GLVersionMajor;
break;
case GL_MINOR_VERSION:
(*params) = MG_Global::GL::GLVersionMinor;
break;
case GL_MAX_TEXTURE_SIZE:
// TODO: Get real GL_MAX_TEXTURE_SIZE.
(*params) = 32768;
break;
default:
break;
}
}
}
@@ -0,0 +1,17 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_GL_GETTER_H
#define MOBILEGL_GL_GETTER_H
#include "../../../../Includes.h"
namespace MG_GL::GL {
const ::GLubyte* GetString(GLenum name);
const ::GLubyte* GetStringi(GLenum name, GLuint index);
::GLenum GetError();
void GetIntegerv(GLenum pname, GLint *params);
}
#endif //MOBILEGL_GL_GETTER_H
@@ -0,0 +1,12 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "GL_Program.h"
namespace MG_GL::GL {
void GetProgramiv(GLuint program, GLenum pname, GLint *params) {
// TODO: Check if program linking is successful.
*params = GL_TRUE;
}
}
@@ -0,0 +1,14 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_GL_PROGRAM_H
#define MOBILEGL_GL_PROGRAM_H
#include "../../../../Includes.h"
namespace MG_GL::GL {
void GetProgramiv(GLuint program, GLenum pname, GLint *params);
}
#endif //MOBILEGL_GL_PROGRAM_H
@@ -0,0 +1,12 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "GL_Shader.h"
namespace MG_GL::GL {
void GetShaderiv(GLuint shader, GLenum pname, GLint *params) {
// TODO: Check if shader compilation is successful.
*params = GL_TRUE;
}
}
@@ -0,0 +1,14 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_GL_SHADER_H
#define MOBILEGL_GL_SHADER_H
#include "../../../../Includes.h"
namespace MG_GL::GL {
void GetShaderiv(GLuint shader, GLenum pname, GLint *params);
}
#endif //MOBILEGL_GL_SHADER_H
@@ -0,0 +1,93 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "GL_Texture.h"
namespace MG_GL::GL {
void ActiveTexture(GLenum texture) {
MG_Util::Debug::LogD("glActiveTexture, texture: %d", texture);
GLenum result = MG_State::BindTextureUnit(texture);
if (result == GL_NO_ERROR)
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
void BindTexture(GLenum target, GLuint texture) {
MG_Util::Debug::LogD("glBindTexture, target: %d, texture: %d", target, texture);
GLenum result = MG_State::BindTexture(target, texture);
if (result == GL_NO_ERROR)
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
void DeleteTextures(GLsizei n, const GLuint* textures) {
MG_Util::Debug::LogD("glDeleteTextures, n: %d, textures: %p", n, textures);
GLenum result = MG_State::DeleteTextures(n, textures);
if (result == GL_NO_ERROR)
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
void GenTextures(GLsizei n, GLuint* textures) {
MG_Util::Debug::LogD("glGenTextures, n: %d, textures: %p", n, textures);
GLenum result = MG_State::CreateTextures(n, textures);
if (result == GL_NO_ERROR)
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
void TexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const void* data) {
MG_Util::Debug::LogD("glTexImage2D, target: %d, level: %d, internalFormat: %d, width: %d, height: %d, format: %d, type: %d, data: %p",
target, level, internalFormat, width, height, format, type, data);
GLenum result = MG_State::UploadTexture2D(target, level, internalFormat, width, height, border, format, type, data);
if (result == GL_NO_ERROR)
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
MG_Util::Debug::LogD("glTexParameterf, target: %d, pname: %d, param: %f", target, pname, param);
GLenum result = MG_State::SetTexturePropertyFloat(target, pname, param);
if (result == GL_NO_ERROR)
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
void TexParameteri(GLenum target, GLenum pname, GLint param) {
MG_Util::Debug::LogD("glTexParameteri, target: %d, pname: %d, param: %d", target, pname, param);
GLenum result = MG_State::SetTexturePropertyInt(target, pname, param);
if (result == GL_NO_ERROR)
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
GLsizei height, GLenum format, GLenum type, const void* pixels) {
MG_Util::Debug::LogD("glTexSubImage2D, target: %d, level: %d, xoffset: %d, yoffset: %d, width: %d, height: %d, format: %d, type: %d, pixels: %p",
target, level, xoffset, yoffset, width, height, format, type, pixels);
GLenum result = MG_State::UpdateTextureRegion2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
if (result == GL_NO_ERROR)
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params) {
MG_Util::Debug::LogD("glGetTexLevelParameteriv, target: %d, level: %d, pname: %d, params: %p",
target, level, pname, params);
GLenum result = MG_State::GetTextureLevelPropertyIntVector(target, level, pname, params);
if (result == GL_NO_ERROR)
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
}
@@ -0,0 +1,22 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_GL_TEXTURE_H
#define MOBILEGL_GL_TEXTURE_H
#include "../../../../Includes.h"
namespace MG_GL::GL {
void ActiveTexture(GLenum texture);
void BindTexture(GLenum target, GLuint texture);
void DeleteTextures(GLsizei n, const GLuint* textures);
void GenTextures(GLsizei n, GLuint* textures);
void TexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data);
void TexParameterf(GLenum target, GLenum pname, GLfloat param);
void TexParameteri(GLenum target, GLenum pname, GLint param);
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);
}
#endif //MOBILEGL_GL_TEXTURE_H
@@ -0,0 +1,9 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "GL_VertexArray.h"
namespace MG_GL::GL {
}
@@ -0,0 +1,14 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_GL_VERTEXARRAY_H
#define MOBILEGL_GL_VERTEXARRAY_H
#include "../../../../Includes.h"
namespace MG_GL::GL {
}
#endif //MOBILEGL_GL_VERTEXARRAY_H
@@ -0,0 +1,24 @@
//
// Created by BZLZHH on 2025/3/15.
//
#include "LookUp.h"
#include "../../../../Includes.h"
namespace MG_GL::GLX {
void* GetProcAddress(const char *name) {
void* proc = dlsym(RTLD_DEFAULT, (const char*)name);
if (!proc) {
MG_Util::Debug::LogW("Failed to get function: %s", (const char*)name);
return nullptr;
}
return proc;
}
void* GetProcAddressARB(const char *name) {
return GetProcAddress(name);
}
}
@@ -0,0 +1,12 @@
//
// Created by BZLZHH on 2025/3/15.
//
#ifndef MOBILEGL_LOOKUP_H
#define MOBILEGL_LOOKUP_H
namespace MG_GL::GLX {
void* GetProcAddress(const char *name);
void* GetProcAddressARB(const char *name);
}
#endif //MOBILEGL_LOOKUP_H