fixes 3372 by implement hi dpi aware in raylib

This commit is contained in:
Yan Pujante 2023-11-12 10:52:45 -08:00
parent 87cd7aee4d
commit e014ce32c1
3 changed files with 154 additions and 39 deletions

View File

@ -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")

View File

@ -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

View File

@ -178,6 +178,7 @@ jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaB
<span id='controls'>
<span><input type="button" value="📜 SOURCE CODE" onclick="location.href='https://github.com/raysan5/raylib';"/></span>
<span><label><input type="checkbox" id="4k" value="4k" onclick="Module.setHighDPIAware(document.getElementById('4k').checked)">4k</label> </span>
<span><input type="button" value="🖵 FULLSCREEN" onclick="Module.requestFullscreen(false, false)"></span>
<span><input type="button" id="btn-audio" value="🔇 MUTE" onclick="toggleAudio()"></span>
</span>