From e014ce32c17d600812ffa453c89b95e2dd611566 Mon Sep 17 00:00:00 2001 From: Yan Pujante Date: Sun, 12 Nov 2023 10:52:45 -0800 Subject: [PATCH] fixes 3372 by implement hi dpi aware in raylib --- examples/CMakeLists.txt | 1 + src/platforms/rcore_web.c | 191 ++++++++++++++++++++++++++++++-------- src/shell.html | 1 + 3 files changed, 154 insertions(+), 39 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3bcdc19f0..3bfe2c9cd 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -99,6 +99,7 @@ elseif (${PLATFORM} MATCHES "Web") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY") # Since WASM is used, ALLOW_MEMORY_GROWTH has no extra overheads set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s ALLOW_MEMORY_GROWTH=1 --no-heap-copy") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s EXPORTED_FUNCTIONS=_main,_SetHighDPIAware,_FullscreenCallback -s EXPORTED_RUNTIME_METHODS=cwrap") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --shell-file ${CMAKE_SOURCE_DIR}/src/shell.html") set(CMAKE_EXECUTABLE_SUFFIX ".html") diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 21baada48..1df9a58d8 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -73,6 +73,7 @@ //---------------------------------------------------------------------------------- typedef struct { GLFWwindow *handle; // GLFW window handle (graphic device) + bool isHighDPIAware; } PlatformData; //---------------------------------------------------------------------------------- @@ -116,6 +117,15 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData); static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData); +static bool IsHighDPIAware(); +static float GetDevicePixelRatio(); +static void InstallModuleJSAPI(); +static void AdjustWindowSize(int width, int height, int fbWidth, int fbHeight); +static void AdjustFrameBufferSize(int fbWidth, int fbHeight); + +void SetHighDPIAware(bool flag); +void FullscreenCallback(bool isFullscreen); + //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- @@ -298,7 +308,8 @@ void SetWindowMaxSize(int width, int height) // Set window dimensions void SetWindowSize(int width, int height) { - glfwSetWindowSize(platform.handle, width, height); +// glfwSetWindowSize(platform.handle, width, height); + WindowSizeCallback(platform.handle, width, height); } // Set window opacity, value opacity is between 0.0 and 1.0 @@ -723,6 +734,11 @@ int InitPlatform(void) glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0 } + if (CORE.Window.flags & FLAG_WINDOW_HIGHDPI) + { + platform.isHighDPIAware = true; + } + // NOTE: When asking for an OpenGL context version, most drivers provide the highest supported version // with backward compatibility to older OpenGL versions. // For example, if using OpenGL 1.1, driver can provide a 4.3 backwards compatible context. @@ -867,25 +883,14 @@ int InitPlatform(void) glfwMakeContextCurrent(platform.handle); result = true; // TODO: WARNING: glfwGetError(NULL); symbol can not be found in Web + InstallModuleJSAPI(); + // Check context activation if (result == true) //(result != GLFW_NO_WINDOW_CONTEXT) && (result != GLFW_PLATFORM_ERROR)) { CORE.Window.ready = true; - - int fbWidth; - int fbHeight; - - glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight); - - // Screen scaling matrix is required in case desired screen area is different from display area - CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f); - - // no need to scale mouse as glfw is doing it already - - CORE.Window.render.width = fbWidth; - CORE.Window.render.height = fbHeight; - CORE.Window.currentFbo.width = fbWidth; - CORE.Window.currentFbo.height = fbHeight; + AdjustFrameBufferSize((int) CORE.Window.screen.width, (int) CORE.Window.screen.height); + emscripten_set_element_css_size("#canvas", CORE.Window.screen.width, CORE.Window.screen.height); TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); @@ -969,32 +974,56 @@ static void ErrorCallback(int error, const char *description) TRACELOG(LOG_WARNING, "GLFW: Error: %i Description: %s", error, description); } +// AdjustWindowSize +static void AdjustWindowSize(int width, int height, int fbWidth, int fbHeight) +{ + TRACELOG(LOG_INFO, "AdjustWindowSize: %dx%d | %dx%d", width, height, fbWidth, fbHeight); + CORE.Window.screen.width = width; + CORE.Window.screen.height = height; + + AdjustFrameBufferSize(width, height); + + emscripten_set_element_css_size("#canvas", width, height); + + EM_ASM({ + GLFW.active.width = $0; + GLFW.active.height = $1; + }, + width, height + ); +} + +// AdjustFrameBufferSize +static void AdjustFrameBufferSize(int fbWidth, int fbHeight) +{ + TRACELOG(LOG_INFO, "AdjustFrameBufferSize: %dx%d", fbWidth, fbHeight); + + float scale = GetDevicePixelRatio(); + fbWidth = (int) ((float) fbWidth * scale); + fbHeight = (int) ((float) fbHeight * scale); + + // Screen scaling matrix is required in case desired screen area is different from display area + CORE.Window.screenScale = MatrixScale((float)fbWidth/(float)CORE.Window.screen.width, (float)fbHeight/(float)CORE.Window.screen.height, 1.0f); + + SetMouseScale(1.0f / scale, 1.0f / scale); + + CORE.Window.render.width = fbWidth; + CORE.Window.render.height = fbHeight; + CORE.Window.currentFbo.width = fbWidth; + CORE.Window.currentFbo.height = fbHeight; + CORE.Window.resizedLastFrame = true; + + emscripten_set_canvas_element_size("#canvas", fbWidth, fbHeight); + + SetupViewport(fbWidth, fbHeight); +} + // GLFW3 WindowSize Callback, runs when window is resizedLastFrame // NOTE: Window resizing not allowed by default static void WindowSizeCallback(GLFWwindow *window, int width, int height) { - CORE.Window.screen.width = width; - CORE.Window.screen.height = height; - - // Same logic from InitPlatform - - int fbWidth; - int fbHeight; - - glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight); - - // Screen scaling matrix is required in case desired screen area is different from display area - CORE.Window.screenScale = MatrixScale((float)fbWidth/(float)CORE.Window.screen.width, (float)fbHeight/(float)CORE.Window.screen.height, 1.0f); - - CORE.Window.render.width = fbWidth; - CORE.Window.render.height = fbHeight; - CORE.Window.currentFbo.width = fbWidth; - CORE.Window.currentFbo.height = fbHeight; - CORE.Window.resizedLastFrame = true; - - SetupViewport(fbWidth, fbHeight); - - // NOTE: Postprocessing texture is not scaled to new size + TRACELOG(LOG_INFO, "WindowSizeCallback: %dx%d", width, height); + AdjustWindowSize(width, height, width, height); } // GLFW3 WindowIconify Callback, runs when window is minimized/restored @@ -1204,7 +1233,7 @@ static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent * if (height < CORE.Window.screenMin.height) height = CORE.Window.screenMin.height; else if (height > CORE.Window.screenMax.height && CORE.Window.screenMax.height > 0) height = CORE.Window.screenMax.height; - SetWindowSize(width, height); // will trigger callback + SetWindowSize(width, height); return 1; // The event was consumed by the callback handler } @@ -1299,4 +1328,88 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent return 1; // The event was consumed by the callback handler } +// InstallModuleJSAPI +void InstallModuleJSAPI() +{ + EM_ASM( + { + Module.raylib = {}; // used to store width/height before fullscreen + const cb = Module.requestFullscreen; + Module.requestFullscreen = (pointerLock, resize) => { + const canvas = document.getElementById('canvas'); + Module.raylib.screenWidth = canvas.clientWidth; + Module.raylib.screenHeight = canvas.clientHeight; + cb(pointerLock, $0); + }; + Module.onFullscreen = Module.cwrap('FullscreenCallback', null, ['boolean']); // called by emscripten + Module.setHighDPIAware = Module.cwrap('SetHighDPIAware', null, ['boolean']); + }, + (CORE.Window.flags & FLAG_WINDOW_RESIZABLE) != 0 + ); +} + +// FullscreenCallback +void FullscreenCallback(bool isFullscreen) +{ + TRACELOG(LOG_INFO, "FullscreenCallback(%s)", isFullscreen ? "true" : "false"); + if (isFullscreen) + { + if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) + { + if(IsHighDPIAware()) + { + int screenWidth, screenHeight; + emscripten_get_screen_size(&screenWidth, &screenHeight); + AdjustFrameBufferSize(screenWidth, screenWidth); + } + } + else + { + int screenWidth, screenHeight; + emscripten_get_screen_size(&screenWidth, &screenHeight); + TRACELOG(LOG_INFO, "fullscreen resizable %dx%d", screenWidth, screenHeight); + SetWindowSize(screenWidth, screenHeight); + } + } + else + { + SetWindowSize(EM_ASM_INT(return Module.raylib.screenWidth;), EM_ASM_INT(return Module.raylib.screenHeight;)); + } + + CORE.Window.fullscreen = isFullscreen; +} + +// SetHighDPIAware +void SetHighDPIAware(bool flag) +{ + TRACELOG(LOG_INFO, "SetHighDPIAware(%s)", flag ? "true" : "false"); + if (platform.isHighDPIAware != flag) + { + platform.isHighDPIAware = flag; + if(CORE.Window.fullscreen) + { + int screenWidth, screenHeight; + emscripten_get_screen_size(&screenWidth, &screenHeight); + AdjustFrameBufferSize(screenWidth, screenWidth); + } + else + SetWindowSize(GetScreenWidth(), GetScreenHeight()); + } +} + +// IsHighDPIAware +static bool IsHighDPIAware() +{ + return platform.isHighDPIAware; +} + +// GetDevicePixelRatio +static float GetDevicePixelRatio() +{ + if (IsHighDPIAware()) + return (float) EM_ASM_DOUBLE({ console.log("dpr: " + devicePixelRatio); return (typeof devicePixelRatio == 'number' && devicePixelRatio) || 1.0; }); + else + return 1.0f; +} + // EOF diff --git a/src/shell.html b/src/shell.html index 6effbcaa1..21d779246 100644 --- a/src/shell.html +++ b/src/shell.html @@ -178,6 +178,7 @@ jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaB +