Skip to content
Snippets Groups Projects
Commit a9042e65 authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

Start aligning SDL and GDI features/behaviour

Move snap logic into bitmap
Move new mode window size logic into bitmap
parent 77b0c723
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
Pipeline #4183 passed
/* $Id: bitmap_con.c,v 1.148 2020/06/27 00:04:44 deuce Exp $ */
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h> /* NULL */
#include <stdlib.h>
#include <string.h>
......@@ -1612,6 +1614,64 @@ static int init_screens(int *width, int *height)
/* Called from drivers */
/***********************/
// Must be called with vstatlock
static void
get_scaled_win_size(int scale, bool wc, int *w, int *h, int maxwidth, int maxheight)
{
*w = vstat.scrnwidth * scale;
*h = vstat.scrnheight * scale;
if (wc)
*h = INT_MAX;
else
*w = INT_MAX;
if (*w > maxwidth && maxwidth > 0)
*w = maxwidth;
if (*h > maxheight && maxheight > 0)
*h = maxheight;
aspect_fix_wc(w, h, wc, vstat.aspect_width, vstat.aspect_height);
}
// Must be called with vstatlock
void
bitmap_snap(bool grow, int maxwidth, int maxheight)
{
int mult;
int wc;
int cw;
int cs;
int w, h;
w = vstat.winwidth;
h = vstat.winheight;
if (vstat.aspect_width == 0 || vstat.aspect_height == 0)
wc = true;
else
wc = lround((double)(vstat.scrnheight * vstat.aspect_width) / vstat.aspect_height) <= vstat.scrnwidth;
if (wc) {
mult = vstat.winwidth / vstat.scrnwidth;
cw = vstat.winwidth;
cs = vstat.scrnwidth;
}
else {
mult = vstat.winheight / vstat.scrnheight;
cw = vstat.winheight;
cs = vstat.winwidth;
}
if (grow) {
mult++;
}
else {
if (cw % cs == 0)
mult--;
}
if (mult < 1)
mult = 1;
do {
get_scaled_win_size(mult, wc, &vstat.winwidth, &vstat.winheight, maxwidth, maxheight);
mult--;
} while ((vstat.winwidth > maxwidth || vstat.winheight > maxheight) && mult > 1);
}
/*
* This function is intended to be called from the driver.
* as a result, it cannot block waiting for driver status
......@@ -1624,9 +1684,16 @@ static int init_screens(int *width, int *height)
* out after this and only grab that lock again briefly to update
* vstat.scaling.
*/
int bitmap_drv_init_mode(int mode, int *width, int *height)
int bitmap_drv_init_mode(int mode, int *width, int *height, int maxwidth, int maxheight)
{
int i;
int64_t os;
int64_t ls;
int64_t ns;
int64_t bs;
int w, h;
int mult;
bool wc;
if(!bitmap_initialized)
return(-1);
......@@ -1635,6 +1702,9 @@ int bitmap_drv_init_mode(int mode, int *width, int *height)
return(-1);
}
// Save the old diagonal (no point is sqrting here)
os = ((int64_t)vstat.winwidth * vstat.winwidth) + ((int64_t)vstat.winheight * vstat.winheight);
/* Initialize video memory with black background, white foreground */
for (i = 0; i < vstat.cols*vstat.rows; ++i) {
if (i > 0)
......@@ -1674,6 +1744,41 @@ int bitmap_drv_init_mode(int mode, int *width, int *height)
cio_textinfo.winright=cio_textinfo.screenwidth;
cio_textinfo.winbottom=cio_textinfo.screenheight;
// Now calculate the closest diagonal new size that's smaller than max...
if (vstat.aspect_width == 0 || vstat.aspect_height == 0)
wc = true;
else
wc = lround((double)(vstat.scrnheight * vstat.aspect_width) / vstat.aspect_height) <= vstat.scrnwidth;
mult = 1;
get_scaled_win_size(mult, wc, &w, &h, maxwidth, maxheight);
bs = ((int64_t)w * w) + ((int64_t)h * h);
ls = bs;
ns = bs;
while (ns < os) {
mult++;
get_scaled_win_size(mult, wc, &w, &h, maxwidth, maxheight);
if ((maxwidth > 0) && (w > maxwidth)) {
mult--;
ns = ls;
break;
}
if ((maxheight > 0) && (h > maxheight)) {
mult--;
ns = ls;
break;
}
bs = ((int64_t)w * w) + ((int64_t)h * h);
ls = ns;
ns = bs;
}
if ((os - ls) <= (ns - os)) {
if (mult > 1)
mult--;
}
get_scaled_win_size(mult, wc, &w, &h, maxwidth, maxheight);
vstat.winwidth = w;
vstat.winheight = h;
return(0);
}
......
......@@ -50,12 +50,13 @@ int bitmap_setpalette(uint32_t index, uint16_t r, uint16_t g, uint16_t b);
#ifdef BITMAP_CIOLIB_DRIVER
/* Called from drivers */
int bitmap_drv_init_mode(int mode, int *width, int *height);
int bitmap_drv_init_mode(int mode, int *width, int *height, int maxwidth, int maxheight);
int bitmap_drv_init(void (*drawrect_cb) (struct rectlist *data)
,void (*flush) (void));
void bitmap_drv_request_pixels(void);
void bitmap_drv_request_some_pixels(int x, int y, int width, int height);
void bitmap_drv_free_rect(struct rectlist *rect);
void bitmap_snap(bool grow, int maxwidth, int maxheight);
#endif
#endif
......@@ -26,6 +26,32 @@ static struct graphics_buffer *free_list;
x = 255; \
} while(0)
/*
* Corrects width/height to have the specified aspect ratio
* any fit inside the specified rectangle
*/
void
aspect_fix_wc(int *x, int *y, bool wc, int aspect_width, int aspect_height)
{
int bestx, besty;
if (aspect_width == 0 || aspect_height == 0)
return;
if (r2yptr != NULL && y2rptr != NULL) {
bestx = lround((double)*y * aspect_width / aspect_height);
besty = lround((double)*x * aspect_height / aspect_width);
}
else {
bestx = lround((double)*y * *x / *y);
besty = lround((double)*x * *y / *x);
}
if (wc)
*y = besty;
else
*x = bestx;
}
/*
* Corrects width/height to have the specified aspect ratio
* any fit inside the specified rectangle
......
#include <stdbool.h>
#include "bitmap_con.h"
struct graphics_buffer {
......@@ -19,6 +21,7 @@ struct graphics_buffer * do_scale(struct rectlist* rect, int xscale, int yscale,
void aspect_correct(int *x, int *y, int aspect_width, int aspect_height);
void aspect_reverse(int *x, int *y, int scrnwidth, int scrnheight, int aspect_width, int aspect_height);
void aspect_fix(int *x, int *y, int aspect_width, int aspect_height);
void aspect_fix_wc(int *x, int *y, bool wc, int aspect_width, int aspect_height);
void aspect_fix_low(int *x, int *y, int aspect_width, int aspect_height);
void calc_scaling_factors(int *x, int *y, int winwidth, int winheight, int aspect_width, int aspect_height, int scrnwidth, int scrnheight);
void aspect_fix_inside(int *x, int *y, int aspect_width, int aspect_height);
......@@ -359,6 +359,8 @@ static int sdl_init_mode(int mode)
{
int oldcols;
int scaling = 1;
int w, h;
SDL_Rect r;
if (mode != CIOLIB_MODE_CUSTOM) {
pthread_mutex_lock(&vstatlock);
......@@ -373,37 +375,15 @@ static int sdl_init_mode(int mode)
pthread_mutex_lock(&vstatlock);
oldcols = vstat.cols;
bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height);
if (vstat.scrnwidth > 0) {
for (scaling = 1; (scaling + 1) * vstat.scrnwidth < vstat.winwidth; scaling++)
;
}
vstat.winwidth = vstat.scrnwidth * scaling;
vstat.winheight = vstat.scrnheight * scaling;
aspect_fix(&vstat.winwidth, &vstat.winheight, vstat.aspect_width, vstat.aspect_height);
if (oldcols != vstat.cols) {
if (oldcols == 0) {
if (ciolib_initial_window_width > 0)
vstat.winwidth = ciolib_initial_window_width;
if (ciolib_initial_window_height > 0)
vstat.winheight = ciolib_initial_window_height;
if (vstat.cols == 40)
oldcols = 40;
}
if (oldcols == 40) {
vstat.winwidth /= 2;
vstat.winheight /= 2;
}
if (vstat.cols == 40) {
vstat.winwidth *= 2;
vstat.winheight *= 2;
}
}
if (vstat.winwidth < vstat.scrnwidth)
vstat.winwidth = vstat.scrnwidth;
if (vstat.winheight < vstat.scrnheight)
vstat.winheight = vstat.scrnheight;
if (sdl.GetDisplayUsableBounds(0, &r) == 0) {
w = r.w;
h = r.h;
}
else {
w = 0;
h = 0;
}
bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height, w, h);
internal_scaling = window_can_scale_internally(&vstat);
pthread_mutex_lock(&sdl_mode_mutex);
sdl_mode = true;
......@@ -891,62 +871,22 @@ void sdl_video_event_thread(void *data)
if ((ev.key.keysym.mod & KMOD_ALT) &&
(ev.key.keysym.sym == SDLK_LEFT ||
ev.key.keysym.sym == SDLK_RIGHT)) {
int w, h;
// Don't allow ALT-DIR to change size when maximized...
if ((sdl.GetWindowFlags(win) & SDL_WINDOW_MAXIMIZED) == 0) {
bool wc;
update_cvstat(&cvstat);
w = cvstat.winwidth;
h = cvstat.winheight;
aspect_fix(&w, &h, cvstat.aspect_width, cvstat.aspect_height);
if (cvstat.aspect_width == 0 || cvstat.aspect_height == 0)
wc = true;
else
wc = lround((double)(h * cvstat.aspect_width) / cvstat.aspect_height * cvstat.scrnwidth / cvstat.scrnheight) > w;
switch(ev.key.keysym.sym) {
case SDLK_LEFT:
if (wc) {
if (w % (cvstat.scrnwidth)) {
w = w - w % cvstat.scrnwidth;
}
else {
w -= cvstat.scrnwidth;
if (w < cvstat.scrnwidth)
w = cvstat.scrnwidth;
}
}
else {
if (h % (cvstat.scrnheight)) {
h = h - h % cvstat.scrnheight;
}
else {
h -= cvstat.scrnheight;
if (h < cvstat.scrnheight)
h = cvstat.scrnheight;
}
}
break;
case SDLK_RIGHT:
if (wc)
w = (w - w % cvstat.scrnwidth) + cvstat.scrnwidth;
else
h = (h - h % cvstat.scrnheight) + cvstat.scrnheight;
break;
int w, h;
SDL_Rect r;
if (sdl.GetDisplayUsableBounds(0, &r) == 0) {
w = r.w;
h = r.h;
}
if (wc)
h = INT_MAX;
else
w = INT_MAX;
aspect_fix(&w, &h, cvstat.aspect_width, cvstat.aspect_height);
if (w > 16384 || h > 16384)
beep();
else {
cvstat.winwidth = w;
cvstat.winheight = h;
internal_scaling = window_can_scale_internally(&cvstat);
w = 0;
h = 0;
}
pthread_mutex_lock(&vstatlock);
bitmap_snap(ev.key.keysym.sym == SDLK_RIGHT, w, h);
pthread_mutex_unlock(&vstatlock);
update_cvstat(&cvstat);
setup_surfaces_locked(&cvstat);
}
break;
......
......@@ -202,6 +202,10 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
xp_dlclose(sdl_dll);
return(-1);
}
if((sdlf->GetDisplayUsableBounds=xp_dlsym(sdl_dll, SDL_GetDisplayUsableBounds))==NULL) {
xp_dlclose(sdl_dll);
return(-1);
}
#ifndef STATIC_SDL
{
int (HACK_HACK_HACK *ra)(char *name, Uint32 style, void *hInst);
......
......@@ -56,6 +56,7 @@ struct sdlfuncs {
void (HACK_HACK_HACK *FreeCursor) (SDL_Cursor *curs);
void(HACK_HACK_HACK *free) (void *);
Uint32(HACK_HACK_HACK *GetWindowFlags) (SDL_Window * window);
int (HACK_HACK_HACK *GetDisplayUsableBounds) (int, SDL_Rect *);
int gotfuncs;
};
......
......@@ -197,8 +197,8 @@ UnadjustWindowSize(int *w, int *h)
ret = AdjustWindowRect(&r, style, FALSE);
if (ret) {
w += r.left - r.right;
h += r.top - r.bottom;
*w += r.left - r.right;
*h += r.top - r.bottom;
}
return ret;
}
......@@ -222,7 +222,6 @@ gdi_handle_wm_size(WPARAM wParam, LPARAM lParam)
return 0;
w = lParam & 0xffff;
h = (lParam >> 16) & 0xffff;
UnadjustWindowSize(&w, &h);
pthread_mutex_lock(&vstatlock);
vstat.winwidth = w;
vstat.winheight = h;
......@@ -519,76 +518,34 @@ gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
static bool
gdi_get_monitor_size(int *w, int *h)
{
HMONITOR mon;
MONITORINFO mi;
bool ret;
mon = MonitorFromWindow(win, MONITOR_DEFAULTTOPRIMARY);
mi.cbSize = sizeof(mi);
ret = GetMonitorInfoW(mon, &mi);
*w = mi.rcWork.right - mi.rcWork.left;
*h = mi.rcWork.bottom - mi.rcWork.top;
return ret;
}
static void
gdi_snap(bool grow)
{
bool wc;
int w, h;
int mw, mh;
if (maximized)
return;
mw = GetSystemMetrics(SM_CXMAXTRACK);
mh = GetSystemMetrics(SM_CYMAXTRACK);
gdi_get_monitor_size(&mw, &mh);
UnadjustWindowSize(&mw, &mh);
pthread_mutex_lock(&vstatlock);
w = vstat.winwidth;
h = vstat.winheight;
aspect_fix_inside(&w, &h, vstat.aspect_width, vstat.aspect_height);
if (vstat.aspect_width == 0 || vstat.aspect_height == 0)
wc = true;
else
wc = lround((double)(h * vstat.aspect_width) / vstat.aspect_height * vstat.scrnwidth / vstat.scrnheight) > w;
if (wc)
mw = mw - mw % vstat.scrnwidth;
else
mh = mh - mh % vstat.scrnheight;
mh = mw - mw % vstat.scrnwidth;
if (grow) {
if (wc)
w = (w - w % vstat.scrnwidth) + vstat.scrnwidth;
else
h = (h - h % vstat.scrnheight) + vstat.scrnheight;
}
else {
if (wc) {
if (w % (vstat.scrnwidth)) {
w = w - w % vstat.scrnwidth;
}
else {
w -= vstat.scrnwidth;
if (w < vstat.scrnwidth)
w = vstat.scrnwidth;
}
}
else {
if (h % (vstat.scrnheight)) {
h = h - h % vstat.scrnheight;
}
else {
h -= vstat.scrnheight;
if (h < vstat.scrnheight)
h = vstat.scrnheight;
}
}
}
if (wc)
h = INT_MAX;
else
w = INT_MAX;
if (w > mw)
w = mw;
if (h > mh)
h = mh;
aspect_fix_inside(&w, &h, vstat.aspect_width, vstat.aspect_height);
if (w > 16384 || h > 16384)
gdi_beep();
else {
vstat.winwidth = w;
vstat.winheight = h;
bitmap_snap(grow, mw, mh);
set_ciolib_scaling();
gdi_setwinsize(w, h);
}
gdi_setwinsize(vstat.winwidth, vstat.winheight);
pthread_mutex_unlock(&vstatlock);
}
......@@ -618,7 +575,6 @@ magic_message(MSG msg)
r.left = r.top = 0;
r.right = vstat.winwidth = msg.wParam;
r.bottom = vstat.winheight = msg.lParam;
set_ciolib_scaling();
pthread_mutex_unlock(&vstatlock);
AdjustWindowRect(&r, style, FALSE);
SetWindowPos(win, NULL, 0, 0, r.right - r.left, r.bottom - r.top, SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
......@@ -778,8 +734,8 @@ gdi_beep(void)
void
gdi_textmode(int mode)
{
int oldcols;
int scaling = 1;
int mw, mh;
if (mode != CIOLIB_MODE_CUSTOM) {
pthread_mutex_lock(&vstatlock);
......@@ -791,37 +747,9 @@ gdi_textmode(int mode)
}
pthread_mutex_lock(&vstatlock);
oldcols = vstat.cols;
bitmap_drv_init_mode(mode, NULL, NULL);
if (vstat.scrnwidth > 0) {
for (scaling = 1; (scaling + 1) * vstat.scrnwidth < vstat.winwidth; scaling++)
;
}
vstat.winwidth = vstat.scrnwidth * scaling;
vstat.winheight = vstat.scrnheight * scaling;
aspect_fix_inside(&vstat.winwidth, &vstat.winheight, vstat.aspect_width, vstat.aspect_height);
if (oldcols != vstat.cols) {
if (oldcols == 0) {
if (ciolib_initial_window_width > 0)
vstat.winwidth = ciolib_initial_window_width;
if (ciolib_initial_window_height > 0)
vstat.winheight = ciolib_initial_window_height;
if (vstat.cols == 40)
oldcols = 40;
}
if (oldcols == 40) {
vstat.winwidth /= 2;
vstat.winheight /= 2;
}
if (vstat.cols == 40) {
vstat.winwidth *= 2;
vstat.winheight *= 2;
}
}
if (vstat.winwidth < vstat.scrnwidth)
vstat.winwidth = vstat.scrnwidth;
if (vstat.winheight < vstat.scrnheight)
vstat.winheight = vstat.scrnheight;
gdi_get_monitor_size(&mw, &mh);
UnadjustWindowSize(&mw, &mh);
bitmap_drv_init_mode(mode, NULL, NULL, mw, mh);
set_ciolib_scaling();
gdi_setwinsize(vstat.winwidth, vstat.winheight);
pthread_mutex_unlock(&vstatlock);
......
......@@ -417,7 +417,7 @@ static void init_mode_internal(int mode)
release_buffer(last);
last = NULL;
}
bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height);
bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height, 0, 0);
/* Deal with 40 col doubling */
if(oldcols != vstat.cols) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment