From 681d137cd97be1ae3c945f03e98fc5e088589997 Mon Sep 17 00:00:00 2001 From: Emmanuel Boutin Date: Thu, 5 Jan 2023 19:42:46 +0100 Subject: [PATCH] Add support for externally provided GL3 --- CMakeLists.txt | 4 +- conanfile.py | 8 +- premake5.lua | 11 ++- skeleton/glfw.cpp | 2 +- skeleton/win.cpp | 2 +- src/CMakeLists.txt | 3 + src/gl/gl3device.cpp | 195 ++++++++++++++++++++++++++++++++++++++++--- src/gl/rwgl3.h | 15 +++- src/gl/rwgl3impl.h | 8 +- src/gl/rwgl3plg.h | 7 ++ 10 files changed, 229 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f4d3ce..2f7f750 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,7 +38,7 @@ if(NOT LIBRW_PLATFORM IN_LIST LIBRW_PLATFORMS) message(FATAL_ERROR "Illegal LIBRW_PLATFORM=${LIBRW_PLATFORM}") endif() -set(LIBRW_GL3_GFXLIBS "GLFW" "SDL2") +set(LIBRW_GL3_GFXLIBS "GLFW" "SDL2" "EXTGL3") set(LIBRW_GL3_GFXLIB "GLFW" CACHE STRING "gfxlib for gl3") set_property(CACHE LIBRW_GL3_GFXLIB PROPERTY STRINGS ${LIBRW_GL3_GFXLIBS}) if(LIBRW_PLATFORM_GL3) @@ -124,6 +124,8 @@ if(LIBRW_INSTALL) elseif(LIBRW_PLATFORM_GL3) if(LIBRW_GL3_GFXLIB STREQUAL "GLFW") set(platform "-gl3-glfw") + elseif(LIBRW_GL3_GFXLIB STREQUAL "EXTGL3") + set(platform "-gl3-extgl3") else() set(platform "-gl3-sdl2") endif() diff --git a/conanfile.py b/conanfile.py index aa36dd5..fff2add 100644 --- a/conanfile.py +++ b/conanfile.py @@ -13,7 +13,7 @@ class LibrwConan(ConanFile): generators = "cmake", "cmake_find_package" options = { "platform": ["null", "gl3", "d3d9", "ps2"], - "gl3_gfxlib": ["glfw", "sdl2"], + "gl3_gfxlib": ["glfw", "sdl2", "extgl3"], } default_options = { "platform": "gl3", @@ -124,7 +124,11 @@ class LibrwConan(ConanFile): self.cpp_info.defines.append("RW_NULL") elif self.options.platform == "gl3": self.cpp_info.defines.append("RW_GL3") - if self.options.gl3_gfxlib == "sdl2": + if self.options.gl3_gfxlib == "glfw": + self.cpp_info.defines.append("LIBRW_GLFW") + elif self.options.gl3_gfxlib == "extgl3": + self.cpp_info.defines.append("LIBRW_EXTGL3") + elif self.options.gl3_gfxlib == "sdl2": self.cpp_info.defines.append("LIBRW_SDL2") elif self.options.platform == "d3d9": self.cpp_info.defines.append("RW_D3D9") diff --git a/premake5.lua b/premake5.lua index e9e7839..4dc85b7 100755 --- a/premake5.lua +++ b/premake5.lua @@ -6,6 +6,7 @@ newoption { allowed = { { "glfw", "GLFW" }, { "sdl2", "SDL2" }, + { "extgl3", "EXTGL3" }, }, } @@ -62,8 +63,12 @@ workspace "librw" defines { "RW_NULL" } filter { "platforms:*gl3" } defines { "RW_GL3" } - if _OPTIONS["gfxlib"] == "sdl2" then + if _OPTIONS["gfxlib"] == "glfw" then + defines { "LIBRW_GLFW" } + elseif _OPTIONS["gfxlib"] == "sdl2" then defines { "LIBRW_SDL2" } + elseif _OPTIONS["gfxlib"] == "extgl3" then + defines { "LIBRW_EXTGL3" } end filter { "platforms:*d3d9" } defines { "RW_D3D9" } @@ -131,7 +136,7 @@ function findlibs() links { "GL" } if _OPTIONS["gfxlib"] == "glfw" then links { "glfw" } - else + elseif _OPTIONS["gfxlib"] == "sdl2" then links { "SDL2" } end filter { "platforms:win-amd64-gl3" } @@ -144,7 +149,7 @@ function findlibs() links { "opengl32" } if _OPTIONS["gfxlib"] == "glfw" then links { "glfw3" } - else + elseif _OPTIONS["gfxlib"] == "sdl2" then links { "SDL2" } end filter { "platforms:*d3d9" } diff --git a/skeleton/glfw.cpp b/skeleton/glfw.cpp index 23832c0..cae9b9a 100644 --- a/skeleton/glfw.cpp +++ b/skeleton/glfw.cpp @@ -1,4 +1,4 @@ -#ifndef LIBRW_SDL2 +#ifdef LIBRW_GLFW #include #include "skeleton.h" diff --git a/skeleton/win.cpp b/skeleton/win.cpp index 9f1ee5a..373c598 100644 --- a/skeleton/win.cpp +++ b/skeleton/win.cpp @@ -291,7 +291,7 @@ SetMousePosition(int x, int y) #endif -#ifdef RW_OPENGL +#if defined(RW_OPENGL) && !defined(LIBRW_EXTGL3) int main(int argc, char *argv[]); int WINAPI diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0e3d637..993c816 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -153,10 +153,13 @@ if(LIBRW_PLATFORM_GL3) if (NOT TARGET glfw) find_package(glfw3 REQUIRED) endif() + target_compile_definitions(librw PUBLIC LIBRW_GLFW) target_link_libraries(librw PUBLIC glfw ) + elseif (LIBRW_GL3_GFXLIB STREQUAL "EXTGL3") + target_compile_definitions(librw PUBLIC LIBRW_EXTGL3) elseif (LIBRW_GL3_GFXLIB STREQUAL "SDL2") if (NOT TARGET SDL2::SDL2) find_package(SDL2 REQUIRED) diff --git a/src/gl/gl3device.cpp b/src/gl/gl3device.cpp index 96bddb2..42ff0f2 100644 --- a/src/gl/gl3device.cpp +++ b/src/gl/gl3device.cpp @@ -1244,10 +1244,13 @@ getFramebufferRect(Raster *frameBuffer) Rect r; Raster *fb = frameBuffer->parent; if(fb->type == Raster::CAMERA){ -#ifdef LIBRW_SDL2 +#if defined(LIBRW_SDL2) SDL_GetWindowSize(glGlobals.window, &r.w, &r.h); -#else +#elif defined(LIBRW_GLFW) glfwGetFramebufferSize(glGlobals.window, &r.w, &r.h); +#elif defined(LIBRW_EXTGL3) + r.w = fb->width; + r.h = fb->height; #endif }else{ r.w = fb->width; @@ -1406,18 +1409,20 @@ showRaster(Raster *raster, uint32 flags) // glViewport(raster->offsetX, raster->offsetY, // raster->width, raster->height); -#ifdef LIBRW_SDL2 +#if defined(LIBRW_SDL2) if(flags & Raster::FLIPWAITVSYNCH) SDL_GL_SetSwapInterval(1); else SDL_GL_SetSwapInterval(0); SDL_GL_SwapWindow(glGlobals.window); -#else +#elif defined(LIBRW_GLFW) if(flags & Raster::FLIPWAITVSYNCH) glfwSwapInterval(1); else glfwSwapInterval(0); glfwSwapBuffers(glGlobals.window); +#elif defined(LIBRW_EXTGL3) + // Do nothing #endif } @@ -1447,7 +1452,7 @@ rasterRenderFast(Raster *raster, int32 x, int32 y) return 0; } -#ifdef LIBRW_SDL2 +#if defined(LIBRW_SDL2) static void addVideoMode(int displayIndex, int modeIndex) @@ -1600,7 +1605,8 @@ stopSDL2(void) SDL_DestroyWindow(glGlobals.window); return 1; } -#else + +#elif defined(LIBRW_GLFW) static void addVideoMode(const GLFWvidmode *mode) @@ -1764,6 +1770,113 @@ stopGLFW(void) glfwDestroyWindow(glGlobals.window); return 1; } + +#elif defined(LIBRW_EXTGL3) + +// Apple defines everything on his own +#ifndef __APPLE__ + +#if defined(_WIN32) || defined(__WIN32__) +#ifndef WIN32_LEAN_AND_MEAN + // Reduce a bit header VC++ compilation time +#define WIN32_LEAN_AND_MEAN 1 +#define LE_ME_ISDEF +#endif + +// APIENTRY is defined in glad.h as well as by windows.h. +// Undefine it to prevent a macro redefinition warning. +#undef APIENTRY +#include //For wglGetProcAddress +#ifdef LE_ME_ISDEF +#undef WIN32_LEAN_AND_MEAN +#undef LE_ME_ISDEF +#endif + +void* __defaultGetProcAddress(const char* name) +{ + void* p = (void*)wglGetProcAddress(name); + if (p == 0 || (p == (void*)0x1) || (p == (void*)0x2) || (p == (void*)0x3) || (p == (void*)-1)) + { + HMODULE module = LoadLibraryA("opengl32.dll"); + p = (void*)GetProcAddress(module, name); + } + return p; +} +#else // Linux + // GLX_ARB_get_proc_address + // glXGetProcAddressARB is statically exported by all libGL implementations, + // while glXGetProcAddress may be not available. + #ifdef __cplusplus + extern "C" { + #endif + extern void (*glXGetProcAddressARB(const GLubyte *procName))(); + #ifdef __cplusplus + } + #endif + #define __defaultGetProcAddress(name) (*glXGetProcAddressARB)((const GLubyte*)name) +#endif + +#endif // __APPLE__ + +void* defaultGetProcAddress(const char* fname) +{ + void* pret = (void*) __defaultGetProcAddress(fname); + + // Some drivers return values from 0, -1, 1, 2 or 3 + if ( pret == (void*)-1 || pret == (void*)1 || pret == (void*)2 || pret == (void*)3 ) + pret = (void*)0; + + return pret; +} + +static int +openEXTGL3(EngineOpenParams *openparams) +{ + glGlobals.winWidth = openparams->width; + glGlobals.winHeight = openparams->height; + glGlobals.winTitle = openparams->windowtitle; + glGlobals.modes = NULL; + glGlobals.numModes = 0; + glGlobals.currentMode = -1; + + memset(&gl3Caps, 0, sizeof(gl3Caps)); + gl3Caps.gles = openparams->gles; + gl3Caps.glversion = openparams->glversion; + gl3Caps.loadproc = openparams->loadproc ? openparams->loadproc : defaultGetProcAddress; + + return 1; +} + +static int +closeEXTGL3(void) +{ + return 1; +} + +static int +startEXTGL3(void) +{ + if (!((gl3Caps.gles ? gladLoadGLES2Loader : gladLoadGLLoader) (gl3Caps.loadproc, gl3Caps.glversion)) ) { + RWERROR((ERR_GENERAL, "gladLoadGLLoader failed")); + return 0; + } + + printf("OpenGL version: %s\n", glGetString(GL_VERSION)); + + glGlobals.presentWidth = 0; + glGlobals.presentHeight = 0; + glGlobals.presentOffX = 0; + glGlobals.presentOffY = 0; + + return 1; +} + +static int +stopEXTGL3(void) +{ + return 1; +} + #endif static int @@ -1920,7 +2033,7 @@ finalizeOpenGL(void) return 1; } -#ifdef LIBRW_SDL2 +#if defined(LIBRW_SDL2) static int deviceSystemSDL2(DeviceReq req, void *arg, int32 n) { @@ -1984,7 +2097,7 @@ deviceSystemSDL2(DeviceReq req, void *arg, int32 n) return 1; } -#else +#elif defined(LIBRW_GLFW) static int deviceSystemGLFW(DeviceReq req, void *arg, int32 n) @@ -2071,6 +2184,66 @@ deviceSystemGLFW(DeviceReq req, void *arg, int32 n) return 1; } +#elif defined(LIBRW_EXTGL3) + +static int +deviceSystemEXTGL3(DeviceReq req, void *arg, int32 n) +{ + VideoMode *rwmode; + + switch(req){ + case DEVICEOPEN: + return openEXTGL3((EngineOpenParams*)arg); + case DEVICECLOSE: + return closeEXTGL3(); + + case DEVICEINIT: + return startEXTGL3() && initOpenGL(); + case DEVICETERM: + return termOpenGL() && stopEXTGL3(); + + case DEVICEFINALIZE: + return finalizeOpenGL(); + + // no sub-systems + + case DEVICEGETNUMVIDEOMODES: + return glGlobals.numModes; + + case DEVICEGETCURRENTVIDEOMODE: + return glGlobals.currentMode; + + case DEVICESETVIDEOMODE: + if(n >= glGlobals.numModes) + return 0; + glGlobals.currentMode = n; + return 1; + + case DEVICEGETVIDEOMODEINFO: + return 0; + + case DEVICEGETMAXMULTISAMPLINGLEVELS: + { + GLint maxSamples; + glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + if(maxSamples == 0) + return 1; + return maxSamples; + } + case DEVICEGETMULTISAMPLINGLEVELS: + if(glGlobals.numSamples == 0) + return 1; + return glGlobals.numSamples; + case DEVICESETMULTISAMPLINGLEVELS: + glGlobals.numSamples = (uint32)n; + return 1; + default: + assert(0 && "not implemented"); + return 0; + } + return 1; +} + #endif Device renderdevice = { @@ -2090,10 +2263,12 @@ Device renderdevice = { gl3::im3DRenderPrimitive, gl3::im3DRenderIndexedPrimitive, gl3::im3DEnd, -#ifdef LIBRW_SDL2 +#if defined(LIBRW_SDL2) gl3::deviceSystemSDL2 -#else +#elif defined(LIBRW_GLFW) gl3::deviceSystemGLFW +#elif defined(LIBRW_EXTGL3) + gl3::deviceSystemEXTGL3 #endif }; diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 3275679..3315227 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -1,8 +1,8 @@ #ifdef RW_GL3 #include "glad/glad.h" -#ifdef LIBRW_SDL2 +#if defined(LIBRW_SDL2) #include -#else +#elif defined(LIBRW_GLFW) #include #endif #endif @@ -12,11 +12,15 @@ namespace rw { #ifdef RW_GL3 struct EngineOpenParams { -#ifdef LIBRW_SDL2 +#if defined(LIBRW_SDL2) SDL_Window **window; bool32 fullscreen; -#else +#elif defined(LIBRW_GLFW) GLFWwindow **window; +#elif defined(LIBRW_EXTGL3) + int gles; + int glversion; + GLADloadproc loadproc; #endif int width, height; const char *windowtitle; @@ -274,6 +278,9 @@ struct Gl3Caps { int gles; int glversion; +#ifdef LIBRW_EXTGL3 + GLADloadproc loadproc; +#endif bool dxtSupported; bool astcSupported; // not used yet float maxAnisotropy; diff --git a/src/gl/rwgl3impl.h b/src/gl/rwgl3impl.h index 39f0050..f627614 100644 --- a/src/gl/rwgl3impl.h +++ b/src/gl/rwgl3impl.h @@ -24,9 +24,9 @@ void im3DEnd(void); struct DisplayMode { -#ifdef LIBRW_SDL2 +#if defined(LIBRW_SDL2) SDL_DisplayMode mode; -#else +#elif defined(LIBRW_GLFW) GLFWvidmode mode; #endif int32 depth; @@ -35,11 +35,11 @@ struct DisplayMode struct GlGlobals { -#ifdef LIBRW_SDL2 +#if defined(LIBRW_SDL2) SDL_Window **pWindow; SDL_Window *window; SDL_GLContext glcontext; -#else +#elif defined(LIBRW_GLFW) GLFWwindow **pWindow; GLFWwindow *window; diff --git a/src/gl/rwgl3plg.h b/src/gl/rwgl3plg.h index 5374b3e..c896b8e 100644 --- a/src/gl/rwgl3plg.h +++ b/src/gl/rwgl3plg.h @@ -11,6 +11,13 @@ void skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance void skinRenderCB(Atomic *atomic, InstanceDataHeader *header); void uploadSkinMatrices(Atomic *atomic); +#ifdef LIBRW_EXTGL3 +namespace extgl3 { + +void init(void); + +} +#endif } }