mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Feat|Fix] (...): Emulate EGL. Emulate glClear and glClearColor.
Signed-off-by: BZLZHH <admin@bzlzhh.top>
This commit is contained in:
+1
-1
@@ -27,7 +27,7 @@ namespace MG_Global {
|
||||
}
|
||||
|
||||
namespace Common {
|
||||
inline const int LogLevel = MG_Constants::Common::LOG_LEVEL_INFO;
|
||||
inline const int LogLevel = MG_Constants::Common::LOG_LEVEL_DEBUG;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
inline const char* LOG_FILE_PATH = "/sdcard/MG/latest.log";
|
||||
|
||||
+23
-2
@@ -21,8 +21,14 @@
|
||||
#ifndef MOBILEGL_DEBUG_H
|
||||
#include "MG_UTIL/Debug/Debug.h"
|
||||
#endif
|
||||
#ifndef MOBILEGL_MESAEMU_H
|
||||
#include "MG_GL/TEMP_MESA/MesaEmu.h"
|
||||
//#ifndef MOBILEGL_MESAEMU_H
|
||||
//#include "MG_GL/TEMP_MESA/MesaEmu.h"
|
||||
//#endif
|
||||
#ifndef MOBILEGL_GL_DEPTH_H
|
||||
#include "MG_GL/GL/Depth/GL_Depth.h"
|
||||
#endif
|
||||
#ifndef MOBILEGL_EGL_EMU_H
|
||||
#include "MG_GL/EGL/EGL_EMU.h"
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
@@ -37,11 +43,25 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <atomic>
|
||||
#include <regex>
|
||||
#include <strstream>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <random>
|
||||
#include <unordered_map>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
#include <glslang/Include/Types.h>
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
#include <spirv_cross/spirv_cross_c.h>
|
||||
#include <glslang/SPIRV/GlslangToSpv.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#include <pthread.h>
|
||||
#include <vulkan/vulkan_android.h>
|
||||
#include <android/native_window.h>
|
||||
#elif _WIN32
|
||||
#include <windows.h>
|
||||
#include <processthreadsapi.h>
|
||||
@@ -49,5 +69,6 @@
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
@@ -0,0 +1,547 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/3/30.
|
||||
//
|
||||
|
||||
#include "EGL_EMU.h"
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/3/30.
|
||||
//
|
||||
|
||||
#ifndef MOBILEGL_EGL_EMU_H
|
||||
#define MOBILEGL_EGL_EMU_H
|
||||
|
||||
#include "../../Includes.h"
|
||||
|
||||
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;
|
||||
|
||||
extern "C" MG_EXPORT EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint* attrib_list);
|
||||
extern "C" MG_EXPORT EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config);
|
||||
extern "C" MG_EXPORT EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext shareCtx, const EGLint* attrib_list);
|
||||
extern "C" MG_EXPORT EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor);
|
||||
extern "C" MG_EXPORT EGLDisplay eglGetDisplay(NativeDisplayType display);
|
||||
extern "C" MG_EXPORT EGLint eglGetError();
|
||||
extern "C" MG_EXPORT EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
extern "C" MG_EXPORT EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
|
||||
extern "C" MG_EXPORT EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
|
||||
extern "C" MG_EXPORT EGLBoolean eglTerminate(EGLDisplay dpy);
|
||||
extern "C" MG_EXPORT EGLBoolean eglReleaseThread(void);
|
||||
extern "C" MG_EXPORT EGLContext eglGetCurrentContext(void);
|
||||
extern "C" MG_EXPORT EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
extern "C" MG_EXPORT EGLBoolean eglBindAPI(EGLenum api);
|
||||
extern "C" MG_EXPORT EGLSurface eglGetCurrentSurface(EGLint readdraw);
|
||||
extern "C" MG_EXPORT EGLBoolean eglQuerySurface(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint *value);
|
||||
extern "C" MG_EXPORT EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval);
|
||||
extern "C" MG_EXPORT EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
|
||||
extern "C" MG_EXPORT EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
|
||||
#endif //MOBILEGL_EGL_EMU_H
|
||||
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// 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) {
|
||||
EGLContext ctx = eglGetCurrentContext();
|
||||
if (ctx == EGL_NO_CONTEXT) return;
|
||||
|
||||
VulkanContext& vkCtx = g_contexts[ctx];
|
||||
vkCtx.clearColor = VkClearColorValue{{red, green, blue, alpha}};
|
||||
}
|
||||
|
||||
void Clear(GLbitfield mask) {
|
||||
if ((mask & GL_COLOR_BUFFER_BIT) == 0) return;
|
||||
|
||||
EGLContext eglCtx = eglGetCurrentContext();
|
||||
if (eglCtx == EGL_NO_CONTEXT) return;
|
||||
|
||||
VulkanContext& ctx = g_contexts[eglCtx];
|
||||
VulkanDisplay& disp = g_displays[eglGetCurrentDisplay()];
|
||||
EGLSurface drawSurf = eglGetCurrentSurface(EGL_DRAW);
|
||||
if (drawSurf == EGL_NO_SURFACE) return;
|
||||
|
||||
VulkanSurface& surf = g_surfaces[drawSurf];
|
||||
if (surf.type != VulkanSurface::WINDOW) return;
|
||||
|
||||
VkImage currentImage = surf.images[ctx.frameIndex];
|
||||
|
||||
VkImageMemoryBarrier barrier{};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = currentImage;
|
||||
barrier.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1
|
||||
};
|
||||
barrier.srcAccessMask = 0;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
vkCmdPipelineBarrier(
|
||||
ctx.currentCmdBuffer,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &barrier
|
||||
);
|
||||
|
||||
VkImageSubresourceRange range = barrier.subresourceRange;
|
||||
vkCmdClearColorImage(
|
||||
ctx.currentCmdBuffer,
|
||||
currentImage,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
&ctx.clearColor,
|
||||
1, &range
|
||||
);
|
||||
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = 0;
|
||||
|
||||
vkCmdPipelineBarrier(
|
||||
ctx.currentCmdBuffer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &barrier
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/3/15.
|
||||
//
|
||||
|
||||
#ifndef MOBILEGL_GL_DEPTH_H
|
||||
#define MOBILEGL_GL_DEPTH_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);
|
||||
}
|
||||
|
||||
#endif //MOBILEGL_GL_DEPTH_H
|
||||
@@ -19,11 +19,11 @@ namespace MG_GL::Getter {
|
||||
|
||||
const std::string GetMGName() {
|
||||
#if BACKEND_TYPE == BACKEND_VULKAN
|
||||
return "MobileGLUVK";
|
||||
return "MobileGluvk";
|
||||
#elif BACKEND_TYPE == BACKEND_METAL
|
||||
return "MobileGLUMTL";
|
||||
return "MobileGlumtl";
|
||||
#elif BACKEND_TYPE == BACKEND_GLES
|
||||
return "MobileGLUES";
|
||||
return "MobileGlues";
|
||||
#else
|
||||
return "<Unknown MobileGL Version>";
|
||||
#endif
|
||||
|
||||
@@ -163,8 +163,16 @@ namespace MG_GL::GL {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ namespace MG_GL::GL {
|
||||
const ::GLubyte* GetStringi(GLenum name, GLuint index);
|
||||
::GLenum GetError();
|
||||
void GetIntegerv(GLenum pname, GLint *params);
|
||||
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
|
||||
}
|
||||
|
||||
#endif //MOBILEGL_GL_GETTER_H
|
||||
|
||||
@@ -32,7 +32,7 @@ extern "C" MG_EXPORT type gl##name(__VA_ARGS__) {
|
||||
DECLARE_GL_FUNCTION_HEAD(const GLubyte*, GetStringi, GLenum name, GLuint index) DECLARE_GL_FUNCTION_END(const GLubyte*, GetStringi, name, index)
|
||||
DECLARE_GL_FUNCTION_HEAD(const GLubyte*, GetString, GLenum name) DECLARE_GL_FUNCTION_END(const GLubyte*, GetString, name)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void*, MapBuffer, GLenum target, GLenum access) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void*, MapBuffer, target, access)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearDepth, GLclampd depth) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearDepth, depth)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, ClearDepth, GLclampd depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearDepth, depth)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ActiveTexture, GLenum texture) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ActiveTexture, texture)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, AttachShader, GLuint program, GLuint shader) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, AttachShader, program,shader)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindAttribLocation, GLuint program, GLuint index, const GLchar *name) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindAttribLocation, program,index,name)
|
||||
@@ -48,8 +48,8 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFuncSeparate, GLenum sfactorRGB, GLenum
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BufferData, target,size,data,usage)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BufferSubData, target,offset,size,data)
|
||||
DECLARE_GL_FUNCTION_HEAD(GLenum, CheckFramebufferStatus, GLenum target) DECLARE_GL_FUNCTION_END(GLenum, CheckFramebufferStatus, target)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Clear, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Clear, mask)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearColor, red,green,blue,alpha)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, Clear, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Clear, mask)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, ClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearColor, red,green,blue,alpha)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearDepthf, GLfloat d) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearDepthf, d)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearStencil, GLint s) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearStencil, s)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ColorMask, red,green,blue,alpha)
|
||||
@@ -337,7 +337,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, MemoryBarrierByRegion, GLbitfield barriers)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage2DMultisample, target,samples,internalformat,width,height,fixedsamplelocations)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMultisamplefv, GLenum pname, GLuint index, GLfloat *val) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMultisamplefv, pname,index,val)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, SampleMaski, GLuint maskNumber, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, SampleMaski, maskNumber,mask)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTexLevelParameteriv, GLenum target, GLint level, GLenum pname, GLint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTexLevelParameteriv, target,level,pname,params)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetTexLevelParameteriv, GLenum target, GLint level, GLenum pname, GLint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTexLevelParameteriv, target,level,pname,params)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTexLevelParameterfv, GLenum target, GLint level, GLenum pname, GLfloat *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTexLevelParameterfv, target,level,pname,params)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindVertexBuffer, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindVertexBuffer, bindingindex,buffer,offset,stride)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribFormat, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribFormat, attribindex,size,type,normalized,relativeoffset)
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace MG_Util::Debug {
|
||||
vprintf(full_format.c_str(), args);
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
LogWrite(full_format.c_str(), args_copy);
|
||||
LogWrite(full_format.c_str(), args);
|
||||
va_end(args_copy);
|
||||
}
|
||||
|
||||
@@ -128,7 +128,6 @@ void Log##name(const char* format, ...) { \
|
||||
va_start(args, format);
|
||||
vfprintf(logFile, format, args);
|
||||
va_end(args);
|
||||
fprintf(logFile, "\n");
|
||||
fflush(logFile);
|
||||
#if FORCE_SYNC_WITH_LOG_FILE == 1
|
||||
int fd = fileno(logFile);
|
||||
@@ -270,7 +269,7 @@ void Log##name(const char* format, ...) { \
|
||||
CASE(GL_LIST_INDEX)
|
||||
CASE(GL_LIST_MODE)
|
||||
|
||||
/* Depth buffer */
|
||||
/* Common buffer */
|
||||
CASE(GL_NEVER)
|
||||
CASE(GL_LESS)
|
||||
CASE(GL_EQUAL)
|
||||
|
||||
Reference in New Issue
Block a user