From 3e6aa18fbe9f6c2e9b232490c3fe37bedfd93cef Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sat, 22 Mar 2025 03:43:35 +0100 Subject: [PATCH] starting merge --- Examples/OpenGL/main.c | 2 +- Sources/Backends/OpenGL/EGL/EGLContext.c | 0 Sources/Backends/OpenGL/EGL/EGLContext.h | 19 ---- Sources/Backends/OpenGL/EGL/EGLInstance.c | 107 ++++++++++++++++++++ Sources/Backends/OpenGL/EGL/EGLInstance.h | 31 ++++++ Sources/Backends/OpenGL/OpenGL.c | 14 ++- Sources/Backends/OpenGL/OpenGL.h | 6 ++ Sources/Backends/Vulkan/VulkanCommandList.c | 2 +- Sources/Backends/Vulkan/VulkanLoader.c | 69 ++----------- Sources/PulseBackend.c | 2 +- Sources/PulseInternal.c | 48 +++++++++ Sources/PulseInternal.h | 29 ++++++ 12 files changed, 245 insertions(+), 84 deletions(-) delete mode 100644 Sources/Backends/OpenGL/EGL/EGLContext.c delete mode 100644 Sources/Backends/OpenGL/EGL/EGLContext.h create mode 100644 Sources/Backends/OpenGL/EGL/EGLInstance.c create mode 100644 Sources/Backends/OpenGL/EGL/EGLInstance.h diff --git a/Examples/OpenGL/main.c b/Examples/OpenGL/main.c index 9df25ad..9927330 100644 --- a/Examples/OpenGL/main.c +++ b/Examples/OpenGL/main.c @@ -28,6 +28,6 @@ int main(int ac, char** av) PulseSetDebugCallback(backend, DebugCallBack); PulseUnloadBackend(backend); - puts("Successfully executed Pulse example using OpenGL !"); + printf("Successfully executed Pulse example using %s !\n", backend_type == PULSE_BACKEND_OPENGL ? "OpenGL" : "OpenGL ES"); return 0; } diff --git a/Sources/Backends/OpenGL/EGL/EGLContext.c b/Sources/Backends/OpenGL/EGL/EGLContext.c deleted file mode 100644 index e69de29..0000000 diff --git a/Sources/Backends/OpenGL/EGL/EGLContext.h b/Sources/Backends/OpenGL/EGL/EGLContext.h deleted file mode 100644 index 769b363..0000000 --- a/Sources/Backends/OpenGL/EGL/EGLContext.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (C) 2025 kanel -// This file is part of "Pulse" -// For conditions of distribution and use, see copyright notice in LICENSE - -#ifdef PULSE_ENABLE_OPENGL_BACKEND - -#ifndef PULSE_EGL_CONTEXT_H_ -#define PULSE_EGL_CONTEXT_H_ - -typedef struct EGLContext -{ - EGLDisplay display; - EGLSurface surface; - EGLContext handle; -} EGLContext; - -#endif // PULSE_EGL_CONTEXT_H_ - -#endif // PULSE_ENABLE_OPENGL_BACKEND diff --git a/Sources/Backends/OpenGL/EGL/EGLInstance.c b/Sources/Backends/OpenGL/EGL/EGLInstance.c new file mode 100644 index 0000000..70e3ee0 --- /dev/null +++ b/Sources/Backends/OpenGL/EGL/EGLInstance.c @@ -0,0 +1,107 @@ +// Copyright (C) 2025 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#include "EGLInstance.h" +#include "../../../PulseInternal.h" + +static PulseLibModule egl_lib_module = PULSE_NULL_LIB_MODULE; +static uint32_t loader_references_count = 0; + +static bool EGLLoadFunctions(EGLInstance* instance) +{ + #ifdef PULSE_PLAT_WINDOWS + const char* libnames[] = { + "libEGL.dll" + }; + #else + const char* libnames[] = { + "libEGL.so.1", + "libEGL.so" + }; + #endif + + + for(size_t i = 0; i < sizeof(libnames) / sizeof(const char*); i++) + { + if(loader_references_count == 0) + egl_lib_module = PulseLoadLibrary(libnames[i]); + if(egl_lib_module) + { + instance->eglGetProcAddress = (PFNEGLGETPROCADDRESSPROC)PulseLoadSymbolFromLibModule(egl_lib_module, "eglGetProcAddress"); + if(instance->eglGetProcAddress == PULSE_NULLPTR) + { + PulseUnloadLibrary(egl_lib_module); + egl_lib_module = PULSE_NULL_LIB_MODULE; + } + else + break; + } + } + if(!egl_lib_module) + { + PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED); + return false; + } + loader_references_count++; + + #define PULSE_EGL_FUNCTION(fn, T) \ + instance->fn = (T)instance->eglGetProcAddress(#fn); \ + if(!instance->fn) \ + return false; + #include "EGLFunctions.h" + #undef PULSE_EGL_FUNCTION + + return true; +} + +bool EGLLoadInstance(EGLInstance* instance, bool es_context) +{ + PULSE_CHECK_PTR_RETVAL(instance, false); + + if(!EGLLoadFunctions(instance)) + return false; + + instance->display = instance->eglGetDisplay(EGL_DEFAULT_DISPLAY); + PULSE_CHECK_PTR_RETVAL(instance->display, false); + + instance->eglInitialize(instance->display, PULSE_NULLPTR, PULSE_NULLPTR); + EGLint attribs[] = { + EGL_RENDERABLE_TYPE, es_context ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_BIT, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_NONE + }; + EGLint num_configs; + instance->eglChooseConfig(instance->display, attribs, &instance->config, 1, &num_configs); + EGLint ctxAttribs[] = { + es_context ? EGL_CONTEXT_CLIENT_VERSION : EGL_CONTEXT_MAJOR_VERSION, 3, + EGL_NONE + }; + instance->eglBindAPI(es_context ? EGL_OPENGL_ES_API : EGL_OPENGL_API); + instance->context = instance->eglCreateContext(instance->display, instance->config, EGL_NO_CONTEXT, ctxAttribs); + PULSE_CHECK_PTR_RETVAL(instance->context, false); + + EGLint pbufferAttribs[] = { + EGL_WIDTH, 1, + EGL_HEIGHT, 1, + EGL_NONE + }; + instance->surface = instance->eglCreatePbufferSurface(instance->display, instance->config, pbufferAttribs); + PULSE_CHECK_PTR_RETVAL(instance->surface, false); + + return instance->eglMakeCurrent(instance->display, instance->surface, instance->surface, instance->context); +} + +void EGLUnloadInstance(EGLInstance* instance) +{ + PULSE_CHECK_PTR(instance); + instance->eglDestroySurface(instance->display, instance->surface); + instance->eglDestroyContext(instance->display, instance->context); + instance->eglTerminate(instance->display); + + loader_references_count--; + if(loader_references_count != 0) + return; + PulseUnloadLibrary(egl_lib_module); + egl_lib_module = PULSE_NULL_LIB_MODULE; +} diff --git a/Sources/Backends/OpenGL/EGL/EGLInstance.h b/Sources/Backends/OpenGL/EGL/EGLInstance.h new file mode 100644 index 0000000..3bb22dc --- /dev/null +++ b/Sources/Backends/OpenGL/EGL/EGLInstance.h @@ -0,0 +1,31 @@ +// Copyright (C) 2025 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#ifdef PULSE_ENABLE_OPENGL_BACKEND + +#ifndef PULSE_EGL_CONTEXT_H_ +#define PULSE_EGL_CONTEXT_H_ + +#define EGL_EGL_PROTOTYPES 0 +#include +#include + +typedef struct EGLInstance +{ + EGLDisplay display; + EGLSurface surface; + EGLContext context; + EGLConfig config; + + #define PULSE_EGL_FUNCTION(fn, T) T fn; + #include "EGLFunctions.h" + #undef PULSE_EGL_FUNCTION +} EGLInstance; + +bool EGLLoadInstance(EGLInstance* instance, bool es_context); +void EGLUnloadInstance(EGLInstance* instance); + +#endif // PULSE_EGL_CONTEXT_H_ + +#endif // PULSE_ENABLE_OPENGL_BACKEND diff --git a/Sources/Backends/OpenGL/OpenGL.c b/Sources/Backends/OpenGL/OpenGL.c index 569f465..2e5a99b 100644 --- a/Sources/Backends/OpenGL/OpenGL.c +++ b/Sources/Backends/OpenGL/OpenGL.c @@ -9,11 +9,15 @@ PulseBackendFlags OpenGLCheckSupport(PulseBackendFlags candidates, PulseShaderFormatsFlags shader_formats_used) { - if(candidates != PULSE_BACKEND_ANY && (candidates & PULSE_BACKEND_OPENGL) == 0) + if(candidates != PULSE_BACKEND_ANY && ((candidates & PULSE_BACKEND_OPENGL) == 0 || (candidates & PULSE_BACKEND_OPENGL_ES) == 0)) return PULSE_BACKEND_INVALID; if((shader_formats_used & PULSE_SHADER_FORMAT_GLSL_BIT) == 0) return PULSE_BACKEND_INVALID; + EGLInstance instance; + if(!EGLLoadInstance(&instance, candidates)) + return PULSE_BACKEND_INVALID; + EGLUnloadInstance(&instance); return PULSE_BACKEND_OPENGL; } @@ -23,12 +27,18 @@ bool OpenGLLoadBackend(PulseBackend backend, PulseDebugLevel debug_level) PULSE_UNUSED(debug_level); OpenGLDriverData* driver_data = (OpenGLDriverData*)calloc(1, sizeof(OpenGLDriverData)); PULSE_CHECK_ALLOCATION_RETVAL(driver_data, false); + #ifdef PULSE_PLAT_WINDOWS + // WGL support + #else + EGLLoadInstance(&driver_data->egl_instance, false); + #endif OpenGLDriver.driver_data = driver_data; return true; } void OpenGLUnloadBackend(PulseBackend backend) { + EGLUnloadInstance(&OPENGL_RETRIEVE_DRIVER_DATA_AS(backend, OpenGLDriverData*)->egl_instance); free(backend->driver_data); } @@ -48,12 +58,14 @@ bool OpenGLESLoadBackend(PulseBackend backend, PulseDebugLevel debug_level) PULSE_UNUSED(debug_level); OpenGLDriverData* driver_data = (OpenGLDriverData*)calloc(1, sizeof(OpenGLDriverData)); PULSE_CHECK_ALLOCATION_RETVAL(driver_data, false); + EGLLoadInstance(&driver_data->egl_instance, true); OpenGLDriver.driver_data = driver_data; return true; } void OpenGLESUnloadBackend(PulseBackend backend) { + EGLUnloadInstance(&OPENGL_RETRIEVE_DRIVER_DATA_AS(backend, OpenGLDriverData*)->egl_instance); free(backend->driver_data); } diff --git a/Sources/Backends/OpenGL/OpenGL.h b/Sources/Backends/OpenGL/OpenGL.h index 62095fc..caeff43 100644 --- a/Sources/Backends/OpenGL/OpenGL.h +++ b/Sources/Backends/OpenGL/OpenGL.h @@ -11,8 +11,14 @@ #define OPENGL_RETRIEVE_DRIVER_DATA_AS(handle, cast) ((cast)handle->driver_data) +#include "EGL/EGLInstance.h" + typedef struct OpenGLDriverData { + union + { + EGLInstance egl_instance; + }; } OpenGLDriverData; PulseBackendFlags OpenGLCheckSupport(PulseBackendFlags candidates, PulseShaderFormatsFlags shader_formats_used); // Return PULSE_BACKEND_OPENGL in case of success and PULSE_BACKEND_INVALID otherwise diff --git a/Sources/Backends/Vulkan/VulkanCommandList.c b/Sources/Backends/Vulkan/VulkanCommandList.c index 46aa1b4..10533d0 100644 --- a/Sources/Backends/Vulkan/VulkanCommandList.c +++ b/Sources/Backends/Vulkan/VulkanCommandList.c @@ -12,7 +12,7 @@ static void VulkanInitCommandList(VulkanCommandPool* pool, PulseCommandList cmd) { PULSE_CHECK_PTR(pool); - PULSE_CHECK_PTR(cmd); + PULSE_CHECK_HANDLE(cmd); VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(pool->device, VulkanDevice*); VulkanCommandList* vulkan_cmd = VULKAN_RETRIEVE_DRIVER_DATA_AS(cmd, VulkanCommandList*); diff --git a/Sources/Backends/Vulkan/VulkanLoader.c b/Sources/Backends/Vulkan/VulkanLoader.c index 476ae05..2b5f675 100644 --- a/Sources/Backends/Vulkan/VulkanLoader.c +++ b/Sources/Backends/Vulkan/VulkanLoader.c @@ -11,35 +11,7 @@ #include "VulkanDevice.h" #include "VulkanInstance.h" -#ifdef PULSE_PLAT_MACOS - #include // getenv -#endif - -#ifdef PULSE_PLAT_WINDOWS - typedef const char* LPCSTR; - typedef struct HINSTANCE__* HINSTANCE; - typedef HINSTANCE HMODULE; - #if defined(_MINWINDEF_) - /* minwindef.h defines FARPROC, and attempting to redefine it may conflict with -Wstrict-prototypes */ - #elif defined(_WIN64) - typedef __int64 (__stdcall* FARPROC)(void); - #else - typedef int (__stdcall* FARPROC)(void); - #endif -#endif - -#ifdef PULSE_PLAT_WINDOWS - __declspec(dllimport) HMODULE __stdcall LoadLibraryA(LPCSTR); - __declspec(dllimport) FARPROC __stdcall GetProcAddress(HMODULE, LPCSTR); - __declspec(dllimport) int __stdcall FreeLibrary(HMODULE); - typedef HMODULE LibModule; -#else - #include - typedef void* LibModule; -#endif - -static LibModule vulkan_lib_module = PULSE_NULLPTR; - +static PulseLibModule vulkan_lib_module = PULSE_NULL_LIB_MODULE; static uint32_t loader_references_count = 0; static bool VulkanLoadGlobalFunctions(void* context, PFN_vkVoidFunction (*load)(void*, const char*)); @@ -62,33 +34,6 @@ static inline PFN_vkVoidFunction vkGetDeviceProcAddrStub(VulkanInstance* instanc return fn; } -static inline LibModule LoadLibrary(const char* libname) -{ - #ifdef PULSE_PLAT_WINDOWS - return LoadLibraryA(libname); - #else - return dlopen(libname, RTLD_NOW | RTLD_LOCAL); - #endif -} - -static inline void* GetSymbol(LibModule module, const char* name) -{ - #ifdef PULSE_PLAT_WINDOWS - return (void*)(void(*)(void))GetProcAddress(module, name); - #else - return dlsym(module, name); - #endif -} - -static inline void UnloadLibrary(LibModule lib) -{ - #ifdef PULSE_PLAT_WINDOWS - FreeLibrary(lib); - #else - dlclose(lib); - #endif -} - bool VulkanInitLoader() { #if defined(PULSE_PLAT_WINDOWS) @@ -116,15 +61,17 @@ bool VulkanInitLoader() for(size_t i = 0; i < sizeof(libnames) / sizeof(const char*); i++) { - vulkan_lib_module = LoadLibrary(libnames[i]); + vulkan_lib_module = PulseLoadLibrary(libnames[i]); if(vulkan_lib_module) { - VulkanGetGlobal()->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)GetSymbol(vulkan_lib_module, "vkGetInstanceProcAddr"); + VulkanGetGlobal()->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)PulseLoadSymbolFromLibModule(vulkan_lib_module, "vkGetInstanceProcAddr"); if(VulkanGetGlobal()->vkGetInstanceProcAddr == PULSE_NULLPTR) { - UnloadLibrary(vulkan_lib_module); + PulseUnloadLibrary(vulkan_lib_module); vulkan_lib_module = PULSE_NULLPTR; } + else + break; } } if(!vulkan_lib_module) @@ -151,8 +98,8 @@ void VulkanLoaderShutdown() loader_references_count--; if(loader_references_count != 0) return; - UnloadLibrary(vulkan_lib_module); - vulkan_lib_module = PULSE_NULLPTR; + PulseUnloadLibrary(vulkan_lib_module); + vulkan_lib_module = PULSE_NULL_LIB_MODULE; } static bool VulkanLoadGlobalFunctions(void* context, PFN_vkVoidFunction (*load)(void*, const char*)) diff --git a/Sources/PulseBackend.c b/Sources/PulseBackend.c index 4791f3b..e5b168a 100644 --- a/Sources/PulseBackend.c +++ b/Sources/PulseBackend.c @@ -116,7 +116,7 @@ static PulseBackend PulseGetBackendFromFlag(PulseBackendBits flag) case PULSE_BACKEND_SOFTWARE: return &SoftwareDriver; #endif #ifdef PULSE_ENABLE_OPENGL_BACKEND - case PULSE_BACKEND_OPENGL: return &OpenGLDriver; + case PULSE_BACKEND_OPENGL: case PULSE_BACKEND_OPENGL_ES: return &OpenGLESDriver; #endif diff --git a/Sources/PulseInternal.c b/Sources/PulseInternal.c index 4fdbc76..d869e3b 100644 --- a/Sources/PulseInternal.c +++ b/Sources/PulseInternal.c @@ -33,3 +33,51 @@ emscripten_thread_sleep(ms); } #endif + +#ifdef PULSE_PLAT_WINDOWS + PULSE_IMPORT_API HMODULE __stdcall LoadLibraryA(LPCSTR); + PULSE_IMPORT_API FARPROC __stdcall GetProcAddress(HMODULE, LPCSTR); + PULSE_IMPORT_API int __stdcall FreeLibrary(HMODULE); +#else + #ifdef PULSE_PLAT_MACOS + #include + #endif + #include +#endif + +PulseLibModule PulseLoadLibrary(const char* libpath) +{ + PulseLibModule module; + #ifdef PULSE_PLAT_WINDOWS + module = LoadLibraryA(libpath); + #else + dlerror(); + module = dlopen(libpath, RTLD_NOW | RTLD_LOCAL); + #endif + return (module ? module : PULSE_NULL_LIB_MODULE); +} + +PFN_PulseLibFunction PulseLoadSymbolFromLibModule(PulseLibModule module, const char* symbol) +{ + if(module == PULSE_NULL_LIB_MODULE) + return PULSE_NULLPTR; + PFN_PulseLibFunction function; + #ifdef PULSE_PLAT_WINDOWS + function = (PFN_PulseLibFunction)GetProcAddress(module, symbol); + #else + void* symbol_ptr = (PFN_PulseLibFunction)dlsym(module, symbol); + *(void**)(&function) = symbol_ptr; + #endif + return function; +} + +void PulseUnloadLibrary(PulseLibModule module) +{ + if(module == PULSE_NULL_LIB_MODULE) + return; + #ifdef PULSE_PLAT_WINDOWS + FreeLibrary(module); + #else + dlclose(module); + #endif +} diff --git a/Sources/PulseInternal.h b/Sources/PulseInternal.h index 9f96384..69d535f 100644 --- a/Sources/PulseInternal.h +++ b/Sources/PulseInternal.h @@ -157,6 +157,35 @@ typedef struct PulseComputePassHandler PulseThreadID PulseGetThreadID(); void PulseSleep(int32_t ms); +#ifdef KANEL_CLI_PLAT_WINDOWS + typedef const char* LPCSTR; + typedef struct HINSTANCE__* HINSTANCE; + typedef HINSTANCE HMODULE; + #if defined(_MINWINDEF_) + /* minwindef.h defines FARPROC, and attempting to redefine it may conflict with -Wstrict-prototypes */ + #elif defined(_WIN64) + typedef __int64 (__stdcall* FARPROC)(void); + #else + typedef int (__stdcall* FARPROC)(void); + #endif +#else + #include +#endif + +#ifdef PULSE_PLAT_WINDOWS + typedef HMODULE PulseLibModule; +#else + typedef void* PulseLibModule; +#endif + +typedef void(*PFN_PulseLibFunction)(void); + +#define PULSE_NULL_LIB_MODULE PULSE_NULLPTR + +PulseLibModule PulseLoadLibrary(const char* libpath); // Returns PULSE_NULL_LIB_MODULE in case of failure +PFN_PulseLibFunction PulseLoadSymbolFromLibModule(PulseLibModule module, const char* symbol); +void PulseUnloadLibrary(PulseLibModule module); + void PulseSetInternalError(PulseErrorType error); void PulseLogBackend(PulseBackend backend, PulseDebugMessageSeverity type, const char* message, const char* file, const char* function, int line, ...);