From aa31fc0c9b5933e73bfb0dce4f7769c16232b78a Mon Sep 17 00:00:00 2001 From: Krisztiaan Date: Thu, 27 Aug 2026 21:45:30 +0200 Subject: [PATCH 1/5] Extract native window boundary --- code/bgfxbackend.cpp | 42 ++++++++++++---------- code/bgfxbackend.h | 7 ++-- code/mainopt.cpp | 3 +- code/nativewindow.hh | 27 ++++++++++++++ code/startup.cpp | 7 +++- code/video.cpp | 83 ++++++++++++++++++-------------------------- code/video.h | 15 ++++---- code/winstub.cpp | 47 +++++++++++++++++++++++-- code/winstub.h | 4 +++ 9 files changed, 152 insertions(+), 83 deletions(-) create mode 100644 code/nativewindow.hh diff --git a/code/bgfxbackend.cpp b/code/bgfxbackend.cpp index b771f99b..d9d8a7b5 100644 --- a/code/bgfxbackend.cpp +++ b/code/bgfxbackend.cpp @@ -52,8 +52,8 @@ static int _FrameWidth = 0; static int _FrameHeight = 0; static int _PrescaleWidth = 0; static int _PrescaleHeight = 0; -static int _WindowWidth = 0; -static int _WindowHeight = 0; +static int _DrawableWidth = 0; +static int _DrawableHeight = 0; static unsigned int _ResetFlags = BGFX_RESET_FLIP_AFTER_RENDER; // True while the frame texture holds the game's own 565 layout. When the hardware cannot @@ -233,12 +233,12 @@ static bool Ensure_Prescale_Target(int width, int height) /// Starts the renderer on an existing window. /// /// The window the frame is presented into. -/// The width of that window's client area. -/// The height of that window's client area. +/// The drawable area's width in physical pixels. +/// The drawable area's height in physical pixels. /// Which graphics API to ask for, or auto to let bgfx decide. /// Should presents wait for the display's refresh? /// bool; Did the renderer start? -bool Backend_Init(HWND window, int windowwidth, int windowheight, BackendRenderer renderer, bool vsync) +bool Backend_Init(NativeWindow const & window, int drawablewidth, int drawableheight, BackendRenderer renderer, bool vsync) { if (_Initialized) { return(true); @@ -249,14 +249,18 @@ bool Backend_Init(HWND window, int windowwidth, int windowheight, BackendRendere // renderFrame before init is what selects that. bgfx::renderFrame(); - _WindowWidth = windowwidth; - _WindowHeight = windowheight; + _DrawableWidth = drawablewidth; + _DrawableHeight = drawableheight; _ResetFlags = BGFX_RESET_FLIP_AFTER_RENDER | (vsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); bgfx::Init init; - init.platformData.nwh = window; - init.resolution.width = (uint32_t)windowwidth; - init.resolution.height = (uint32_t)windowheight; + init.platformData.ndt = window.Display; + init.platformData.nwh = window.Handle; + init.platformData.type = window.Type == NativeWindowType::Wayland + ? bgfx::NativeWindowHandleType::Wayland + : bgfx::NativeWindowHandleType::Default; + init.resolution.width = (uint32_t)drawablewidth; + init.resolution.height = (uint32_t)drawableheight; init.resolution.reset = _ResetFlags; init.callback = &_Callback; @@ -396,21 +400,21 @@ bool Backend_Set_Frame_Size(int width, int height) /// -/// Tells the renderer the window's client area changed size. +/// Tells the renderer the drawable area changed size. /// -void Backend_On_Resize(int windowwidth, int windowheight) +void Backend_On_Resize(int drawablewidth, int drawableheight) { - if (!_Initialized || windowwidth <= 0 || windowheight <= 0) { + if (!_Initialized || drawablewidth <= 0 || drawableheight <= 0) { return; } - if (_WindowWidth == windowwidth && _WindowHeight == windowheight) { + if (_DrawableWidth == drawablewidth && _DrawableHeight == drawableheight) { return; } - _WindowWidth = windowwidth; - _WindowHeight = windowheight; - bgfx::reset((uint32_t)windowwidth, (uint32_t)windowheight, _ResetFlags); + _DrawableWidth = drawablewidth; + _DrawableHeight = drawableheight; + bgfx::reset((uint32_t)drawablewidth, (uint32_t)drawableheight, _ResetFlags); } @@ -431,7 +435,7 @@ void Backend_Present(void const * pixels, int pitch, int destx, int desty, int d } // A minimized window has no client area to present into. - if (_WindowWidth <= 0 || _WindowHeight <= 0) { + if (_DrawableWidth <= 0 || _DrawableHeight <= 0) { return; } @@ -483,7 +487,7 @@ void Backend_Present(void const * pixels, int pitch, int destx, int desty, int d // share the window's shape. bgfx::setViewFrameBuffer(VIEW_PRESENT, BGFX_INVALID_HANDLE); bgfx::setViewClear(VIEW_PRESENT, BGFX_CLEAR_COLOR, 0x000000FF); - Set_View_Transform(VIEW_PRESENT, _WindowWidth, _WindowHeight); + Set_View_Transform(VIEW_PRESENT, _DrawableWidth, _DrawableHeight); Submit_Quad(VIEW_PRESENT, source, (float)destx, (float)desty, (float)destwidth, (float)destheight, samplerflags); bgfx::frame(); diff --git a/code/bgfxbackend.h b/code/bgfxbackend.h index a6cadfcf..8f3cb418 100644 --- a/code/bgfxbackend.h +++ b/code/bgfxbackend.h @@ -13,7 +13,7 @@ #pragma once -#include +#include "nativewindow.hh" enum BackendRenderer { @@ -32,11 +32,12 @@ enum BackendScaleMode { }; -bool Backend_Init(HWND window, int windowwidth, int windowheight, BackendRenderer renderer, bool vsync); +// Drawable sizes are physical pixel dimensions supplied by the application shell. +bool Backend_Init(NativeWindow const & window, int drawablewidth, int drawableheight, BackendRenderer renderer, bool vsync); void Backend_Shutdown(void); bool Backend_Set_Frame_Size(int width, int height); -void Backend_On_Resize(int windowwidth, int windowheight); +void Backend_On_Resize(int drawablewidth, int drawableheight); // Uploads the frame and presents it. The pixels are 16 bit 565 and stay owned by the // caller; they are consumed before this returns. diff --git a/code/mainopt.cpp b/code/mainopt.cpp index cb663708..cc332df4 100644 --- a/code/mainopt.cpp +++ b/code/mainopt.cpp @@ -26,6 +26,7 @@ #include "language\language.h" #include "misc.h" #include "video.h" +#include "winstub.h" #include "mixfile.h" #include "msgbox.h" #include "newmenu.h" @@ -195,7 +196,7 @@ bool Change_Display_Mode(int width, int height) Hide_Mouse(); - if (!Video_Set_Mode(width, height)) { + if (!Video_Set_Mode(width, height, Win_Window_Refresh_Rate(MainWindow))) { DebugString("Video_Set_Mode failed.\n"); Show_Mouse(); return(false); diff --git a/code/nativewindow.hh b/code/nativewindow.hh new file mode 100644 index 00000000..7a4e326f --- /dev/null +++ b/code/nativewindow.hh @@ -0,0 +1,27 @@ +/******************************************************************************* + * O P E N T S + ******************************************************************************* + * SPDX-License-Identifier: GPL-3.0-or-later + * Copyright 2026 OpenTS contributors + * + * See LICENSE.md for applicable additional terms and warranty disclaimers. + ******************************************************************************/ + +#pragma once + + +enum class NativeWindowType +{ + Default, + Wayland +}; + + +// The native handles bgfx needs to present into a window supplied by the application shell. +// Display is unused on platforms where the window identifies its display by itself. +struct NativeWindow +{ + void * Display; + void * Handle; + NativeWindowType Type; +}; diff --git a/code/startup.cpp b/code/startup.cpp index b4671501..2b2bc1ba 100644 --- a/code/startup.cpp +++ b/code/startup.cpp @@ -574,7 +574,12 @@ int CALLBACK WinMain ( HINSTANCE instance , HINSTANCE , char * command_line , in Audio.Init(MainWindow, 16, 0, 22050); - if (!Video_Init(MainWindow)) { + int drawablewidth = 0; + int drawableheight = 0; + int refreshrate = Win_Window_Refresh_Rate(MainWindow); + NativeWindow nativewindow = Win_Native_Window(MainWindow); + if (!Win_Window_Drawable_Size(MainWindow, drawablewidth, drawableheight) + || !Video_Init(nativewindow, drawablewidth, drawableheight, refreshrate)) { MessageBox(MainWindow, Fetch_String(TXT_VIDEO_ERROR), Fetch_String(TXT_SHORT_TITLE), MB_ICONWARNING); exit(EXIT_FAILURE); } diff --git a/code/video.cpp b/code/video.cpp index e25f6fa8..0683055e 100644 --- a/code/video.cpp +++ b/code/video.cpp @@ -41,7 +41,6 @@ int VideoModeHeight = 0; */ bool WindowedMode = false; -static HWND _Window = NULL; static bool _Initialized = false; static VideoScaleInfo _ScaleInfo; @@ -60,21 +59,13 @@ static bool _Presenting = false; /// /// Works out the shortest sensible gap between presents from the display's refresh rate. /// -static void Update_Present_Interval(void) +static void Update_Present_Interval(int refreshrate) { - int refresh = 0; - HDC dc = GetDC(_Window); - - if (dc != NULL) { - refresh = GetDeviceCaps(dc, VREFRESH); - ReleaseDC(_Window, dc); - } - - if (refresh <= 1) { - refresh = 60; + if (refreshrate <= 1) { + refreshrate = 60; } - _PresentInterval = (unsigned int)(1000 / refresh); + _PresentInterval = (unsigned int)(1000 / refreshrate); if (_PresentInterval < 3) { _PresentInterval = 3; } @@ -91,33 +82,21 @@ static void Update_Present_Interval(void) /// static void Update_Scale_Info(void) { - RECT client; - _ScaleInfo.GameWidth = VideoModeWidth; _ScaleInfo.GameHeight = VideoModeHeight; - if (_Window == NULL || !GetClientRect(_Window, &client)) { - client.left = 0; - client.top = 0; - client.right = VideoModeWidth; - client.bottom = VideoModeHeight; - } - - _ScaleInfo.WindowWidth = client.right - client.left; - _ScaleInfo.WindowHeight = client.bottom - client.top; - - if (_ScaleInfo.GameWidth <= 0 || _ScaleInfo.GameHeight <= 0 || _ScaleInfo.WindowWidth <= 0 || _ScaleInfo.WindowHeight <= 0) { + if (_ScaleInfo.GameWidth <= 0 || _ScaleInfo.GameHeight <= 0 || _ScaleInfo.DrawableWidth <= 0 || _ScaleInfo.DrawableHeight <= 0) { _ScaleInfo.DestX = 0; _ScaleInfo.DestY = 0; - _ScaleInfo.DestWidth = _ScaleInfo.WindowWidth; - _ScaleInfo.DestHeight = _ScaleInfo.WindowHeight; + _ScaleInfo.DestWidth = _ScaleInfo.DrawableWidth; + _ScaleInfo.DestHeight = _ScaleInfo.DrawableHeight; _ScaleInfo.ScaleX = 1.0f; _ScaleInfo.ScaleY = 1.0f; return; } - double scalex = (double)_ScaleInfo.WindowWidth / (double)_ScaleInfo.GameWidth; - double scaley = (double)_ScaleInfo.WindowHeight / (double)_ScaleInfo.GameHeight; + double scalex = (double)_ScaleInfo.DrawableWidth / (double)_ScaleInfo.GameWidth; + double scaley = (double)_ScaleInfo.DrawableHeight / (double)_ScaleInfo.GameHeight; double scale = (scalex < scaley) ? scalex : scaley; if (Options.IntegerScaling && scale >= 1.0) { @@ -126,8 +105,8 @@ static void Update_Scale_Info(void) _ScaleInfo.DestWidth = (int)((double)_ScaleInfo.GameWidth * scale); _ScaleInfo.DestHeight = (int)((double)_ScaleInfo.GameHeight * scale); - _ScaleInfo.DestX = (_ScaleInfo.WindowWidth - _ScaleInfo.DestWidth) / 2; - _ScaleInfo.DestY = (_ScaleInfo.WindowHeight - _ScaleInfo.DestHeight) / 2; + _ScaleInfo.DestX = (_ScaleInfo.DrawableWidth - _ScaleInfo.DestWidth) / 2; + _ScaleInfo.DestY = (_ScaleInfo.DrawableHeight - _ScaleInfo.DestHeight) / 2; _ScaleInfo.ScaleX = (float)((double)_ScaleInfo.DestWidth / (double)_ScaleInfo.GameWidth); _ScaleInfo.ScaleY = (float)((double)_ScaleInfo.DestHeight / (double)_ScaleInfo.GameHeight); } @@ -154,24 +133,26 @@ static BackendScaleMode Backend_Scale_Mode(void) /// /// Starts the presenter on the game's window. /// -/// The main window. Its client area receives the frame. +/// The native window whose drawable area receives the frame. +/// The drawable area's width in physical pixels. +/// The drawable area's height in physical pixels. +/// The display refresh rate in hertz, or zero when unknown. /// bool; Did the presenter start? A false return is fatal to the game. -bool Video_Init(HWND window) +bool Video_Init(NativeWindow const & window, int drawablewidth, int drawableheight, int refreshrate) { - RECT client; - if (_Initialized) { return(true); } - if (window == NULL || !GetClientRect(window, &client)) { + if (window.Handle == nullptr || drawablewidth <= 0 || drawableheight <= 0) { return(false); } - _Window = window; + _ScaleInfo.DrawableWidth = drawablewidth; + _ScaleInfo.DrawableHeight = drawableheight; BackendRenderer renderer = (BackendRenderer)Options.Renderer; - if (!Backend_Init(window, client.right - client.left, client.bottom - client.top, renderer, Options.VSync)) { + if (!Backend_Init(window, drawablewidth, drawableheight, renderer, Options.VSync)) { return(false); } @@ -186,7 +167,7 @@ bool Video_Init(HWND window) } Update_Scale_Info(); - Update_Present_Interval(); + Update_Present_Interval(refreshrate); return(true); } @@ -203,7 +184,6 @@ void Video_Shutdown(void) Win_Cursor_Shutdown(); Backend_Shutdown(); _Initialized = false; - _Window = NULL; _FrameIsDirty = false; } @@ -215,8 +195,9 @@ void Video_Shutdown(void) /// /// The new frame width. /// The new frame height. +/// The display refresh rate in hertz, or zero when unknown. /// bool; Was the mode changed? -bool Video_Set_Mode(int width, int height) +bool Video_Set_Mode(int width, int height, int refreshrate) { if (!_Initialized || width <= 0 || height <= 0) { return(false); @@ -230,7 +211,7 @@ bool Video_Set_Mode(int width, int height) VideoModeHeight = height; Update_Scale_Info(); - Update_Present_Interval(); + Update_Present_Interval(refreshrate); Win_Cursor_Refresh(); _FrameIsDirty = true; return(true); @@ -238,17 +219,19 @@ bool Video_Set_Mode(int width, int height) /// -/// Tells the presenter the window's client area changed size. +/// Tells the presenter the drawable area or display timing changed. /// -void Video_On_Resize(int width, int height) +void Video_On_Resize(int drawablewidth, int drawableheight, int refreshrate) { - if (!_Initialized || width <= 0 || height <= 0) { + if (!_Initialized || drawablewidth <= 0 || drawableheight <= 0) { return; } - Backend_On_Resize(width, height); + _ScaleInfo.DrawableWidth = drawablewidth; + _ScaleInfo.DrawableHeight = drawableheight; + Backend_On_Resize(drawablewidth, drawableheight); Update_Scale_Info(); - Update_Present_Interval(); + Update_Present_Interval(refreshrate); Win_Cursor_Refresh(); Video_Mark_Dirty(); } @@ -258,13 +241,13 @@ void Video_On_Resize(int width, int height) /// Tells the presenter the desktop's display settings changed. /// The window may now be on a monitor that refreshes at a different rate. /// -void Video_On_Display_Change(void) +void Video_On_Display_Change(int refreshrate) { if (!_Initialized) { return; } - Update_Present_Interval(); + Update_Present_Interval(refreshrate); Video_Mark_Dirty(); } diff --git a/code/video.h b/code/video.h index 332b433e..fe81a493 100644 --- a/code/video.h +++ b/code/video.h @@ -9,7 +9,7 @@ #pragma once -#include "win.h" +#include "nativewindow.hh" // How the presented frame is filtered when the window is larger than it. @@ -22,12 +22,13 @@ enum VideoScaleMode { // Where the game's frame lands inside the window. The frame keeps its aspect ratio, so // the destination is centered and the window may show bars on two of its sides. +// Drawable dimensions and the destination rectangle are measured in physical pixels. struct VideoScaleInfo { int GameWidth; int GameHeight; - int WindowWidth; - int WindowHeight; + int DrawableWidth; + int DrawableHeight; int DestX; int DestY; int DestWidth; @@ -37,12 +38,12 @@ struct VideoScaleInfo }; -bool Video_Init(HWND window); +bool Video_Init(NativeWindow const & window, int drawablewidth, int drawableheight, int refreshrate); void Video_Shutdown(void); -bool Video_Set_Mode(int width, int height); -void Video_On_Resize(int width, int height); -void Video_On_Display_Change(void); +bool Video_Set_Mode(int width, int height, int refreshrate); +void Video_On_Resize(int drawablewidth, int drawableheight, int refreshrate); +void Video_On_Display_Change(int refreshrate); void Video_Mark_Dirty(void); void Video_Present(void); diff --git a/code/winstub.cpp b/code/winstub.cpp index ab9f5d72..8fba10c1 100644 --- a/code/winstub.cpp +++ b/code/winstub.cpp @@ -64,6 +64,7 @@ #include "movie.h" #include "movies.h" #include "msgroute.h" +#include "nativewindow.hh" #include "pcx.h" #include "resource.h" #include "theme.h" @@ -273,7 +274,7 @@ LRESULT CALLBACK /*_export*/ Windows_Procedure(HWND hwnd, UINT message, UINT wPa case WM_SIZE: if (wParam != SIZE_MINIMIZED) { - Video_On_Resize(LOWORD(lParam), HIWORD(lParam)); + Video_On_Resize(LOWORD(lParam), HIWORD(lParam), Win_Window_Refresh_Rate(hwnd)); if (MouseCursor != NULL) { ((WWMouseClass *)MouseCursor)->Calc_Confining_Rect(); } @@ -281,7 +282,7 @@ LRESULT CALLBACK /*_export*/ Windows_Procedure(HWND hwnd, UINT message, UINT wPa break; case WM_DISPLAYCHANGE: - Video_On_Display_Change(); + Video_On_Display_Change(Win_Window_Refresh_Rate(hwnd)); break; case WM_CLOSE: @@ -393,6 +394,48 @@ LRESULT CALLBACK /*_export*/ Windows_Procedure(HWND hwnd, UINT message, UINT wPa } +/// +/// Describes a Win32 window for the renderer without exposing Win32 types to it. +/// +NativeWindow Win_Native_Window(HWND window) +{ + return({ nullptr, window, NativeWindowType::Default }); +} + + +/// +/// Fetches the drawable dimensions of a per-monitor DPI-aware Win32 window. +/// +bool Win_Window_Drawable_Size(HWND window, int & width, int & height) +{ + RECT client; + if (window == NULL || !GetClientRect(window, &client)) { + return(false); + } + + width = client.right - client.left; + height = client.bottom - client.top; + return(width > 0 && height > 0); +} + + +/// +/// Fetches the refresh rate of the display carrying a Win32 window. +/// +int Win_Window_Refresh_Rate(HWND window) +{ + int refreshrate = 0; + HDC dc = GetDC(window); + + if (dc != NULL) { + refreshrate = GetDeviceCaps(dc, VREFRESH); + ReleaseDC(window, dc); + } + + return(refreshrate); +} + + /// /// Fetches the build number of this executable. /// This routine is used by the network code to check that every machine joining a diff --git a/code/winstub.h b/code/winstub.h index 6cbd3b86..ea3ef451 100644 --- a/code/winstub.h +++ b/code/winstub.h @@ -17,8 +17,12 @@ class Surface; class PaletteClass; +struct NativeWindow; void Create_Main_Window ( HINSTANCE instance , int command_show , int width , int height); +NativeWindow Win_Native_Window(HWND window); +bool Win_Window_Drawable_Size(HWND window, int & width, int & height); +int Win_Window_Refresh_Rate(HWND window); void Load_Title_Screen(char const * name, Surface * surface, PaletteClass * palette); From a7ed70f63cbcba970aa4482e2ccff02629845f3d Mon Sep 17 00:00:00 2001 From: Krisztiaan Date: Thu, 27 Aug 2026 21:57:36 +0200 Subject: [PATCH 2/5] Use explicit native window construction --- code/bgfxbackend.cpp | 3 --- code/nativewindow.hh | 8 -------- code/winstub.cpp | 12 ++---------- 3 files changed, 2 insertions(+), 21 deletions(-) diff --git a/code/bgfxbackend.cpp b/code/bgfxbackend.cpp index d9d8a7b5..8d825433 100644 --- a/code/bgfxbackend.cpp +++ b/code/bgfxbackend.cpp @@ -256,9 +256,6 @@ bool Backend_Init(NativeWindow const & window, int drawablewidth, int drawablehe bgfx::Init init; init.platformData.ndt = window.Display; init.platformData.nwh = window.Handle; - init.platformData.type = window.Type == NativeWindowType::Wayland - ? bgfx::NativeWindowHandleType::Wayland - : bgfx::NativeWindowHandleType::Default; init.resolution.width = (uint32_t)drawablewidth; init.resolution.height = (uint32_t)drawableheight; init.resolution.reset = _ResetFlags; diff --git a/code/nativewindow.hh b/code/nativewindow.hh index 7a4e326f..468875de 100644 --- a/code/nativewindow.hh +++ b/code/nativewindow.hh @@ -10,18 +10,10 @@ #pragma once -enum class NativeWindowType -{ - Default, - Wayland -}; - - // The native handles bgfx needs to present into a window supplied by the application shell. // Display is unused on platforms where the window identifies its display by itself. struct NativeWindow { void * Display; void * Handle; - NativeWindowType Type; }; diff --git a/code/winstub.cpp b/code/winstub.cpp index 8fba10c1..fb70b5d3 100644 --- a/code/winstub.cpp +++ b/code/winstub.cpp @@ -394,18 +394,13 @@ LRESULT CALLBACK /*_export*/ Windows_Procedure(HWND hwnd, UINT message, UINT wPa } -/// -/// Describes a Win32 window for the renderer without exposing Win32 types to it. -/// NativeWindow Win_Native_Window(HWND window) { - return({ nullptr, window, NativeWindowType::Default }); + return(NativeWindow{ nullptr, window }); } -/// -/// Fetches the drawable dimensions of a per-monitor DPI-aware Win32 window. -/// +// Client dimensions are physical pixels because the process is per-monitor DPI aware. bool Win_Window_Drawable_Size(HWND window, int & width, int & height) { RECT client; @@ -419,9 +414,6 @@ bool Win_Window_Drawable_Size(HWND window, int & width, int & height) } -/// -/// Fetches the refresh rate of the display carrying a Win32 window. -/// int Win_Window_Refresh_Rate(HWND window) { int refreshrate = 0; From b1aebac91ed0eea77eefc83ce223309aa8a15068 Mon Sep 17 00:00:00 2001 From: Krisztiaan Date: Sat, 29 Aug 2026 17:10:56 +0200 Subject: [PATCH 3/5] Separate display timing and identify native windows --- code/bgfxbackend.cpp | 3 +++ code/mainopt.cpp | 3 +-- code/nativewindow.hh | 8 ++++++++ code/video.cpp | 9 +++------ code/video.h | 4 ++-- code/winstub.cpp | 5 +++-- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/code/bgfxbackend.cpp b/code/bgfxbackend.cpp index 8d825433..2fc384ca 100644 --- a/code/bgfxbackend.cpp +++ b/code/bgfxbackend.cpp @@ -256,6 +256,9 @@ bool Backend_Init(NativeWindow const & window, int drawablewidth, int drawablehe bgfx::Init init; init.platformData.ndt = window.Display; init.platformData.nwh = window.Handle; + init.platformData.type = window.Type == NATIVE_WINDOW_WAYLAND + ? bgfx::NativeWindowHandleType::Wayland + : bgfx::NativeWindowHandleType::Default; init.resolution.width = (uint32_t)drawablewidth; init.resolution.height = (uint32_t)drawableheight; init.resolution.reset = _ResetFlags; diff --git a/code/mainopt.cpp b/code/mainopt.cpp index cc332df4..cb663708 100644 --- a/code/mainopt.cpp +++ b/code/mainopt.cpp @@ -26,7 +26,6 @@ #include "language\language.h" #include "misc.h" #include "video.h" -#include "winstub.h" #include "mixfile.h" #include "msgbox.h" #include "newmenu.h" @@ -196,7 +195,7 @@ bool Change_Display_Mode(int width, int height) Hide_Mouse(); - if (!Video_Set_Mode(width, height, Win_Window_Refresh_Rate(MainWindow))) { + if (!Video_Set_Mode(width, height)) { DebugString("Video_Set_Mode failed.\n"); Show_Mouse(); return(false); diff --git a/code/nativewindow.hh b/code/nativewindow.hh index 468875de..8a98d0c9 100644 --- a/code/nativewindow.hh +++ b/code/nativewindow.hh @@ -10,10 +10,18 @@ #pragma once +enum NativeWindowType +{ + NATIVE_WINDOW_DEFAULT, + NATIVE_WINDOW_WAYLAND, +}; + + // The native handles bgfx needs to present into a window supplied by the application shell. // Display is unused on platforms where the window identifies its display by itself. struct NativeWindow { + NativeWindowType Type; void * Display; void * Handle; }; diff --git a/code/video.cpp b/code/video.cpp index 0683055e..cdc999f3 100644 --- a/code/video.cpp +++ b/code/video.cpp @@ -195,9 +195,8 @@ void Video_Shutdown(void) /// /// The new frame width. /// The new frame height. -/// The display refresh rate in hertz, or zero when unknown. /// bool; Was the mode changed? -bool Video_Set_Mode(int width, int height, int refreshrate) +bool Video_Set_Mode(int width, int height) { if (!_Initialized || width <= 0 || height <= 0) { return(false); @@ -211,7 +210,6 @@ bool Video_Set_Mode(int width, int height, int refreshrate) VideoModeHeight = height; Update_Scale_Info(); - Update_Present_Interval(refreshrate); Win_Cursor_Refresh(); _FrameIsDirty = true; return(true); @@ -219,9 +217,9 @@ bool Video_Set_Mode(int width, int height, int refreshrate) /// -/// Tells the presenter the drawable area or display timing changed. +/// Tells the presenter the drawable area changed size. /// -void Video_On_Resize(int drawablewidth, int drawableheight, int refreshrate) +void Video_On_Resize(int drawablewidth, int drawableheight) { if (!_Initialized || drawablewidth <= 0 || drawableheight <= 0) { return; @@ -231,7 +229,6 @@ void Video_On_Resize(int drawablewidth, int drawableheight, int refreshrate) _ScaleInfo.DrawableHeight = drawableheight; Backend_On_Resize(drawablewidth, drawableheight); Update_Scale_Info(); - Update_Present_Interval(refreshrate); Win_Cursor_Refresh(); Video_Mark_Dirty(); } diff --git a/code/video.h b/code/video.h index fe81a493..08f80390 100644 --- a/code/video.h +++ b/code/video.h @@ -41,8 +41,8 @@ struct VideoScaleInfo bool Video_Init(NativeWindow const & window, int drawablewidth, int drawableheight, int refreshrate); void Video_Shutdown(void); -bool Video_Set_Mode(int width, int height, int refreshrate); -void Video_On_Resize(int drawablewidth, int drawableheight, int refreshrate); +bool Video_Set_Mode(int width, int height); +void Video_On_Resize(int drawablewidth, int drawableheight); void Video_On_Display_Change(int refreshrate); void Video_Mark_Dirty(void); diff --git a/code/winstub.cpp b/code/winstub.cpp index fb70b5d3..c9c63111 100644 --- a/code/winstub.cpp +++ b/code/winstub.cpp @@ -274,7 +274,8 @@ LRESULT CALLBACK /*_export*/ Windows_Procedure(HWND hwnd, UINT message, UINT wPa case WM_SIZE: if (wParam != SIZE_MINIMIZED) { - Video_On_Resize(LOWORD(lParam), HIWORD(lParam), Win_Window_Refresh_Rate(hwnd)); + Video_On_Resize(LOWORD(lParam), HIWORD(lParam)); + Video_On_Display_Change(Win_Window_Refresh_Rate(hwnd)); if (MouseCursor != NULL) { ((WWMouseClass *)MouseCursor)->Calc_Confining_Rect(); } @@ -396,7 +397,7 @@ LRESULT CALLBACK /*_export*/ Windows_Procedure(HWND hwnd, UINT message, UINT wPa NativeWindow Win_Native_Window(HWND window) { - return(NativeWindow{ nullptr, window }); + return(NativeWindow{ NATIVE_WINDOW_DEFAULT, nullptr, window }); } From 6cdb95e9bb6b86264fec0b380d275d4372b13bd8 Mon Sep 17 00:00:00 2001 From: Krisztiaan Date: Sat, 29 Aug 2026 21:44:37 +0200 Subject: [PATCH 4/5] Document the native window boundary --- manual/changes/native-window-boundary.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 manual/changes/native-window-boundary.md diff --git a/manual/changes/native-window-boundary.md b/manual/changes/native-window-boundary.md new file mode 100644 index 00000000..dcfa18f1 --- /dev/null +++ b/manual/changes/native-window-boundary.md @@ -0,0 +1,9 @@ +--- +title: Separate native window handling from video presentation +category: internal +release: 0.1.0 +targets: [] +credit: [Krisztiaan] +--- + +The application shell now supplies the native window handle, physical drawable size, and display refresh rate to the video presenter. The presenter no longer owns Win32 window queries, and the bgfx backend alone translates the native handle into bgfx platform data. This is an internal boundary change; the supported target and video configuration are unchanged. From 688306d1b4bc22707f56b94551c47d2d92007b7b Mon Sep 17 00:00:00 2001 From: Kirill Andriiashin Date: Sun, 30 Aug 2026 13:59:39 +0300 Subject: [PATCH 5/5] Apply suggestion from @ZivDero --- manual/changes/native-window-boundary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/changes/native-window-boundary.md b/manual/changes/native-window-boundary.md index dcfa18f1..1b7b4357 100644 --- a/manual/changes/native-window-boundary.md +++ b/manual/changes/native-window-boundary.md @@ -1,7 +1,7 @@ --- title: Separate native window handling from video presentation category: internal -release: 0.1.0 +release: 0.2.0 targets: [] credit: [Krisztiaan] ---