Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 20 additions & 19 deletions code/bgfxbackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -233,12 +233,12 @@ static bool Ensure_Prescale_Target(int width, int height)
/// Starts the renderer on an existing window.
/// </summary>
/// <param name="window">The window the frame is presented into.</param>
/// <param name="windowwidth">The width of that window's client area.</param>
/// <param name="windowheight">The height of that window's client area.</param>
/// <param name="drawablewidth">The drawable area's width in physical pixels.</param>
/// <param name="drawableheight">The drawable area's height in physical pixels.</param>
/// <param name="renderer">Which graphics API to ask for, or auto to let bgfx decide.</param>
/// <param name="vsync">Should presents wait for the display's refresh?</param>
/// <returns>bool; Did the renderer start?</returns>
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);
Expand All @@ -249,14 +249,15 @@ 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.resolution.width = (uint32_t)drawablewidth;
init.resolution.height = (uint32_t)drawableheight;
init.resolution.reset = _ResetFlags;
init.callback = &_Callback;

Expand Down Expand Up @@ -396,21 +397,21 @@ bool Backend_Set_Frame_Size(int width, int height)


/// <summary>
/// Tells the renderer the window's client area changed size.
/// Tells the renderer the drawable area changed size.
/// </summary>
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);
}


Expand All @@ -431,7 +432,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;
}

Expand Down Expand Up @@ -483,7 +484,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();
Expand Down
7 changes: 4 additions & 3 deletions code/bgfxbackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#pragma once

#include <windows.h>
#include "nativewindow.hh"


enum BackendRenderer {
Expand All @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion code/mainopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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))) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refresh rate isn't a mode property tho, IMO should keep it out of here.
Refresh rate should live as a Video_Init args instead alongside the other display properties.

DebugString("Video_Set_Mode failed.\n");
Show_Mouse();
return(false);
Expand Down
19 changes: 19 additions & 0 deletions code/nativewindow.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*******************************************************************************
* 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


// 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;
};
Comment on lines +15 to +19

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BGFX takes NativeWindowHandleType::Enum so we might want like,

enum NativeWindowType {
	NATIVE_WINDOW_DEFAULT,
	NATIVE_WINDOW_WAYLAND,
};

struct NativeWindow
{
	NativeWindowType Type;
	void * Display;
	void * Handle;
};

for the future.

7 changes: 6 additions & 1 deletion code/startup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
83 changes: 33 additions & 50 deletions code/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ int VideoModeHeight = 0;
*/
bool WindowedMode = false;

static HWND _Window = NULL;
static bool _Initialized = false;
static VideoScaleInfo _ScaleInfo;

Expand All @@ -60,21 +59,13 @@ static bool _Presenting = false;
/// <summary>
/// Works out the shortest sensible gap between presents from the display's refresh rate.
/// </summary>
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;
}
Expand All @@ -91,33 +82,21 @@ static void Update_Present_Interval(void)
/// </summary>
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) {
Expand All @@ -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);
}
Expand All @@ -154,24 +133,26 @@ static BackendScaleMode Backend_Scale_Mode(void)
/// <summary>
/// Starts the presenter on the game's window.
/// </summary>
/// <param name="window">The main window. Its client area receives the frame.</param>
/// <param name="window">The native window whose drawable area receives the frame.</param>
/// <param name="drawablewidth">The drawable area's width in physical pixels.</param>
/// <param name="drawableheight">The drawable area's height in physical pixels.</param>
/// <param name="refreshrate">The display refresh rate in hertz, or zero when unknown.</param>
/// <returns>bool; Did the presenter start? A false return is fatal to the game.</returns>
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);
}

Expand All @@ -186,7 +167,7 @@ bool Video_Init(HWND window)
}

Update_Scale_Info();
Update_Present_Interval();
Update_Present_Interval(refreshrate);
return(true);
}

Expand All @@ -203,7 +184,6 @@ void Video_Shutdown(void)
Win_Cursor_Shutdown();
Backend_Shutdown();
_Initialized = false;
_Window = NULL;
_FrameIsDirty = false;
}

Expand All @@ -215,8 +195,9 @@ void Video_Shutdown(void)
/// </summary>
/// <param name="width">The new frame width.</param>
/// <param name="height">The new frame height.</param>
/// <param name="refreshrate">The display refresh rate in hertz, or zero when unknown.</param>
/// <returns>bool; Was the mode changed?</returns>
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);
Expand All @@ -230,25 +211,27 @@ 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);
}


/// <summary>
/// Tells the presenter the window's client area changed size.
/// Tells the presenter the drawable area or display timing changed.
/// </summary>
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();
}
Expand All @@ -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.
/// </summary>
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();
}

Expand Down
Loading
Loading