# HG changeset patch # User Michael Pavone # Date 1679895558 25200 # Node ID b7768c58f0daf3dd4304bd46cbcfa901e82f110e # Parent a8080240cb921b9f61d35b85f0ceada4b8dddfaa Initial stab at DPI scaling support diff -r a8080240cb92 -r b7768c58f0da nuklear_ui/blastem_nuklear.c --- a/nuklear_ui/blastem_nuklear.c Thu Mar 23 22:38:51 2023 -0700 +++ b/nuklear_ui/blastem_nuklear.c Sun Mar 26 22:39:18 2023 -0700 @@ -2327,11 +2327,6 @@ } } -static void fb_resize(void) -{ - nk_rawfb_resize_fb(fb_context, NULL, render_width(), render_height(), 0); -} - #ifndef DISABLE_OPENGL static struct nk_image load_image_texture(uint32_t *buf, uint32_t width, uint32_t height) { @@ -2418,10 +2413,26 @@ context->style.combo.button.text_hover = context->style.property.inc_button.text_hover; } +static void fb_resize(void) +{ + nk_rawfb_resize_fb(fb_context, NULL, render_width(), render_height(), 0); + style_init(); + texture_init(); +} + static void context_created(void) { context = nk_sdl_init(render_get_window()); - nk_sdl_device_create(); +#ifndef DISABLE_OPENGL + if (render_has_gl()) { + nk_sdl_device_create(); + } else { +#endif + fb_context = nk_rawfb_init(NULL, context, render_width(), render_height(), 0); + render_set_ui_fb_resize_handler(fb_resize); +#ifndef DISABLE_OPENGL + } +#endif style_init(); texture_init(); } diff -r a8080240cb92 -r b7768c58f0da nuklear_ui/nuklear_sdl_gles2.h --- a/nuklear_ui/nuklear_sdl_gles2.h Thu Mar 23 22:38:51 2023 -0700 +++ b/nuklear_ui/nuklear_sdl_gles2.h Sun Mar 26 22:39:18 2023 -0700 @@ -23,6 +23,7 @@ #include #endif #endif +#include "../render.h" NK_API struct nk_context* nk_sdl_init(SDL_Window *win); @@ -118,7 +119,7 @@ "}\n"; struct nk_sdl_device *dev = &sdl.ogl; - + nk_buffer_init_default(&dev->cmds); dev->prog = glCreateProgram(); dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); @@ -148,7 +149,7 @@ dev->vp = offsetof(struct nk_sdl_vertex, position); dev->vt = offsetof(struct nk_sdl_vertex, uv); dev->vc = offsetof(struct nk_sdl_vertex, col); - + /* Allocate buffers */ glGenBuffers(1, &dev->vbo); glGenBuffers(1, &dev->ebo); @@ -233,7 +234,7 @@ /* Bind buffers */ glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - + { /* buffer setup */ glEnableVertexAttribArray((GLuint)dev->attrib_pos); @@ -445,7 +446,7 @@ } else if (evt->type == SDL_MOUSEBUTTONDOWN || evt->type == SDL_MOUSEBUTTONUP) { /* mouse button */ int down = evt->type == SDL_MOUSEBUTTONDOWN; - const int x = evt->button.x, y = evt->button.y; + const int x = render_ui_to_pixels_x(evt->button.x), y = render_ui_to_pixels_y(evt->button.y); if (evt->button.button == SDL_BUTTON_LEFT) { if (evt->button.clicks > 1) nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, down); @@ -458,9 +459,9 @@ } else if (evt->type == SDL_MOUSEMOTION) { /* mouse motion */ if (ctx->input.mouse.grabbed) { - int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y; - nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel); - } else nk_input_motion(ctx, evt->motion.x, evt->motion.y); + int x = render_ui_to_pixels_x((int)ctx->input.mouse.prev.x), y = render_ui_to_pixels_y((int)ctx->input.mouse.prev.y); + nk_input_motion(ctx, x + render_ui_to_pixels_x(evt->motion.xrel), y + render_ui_to_pixels_y(evt->motion.yrel)); + } else nk_input_motion(ctx, render_ui_to_pixels_x(evt->motion.x), render_ui_to_pixels_y(evt->motion.y)); return 1; } else if (evt->type == SDL_TEXTINPUT) { /* text input */ diff -r a8080240cb92 -r b7768c58f0da render.h --- a/render.h Thu Mar 23 22:38:51 2023 -0700 +++ b/render.h Sun Mar 26 22:39:18 2023 -0700 @@ -146,6 +146,8 @@ void render_set_external_sync(uint8_t ext_sync_on); void render_reset_mappings(void); void render_update_display(void); +int render_ui_to_pixels_x(int ui); +int render_ui_to_pixels_y(int ui); #ifndef IS_LIB uint8_t render_create_thread(render_thread *thread, const char *name, render_thread_fun fun, void *data); #endif diff -r a8080240cb92 -r b7768c58f0da render_sdl.c --- a/render_sdl.c Thu Mar 23 22:38:51 2023 -0700 +++ b/render_sdl.c Sun Mar 26 22:39:18 2023 -0700 @@ -297,9 +297,9 @@ } } +static int tex_width, tex_height; #ifndef DISABLE_OPENGL static GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, un_height, un_texsize, at_pos; -static int tex_width, tex_height; static GLfloat vertex_data_default[] = { -1.0f, -1.0f, @@ -810,6 +810,17 @@ return desired_index; } +static float ui_scale_x = 1.0f, ui_scale_y = 1.0f; +int render_ui_to_pixels_x(int ui) +{ + return ui * ui_scale_x + 0.5f; +} + +int render_ui_to_pixels_y(int ui) +{ + return ui * ui_scale_y + 0.5f; +} + static int32_t handle_event(SDL_Event *event) { if (custom_event_handler) { @@ -868,7 +879,7 @@ break; } case SDL_MOUSEMOTION: - handle_mouse_moved(event->motion.which, event->motion.x, event->motion.y + overscan_top[video_standard], event->motion.xrel, event->motion.yrel); + handle_mouse_moved(event->motion.which, event->motion.x * ui_scale_x + 0.5f, event->motion.y * ui_scale_y + 0.5f + overscan_top[video_standard], event->motion.xrel, event->motion.yrel); break; case SDL_MOUSEBUTTONDOWN: handle_mousedown(event->button.which, event->button.button); @@ -883,10 +894,7 @@ if (!main_window) { break; } - main_width = event->window.data1; - main_height = event->window.data2; need_ui_fb_resize = 1; - update_aspect(); #ifndef DISABLE_OPENGL if (render_gl) { if (on_context_destroyed) { @@ -895,12 +903,26 @@ gl_teardown(); SDL_GL_DeleteContext(main_context); main_context = SDL_GL_CreateContext(main_window); + SDL_GL_GetDrawableSize(main_window, &main_width, &main_height); + update_aspect(); gl_setup(); if (on_context_created) { on_context_created(); } + } else { +#endif + SDL_GetRendererOutputSize(main_renderer, &main_width, &main_height); + update_aspect(); +#ifndef DISABLE_OPENGL } #endif + if (main_width != event->window.data1 || main_height != event->window.data2) { + debug_message("Window resized - UI units %dx%d, pixels %dx%d\n", event->window.data1, event->window.data2, main_width, main_height); + } else { + debug_message("Window resized: %dx%d\n", main_width, main_height); + } + ui_scale_x = (float)main_width / (float)event->window.data1; + ui_scale_y = (float)main_height / (float)event->window.data2; break; case SDL_WINDOWEVENT_CLOSE: if (main_window && SDL_GetWindowID(main_window) == event->window.windowID) { @@ -1002,7 +1024,7 @@ void window_setup(void) { - uint32_t flags = SDL_WINDOW_RESIZABLE; + uint32_t flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI; if (is_fullscreen) { flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } @@ -1089,6 +1111,9 @@ if (!main_window) { fatal_error("Unable to create SDL window: %s\n", SDL_GetError()); } + SDL_GetWindowSize(main_window, &main_width, &main_height); + debug_message("Window created with size: %d x %d\n", main_width, main_height); + int orig_width = main_width, orig_height = main_height; #ifndef DISABLE_OPENGL if (gl_enabled) { @@ -1123,6 +1148,7 @@ #endif } } + SDL_GL_GetDrawableSize(main_window, &main_width, &main_height); } else { warning("OpenGL 2.0 is unavailable, falling back to SDL2 renderer\n"); } @@ -1138,6 +1164,7 @@ if (!main_renderer) { fatal_error("unable to create SDL renderer: %s\n", SDL_GetError()); } + SDL_GetRendererOutputSize(main_renderer, &main_width, &main_height); SDL_RendererInfo rinfo; SDL_GetRendererInfo(main_renderer, &rinfo); debug_message("SDL2 Render Driver: %s\n", rinfo.name); @@ -1148,8 +1175,13 @@ } #endif - SDL_GetWindowSize(main_window, &main_width, &main_height); - debug_message("Window created with size: %d x %d\n", main_width, main_height); + if (main_width != orig_width || main_height != orig_height) { + debug_message("True window resolution %d x %d\n", main_width, main_height); + } + ui_scale_x = (float)main_width / (float)orig_width; + ui_scale_y = (float)main_height / (float)orig_height; + + update_aspect(); render_alloc_surfaces(); def.ptrval = "off"; @@ -1158,6 +1190,11 @@ void render_init(int width, int height, char * title, uint8_t fullscreen) { +#ifdef SDL_HINT_WINDOWS_DPI_SCALING + //In some ways, the other DPI scaling option for SDL2 on Windows is better for BlastEm's needs, + //but setting this makes it more consistent with how high DPI support works on other platforms + SDL_SetHint(SDL_HINT_WINDOWS_DPI_SCALING, "1"); +#endif if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) { fatal_error("Unable to init SDL: %s\n", SDL_GetError()); }