Merge pull request #2432 from Cacodemon345/multimonitor-take2-ui

Multi-monitor support
This commit is contained in:
Jasmine Iwanek
2022-07-10 20:16:35 -04:00
committed by GitHub
67 changed files with 1285 additions and 574 deletions

View File

@@ -139,10 +139,6 @@ char log_path[1024] = { '\0'}; /* (O) full path of logfile */
char vm_name[1024] = { '\0'}; /* (O) display name of the VM */
/* Configuration values. */
int window_w; /* (C) window size and */
int window_h; /* position info */
int window_x;
int window_y;
int window_remember;
int vid_resize; /* (C) allow resizing */
int invert_display = 0; /* (C) invert the display */
@@ -166,6 +162,8 @@ int postcard_enabled = 0; /* (C) enable POST card */
int isamem_type[ISAMEM_MAX] = { 0,0,0,0 }; /* (C) enable ISA mem cards */
int isartc_type = 0; /* (C) enable ISA RTC card */
int gfxcard = 0; /* (C) graphics/video card */
int gfxcard_2 = 0; /* (C) graphics/video card */
int show_second_monitors = 1; /* (C) show non-primary monitors */
int sound_is_float = 1; /* (C) sound uses FP values */
int GAMEBLASTER = 0; /* (C) sound option */
int GUS = 0; /* (C) sound option */
@@ -201,17 +199,17 @@ char exe_path[2048]; /* path (dir) of executable */
char usr_path[1024]; /* path (dir) of user data */
char cfg_path[1024]; /* full path of config file */
FILE *stdlog = NULL; /* file to log output to */
int scrnsz_x = SCREEN_RES_X; /* current screen size, X */
int scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */
//int scrnsz_x = SCREEN_RES_X; /* current screen size, X */
//int scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */
int config_changed; /* config has changed */
int title_update;
int framecountx = 0;
int hard_reset_pending = 0;
int unscaled_size_x = SCREEN_RES_X; /* current unscaled size X */
int unscaled_size_y = SCREEN_RES_Y; /* current unscaled size Y */
int efscrnsz_y = SCREEN_RES_Y;
//int unscaled_size_x = SCREEN_RES_X; /* current unscaled size X */
//int unscaled_size_y = SCREEN_RES_Y; /* current unscaled size Y */
//int efscrnsz_y = SCREEN_RES_Y;
static wchar_t mouse_msg[3][200];
@@ -855,6 +853,15 @@ pc_init_modules(void)
}
}
if (! video_card_available(gfxcard_2)) {
char temp[1024] = { 0 };
char tempc[1024] = { 0 };
device_get_name(video_card_getdevice(gfxcard_2), 0, tempc);
snprintf(temp, sizeof(temp), "Video card #2 \"%s\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card.", tempc);
ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2128, temp);
gfxcard_2 = 0;
}
atfullspeed = 0;
random_init();
@@ -1250,14 +1257,13 @@ pc_onesec(void)
title_update = 1;
}
void
set_screen_size(int x, int y)
set_screen_size_monitor(int x, int y, int monitor_index)
{
int owsx = scrnsz_x;
int owsy = scrnsz_y;
int temp_overscan_x = overscan_x;
int temp_overscan_y = overscan_y;
int owsx = monitors[monitor_index].mon_scrnsz_x;
int owsy = monitors[monitor_index].mon_scrnsz_y;
int temp_overscan_x = monitors[monitor_index].mon_overscan_x;
int temp_overscan_y = monitors[monitor_index].mon_overscan_y;
double dx, dy, dtx, dty;
/* Make sure we keep usable values. */
@@ -1270,78 +1276,89 @@ set_screen_size(int x, int y)
if (y > 2048) y = 2048;
/* Save the new values as "real" (unscaled) resolution. */
unscaled_size_x = x;
efscrnsz_y = y;
monitors[monitor_index].mon_unscaled_size_x = x;
monitors[monitor_index].mon_efscrnsz_y = y;
if (suppress_overscan)
temp_overscan_x = temp_overscan_y = 0;
temp_overscan_x = temp_overscan_y = 0;
if (force_43) {
dx = (double)x;
dtx = (double)temp_overscan_x;
dx = (double)x;
dtx = (double)temp_overscan_x;
dy = (double)y;
dty = (double)temp_overscan_y;
dy = (double)y;
dty = (double)temp_overscan_y;
/* Account for possible overscan. */
if (!(video_is_ega_vga()) && (temp_overscan_y == 16)) {
/* CGA */
dy = (((dx - dtx) / 4.0) * 3.0) + dty;
} else if (!(video_is_ega_vga()) && (temp_overscan_y < 16)) {
/* MDA/Hercules */
dy = (x / 4.0) * 3.0;
} else {
if (enable_overscan) {
/* EGA/(S)VGA with overscan */
dy = (((dx - dtx) / 4.0) * 3.0) + dty;
} else {
/* EGA/(S)VGA without overscan */
dy = (x / 4.0) * 3.0;
}
}
unscaled_size_y = (int)dy;
/* Account for possible overscan. */
if (video_get_type_monitor(monitor_index) != VIDEO_FLAG_TYPE_SPECIAL && (temp_overscan_y == 16)) {
/* CGA */
dy = (((dx - dtx) / 4.0) * 3.0) + dty;
} else if (video_get_type_monitor(monitor_index) != VIDEO_FLAG_TYPE_SPECIAL && (temp_overscan_y < 16)) {
/* MDA/Hercules */
dy = (x / 4.0) * 3.0;
} else {
if (enable_overscan) {
/* EGA/(S)VGA with overscan */
dy = (((dx - dtx) / 4.0) * 3.0) + dty;
} else {
/* EGA/(S)VGA without overscan */
dy = (x / 4.0) * 3.0;
}
}
monitors[monitor_index].mon_unscaled_size_y = (int)dy;
} else
unscaled_size_y = efscrnsz_y;
monitors[monitor_index].mon_unscaled_size_y = monitors[monitor_index].mon_efscrnsz_y;
switch(scale) {
case 0: /* 50% */
scrnsz_x = (unscaled_size_x>>1);
scrnsz_y = (unscaled_size_y>>1);
break;
case 0: /* 50% */
monitors[monitor_index].mon_scrnsz_x = (monitors[monitor_index].mon_unscaled_size_x>>1);
monitors[monitor_index].mon_scrnsz_y = (monitors[monitor_index].mon_unscaled_size_y>>1);
break;
case 1: /* 100% */
scrnsz_x = unscaled_size_x;
scrnsz_y = unscaled_size_y;
break;
case 1: /* 100% */
monitors[monitor_index].mon_scrnsz_x = monitors[monitor_index].mon_unscaled_size_x;
monitors[monitor_index].mon_scrnsz_y = monitors[monitor_index].mon_unscaled_size_y;
break;
case 2: /* 150% */
scrnsz_x = ((unscaled_size_x*3)>>1);
scrnsz_y = ((unscaled_size_y*3)>>1);
break;
case 2: /* 150% */
monitors[monitor_index].mon_scrnsz_x = ((monitors[monitor_index].mon_unscaled_size_x*3)>>1);
monitors[monitor_index].mon_scrnsz_y = ((monitors[monitor_index].mon_unscaled_size_y*3)>>1);
break;
case 3: /* 200% */
scrnsz_x = (unscaled_size_x<<1);
scrnsz_y = (unscaled_size_y<<1);
break;
case 3: /* 200% */
monitors[monitor_index].mon_scrnsz_x = (monitors[monitor_index].mon_unscaled_size_x<<1);
monitors[monitor_index].mon_scrnsz_y = (monitors[monitor_index].mon_unscaled_size_y<<1);
break;
}
/* If the resolution has changed, let the main thread handle it. */
if ((owsx != scrnsz_x) || (owsy != scrnsz_y))
atomic_flag_clear(&doresize);
atomic_store(&doresize_monitors[monitor_index], 1);
}
void
set_screen_size(int x, int y)
{
set_screen_size_monitor(x, y, monitor_index_global);
}
void
reset_screen_size_monitor(int monitor_index)
{
set_screen_size(monitors[monitor_index].mon_unscaled_size_x, monitors[monitor_index].mon_efscrnsz_y);
}
void
reset_screen_size(void)
{
set_screen_size(unscaled_size_x, efscrnsz_y);
for (int i = 0; i < MONITORS_NUM; i++)
set_screen_size(monitors[i].mon_unscaled_size_x, monitors[i].mon_efscrnsz_y);
}
void
set_screen_size_natural(void)
{
set_screen_size(unscaled_size_x, unscaled_size_y);
for (int i = 0; i < MONITORS_NUM; i++)
set_screen_size(monitors[i].mon_unscaled_size_x, monitors[i].mon_unscaled_size_y);
}

View File

@@ -552,14 +552,8 @@ load_general(void)
if (window_remember || (vid_resize & 2)) {
if (!window_remember)
config_delete_var(cat, "window_remember");
p = config_get_string(cat, "window_coordinates", NULL);
if (p == NULL)
p = "0, 0, 0, 0";
sscanf(p, "%i, %i, %i, %i", &window_w, &window_h, &window_x, &window_y);
} else {
config_delete_var(cat, "window_remember");
config_delete_var(cat, "window_coordinates");
window_w = window_h = window_x = window_y = 0;
}
@@ -932,6 +926,49 @@ load_video(void)
voodoo_enabled = !!config_get_int(cat, "voodoo", 0);
ibm8514_enabled = !!config_get_int(cat, "8514a", 0);
xga_enabled = !!config_get_int(cat, "xga", 0);
show_second_monitors = !!config_get_int(cat, "show_second_monitors", 1);
p = config_get_string(cat, "gfxcard_2", NULL);
if (!p) p = "none";
gfxcard_2 = video_get_video_from_internal_name(p);
}
static void
load_monitor(int monitor_index)
{
char monitor_config_name[sizeof("Monitor #") + 12] = { [0] = 0 };
char* ptr = NULL;
if (monitor_index == 0) {
/* Migrate configs */
ptr = config_get_string("General", "window_coordinates", NULL);
config_delete_var("General", "window_coordinates");
}
snprintf(monitor_config_name, sizeof(monitor_config_name), "Monitor #%i", monitor_index + 1);
if (!ptr) ptr = config_get_string(monitor_config_name, "window_coordinates", "0, 0, 0, 0");
if (window_remember || (vid_resize & 2)) sscanf(ptr, "%i, %i, %i, %i",
&monitor_settings[monitor_index].mon_window_x, &monitor_settings[monitor_index].mon_window_y,
&monitor_settings[monitor_index].mon_window_w, &monitor_settings[monitor_index].mon_window_h);
}
static void
save_monitor(int monitor_index)
{
char monitor_config_name[sizeof("Monitor #") + 12] = { [0] = 0 };
char saved_coordinates[12 * 4 + 8 + 1] = { [0] = 0 };
snprintf(monitor_config_name, sizeof(monitor_config_name), "Monitor #%i", monitor_index + 1);
if (!(monitor_settings[monitor_index].mon_window_x == 0
&& monitor_settings[monitor_index].mon_window_y == 0
&& monitor_settings[monitor_index].mon_window_w == 0
&& monitor_settings[monitor_index].mon_window_h == 0) && (window_remember || (vid_resize & 2))) {
snprintf(saved_coordinates, sizeof(saved_coordinates), "%i, %i, %i, %i", monitor_settings[monitor_index].mon_window_x, monitor_settings[monitor_index].mon_window_y,
monitor_settings[monitor_index].mon_window_w, monitor_settings[monitor_index].mon_window_h);
config_set_string(monitor_config_name, "window_coordinates", saved_coordinates);
}
else config_delete_var(monitor_config_name, "window_coordinates");
}
@@ -2156,6 +2193,8 @@ config_load(void)
config_log("Config file not present or invalid!\n");
} else {
load_general(); /* General */
for (i = 0; i < MONITORS_NUM; i++)
load_monitor(i);
load_machine(); /* Machine */
load_video(); /* Video */
load_input_devices(); /* Input devices */
@@ -2265,12 +2304,8 @@ save_general(void)
config_set_int(cat, "window_remember", window_remember);
else
config_delete_var(cat, "window_remember");
sprintf(temp, "%i, %i, %i, %i", window_w, window_h, window_x, window_y);
config_set_string(cat, "window_coordinates", temp);
} else {
config_delete_var(cat, "window_remember");
config_delete_var(cat, "window_coordinates");
}
if (vid_resize & 2) {
@@ -2480,6 +2515,16 @@ save_video(void)
else
config_set_int(cat, "xga", xga_enabled);
if (gfxcard_2 == 0)
config_delete_var(cat, "gfxcard_2");
else
config_set_string(cat, "gfxcard_2", video_get_internal_name(gfxcard_2));
if (show_second_monitors == 1)
config_delete_var(cat, "show_second_monitors");
else
config_set_int(cat, "show_second_monitors", show_second_monitors);
delete_section_if_empty(cat);
}
@@ -3079,7 +3124,11 @@ save_other_removable_devices(void)
void
config_save(void)
{
int i;
save_general(); /* General */
for (i = 0; i < MONITORS_NUM; i++)
save_monitor(i);
save_machine(); /* Machine */
save_video(); /* Video */
save_input_devices(); /* Input devices */

View File

@@ -80,9 +80,11 @@ extern char log_path[1024]; /* (O) full path of logfile */
extern char vm_name[1024]; /* (O) display name of the VM */
extern int window_w, window_h, /* (C) window size and */
window_x, window_y, /* position info */
window_remember,
#define window_x monitor_settings[0].mon_window_x
#define window_y monitor_settings[0].mon_window_y
#define window_w monitor_settings[0].mon_window_w
#define window_h monitor_settings[0].mon_window_h
extern int window_remember,
vid_resize, /* (C) allow resizing */
invert_display, /* (C) invert the display */
suppress_overscan; /* (C) suppress overscans */
@@ -141,9 +143,6 @@ extern char cfg_path[1024]; /* full path of config file */
#ifndef USE_NEW_DYNAREC
extern FILE *stdlog; /* file to log output to */
#endif
extern int scrnsz_x, /* current screen size, X */
scrnsz_y; /* current screen size, Y */
extern int efscrnsz_y;
extern int config_changed; /* config has changed */
@@ -156,7 +155,9 @@ extern void pclog_toggle_suppr(void);
extern void pclog(const char *fmt, ...);
extern void fatal(const char *fmt, ...);
extern void set_screen_size(int x, int y);
extern void set_screen_size_monitor(int x, int y, int monitor_index);
extern void reset_screen_size(void);
extern void reset_screen_size_monitor(int monitor_index);
extern void set_screen_size_natural(void);
extern void update_mouse_msg();
#if 0

View File

@@ -77,7 +77,6 @@ extern "C" {
/* Global variables residing in the platform module. */
extern int dopause, /* system is paused */
mouse_capture; /* mouse is captured in app */
extern atomic_flag_t doresize; /* screen resize requested */
extern volatile int is_quit; /* system exit requested */
#ifdef MTR_ENABLED
@@ -90,9 +89,6 @@ extern char emu_version[200]; /* version ID string */
extern int rctrl_is_lalt;
extern int update_icons;
extern int unscaled_size_x, /* current unscaled size X */
unscaled_size_y; /* current unscaled size Y */
extern int kbd_req_capture, hide_status_bar, hide_tool_bar;
/* System-related functions. */
@@ -120,7 +116,8 @@ extern char *plat_vidapi_name(int api);
extern int plat_setvid(int api);
extern void plat_vidsize(int x, int y);
extern void plat_setfullscreen(int on);
extern void plat_resize(int x, int y);
extern void plat_resize_monitor(int x, int y, int monitor_index);
extern void plat_resize(int x, int y);
extern void plat_vidapi_enable(int enabled);
extern void plat_vidapi_reload(void);
extern void plat_vid_reload_options(void);

View File

@@ -62,6 +62,8 @@ extern void ui_check_menu_item(int id, int checked);
extern wchar_t *ui_window_title(wchar_t *s);
extern void ui_status_update(void);
extern void ui_init_monitor(int monitor_index);
extern void ui_deinit_monitor(int monitor_index);
extern int ui_sb_find_part(int tag);
extern void ui_sb_set_ready(int ready);
extern void ui_sb_update_panes(void);

View File

@@ -46,6 +46,8 @@ typedef struct cga_t
int drawcursor;
int fullchange;
uint8_t *vram;
uint8_t charbuffer[256];

View File

@@ -46,14 +46,14 @@ typedef struct ega_t {
readmode, writemode, readplane, vrammask,
chain4, chain2_read, chain2_write, con,
oddeven_page, oddeven_chain, vc, sc,
dispon, hdisp_on, cursoron, blink,
dispon, hdisp_on, cursoron, blink, fullchange,
linepos, vslines, linecountff, oddeven,
lowres, interlace, linedbl, lindebl, rowcount,
vtotal, dispend, vsyncstart, split,
hdisp, hdisp_old, htotal, hdisp_time, rowoffset,
vblankstart, scrollcache, firstline, lastline,
firstline_draw, lastline_draw, x_add, y_add,
displine, video_res_x, video_res_y, video_bpp, index;
displine, res_x, res_y, bpp, index;
uint32_t charseta, charsetb, ma_latch, ma,
maback, ca, vram_limit, overscan_color;

View File

@@ -51,12 +51,18 @@ typedef struct {
int vadj;
int lp_ff;
int fullchange;
int cols[256][2][2];
uint8_t *vram;
int monitor_index;
int prev_monitor_index;
} hercules_t;
#define VIDEO_MONITOR_PROLOGUE() { dev->prev_monitor_index = monitor_index_global; monitor_index_global = dev->monitor_index; }
#define VIDEO_MONITOR_EPILOGUE() { monitor_index_global = dev->prev_monitor_index; }
static void *hercules_init(const device_t *info);
#endif /*VIDEO_HERCULES_H*/

View File

@@ -25,11 +25,16 @@ typedef struct mda_t
int con, coff, cursoron;
int dispon, blink;
int vsynctime;
int vadj;
int vadj;
int monitor_index;
int prev_monitor_index;
uint8_t *vram;
} mda_t;
#define VIDEO_MONITOR_PROLOGUE() { mda->prev_monitor_index = monitor_index_global; monitor_index_global = mda->monitor_index; }
#define VIDEO_MONITOR_EPILOGUE() { monitor_index_global = mda->prev_monitor_index; }
void mda_init(mda_t *mda);
void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink);
void mda_out(uint16_t addr, uint8_t val, void *p);

View File

@@ -35,7 +35,7 @@
typedef struct {
int ena,
x, y, xoff, yoff, xsize, ysize,
x, y, xoff, yoff, cur_xsize, cur_ysize,
v_acc, h_acc;
uint32_t addr, pitch;
} hwcursor_t;

View File

@@ -22,7 +22,7 @@
typedef struct {
int ena;
int x, y, xoff, yoff, xsize, ysize;
int x, y, xoff, yoff, cur_xsize, cur_ysize;
uint32_t addr;
} xga_hwcursor_t;

View File

@@ -22,6 +22,12 @@
#ifndef EMU_VIDEO_H
# define EMU_VIDEO_H
#ifdef __cplusplus
#include <atomic>
using atomic_bool = std::atomic_bool;
#else
#include <stdatomic.h>
#endif
#define makecol(r, g, b) ((b) | ((g) << 8) | ((r) << 16))
#define makecol32(r, g, b) ((b) | ((g) << 8) | ((r) << 16))
@@ -79,20 +85,93 @@ typedef struct {
uint8_t chr[32];
} dbcs_font_t;
struct blit_data_struct;
typedef struct monitor_t
{
char name[512];
int mon_xsize;
int mon_ysize;
int mon_scrnsz_x;
int mon_scrnsz_y;
int mon_efscrnsz_y;
int mon_unscaled_size_x;
int mon_unscaled_size_y;
int mon_res_x;
int mon_res_y;
int mon_bpp;
bitmap_t* target_buffer;
int mon_video_timing_read_b,
mon_video_timing_read_w,
mon_video_timing_read_l;
int mon_video_timing_write_b,
mon_video_timing_write_w,
mon_video_timing_write_l;
int mon_overscan_x;
int mon_overscan_y;
int mon_force_resize;
int mon_fullchange;
int mon_changeframecount;
int mon_screenshots;
uint32_t* mon_pal_lookup;
int* mon_cga_palette;
int mon_pal_lookup_static; /* Whether it should not be freed by the API. */
int mon_cga_palette_static; /* Whether it should not be freed by the API. */
const video_timings_t* mon_vid_timings;
int mon_vid_type;
struct blit_data_struct* mon_blit_data_ptr;
} monitor_t;
typedef struct monitor_settings_t {
int mon_window_x; /* (C) window size and position info. */
int mon_window_y;
int mon_window_w;
int mon_window_h;
} monitor_settings_t;
#define MONITORS_NUM 8
extern monitor_t monitors[MONITORS_NUM];
extern monitor_settings_t monitor_settings[MONITORS_NUM];
extern atomic_bool doresize_monitors[MONITORS_NUM];
extern int monitor_index_global;
extern int gfxcard_2;
extern int show_second_monitors;
typedef rgb_t PALETTE[256];
extern int changeframecount;
//extern int changeframecount;
extern volatile int screenshots;
extern bitmap_t *buffer32;
//extern bitmap_t *buffer32;
#define buffer32 (monitors[monitor_index_global].target_buffer)
#define pal_lookup (monitors[monitor_index_global].mon_pal_lookup)
#define overscan_x (monitors[monitor_index_global].mon_overscan_x)
#define overscan_y (monitors[monitor_index_global].mon_overscan_y)
#define video_timing_read_b (monitors[monitor_index_global].mon_video_timing_read_b)
#define video_timing_read_l (monitors[monitor_index_global].mon_video_timing_read_l)
#define video_timing_read_w (monitors[monitor_index_global].mon_video_timing_read_w)
#define video_timing_write_b (monitors[monitor_index_global].mon_video_timing_write_b)
#define video_timing_write_l (monitors[monitor_index_global].mon_video_timing_write_l)
#define video_timing_write_w (monitors[monitor_index_global].mon_video_timing_write_w)
#define video_res_x (monitors[monitor_index_global].mon_res_x)
#define video_res_y (monitors[monitor_index_global].mon_res_y)
#define video_bpp (monitors[monitor_index_global].mon_bpp)
#define xsize (monitors[monitor_index_global].mon_xsize)
#define ysize (monitors[monitor_index_global].mon_ysize)
#define cga_palette (*monitors[monitor_index_global].mon_cga_palette)
#define changeframecount (monitors[monitor_index_global].mon_changeframecount)
#define scrnsz_x (monitors[monitor_index_global].mon_scrnsz_x)
#define scrnsz_y (monitors[monitor_index_global].mon_scrnsz_y)
#define efscrnsz_y (monitors[monitor_index_global].mon_efscrnsz_y)
#define unscaled_size_x (monitors[monitor_index_global].mon_unscaled_size_x)
#define unscaled_size_y (monitors[monitor_index_global].mon_unscaled_size_y)
extern PALETTE cgapal,
cgapal_mono[6];
extern uint32_t pal_lookup[256];
//extern uint32_t pal_lookup[256];
extern int video_fullscreen,
video_fullscreen_scale,
video_fullscreen_first;
extern int fullchange;
video_fullscreen_first;
extern uint8_t fontdat[2048][8];
extern uint8_t fontdatm[2048][16];
extern uint8_t fontdatw[512][32];
@@ -104,24 +183,11 @@ extern uint32_t *video_6to8,
*video_8togs,
*video_8to32,
*video_15to32,
*video_16to32;
extern int xsize,ysize;
*video_16to32;
extern int enable_overscan;
extern int overscan_x,
overscan_y;
extern int force_43;
extern int video_timing_read_b,
video_timing_read_w,
video_timing_read_l;
extern int video_timing_write_b,
video_timing_write_w,
video_timing_write_l;
extern int video_res_x,
video_res_y,
video_bpp;
extern int vid_resize;
extern int cga_palette,
herc_blend;
extern int herc_blend;
extern int vid_cga_contrast;
extern int video_grayscale;
extern int video_graytype;
@@ -134,6 +200,7 @@ extern int readflash;
/* Function handler pointers. */
extern void (*video_recalctimings)(void);
extern void video_screenshot_monitor(uint32_t *buf, int start_x, int start_y, int row_len, int monitor_index);
extern void video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len);
#ifdef _WIN32
@@ -153,34 +220,48 @@ extern const device_t *video_card_getdevice(int card);
extern int video_card_has_config(int card);
extern char *video_get_internal_name(int card);
extern int video_get_video_from_internal_name(char *s);
extern int video_card_get_flags(int card);
extern int video_is_mda(void);
extern int video_is_cga(void);
extern int video_is_ega_vga(void);
extern void video_inform(int type, const video_timings_t *ptr);
extern void video_inform_monitor(int type, const video_timings_t *ptr, int monitor_index);
extern int video_get_type(void);
extern int video_get_type_monitor(int monitor_index);
extern void video_setblit(void(*blit)(int,int,int,int));
extern void video_setblit(void(*blit)(int,int,int,int,int));
extern void video_blend(int x, int y);
extern void video_blend_monitor(int x, int y, int monitor_index);
extern void video_blit_memtoscreen_8(int x, int y, int w, int h);
extern void video_blit_memtoscreen_8_monitor(int x, int y, int w, int h, int monitor_index);
extern void video_blit_memtoscreen(int x, int y, int w, int h);
extern void video_blit_memtoscreen_monitor(int x, int y, int w, int h, int monitor_index);
extern void video_blit_complete(void);
extern void video_wait_for_blit(void);
extern void video_wait_for_buffer(void);
extern void video_blit_complete_monitor(int monitor_index);
extern void video_wait_for_blit_monitor(int monitor_index);
extern void video_wait_for_buffer_monitor(int monitor_index);
extern bitmap_t *create_bitmap(int w, int h);
extern void destroy_bitmap(bitmap_t *b);
extern void cgapal_rebuild_monitor(int monitor_index);
extern void cgapal_rebuild(void);
extern void hline(bitmap_t *b, int x1, int y, int x2, uint32_t col);
extern void updatewindowsize(int x, int y);
extern void video_monitor_init(int);
extern void video_monitor_close(int);
extern void video_init(void);
extern void video_close(void);
extern void video_reset_close(void);
extern void video_pre_reset(int card);
extern void video_reset(int card);
extern uint8_t video_force_resize_get(void);
extern uint8_t video_force_resize_get_monitor(int monitor_index);
extern void video_force_resize_set(uint8_t res);
extern void video_force_resize_set_monitor(uint8_t res, int monitor_index);
extern void video_update_timing(void);
extern void loadfont_ex(char *s, int format, int offset);

View File

@@ -119,6 +119,7 @@ typedef struct {
cursoron,
cgablink;
int vsynctime;
int fullchange;
int vadj;
uint16_t ma, maback;
int dispon;
@@ -242,7 +243,7 @@ vid_out_1512(uint16_t addr, uint8_t val, void *priv)
vid->crtc[vid->crtcreg] = val & crtc_mask[vid->crtcreg];
if (old != val) {
if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) {
fullchange = changeframecount;
vid->fullchange = changeframecount;
recalc_timings_1512(vid);
}
}
@@ -1113,7 +1114,7 @@ vid_out_200(uint16_t addr, uint8_t val, void *priv)
mda->crtc[mda->crtcreg] = val & crtc_mask[mda->crtcreg];
if (old != val) {
if (mda->crtcreg < 0xe || mda->crtcreg > 0x10) {
fullchange = changeframecount;
vid->fullchange = changeframecount;
mda_recalctimings(mda);
}
}
@@ -1145,7 +1146,7 @@ vid_out_200(uint16_t addr, uint8_t val, void *priv)
cga->crtc[cga->crtcreg] = val & crtc_mask[cga->crtcreg];
if (old != val) {
if (cga->crtcreg < 0xe || cga->crtcreg > 0x10) {
fullchange = changeframecount;
vid->fullchange = changeframecount;
cga_recalctimings(cga);
}
}

View File

@@ -97,7 +97,7 @@ typedef struct compaq_plasma_t
int linepos, displine;
uint8_t *vram;
uint64_t dispontime, dispofftime;
int dispon;
int dispon, fullchange;
} compaq_plasma_t;
static uint8_t cga_crtcmask[32] =
@@ -375,7 +375,7 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv)
if (old != val) {
if (self->cga.crtcreg < 0xe || self->cga.crtcreg > 0x10) {
fullchange = changeframecount;
self->fullchange = changeframecount;
compaq_plasma_recalctimings(self);
}
}

View File

@@ -81,6 +81,7 @@ typedef struct {
int dispon;
int con, coff, cursoron, blink;
int vsynctime;
int fullchange;
int vadj;
uint16_t ma, maback;
uint64_t dispontime, dispofftime;
@@ -162,7 +163,7 @@ vid_out(uint16_t addr, uint8_t val, void *p)
pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg];
if (old != val) {
if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10) {
fullchange = changeframecount;
pcjr->fullchange = changeframecount;
recalc_timings(pcjr);
}
}

View File

@@ -91,6 +91,7 @@ typedef struct {
int con, coff,
cursoron,
blink;
int fullchange;
int vsynctime;
int vadj;
uint16_t ma, maback;
@@ -536,7 +537,7 @@ vid_out(uint16_t addr, uint8_t val, void *priv)
vid->crtc[vid->crtcreg] = val & crtcmask[vid->crtcreg];
if (old != val) {
if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) {
fullchange = changeframecount;
vid->fullchange = changeframecount;
recalc_timings(dev);
}
}

View File

@@ -8,7 +8,7 @@ extern "C"
#include <86box/video.h>
}
D3D9Renderer::D3D9Renderer(QWidget *parent)
D3D9Renderer::D3D9Renderer(QWidget *parent, int monitor_index)
: QWidget{parent}, RendererCommon()
{
QPalette pal = palette();
@@ -27,6 +27,7 @@ D3D9Renderer::D3D9Renderer(QWidget *parent)
RendererCommon::parentWidget = parent;
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
this->m_monitor_index = monitor_index;
}
D3D9Renderer::~D3D9Renderer()
@@ -138,8 +139,8 @@ void D3D9Renderer::resizeEvent(QResizeEvent *event)
void D3D9Renderer::blit(int x, int y, int w, int h)
{
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || surfaceInUse) {
video_blit_complete();
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || surfaceInUse) {
video_blit_complete_monitor(m_monitor_index);
return;
}
surfaceInUse = true;
@@ -152,16 +153,16 @@ void D3D9Renderer::blit(int x, int y, int w, int h)
srcRect.right = source.right();
if (screenshots) {
video_screenshot((uint32_t *) &(buffer32->line[y][x]), 0, 0, 2048);
video_screenshot_monitor((uint32_t *) &(monitors[m_monitor_index].target_buffer->line[y][x]), 0, 0, 2048, m_monitor_index);
}
if (SUCCEEDED(d3d9surface->LockRect(&lockRect, &srcRect, 0))) {
for (int y1 = 0; y1 < h; y1++) {
video_copy(((uint8_t*)lockRect.pBits) + (y1 * lockRect.Pitch), &(buffer32->line[y + y1][x]), w * 4);
video_copy(((uint8_t*)lockRect.pBits) + (y1 * lockRect.Pitch), &(monitors[m_monitor_index].target_buffer->line[y + y1][x]), w * 4);
}
video_blit_complete();
video_blit_complete_monitor(m_monitor_index);
d3d9surface->UnlockRect();
}
else video_blit_complete();
else video_blit_complete_monitor(m_monitor_index);
surfaceInUse = false;
QTimer::singleShot(0, this, [this] { this->update(); });
}

View File

@@ -12,7 +12,7 @@ class D3D9Renderer : public QWidget, public RendererCommon
{
Q_OBJECT
public:
explicit D3D9Renderer(QWidget *parent = nullptr);
explicit D3D9Renderer(QWidget *parent = nullptr, int monitor_index = 0);
~D3D9Renderer();
bool hasBlitFunc() override { return true; }
void blit(int x, int y, int w, int h) override;
@@ -39,6 +39,7 @@ private:
std::atomic<bool> surfaceInUse{false}, finalized{false};
bool alreadyInitialized = false;
int m_monitor_index = 0;
};
#endif // D3D9RENDERER_HPP

View File

@@ -32,6 +32,7 @@ extern "C" {
void HardwareRenderer::resizeGL(int w, int h)
{
m_context->makeCurrent(this);
glViewport(0, 0, qRound(w * devicePixelRatio()), qRound(h * devicePixelRatio()));
}

View File

@@ -122,19 +122,13 @@ main_thread_fn()
/* Just so we dont overload the host OS. */
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
/* If needed, handle a screen resize. */
if (!atomic_flag_test_and_set(&doresize) && !video_fullscreen && !is_quit) {
if (vid_resize & 2)
plat_resize(fixed_size_x, fixed_size_y);
else
plat_resize(scrnsz_x, scrnsz_y);
}
}
is_quit = 1;
}
static std::thread* main_thread;
int main(int argc, char* argv[]) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, false);
@@ -258,7 +252,7 @@ int main(int argc, char* argv[]) {
main_window->installEventFilter(&socket);
socket.connectToServer(qgetenv("86BOX_MANAGER_SOCKET"));
}
pc_reset_hard_init();
//pc_reset_hard_init();
/* Set the PAUSE mode depending on the renderer. */
// plat_pause(0);
@@ -284,13 +278,38 @@ int main(int argc, char* argv[]) {
}
/* Initialize the rendering window, or fullscreen. */
auto main_thread = std::thread([] {
main_thread_fn();
QTimer::singleShot(0, &app, []
{
pc_reset_hard_init();
main_thread = new std::thread(main_thread_fn);
});
QTimer resizeTimer;
resizeTimer.setInterval(0);
resizeTimer.callOnTimeout([]()
{
/* If needed, handle a screen resize. */
for (int i = 0; i < MONITORS_NUM; i++) {
if (!monitors[i].target_buffer) continue;
if (atomic_load(&doresize_monitors[i]) == 1 && !video_fullscreen && !is_quit) {
if (vid_resize & 2)
plat_resize_monitor(fixed_size_x, fixed_size_y, i);
else
plat_resize_monitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i);
atomic_store(&doresize_monitors[i], 0);
}
}
if (is_quit) {
QApplication::quit();
}
});
resizeTimer.start();
auto ret = app.exec();
cpu_thread_run = 0;
main_thread.join();
main_thread->join();
pc_close(nullptr);
socket.close();
return ret;

View File

@@ -20,6 +20,8 @@
* Copyright 2021-2022 Teemu Korhonen
* Copyright 2022 dob205
*/
#include <QDebug>
#include "qt_mainwindow.hpp"
#include "ui_qt_mainwindow.h"
@@ -61,6 +63,7 @@ extern "C" {
#include <QPushButton>
#include <QDesktopServices>
#include <QUrl>
#include <QMenuBar>
#include <QCheckBox>
#include <QActionGroup>
#include <QOpenGLContext>
@@ -120,7 +123,7 @@ static BMessageFilter* filter;
#endif
extern void qt_mouse_capture(int);
extern "C" void qt_blit(int x, int y, int w, int h);
extern "C" void qt_blit(int x, int y, int w, int h, int monitor_index);
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
@@ -140,7 +143,7 @@ MainWindow::MainWindow(QWidget *parent) :
statusBar()->setVisible(!hide_status_bar);
statusBar()->setStyleSheet("QStatusBar::item {border: None; } QStatusBar QLabel { margin-right: 2px; margin-bottom: 1px; }");
ui->toolBar->setVisible(!hide_tool_bar);
renderers[0].reset(nullptr);
auto toolbar_spacer = new QWidget();
toolbar_spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
ui->toolBar->addWidget(toolbar_spacer);
@@ -225,7 +228,7 @@ MainWindow::MainWindow(QWidget *parent) :
});
connect(this, &MainWindow::resizeContents, this, [this](int w, int h) {
if (!QApplication::platformName().contains("eglfs") && vid_resize == 0) {
if (!QApplication::platformName().contains("eglfs") && vid_resize != 1) {
w = (w / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.));
int modifiedHeight = (h / (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.))
@@ -238,6 +241,18 @@ MainWindow::MainWindow(QWidget *parent) :
}
});
connect(this, &MainWindow::resizeContentsMonitor, this, [this](int w, int h, int monitor_index)
{
if (!QApplication::platformName().contains("eglfs") && vid_resize != 1) {
qDebug() << "Resize";
w = (w / (!dpi_scale ? util::screenOfWidget(renderers[monitor_index].get())->devicePixelRatio() : 1.));
int modifiedHeight = (h / (!dpi_scale ? util::screenOfWidget(renderers[monitor_index].get())->devicePixelRatio() : 1.));
renderers[monitor_index]->setFixedSize(w, modifiedHeight);
}
});
connect(ui->menubar, &QMenuBar::triggered, this, [this] {
config_save();
if (QApplication::activeWindow() == this)
@@ -263,6 +278,7 @@ MainWindow::MainWindow(QWidget *parent) :
ui->actionHiDPI_scaling->setChecked(dpi_scale);
ui->actionHide_status_bar->setChecked(hide_status_bar);
ui->actionHide_tool_bar->setChecked(hide_tool_bar);
ui->actionShow_non_primary_monitors->setChecked(show_second_monitors);
ui->actionUpdate_status_bar_icons->setChecked(update_icons);
ui->actionEnable_Discord_integration->setChecked(enable_discord);
@@ -305,27 +321,33 @@ MainWindow::MainWindow(QWidget *parent) :
connect(actGroup, &QActionGroup::triggered, [this](QAction* action) {
vid_api = action->property("vid_api").toInt();
RendererStack::Renderer newVidApi = RendererStack::Renderer::Software;
switch (vid_api)
{
case 0:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software);
newVidApi = RendererStack::Renderer::Software;
break;
case 1:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL);
newVidApi = (RendererStack::Renderer::OpenGL);
break;
case 2:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGLES);
newVidApi = (RendererStack::Renderer::OpenGLES);
break;
case 3:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL3);
newVidApi = (RendererStack::Renderer::OpenGL3);
break;
case 4:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Vulkan);
newVidApi = (RendererStack::Renderer::Vulkan);
break;
case 5:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Direct3D9);
newVidApi = (RendererStack::Renderer::Direct3D9);
break;
}
ui->stackedWidget->switchRenderer(newVidApi);
if (!show_second_monitors) return;
for (int i = 1; i < MONITORS_NUM; i++) {
if (renderers[i]) renderers[i]->switchRenderer(newVidApi);
}
});
connect(ui->stackedWidget, &RendererStack::rendererChanged, [this]() {
@@ -495,6 +517,11 @@ MainWindow::MainWindow(QWidget *parent) :
#endif
setContextMenuPolicy(Qt::PreventContextMenu);
connect(this, &MainWindow::initRendererMonitor, this, &MainWindow::initRendererMonitorSlot);
connect(this, &MainWindow::initRendererMonitorForNonQtThread, this, &MainWindow::initRendererMonitorSlot, Qt::BlockingQueuedConnection);
connect(this, &MainWindow::destroyRendererMonitor, this, &MainWindow::destroyRendererMonitorSlot);
connect(this, &MainWindow::destroyRendererMonitorForNonQtThread, this, &MainWindow::destroyRendererMonitorSlot, Qt::BlockingQueuedConnection);
}
void MainWindow::closeEvent(QCloseEvent *event) {
@@ -527,18 +554,74 @@ void MainWindow::closeEvent(QCloseEvent *event) {
window_x = this->geometry().x();
window_y = this->geometry().y();
}
for (int i = 1; i < MONITORS_NUM; i++) {
if (renderers[i]) {
monitor_settings[i].mon_window_w = renderers[i]->geometry().width();
monitor_settings[i].mon_window_h = renderers[i]->geometry().height();
if (!QApplication::platformName().contains("wayland")) continue;
monitor_settings[i].mon_window_x = renderers[i]->geometry().x();
monitor_settings[i].mon_window_y = renderers[i]->geometry().y();
}
}
}
qt_nvr_save();
config_save();
if (ui->stackedWidget->mouse_exit_func)
ui->stackedWidget->mouse_exit_func();
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software);
qt_nvr_save();
config_save();
QApplication::processEvents();
cpu_thread_run = 0;
event->accept();
}
void MainWindow::initRendererMonitorSlot(int monitor_index)
{
auto& secondaryRenderer = this->renderers[monitor_index];
secondaryRenderer.reset(new RendererStack(nullptr, monitor_index));
if (secondaryRenderer) {
connect(this, &MainWindow::pollMouse, secondaryRenderer.get(), &RendererStack::mousePoll, Qt::DirectConnection);
connect(secondaryRenderer.get(), &RendererStack::rendererChanged, this, [this, monitor_index]
{
this->renderers[monitor_index]->show();
});
secondaryRenderer->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
secondaryRenderer->setWindowTitle(QObject::tr("86Box Monitor #") + QString::number(monitor_index + 1));
if (vid_resize == 2) {
secondaryRenderer->setFixedSize(fixed_size_x, fixed_size_y);
}
secondaryRenderer->setWindowIcon(this->windowIcon());
if (show_second_monitors) {
secondaryRenderer->show();
if (window_remember) {
secondaryRenderer->setGeometry(monitor_settings[monitor_index].mon_window_x < 120 ? 120 : monitor_settings[monitor_index].mon_window_x,
monitor_settings[monitor_index].mon_window_y < 120 ? 120 : monitor_settings[monitor_index].mon_window_y,
monitor_settings[monitor_index].mon_window_w > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_w,
monitor_settings[monitor_index].mon_window_h > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_h);
}
secondaryRenderer->switchRenderer((RendererStack::Renderer)vid_api);
}
}
}
void MainWindow::destroyRendererMonitorSlot(int monitor_index)
{
if (this->renderers[monitor_index]) {
if (window_remember) {
monitor_settings[monitor_index].mon_window_w = renderers[monitor_index]->geometry().width();
monitor_settings[monitor_index].mon_window_h = renderers[monitor_index]->geometry().height();
monitor_settings[monitor_index].mon_window_x = renderers[monitor_index]->geometry().x();
monitor_settings[monitor_index].mon_window_y = renderers[monitor_index]->geometry().y();
}
config_save();
this->renderers[monitor_index].release()->deleteLater();
}
}
MainWindow::~MainWindow() {
delete ui;
}
@@ -546,6 +629,7 @@ MainWindow::~MainWindow() {
void MainWindow::showEvent(QShowEvent *event) {
if (shownonce) return;
shownonce = true;
if (window_remember) resize(window_w, window_h + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height()));
if (window_remember && !QApplication::platformName().contains("wayland")) {
setGeometry(window_x, window_y, window_w, window_h + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height()));
}
@@ -555,15 +639,8 @@ void MainWindow::showEvent(QShowEvent *event) {
+ (hide_status_bar ? 0 : statusBar()->height())
+ (hide_tool_bar ? 0 : ui->toolBar->height()));
scrnsz_x = fixed_size_x;
scrnsz_y = fixed_size_y;
}
else if (window_remember && vid_resize == 1) {
ui->stackedWidget->setFixedSize(window_w, window_h);
adjustSize();
ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
scrnsz_x = window_w;
scrnsz_y = window_h;
monitors[0].mon_scrnsz_x = fixed_size_x;
monitors[0].mon_scrnsz_y = fixed_size_y;
}
}
@@ -1361,7 +1438,7 @@ void MainWindow::on_actionFullscreen_triggered() {
+ (!hide_status_bar ? statusBar()->height() : 0)
+ (!hide_tool_bar ? ui->toolBar->height() : 0));
emit resizeContents(scrnsz_x, scrnsz_y);
emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
}
} else {
if (video_fullscreen_first)
@@ -1495,9 +1572,13 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
event->accept();
}
void MainWindow::blitToWidget(int x, int y, int w, int h)
void MainWindow::blitToWidget(int x, int y, int w, int h, int monitor_index)
{
ui->stackedWidget->blit(x, y, w, h);
if (monitor_index >= 1) {
if (renderers[monitor_index]) renderers[monitor_index]->blit(x, y, w, h);
else video_blit_complete_monitor(monitor_index);
}
else ui->stackedWidget->blit(x, y, w, h);
}
void MainWindow::keyReleaseEvent(QKeyEvent* event)
@@ -1536,16 +1617,34 @@ void MainWindow::on_actionResizable_window_triggered(bool checked) {
setWindowFlag(Qt::WindowMaximizeButtonHint);
setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, false);
setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
for (int i = 1; i < MONITORS_NUM; i++) {
if (monitors[i].target_buffer) {
renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint);
renderers[i]->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
}
}
} else {
vid_resize = 0;
setWindowFlag(Qt::WindowMaximizeButtonHint, false);
setWindowFlag(Qt::MSWindowsFixedSizeDialogHint);
for (int i = 1; i < MONITORS_NUM; i++) {
if (monitors[i].target_buffer) {
renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint, false);
emit resizeContentsMonitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i);
}
}
}
show();
ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api);
ui->menuWindow_scale_factor->setEnabled(! checked);
emit resizeContents(scrnsz_x, scrnsz_y);
emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api);
for (int i = 1; i < MONITORS_NUM; i++) {
if (monitors[i].target_buffer && show_second_monitors) {
renderers[i]->show();
renderers[i]->switchRenderer((RendererStack::Renderer)vid_api);
QApplication::processEvents();
}
}
}
static void
@@ -1558,6 +1657,9 @@ video_toggle_option(QAction* action, int *val)
endblit();
config_save();
device_force_redraw();
for (int i = 0; i < MONITORS_NUM; i++) {
if (monitors[i].target_buffer) video_force_resize_set_monitor(1, i);
}
}
void MainWindow::on_actionInverted_VGA_monitor_triggered() {
@@ -1572,8 +1674,9 @@ static void update_scaled_checkboxes(Ui::MainWindow* ui, QAction* selected) {
reset_screen_size();
device_force_redraw();
video_force_resize_set(1);
atomic_flag_clear(&doresize);
for (int i = 0; i < MONITORS_NUM; i++) {
if (monitors[i].target_buffer) video_force_resize_set_monitor(1, i);
}
config_save();
}
@@ -1752,7 +1855,6 @@ void MainWindow::on_actionChange_contrast_for_monochrome_display_triggered() {
void MainWindow::on_actionForce_4_3_display_ratio_triggered() {
video_toggle_option(ui->actionForce_4_3_display_ratio, &force_43);
video_force_resize_set(1);
}
void MainWindow::on_actionRemember_size_and_position_triggered()
@@ -1764,6 +1866,14 @@ void MainWindow::on_actionRemember_size_and_position_triggered()
window_x = geometry().x();
window_y = geometry().y();
}
for (int i = 1; i < MONITORS_NUM; i++) {
if (window_remember && renderers[i]) {
monitor_settings[i].mon_window_w = renderers[i]->geometry().width();
monitor_settings[i].mon_window_h = renderers[i]->geometry().height();
monitor_settings[i].mon_window_x = renderers[i]->geometry().x();
monitor_settings[i].mon_window_y = renderers[i]->geometry().y();
}
}
ui->actionRemember_size_and_position->setChecked(window_remember);
}
@@ -1778,7 +1888,10 @@ void MainWindow::on_actionHiDPI_scaling_triggered()
{
dpi_scale ^= 1;
ui->actionHiDPI_scaling->setChecked(dpi_scale);
emit resizeContents(scrnsz_x, scrnsz_y);
emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
for (int i = 1; i < MONITORS_NUM; i++) {
if (renderers[i]) emit resizeContentsMonitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i);
}
}
void MainWindow::on_actionHide_status_bar_triggered()
@@ -1794,7 +1907,7 @@ void MainWindow::on_actionHide_status_bar_triggered()
} else {
int vid_resize_orig = vid_resize;
vid_resize = 0;
emit resizeContents(scrnsz_x, scrnsz_y);
emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
vid_resize = vid_resize_orig;
}
}
@@ -1812,7 +1925,7 @@ void MainWindow::on_actionHide_tool_bar_triggered()
} else {
int vid_resize_orig = vid_resize;
vid_resize = 0;
emit resizeContents(scrnsz_x, scrnsz_y);
emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
vid_resize = vid_resize_orig;
}
}
@@ -1826,7 +1939,8 @@ void MainWindow::on_actionUpdate_status_bar_icons_triggered()
void MainWindow::on_actionTake_screenshot_triggered()
{
startblit();
screenshots++;
for (int i = 0; i < MONITORS_NUM; i++)
monitors[i].mon_screenshots++;
endblit();
device_force_redraw();
}
@@ -1892,8 +2006,13 @@ void MainWindow::on_actionRenderer_options_triggered()
{
auto dlg = ui->stackedWidget->getOptions(this);
if (dlg)
dlg->exec();
if (dlg) {
if (dlg->exec() == QDialog::Accepted) {
for (int i = 1; i < MONITORS_NUM; i++) {
if (renderers[i] && renderers[i]->hasOptions()) renderers[i]->reloadOptions();
}
}
}
}
void MainWindow::on_actionMCA_devices_triggered()
@@ -1904,3 +2023,36 @@ void MainWindow::on_actionMCA_devices_triggered()
dlg->exec();
}
void MainWindow::on_actionShow_non_primary_monitors_triggered()
{
show_second_monitors ^= 1;
if (show_second_monitors) {
for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) {
auto& secondaryRenderer = renderers[monitor_index];
if (!renderers[monitor_index]) continue;
secondaryRenderer->show();
if (window_remember) {
secondaryRenderer->setGeometry(monitor_settings[monitor_index].mon_window_x < 120 ? 120 : monitor_settings[monitor_index].mon_window_x,
monitor_settings[monitor_index].mon_window_y < 120 ? 120 : monitor_settings[monitor_index].mon_window_y,
monitor_settings[monitor_index].mon_window_w > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_w,
monitor_settings[monitor_index].mon_window_h > 2048 ? 2048 : monitor_settings[monitor_index].mon_window_h);
}
secondaryRenderer->switchRenderer((RendererStack::Renderer)vid_api);
}
} else {
for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) {
auto& secondaryRenderer = renderers[monitor_index];
if (!renderers[monitor_index]) continue;
secondaryRenderer->hide();
if (window_remember && renderers[monitor_index]) {
monitor_settings[monitor_index].mon_window_w = renderers[monitor_index]->geometry().width();
monitor_settings[monitor_index].mon_window_h = renderers[monitor_index]->geometry().height();
monitor_settings[monitor_index].mon_window_x = renderers[monitor_index]->geometry().x();
monitor_settings[monitor_index].mon_window_y = renderers[monitor_index]->geometry().y();
}
}
}
}

View File

@@ -9,6 +9,7 @@
#include <memory>
class MediaMenu;
class RendererStack;
namespace Ui {
class MainWindow;
@@ -26,12 +27,13 @@ public:
void showMessage(int flags, const QString& header, const QString& message);
void getTitle(wchar_t* title);
void blitToWidget(int x, int y, int w, int h);
void blitToWidget(int x, int y, int w, int h, int monitor_index);
QSize getRenderWidgetSize();
void setSendKeyboardInput(bool enabled);
signals:
void paint(const QImage& image);
void resizeContents(int w, int h);
void resizeContentsMonitor(int w, int h, int monitor_index);
void pollMouse();
void statusBarMessage(const QString& msg);
void updateStatusBarPanes();
@@ -40,6 +42,10 @@ signals:
void updateStatusBarTip(int tag);
void updateMenuResizeOptions();
void updateWindowRememberOption();
void initRendererMonitor(int monitor_index);
void destroyRendererMonitor(int monitor_index);
void initRendererMonitorForNonQtThread(int monitor_index);
void destroyRendererMonitorForNonQtThread(int monitor_index);
void setTitle(const QString& title);
void setFullscreen(bool state);
@@ -51,6 +57,8 @@ public slots:
void showSettings();
void hardReset();
void togglePause();
void initRendererMonitorSlot(int monitor_index);
void destroyRendererMonitorSlot(int monitor_index);
private slots:
void on_actionFullscreen_triggered();
void on_actionSettings_triggered();
@@ -115,9 +123,13 @@ protected:
void closeEvent(QCloseEvent* event) override;
void changeEvent(QEvent* event) override;
private slots:
void on_actionShow_non_primary_monitors_triggered();
private:
Ui::MainWindow *ui;
std::unique_ptr<MachineStatus> status;
std::array<std::unique_ptr<RendererStack>, 8> renderers;
std::shared_ptr<MediaMenu> mm;
#ifdef Q_OS_MACOS

View File

@@ -54,7 +54,7 @@
<x>0</x>
<y>0</y>
<width>724</width>
<height>21</height>
<height>23</height>
</rect>
</property>
<widget class="QMenu" name="menuAction">
@@ -161,6 +161,7 @@
<addaction name="actionHide_tool_bar"/>
<addaction name="actionHide_status_bar"/>
<addaction name="separator"/>
<addaction name="actionShow_non_primary_monitors"/>
<addaction name="actionResizable_window"/>
<addaction name="actionRemember_size_and_position"/>
<addaction name="separator"/>
@@ -757,6 +758,14 @@
<number>5</number>
</property>
</action>
<action name="actionShow_non_primary_monitors">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Show non-primary monitors</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@@ -29,6 +29,7 @@
OpenGLRenderer::OpenGLRenderer(QWidget *parent)
: QWindow(parent->windowHandle())
, renderTimer(new QTimer(this))
, options(nullptr)
{
renderTimer->setTimerType(Qt::PreciseTimer);
/* TODO: need's more accuracy, maybe target 1ms earlier and spin yield */
@@ -165,9 +166,7 @@ OpenGLRenderer::initialize()
glTexImage2D(GL_TEXTURE_2D, 0, QOpenGLTexture::RGBA8_UNorm, INIT_WIDTH, INIT_HEIGHT, 0, QOpenGLTexture::BGRA, QOpenGLTexture::UInt32_RGBA8_Rev, NULL);
options = new OpenGLOptions(this, true, glslVersion);
applyOptions();
reloadOptions();
glClearColor(0.f, 0.f, 0.f, 1.f);
@@ -304,6 +303,15 @@ OpenGLRenderer::applyOptions()
currentFilter = options->filter();
}
void
OpenGLRenderer::reloadOptions()
{
if (options) { delete options; options = nullptr; }
options = new OpenGLOptions(this, true, glslVersion);
applyOptions();
}
void
OpenGLRenderer::applyShader(const OpenGLShaderPass &shader)
{

View File

@@ -53,6 +53,7 @@ public:
void finalize() override final;
bool hasOptions() const override { return true; }
QDialog *getOptions(QWidget *parent) override;
void reloadOptions() override;
signals:
void initialized();

View File

@@ -52,7 +52,7 @@ extern MainWindow* main_window;
QElapsedTimer elapsed_timer;
static std::atomic_int blitmx_contention = 0;
static std::mutex blitmx;
static std::recursive_mutex blitmx;
class CharPointer {
public:

View File

@@ -28,6 +28,8 @@ public:
virtual bool hasOptions() const { return false; }
/* Returns options dialog for renderer */
virtual QDialog *getOptions(QWidget *parent) { return nullptr; }
/* Reloads options of renderer */
virtual void reloadOptions() {}
virtual bool hasBlitFunc() { return false; }
virtual void blit(int x, int y, int w, int h) {}

View File

@@ -44,6 +44,7 @@
#endif
extern "C" {
#include <86box/86box.h>
#include <86box/mouse.h>
#include <86box/plat.h>
#include <86box/video.h>
@@ -51,14 +52,21 @@ extern "C" {
double mouse_sensitivity = 1.0;
}
struct mouseinputdata {
int deltax, deltay, deltaz;
int mousebuttons;
};
static mouseinputdata mousedata;
extern "C" void macos_poll_mouse();
extern MainWindow *main_window;
RendererStack::RendererStack(QWidget *parent)
RendererStack::RendererStack(QWidget *parent, int monitor_index)
: QStackedWidget(parent)
, ui(new Ui::RendererStack)
{
ui->setupUi(this);
m_monitor_index = monitor_index;
#if defined __unix__ && !defined __HAIKU__
char *mouse_type = getenv("EMU86BOX_MOUSE"), auto_mouse_type[16];
if (!mouse_type || (mouse_type[0] == '\0') || !stricmp(mouse_type, "auto")) {
@@ -313,7 +321,7 @@ RendererStack::createRenderer(Renderer renderer)
case Renderer::Direct3D9:
{
this->createWinId();
auto hw = new D3D9Renderer(this);
auto hw = new D3D9Renderer(this, m_monitor_index);
rendererWindow = hw;
connect(hw, &D3D9Renderer::error, this, [this](QString str)
{
@@ -398,14 +406,14 @@ RendererStack::createRenderer(Renderer renderer)
void
RendererStack::blitDummy(int x, int y, int w, int h)
{
video_blit_complete();
video_blit_complete_monitor(m_monitor_index);
blitDummied = true;
}
void
RendererStack::blitRenderer(int x, int y, int w, int h)
{
if (blitDummied) { blitDummied = false; video_blit_complete(); return; }
if (blitDummied) { blitDummied = false; video_blit_complete_monitor(m_monitor_index); return; }
directBlitting = true;
rendererWindow->blit(x, y, w, h);
directBlitting = false;
@@ -415,8 +423,8 @@ RendererStack::blitRenderer(int x, int y, int w, int h)
void
RendererStack::blitCommon(int x, int y, int w, int h)
{
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || imagebufs.empty() || std::get<std::atomic_flag *>(imagebufs[currentBuf])->test_and_set() || blitDummied) {
video_blit_complete();
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || imagebufs.empty() || std::get<std::atomic_flag *>(imagebufs[currentBuf])->test_and_set() || blitDummied) {
video_blit_complete_monitor(m_monitor_index);
return;
}
sx = x;
@@ -426,13 +434,21 @@ RendererStack::blitCommon(int x, int y, int w, int h)
uint8_t *imagebits = std::get<uint8_t *>(imagebufs[currentBuf]);
for (int y1 = y; y1 < (y + h); y1++) {
auto scanline = imagebits + (y1 * rendererWindow->getBytesPerRow()) + (x * 4);
video_copy(scanline, &(buffer32->line[y1][x]), w * 4);
video_copy(scanline, &(monitors[m_monitor_index].target_buffer->line[y1][x]), w * 4);
}
if (screenshots) {
video_screenshot((uint32_t *) imagebits, x, y, 2048);
if (monitors[m_monitor_index].mon_screenshots) {
video_screenshot_monitor((uint32_t *) imagebits, x, y, 2048, m_monitor_index);
}
video_blit_complete();
video_blit_complete_monitor(m_monitor_index);
emit blitToRenderer(currentBuf, sx, sy, sw, sh);
currentBuf = (currentBuf + 1) % imagebufs.size();
}
void RendererStack::closeEvent(QCloseEvent* event)
{
if (cpu_thread_run == 0 || is_quit == 1) { event->accept(); return; }
event->ignore();
main_window->close();
}

View File

@@ -23,7 +23,7 @@ class RendererStack : public QStackedWidget {
Q_OBJECT
public:
explicit RendererStack(QWidget *parent = nullptr);
explicit RendererStack(QWidget *parent = nullptr, int monitor_index = 0);
~RendererStack();
void mousePressEvent(QMouseEvent *event) override;
@@ -31,6 +31,7 @@ public:
void mouseMoveEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void leaveEvent(QEvent *event) override;
void closeEvent(QCloseEvent *event) override;
void keyPressEvent(QKeyEvent *event) override
{
event->ignore();
@@ -52,6 +53,8 @@ public:
/* Does current renderer implement options dialog */
bool hasOptions() const { return rendererWindow ? rendererWindow->hasOptions() : false; }
/* Reloads options of current renderer */
void reloadOptions() const { return rendererWindow->reloadOptions(); }
/* Returns options dialog for current renderer */
QDialog *getOptions(QWidget *parent) { return rendererWindow ? rendererWindow->getOptions(parent) : nullptr; }
@@ -87,16 +90,11 @@ private:
Ui::RendererStack *ui;
struct mouseinputdata {
int deltax, deltay, deltaz;
int mousebuttons;
};
mouseinputdata mousedata;
int x, y, w, h, sx, sy, sw, sh;
int currentBuf = 0;
int isMouseDown = 0;
int m_monitor_index = 0;
std::vector<std::tuple<uint8_t *, std::atomic_flag *>> imagebufs;

View File

@@ -46,6 +46,7 @@ SettingsDisplay::~SettingsDisplay()
void SettingsDisplay::save() {
gfxcard = ui->comboBoxVideo->currentData().toInt();
gfxcard_2 = ui->comboBoxVideoSecondary->currentData().toInt();
voodoo_enabled = ui->checkBoxVoodoo->isChecked() ? 1 : 0;
ibm8514_enabled = ui->checkBox8514->isChecked() ? 1 : 0;
xga_enabled = ui->checkBoxXga->isChecked() ? 1 : 0;
@@ -87,11 +88,16 @@ void SettingsDisplay::onCurrentMachineChanged(int machineId) {
if (machine_has_flags(machineId, MACHINE_VIDEO_ONLY) > 0) {
ui->comboBoxVideo->setEnabled(false);
ui->comboBoxVideoSecondary->setEnabled(false);
ui->pushButtonConfigureSecondary->setEnabled(false);
selectedRow = 1;
} else {
ui->comboBoxVideo->setEnabled(true);
ui->comboBoxVideoSecondary->setEnabled(true);
ui->pushButtonConfigureSecondary->setEnabled(true);
}
ui->comboBoxVideo->setCurrentIndex(selectedRow);
if (gfxcard_2 == 0) ui->pushButtonConfigureSecondary->setEnabled(false);
}
void SettingsDisplay::on_pushButtonConfigure_clicked() {
@@ -137,6 +143,41 @@ void SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) {
ui->checkBoxXga->setChecked(xga_enabled);
ui->pushButtonConfigureXga->setEnabled((hasIsa16 || has_MCA) && ui->checkBoxXga->isChecked());
int c = 2;
ui->comboBoxVideoSecondary->clear();
ui->comboBoxVideoSecondary->addItem(QObject::tr("None"), 0);
ui->comboBoxVideoSecondary->setCurrentIndex(0);
// TODO: Implement support for selecting non-MDA secondary cards properly when MDA cards are the primary ones.
if (video_card_get_flags(videoCard) == VIDEO_FLAG_TYPE_MDA) {
ui->comboBoxVideoSecondary->setCurrentIndex(0);
return;
}
while (true) {
const device_t* video_dev = video_card_getdevice(c);
QString name = DeviceConfig::DeviceName(video_dev, video_get_internal_name(c), 1);
if (name.isEmpty()) {
break;
}
if (video_card_available(c) &&
device_is_valid(video_dev, machineId) &&
!(video_card_get_flags(c) == video_card_get_flags(videoCard))) {
ui->comboBoxVideoSecondary->addItem(name, c);
if (c == gfxcard_2)
ui->comboBoxVideoSecondary->setCurrentIndex(ui->comboBoxVideoSecondary->count() - 1);
}
c++;
}
if (gfxcard_2 == 0 || (machine_has_flags(machineId, MACHINE_VIDEO_ONLY) > 0))
{
ui->comboBoxVideoSecondary->setCurrentIndex(0);
ui->pushButtonConfigureSecondary->setEnabled(false);
}
}
void SettingsDisplay::on_checkBoxVoodoo_stateChanged(int state) {
@@ -146,3 +187,21 @@ void SettingsDisplay::on_checkBoxVoodoo_stateChanged(int state) {
void SettingsDisplay::on_checkBoxXga_stateChanged(int state) {
ui->pushButtonConfigureXga->setEnabled(state == Qt::Checked);
}
void SettingsDisplay::on_comboBoxVideoSecondary_currentIndexChanged(int index)
{
if (index < 0) {
ui->pushButtonConfigureSecondary->setEnabled(false);
return;
}
int videoCard = ui->comboBoxVideoSecondary->currentData().toInt();
ui->pushButtonConfigureSecondary->setEnabled(index != 0 && video_card_has_config(videoCard) > 0);
}
void SettingsDisplay::on_pushButtonConfigureSecondary_clicked()
{
auto* device = video_card_getdevice(ui->comboBoxVideoSecondary->currentData().toInt());
DeviceConfig::ConfigureDevice(device, 0, qobject_cast<Settings*>(Settings::settings));
}

View File

@@ -20,6 +20,12 @@ public:
public slots:
void onCurrentMachineChanged(int machineId);
private slots:
void on_pushButtonConfigureSecondary_clicked();
private slots:
void on_comboBoxVideoSecondary_currentIndexChanged(int index);
private slots:
void on_checkBoxVoodoo_stateChanged(int state);
void on_checkBoxXga_stateChanged(int state);

View File

@@ -26,16 +26,29 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxVideo"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="checkBox8514">
<property name="text">
<string>Video:</string>
<string>8514/A</string>
</property>
</widget>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxVideo"/>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="pushButtonConfigure">
<property name="sizePolicy">
@@ -49,53 +62,57 @@
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="pushButtonConfigureVoodoo">
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxVoodoo">
<property name="text">
<string>Voodoo Graphics</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="checkBox8514">
<property name="text">
<string>8514/A</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="pushButtonConfigureXga">
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonConfigureVoodoo">
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Video:</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxXga">
<property name="text">
<string>XGA</string>
</property>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<item row="4" column="2">
<widget class="QPushButton" name="pushButtonConfigureXga">
<property name="text">
<string>Configure</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Video #2:</string>
</property>
</spacer>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBoxVideoSecondary"/>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="pushButtonConfigureSecondary">
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
</layout>
</widget>

View File

@@ -20,9 +20,12 @@
#include "qt_mainwindow.hpp"
#include "ui_qt_mainwindow.h"
#include "qt_util.hpp"
#include <QStatusBar>
#include <QMenuBar>
#include <QTimer>
#include <QScreen>
extern "C"
{
@@ -44,6 +47,11 @@ SpecifyDimensions::SpecifyDimensions(QWidget *parent) :
ui->spinBoxWidth->setValue(main_window->getRenderWidgetSize().width());
ui->spinBoxHeight->setRange(16, 2048);
ui->spinBoxHeight->setValue(main_window->getRenderWidgetSize().height());
if (dpi_scale == 0) {
ui->spinBoxWidth->setValue(main_window->getRenderWidgetSize().width() * util::screenOfWidget(main_window)->devicePixelRatio());
ui->spinBoxHeight->setValue(main_window->getRenderWidgetSize().height() * util::screenOfWidget(main_window)->devicePixelRatio());
}
}
SpecifyDimensions::~SpecifyDimensions()
@@ -62,14 +70,21 @@ void SpecifyDimensions::on_SpecifyDimensions_accepted()
fixed_size_x = ui->spinBoxWidth->value();
fixed_size_y = ui->spinBoxHeight->value();
main_window->setFixedSize(ui->spinBoxWidth->value(),
ui->spinBoxHeight->value()
+ (!hide_status_bar ? main_window->statusBar()->height() : 0)
+ (!hide_tool_bar ? main_window->ui->toolBar->height() : 0)
+ main_window->menuBar()->height());
main_window->resizeContents(fixed_size_x, fixed_size_y);
emit main_window->updateMenuResizeOptions();
main_window->show();
for (int i = 1; i < MONITORS_NUM; i++) {
if (main_window->renderers[i]) {
main_window->renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint, false);
main_window->renderers[i]->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint);
emit main_window->resizeContentsMonitor(fixed_size_x, fixed_size_y, i);
if (show_second_monitors) {
main_window->renderers[i]->show();
main_window->renderers[i]->switchRenderer((RendererStack::Renderer)vid_api);
}
}
}
main_window->ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api);
}
else
@@ -83,6 +98,16 @@ void SpecifyDimensions::on_SpecifyDimensions_accepted()
window_h = ui->spinBoxHeight->value();
main_window->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
emit main_window->resizeContents(ui->spinBoxWidth->value(), ui->spinBoxHeight->value());
for (int i = 1; i < MONITORS_NUM; i++) {
if (main_window->renderers[i]) {
main_window->renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint);
main_window->renderers[i]->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, false);
emit main_window->resizeContentsMonitor(ui->spinBoxWidth->value(), ui->spinBoxHeight->value(), i);
main_window->renderers[i]->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
if (show_second_monitors) { main_window->renderers[i]->show();
main_window->renderers[i]->switchRenderer((RendererStack::Renderer)vid_api); }
}
}
vid_resize = 1;
emit main_window->updateMenuResizeOptions();
}

View File

@@ -55,17 +55,18 @@ wchar_t* ui_window_title(wchar_t* str)
return str;
}
extern "C" void qt_blit(int x, int y, int w, int h)
extern "C" void qt_blit(int x, int y, int w, int h, int monitor_index)
{
main_window->blitToWidget(x, y, w, h);
main_window->blitToWidget(x, y, w, h, monitor_index);
}
void mouse_poll() {
main_window->pollMouse();
}
void plat_resize(int w, int h) {
main_window->resizeContents(w, h);
void plat_resize_monitor(int w, int h, int monitor_index) {
if (monitor_index >= 1) main_window->resizeContentsMonitor(w, h, monitor_index);
else main_window->resizeContents(w, h);
}
void plat_setfullscreen(int on) {
@@ -98,6 +99,20 @@ int ui_msgbox_header(int flags, void *header, void* message) {
return 0;
}
void ui_init_monitor(int monitor_index) {
if (QThread::currentThread() == main_window->thread()) {
emit main_window->initRendererMonitor(monitor_index);
}
else emit main_window->initRendererMonitorForNonQtThread(monitor_index);
}
void ui_deinit_monitor(int monitor_index) {
if (QThread::currentThread() == main_window->thread()) {
emit main_window->destroyRendererMonitor(monitor_index);
}
else emit main_window->destroyRendererMonitorForNonQtThread(monitor_index);
}
int ui_msgbox(int flags, void *message) {
return ui_msgbox_header(flags, nullptr, message);
}

View File

@@ -36,6 +36,7 @@ static zwp_pointer_constraints_v1* conf_pointer_interface = nullptr;
static zwp_locked_pointer_v1* conf_pointer = nullptr;
static int rel_mouse_x = 0, rel_mouse_y = 0;
static bool wl_init_ok = false;
void rel_mouse_event(void* data, zwp_relative_pointer_v1* zwp_relative_pointer_v1, uint32_t tstmp, uint32_t tstmpl, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_real, wl_fixed_t dy_real)
{
@@ -92,15 +93,18 @@ static const struct wl_registry_listener registry_listener = {
void wl_init()
{
wl_display* display = (wl_display*)QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display");
if (display)
{
auto registry = wl_display_get_registry(display);
if (registry)
if (!wl_init_ok) {
wl_display* display = (wl_display*)QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display");
if (display)
{
wl_registry_add_listener(registry, &registry_listener, nullptr);
wl_display_roundtrip(display);
auto registry = wl_display_get_registry(display);
if (registry)
{
wl_registry_add_listener(registry, &registry_listener, nullptr);
wl_display_roundtrip(display);
}
}
wl_init_ok = true;
}
}

View File

@@ -26,6 +26,7 @@ thread_create(void (*thread_rout)(void *param), void *param)
int
thread_wait(thread_t *arg)
{
if (!arg) return 0;
auto thread = reinterpret_cast<std::thread*>(arg);
thread->join();
return 0;

View File

@@ -563,11 +563,12 @@ main_thread(void *param)
SDL_Delay(1);
/* If needed, handle a screen resize. */
if (!atomic_flag_test_and_set(&doresize) && !video_fullscreen && !is_quit) {
if (atomic_load(&doresize_monitors[0]) && !video_fullscreen && !is_quit) {
if (vid_resize & 2)
plat_resize(fixed_size_x, fixed_size_y);
else
plat_resize(scrnsz_x, scrnsz_y);
atomic_store(&doresize_monitors[0], 1);
}
}
@@ -1114,6 +1115,7 @@ void monitor_thread(void* param)
#endif
}
extern int gfxcard_2;
int main(int argc, char** argv)
{
SDL_Event event;
@@ -1127,6 +1129,7 @@ int main(int argc, char** argv)
return 6;
}
gfxcard_2 = 0;
eventthread = SDL_ThreadID();
blitmtx = SDL_CreateMutex();
if (!blitmtx)

View File

@@ -128,18 +128,18 @@ sdl_stretch(int *w, int *h, int *x, int *y)
void
sdl_blit_shim(int x, int y, int w, int h)
sdl_blit_shim(int x, int y, int w, int h, int monitor_index)
{
params.x = x;
params.y = y;
params.w = w;
params.h = h;
if (!(!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)))
if (!(!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) || (monitor_index >= 1))
video_copy(interpixels, &(buffer32->line[y][x]), h * 2048 * sizeof(uint32_t));
if (screenshots)
video_screenshot(interpixels, 0, 0, 2048);
blitreq = 1;
video_blit_complete();
video_blit_complete_monitor(monitor_index);
}
void ui_window_title_real();
@@ -516,3 +516,6 @@ wchar_t* ui_window_title(wchar_t* str)
#endif
return str;
}
void ui_init_monitor(int monitor_index) {}
void ui_deinit_monitor(int monitor_index) {}

View File

@@ -1926,8 +1926,8 @@ static void mach64_vblank_start(svga_t *svga)
svga->overlay.x = (mach64->overlay_y_x_start >> 16) & 0x7ff;
svga->overlay.y = mach64->overlay_y_x_start & 0x7ff;
svga->overlay.xsize = ((mach64->overlay_y_x_end >> 16) & 0x7ff) - svga->overlay.x;
svga->overlay.ysize = (mach64->overlay_y_x_end & 0x7ff) - svga->overlay.y;
svga->overlay.cur_xsize = ((mach64->overlay_y_x_end >> 16) & 0x7ff) - svga->overlay.x;
svga->overlay.cur_ysize = (mach64->overlay_y_x_end & 0x7ff) - svga->overlay.y;
svga->overlay.addr = mach64->buf_offset[0] & 0x3ffff8;
svga->overlay.pitch = mach64->buf_pitch[0] & 0xfff;
@@ -3050,7 +3050,7 @@ uint32_t mach64_readl(uint32_t addr, void *p)
#define DECODE_ARGB1555() \
do \
{ \
for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) \
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++) \
{ \
uint16_t dat = ((uint16_t *)src)[x]; \
\
@@ -3069,7 +3069,7 @@ uint32_t mach64_readl(uint32_t addr, void *p)
#define DECODE_RGB565() \
do \
{ \
for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) \
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++) \
{ \
uint16_t dat = ((uint16_t *)src)[x]; \
\
@@ -3088,7 +3088,7 @@ uint32_t mach64_readl(uint32_t addr, void *p)
#define DECODE_ARGB8888() \
do \
{ \
for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) \
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++) \
{ \
int b = src[0]; \
int g = src[1]; \
@@ -3102,7 +3102,7 @@ uint32_t mach64_readl(uint32_t addr, void *p)
#define DECODE_VYUY422() \
do \
{ \
for (x = 0; x < mach64->svga.overlay_latch.xsize; x += 2) \
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x += 2) \
{ \
uint8_t y1, y2; \
int8_t u, v; \
@@ -3140,7 +3140,7 @@ uint32_t mach64_readl(uint32_t addr, void *p)
#define DECODE_YVYU422() \
do \
{ \
for (x = 0; x < mach64->svga.overlay_latch.xsize; x += 2) \
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x += 2) \
{ \
uint8_t y1, y2; \
int8_t u, v; \
@@ -3217,7 +3217,7 @@ void mach64_overlay_draw(svga_t *svga, int displine)
default:
mach64_log("Unknown Mach64 scaler format %x\n", mach64->scaler_format);
/*Fill buffer with something recognisably wrong*/
for (x = 0; x < mach64->svga.overlay_latch.xsize; x++)
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++)
mach64->overlay_dat[x] = 0xff00ff;
break;
}
@@ -3225,7 +3225,7 @@ void mach64_overlay_draw(svga_t *svga, int displine)
if (overlay_cmp_mix == 2)
{
for (x = 0; x < mach64->svga.overlay_latch.xsize; x++)
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++)
{
int h = h_acc >> 12;
@@ -3238,7 +3238,7 @@ void mach64_overlay_draw(svga_t *svga, int displine)
}
else
{
for (x = 0; x < mach64->svga.overlay_latch.xsize; x++)
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++)
{
int h = h_acc >> 12;
int gr_cmp = 0, vid_cmp = 0;
@@ -3530,7 +3530,7 @@ static void *mach64_common_init(const device_t *info)
mach64_in, mach64_out,
NULL,
mach64_overlay_draw);
mach64->svga.dac_hwcursor.ysize = 64;
mach64->svga.dac_hwcursor.cur_ysize = 64;
if (info->flags & DEVICE_PCI)
mem_mapping_disable(&mach64->bios_rom.mapping);

View File

@@ -169,9 +169,9 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *
ramdac->cmd_r3 = val;
if (ramdac->type >= BT485A)
bt48x_set_bpp(ramdac, svga);
svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = (val & 4) ? 64 : 32;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = (val & 4) ? 64 : 32;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
svga->dac_addr = (svga->dac_addr & 0x00ff) | ((val & 0x03) << 8);
svga_recalctimings(svga);
break;
@@ -191,7 +191,7 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *
break;
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
index = svga->dac_addr & da_mask;
if ((ramdac->type >= BT485) && (svga->dac_hwcursor.xsize == 64))
if ((ramdac->type >= BT485) && (svga->dac_hwcursor.cur_xsize == 64))
cd = (uint8_t *) ramdac->cursor64_data;
else {
index &= 0xff;
@@ -204,19 +204,19 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *
break;
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
break;
case 0x0d: /* Cursor X High Register (RS value = 1101) */
ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8);
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
break;
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
break;
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8);
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
break;
}
@@ -318,7 +318,7 @@ bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga)
break;
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
index = (svga->dac_addr - 1) & da_mask;
if ((ramdac->type >= BT485) && (svga->dac_hwcursor.xsize == 64))
if ((ramdac->type >= BT485) && (svga->dac_hwcursor.cur_xsize == 64))
cd = (uint8_t *) ramdac->cursor64_data;
else {
index &= 0xff;
@@ -376,21 +376,21 @@ bt48x_hwcursor_draw(svga_t *svga, int displine)
/* The planes come in two parts, and each plane is 1bpp,
so a 32x32 cursor has 4 bytes per line, and a 64x64
cursor has 8 bytes per line. */
pitch = (svga->dac_hwcursor_latch.xsize >> 3); /* Bytes per line. */
pitch = (svga->dac_hwcursor_latch.cur_xsize >> 3); /* Bytes per line. */
/* A 32x32 cursor has 128 bytes per line, and a 64x64
cursor has 512 bytes per line. */
bppl = (pitch * svga->dac_hwcursor_latch.ysize); /* Bytes per plane. */
bppl = (pitch * svga->dac_hwcursor_latch.cur_ysize); /* Bytes per plane. */
mode = ramdac->cmd_r2 & 0x03;
if (svga->interlace && svga->dac_hwcursor_oddeven)
svga->dac_hwcursor_latch.addr += pitch;
if (svga->dac_hwcursor_latch.xsize == 64)
if (svga->dac_hwcursor_latch.cur_xsize == 64)
cd = (uint8_t *) ramdac->cursor64_data;
else
cd = (uint8_t *) ramdac->cursor32_data;
for (x = 0; x < svga->dac_hwcursor_latch.xsize; x += 16) {
for (x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += 16) {
dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) |
cd[svga->dac_hwcursor_latch.addr + 1];
dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) |

View File

@@ -70,7 +70,7 @@ cga_out(uint16_t addr, uint8_t val, void *p)
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old != val) {
if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x10)) {
fullchange = changeframecount;
cga->fullchange = changeframecount;
cga_recalctimings(cga);
}
}

View File

@@ -596,7 +596,7 @@ gd54xx_update_overlay(gd54xx_t *gd54xx)
svga_t *svga = &gd54xx->svga;
int bpp = svga->bpp;
svga->overlay.ysize = gd54xx->overlay.wve - gd54xx->overlay.wvs + 1;
svga->overlay.cur_ysize = gd54xx->overlay.wve - gd54xx->overlay.wvs + 1;
gd54xx->overlay.region1size = 32 * gd54xx->overlay.r1sz / bpp + (gd54xx->overlay.r1adjust * 8 / bpp);
gd54xx->overlay.region2size = 32 * gd54xx->overlay.r2sz / bpp + (gd54xx->overlay.r2adjust * 8 / bpp);
@@ -741,10 +741,10 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
svga_recalctimings(svga);
svga->hwcursor.ena = val & CIRRUS_CURSOR_SHOW;
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422)
svga->hwcursor.xsize = svga->hwcursor.ysize =
svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize =
((val & CIRRUS_CURSOR_LARGE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422)) ? 64 : 32;
else
svga->hwcursor.xsize = 32;
svga->hwcursor.cur_xsize = 32;
if ((svga->seqregs[0x12] & CIRRUS_CURSOR_LARGE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5422))
svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((svga->seqregs[0x13] & 0x3c) * 256));
@@ -1837,7 +1837,7 @@ void gd54xx_hwcursor_draw(svga_t *svga, int displine)
int x, xx, comb, b0, b1;
uint8_t dat[2];
int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
int pitch = (svga->hwcursor.xsize == 64) ? 16 : 4;
int pitch = (svga->hwcursor.cur_xsize == 64) ? 16 : 4;
uint32_t bgcol = gd54xx->extpallook[0x00];
uint32_t fgcol = gd54xx->extpallook[0x0f];
uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp;
@@ -1847,9 +1847,9 @@ void gd54xx_hwcursor_draw(svga_t *svga, int displine)
if (svga->interlace && svga->hwcursor_oddeven)
svga->hwcursor_latch.addr += pitch;
for (x = 0; x < svga->hwcursor.xsize; x += 8) {
for (x = 0; x < svga->hwcursor.cur_xsize; x += 8) {
dat[0] = svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask];
if (svga->hwcursor.xsize == 64)
if (svga->hwcursor.cur_xsize == 64)
dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x08) & svga->vram_display_mask];
else
dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x80) & svga->vram_display_mask];
@@ -1883,7 +1883,7 @@ void gd54xx_hwcursor_draw(svga_t *svga, int displine)
svga->hwcursor_latch.addr++;
}
if (svga->hwcursor.xsize == 64)
if (svga->hwcursor.cur_xsize == 64)
svga->hwcursor_latch.addr += 8;
if (svga->interlace && !svga->hwcursor_oddeven)

View File

@@ -111,7 +111,7 @@ ega_out(uint16_t addr, uint8_t val, void *p)
if (!ega->attrff) {
ega->attraddr = val & 31;
if ((val & 0x20) != ega->attr_palette_enable) {
fullchange = 3;
ega->fullchange = 3;
ega->attr_palette_enable = val & 0x20;
ega_recalctimings(ega);
}
@@ -119,13 +119,13 @@ ega_out(uint16_t addr, uint8_t val, void *p)
o = ega->attrregs[ega->attraddr & 31];
ega->attrregs[ega->attraddr & 31] = val;
if (ega->attraddr < 16)
fullchange = changeframecount;
ega->fullchange = changeframecount;
if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10) {
for (c = 0; c < 16; c++) {
if (ega->attrregs[0x10] & 0x80) ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4);
else ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4);
}
fullchange = changeframecount;
ega->fullchange = changeframecount;
}
/* Recalculate timings on change of attribute register 0x11
(overscan border color) too. */
@@ -166,7 +166,7 @@ ega_out(uint16_t addr, uint8_t val, void *p)
switch (ega->seqaddr & 0xf) {
case 1:
if (ega->scrblank && !(val & 0x20))
fullchange = 3;
ega->fullchange = 3;
ega->scrblank = (ega->scrblank & ~0x20) | (val & 0x20);
break;
case 2:
@@ -232,10 +232,10 @@ ega_out(uint16_t addr, uint8_t val, void *p)
if (old != val) {
if (ega->crtcreg < 0xe || ega->crtcreg > 0x10) {
if ((ega->crtcreg == 0xc) || (ega->crtcreg == 0xd)) {
fullchange = 3;
ega->fullchange = 3;
ega->ma_latch = ((ega->crtc[0xc] << 8) | ega->crtc[0xd]) + ((ega->crtc[8] & 0x60) >> 5);
} else {
fullchange = changeframecount;
ega->fullchange = changeframecount;
ega_recalctimings(ega);
}
}
@@ -588,11 +588,11 @@ ega_poll(void *p)
ega->cursoron = ega->blink & (16 + (16 * blink_delay));
if (!(ega->gdcreg[6] & 1) && !(ega->blink & 15))
fullchange = 2;
ega->fullchange = 2;
ega->blink = (ega->blink + 1) & 0x7f;
if (fullchange)
fullchange--;
if (ega->fullchange)
ega->fullchange--;
}
if (ega->vc == ega->vsyncstart) {
ega->dispon = 0;
@@ -773,7 +773,7 @@ ega_write(uint32_t addr, uint8_t val, void *p)
return;
if (!(ega->gdcreg[6] & 1))
fullchange = 2;
ega->fullchange = 2;
switch (ega->writemode) {
case 1:

View File

@@ -123,7 +123,7 @@ ega_render_text_40(ega_t *ega)
ega->firstline_draw = ega->displine;
ega->lastline_draw = ega->displine;
if (fullchange) {
if (ega->fullchange) {
p = &buffer32->line[ega->displine + ega->y_add][ega->x_add];
xinc = (ega->seqregs[1] & 1) ? 16 : 18;
@@ -195,7 +195,7 @@ ega_render_text_80(ega_t *ega)
ega->firstline_draw = ega->displine;
ega->lastline_draw = ega->displine;
if (fullchange) {
if (ega->fullchange) {
p = &buffer32->line[ega->displine + ega->y_add][ega->x_add];
xinc = (ega->seqregs[1] & 1) ? 8 : 9;

View File

@@ -269,7 +269,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p)
case 0x210b: case 0x211b: case 0x212b: case 0x213b:
case 0x214b: case 0x215b: case 0x216b: case 0x217b:
et4000->regs[et4000->index] = val;
svga->hwcursor.xsize = svga->hwcursor.ysize = ((et4000->regs[0xEF] & 4) || (et4000->type == ET4000W32)) ? 128 : 64;
svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = ((et4000->regs[0xEF] & 4) || (et4000->type == ET4000W32)) ? 128 : 64;
svga->hwcursor.x = et4000->regs[0xE0] | ((et4000->regs[0xE1] & 7) << 8);
svga->hwcursor.y = et4000->regs[0xE4] | ((et4000->regs[0xE5] & 7) << 8);
svga->hwcursor.ena = !!(et4000->regs[0xF7] & 0x80);
@@ -284,7 +284,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p)
}
}
if (svga->hwcursor.xsize == 128) {
if (svga->hwcursor.cur_xsize == 128) {
svga->hwcursor.xoff &= 0x7f;
svga->hwcursor.yoff &= 0x7f;
if (et4000->type > ET4000W32P_REVC) {
@@ -303,7 +303,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p)
}
svga->hwcursor.addr = (et4000->regs[0xe8] | (et4000->regs[0xe9] << 8) | ((et4000->regs[0xea] & 7) << 16)) << 2;
add2addr = svga->hwcursor.yoff * ((svga->hwcursor.xsize == 128) ? 32 : 16);
add2addr = svga->hwcursor.yoff * ((svga->hwcursor.cur_xsize == 128) ? 32 : 16);
svga->hwcursor.addr += add2addr;
return;
}
@@ -1764,8 +1764,8 @@ et4000w32p_hwcursor_draw(svga_t *svga, int displine)
et4000w32p_t *et4000 = (et4000w32p_t *)svga->p;
int x, offset, xx, xx2;
int shift = (et4000->adjust_cursor + 1);
int width = (svga->hwcursor_latch.xsize - svga->hwcursor_latch.xoff);
int pitch = (svga->hwcursor_latch.xsize == 128) ? 32 : 16;
int width = (svga->hwcursor_latch.cur_xsize - svga->hwcursor_latch.xoff);
int pitch = (svga->hwcursor_latch.cur_xsize == 128) ? 32 : 16;
int x_acc = 4;
int minus_width = 0;
uint8_t dat;

View File

@@ -66,6 +66,7 @@ hercules_out(uint16_t addr, uint8_t val, void *priv)
hercules_t *dev = (hercules_t *)priv;
uint8_t old;
VIDEO_MONITOR_PROLOGUE()
switch (addr) {
case 0x03b0:
case 0x03b2:
@@ -92,7 +93,7 @@ hercules_out(uint16_t addr, uint8_t val, void *priv)
if (old != val) {
if ((dev->crtcreg < 0xe) || (dev->crtcreg > 0x10)) {
fullchange = changeframecount;
dev->fullchange = changeframecount;
recalc_timings(dev);
}
}
@@ -146,6 +147,8 @@ hercules_out(uint16_t addr, uint8_t val, void *priv)
default:
break;
}
VIDEO_MONITOR_EPILOGUE()
}
@@ -295,6 +298,7 @@ hercules_poll(void *priv)
int drawcursor;
uint32_t *p;
VIDEO_MONITOR_PROLOGUE()
ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
if (! dev->linepos) {
@@ -516,6 +520,7 @@ hercules_poll(void *priv)
}
}
}
VIDEO_MONITOR_EPILOGUE()
}
@@ -527,6 +532,7 @@ hercules_init(const device_t *info)
dev = (hercules_t *)malloc(sizeof(hercules_t));
memset(dev, 0x00, sizeof(hercules_t));
dev->monitor_index = monitor_index_global;
overscan_x = 16;
overscan_y = 28;

View File

@@ -80,14 +80,18 @@ typedef struct {
uint16_t ma, maback;
int con, coff, cursoron;
int dispon, blink;
int vsynctime;
int vsynctime;
int vadj;
int monitor_index, prev_monitor_index;
int cols[256][2][2];
uint8_t *vram;
} herculesplus_t;
#define VIDEO_MONITOR_PROLOGUE() { dev->prev_monitor_index = monitor_index_global; monitor_index_global = dev->monitor_index; }
#define VIDEO_MONITOR_EPILOGUE() { monitor_index_global = dev->prev_monitor_index; }
static video_timings_t timing_herculesplus = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
@@ -180,7 +184,7 @@ herculesplus_in(uint16_t port, void *priv)
break;
case 0x3ba:
/* 0x50: InColor card identity */
/* 0x10: Hercules Plus card identity */
ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10;
break;
}
@@ -489,6 +493,7 @@ herculesplus_poll(void *priv)
uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
int x, oldvc, oldsc;
VIDEO_MONITOR_PROLOGUE();
if (! dev->linepos) {
timer_advance_u64(&dev->timer, dev->dispofftime);
dev->stat |= 1;
@@ -602,6 +607,8 @@ herculesplus_poll(void *priv)
if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))))
dev->con = 1;
}
VIDEO_MONITOR_EPILOGUE();
}
@@ -615,10 +622,11 @@ herculesplus_init(const device_t *info)
memset(dev, 0, sizeof(herculesplus_t));
dev->vram = (uint8_t *)malloc(0x10000); /* 64k VRAM */
dev->monitor_index = monitor_index_global;
timer_add(&dev->timer, herculesplus_poll, dev, 1);
mem_mapping_add(&dev->mapping, 0xb0000, 0x10000,
mem_mapping_add(&dev->mapping, 0xb0000, 0x08000,
herculesplus_read,NULL,NULL,
herculesplus_write,NULL,NULL,
dev->vram, MEM_MAPPING_EXTERNAL, dev);

View File

@@ -1479,7 +1479,7 @@ void
break;
}
svga->hwcursor.ysize = 32;
svga->hwcursor.cur_ysize = 32;
ht216->vram_mask = mem_size - 1;
svga->decode_mask = mem_size - 1;

View File

@@ -636,7 +636,7 @@ ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga
break;
}
svga->dac_hwcursor.addr = ramdac->smlc_part;
svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = (val & 0x04) ? 64 : 32;
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = (val & 0x04) ? 64 : 32;
svga->dac_hwcursor.ena = ((val & 0x03) != 0x00);
break;
case 0x031:
@@ -681,14 +681,14 @@ ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga
}
break;
case 0x035:
if (svga->dac_hwcursor.xsize == 64)
if (svga->dac_hwcursor.cur_xsize == 64)
ramdac->cursor_hotspot_x = (val & 0x3f);
else
ramdac->cursor_hotspot_x = (val & 0x1f);
svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x;
break;
case 0x036:
if (svga->dac_hwcursor.xsize == 64)
if (svga->dac_hwcursor.cur_xsize == 64)
ramdac->cursor_hotspot_y = (val & 0x3f);
else
ramdac->cursor_hotspot_y = (val & 0x1f);
@@ -852,7 +852,7 @@ ibm_rgb528_hwcursor_draw(svga_t *svga, int displine)
/* The planes come in one part, and each plane is 2bpp,
so a 32x32 cursor has 8 bytes per line, and a 64x64
cursor has 16 bytes per line. */
pitch = (svga->dac_hwcursor_latch.xsize >> 2); /* Bytes per line. */
pitch = (svga->dac_hwcursor_latch.cur_xsize >> 2); /* Bytes per line. */
if ((ramdac->indexed_data[0x071] & 0x20) && svga->dac_hwcursor_oddeven)
svga->dac_hwcursor_latch.addr += pitch;
@@ -861,7 +861,7 @@ ibm_rgb528_hwcursor_draw(svga_t *svga, int displine)
x_pos = offset + svga->x_add;
p = buffer32->line[y_pos];
for (x = 0; x < svga->dac_hwcursor_latch.xsize; x++) {
for (x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x++) {
if (!(x & 3))
four_pixels = ramdac->indexed_data[svga->dac_hwcursor_latch.addr];

View File

@@ -110,6 +110,8 @@ void mda_poll(void *p)
uint8_t chr, attr;
int oldsc;
int blink;
VIDEO_MONITOR_PROLOGUE()
if (!mda->linepos)
{
timer_advance_u64(&mda->timer, mda->dispofftime);
@@ -252,6 +254,7 @@ void mda_poll(void *p)
mda->con = 1;
}
}
VIDEO_MONITOR_EPILOGUE();
}
void mda_init(mda_t *mda)
@@ -278,6 +281,7 @@ void mda_init(mda_t *mda)
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
overscan_x = overscan_y = 0;
mda->monitor_index = monitor_index_global;
cga_palette = device_get_config_int("rgb_type") << 1;
if (cga_palette > 6)

View File

@@ -3250,7 +3250,7 @@ static void s3_trio64v_recalctimings(svga_t *svga)
svga->overlay.x = s3->streams.sec_x - s3->streams.pri_x;
svga->overlay.y = s3->streams.sec_y - s3->streams.pri_y;
svga->overlay.ysize = s3->streams.sec_h;
svga->overlay.cur_ysize = s3->streams.sec_h;
if (s3->streams.buffer_ctrl & 2)
svga->overlay.addr = s3->streams.sec_fb1;
@@ -7069,7 +7069,7 @@ static void *s3_init(const device_t *info)
}
}
svga->hwcursor.ysize = 64;
svga->hwcursor.cur_ysize = 64;
if (chip == S3_VISION964 && info->local != S3_ELSAWIN2KPROX_964)
svga->dac_hwcursor_draw = bt48x_hwcursor_draw;

View File

@@ -830,7 +830,7 @@ static void s3_virge_recalctimings(svga_t *svga)
svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x;
svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y;
svga->overlay.ysize = virge->streams.sec_h;
svga->overlay.cur_ysize = virge->streams.sec_h;
if (virge->streams.buffer_ctrl & 2)
svga->overlay.addr = virge->streams.sec_fb1;
@@ -3958,7 +3958,7 @@ static void *s3_virge_init(const device_t *info)
s3_virge_in, s3_virge_out,
s3_virge_hwcursor_draw,
s3_virge_overlay_draw);
virge->svga.hwcursor.ysize = 64;
virge->svga.hwcursor.cur_ysize = 64;
if (info->local == S3_VIRGE_GX2)
rom_init(&virge->bios_rom, (char *) bios_fn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);

View File

@@ -179,6 +179,7 @@ typedef struct sigma_t
int plane;
int revision;
int fullchange;
} sigma_t;
#define COMPOSITE_OLD 0
@@ -228,7 +229,7 @@ sigma_out(uint16_t addr, uint8_t val, void *p)
sigma->crtc[sigma->crtcreg] = val & crtcmask[sigma->crtcreg];
if (old != val) {
if (sigma->crtcreg < 0xe || sigma->crtcreg > 0x10) {
fullchange = changeframecount;
sigma->fullchange = changeframecount;
sigma_recalctimings(sigma);
}
}

View File

@@ -669,34 +669,34 @@ svga_poll(void *p)
if (!svga->linepos) {
if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) {
svga->hwcursor_on = svga->hwcursor.ysize - svga->hwcursor_latch.yoff;
svga->hwcursor_on = svga->hwcursor.cur_ysize - svga->hwcursor_latch.yoff;
svga->hwcursor_oddeven = 0;
}
if (svga->displine == (svga->hwcursor_latch.y + 1) && svga->hwcursor_latch.ena &&
svga->interlace) {
svga->hwcursor_on = svga->hwcursor.ysize - (svga->hwcursor_latch.yoff + 1);
svga->hwcursor_on = svga->hwcursor.cur_ysize - (svga->hwcursor_latch.yoff + 1);
svga->hwcursor_oddeven = 1;
}
if (svga->displine == svga->dac_hwcursor_latch.y && svga->dac_hwcursor_latch.ena) {
svga->dac_hwcursor_on = svga->dac_hwcursor.ysize - svga->dac_hwcursor_latch.yoff;
svga->dac_hwcursor_on = svga->dac_hwcursor.cur_ysize - svga->dac_hwcursor_latch.yoff;
svga->dac_hwcursor_oddeven = 0;
}
if (svga->displine == (svga->dac_hwcursor_latch.y + 1) && svga->dac_hwcursor_latch.ena &&
svga->interlace) {
svga->dac_hwcursor_on = svga->dac_hwcursor.ysize - (svga->dac_hwcursor_latch.yoff + 1);
svga->dac_hwcursor_on = svga->dac_hwcursor.cur_ysize - (svga->dac_hwcursor_latch.yoff + 1);
svga->dac_hwcursor_oddeven = 1;
}
if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena) {
svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff;
svga->overlay_on = svga->overlay_latch.cur_ysize - svga->overlay_latch.yoff;
svga->overlay_oddeven = 0;
}
if (svga->displine == svga->overlay_latch.y+1 && svga->overlay_latch.ena && svga->interlace) {
svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff;
svga->overlay_on = svga->overlay_latch.cur_ysize - svga->overlay_latch.yoff;
svga->overlay_oddeven = 1;
}
@@ -966,9 +966,9 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize,
svga->hwcursor_draw = hwcursor_draw;
svga->overlay_draw = overlay_draw;
svga->hwcursor.xsize = svga->hwcursor.ysize = 32;
svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = 32;
svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 32;
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 32;
svga->translate_address = NULL;
svga->ksc5601_english_font_type = 0;

View File

@@ -40,6 +40,7 @@
typedef struct {
const device_t *device;
int flags;
} VIDEO_CARD;
@@ -109,13 +110,13 @@ video_cards[] = {
{ &cpqega_device },
{ &ega_device },
{ &g2_gc205_device },
{ &hercules_device },
{ &herculesplus_device },
{ &hercules_device, VIDEO_FLAG_TYPE_MDA },
{ &herculesplus_device, VIDEO_FLAG_TYPE_MDA },
{ &incolor_device },
{ &im1024_device },
{ &iskra_ega_device },
{ &et4000_kasan_isa_device },
{ &mda_device },
{ &mda_device, VIDEO_FLAG_TYPE_MDA },
{ &genius_device },
{ &nga_device },
{ &ogc_device },
@@ -275,6 +276,10 @@ vid_table_log(const char *fmt, ...)
void
video_reset_close(void)
{
for (int i = 1; i < MONITORS_NUM; i++)
video_monitor_close(i);
monitor_index_global = 0;
video_inform(VIDEO_FLAG_TYPE_NONE, &timing_default);
was_reset = 0;
}
@@ -289,16 +294,18 @@ video_prepare(void)
fontdatksc5601 = NULL;
}
/* Reset the CGA palette. */
cga_palette = 0;
cgapal_rebuild();
/* Reset the blend. */
herc_blend = 0;
/* Do an inform on the default values, so that that there's some sane values initialized
even if the device init function does not do an inform of its own. */
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_default);
for (int i = 0; i < MONITORS_NUM; i++) {
/* Reset the CGA palette. */
if (monitors[i].mon_cga_palette) *monitors[i].mon_cga_palette = 0;
cgapal_rebuild_monitor(i);
/* Do an inform on the default values, so that that there's some sane values initialized
even if the device init function does not do an inform of its own. */
video_inform_monitor(VIDEO_FLAG_TYPE_SPECIAL, &timing_default, i);
}
}
@@ -321,6 +328,7 @@ video_reset(int card)
vid_table_log("VIDEO: reset (gfxcard=%d, internal=%d)\n",
card, machine_has_flags(machine, MACHINE_VIDEO) ? 1 : 0);
monitor_index_global = 0;
loadfont("roms/video/mda/mda.rom", 0);
/* Do not initialize internal cards here. */
@@ -334,6 +342,17 @@ video_reset(int card)
device_add(video_cards[card].device);
}
if (!(card == VID_NONE)
&& !machine_has_flags(machine, MACHINE_VIDEO_ONLY)
&& gfxcard_2 != 0
&& (video_cards[gfxcard_2].flags != video_cards[gfxcard].flags)
&& device_is_valid(video_card_getdevice(gfxcard_2), machine)) {
video_monitor_init(1);
monitor_index_global = 1;
device_add(video_cards[gfxcard_2].device);
monitor_index_global = 0;
}
/* Enable the Voodoo if configured. */
if (voodoo_enabled)
device_add(&voodoo_device);
@@ -351,6 +370,11 @@ video_card_available(int card)
return(1);
}
int
video_card_get_flags(int card)
{
return video_cards[card].flags;
}
const device_t *
video_card_getdevice(int card)

View File

@@ -503,7 +503,7 @@ tgui_out(uint16_t addr, uint8_t val, void *p)
case 0x50:
if (tgui->type >= TGUI_9440) {
svga->hwcursor.ena = !!(val & 0x80);
svga->hwcursor.xsize = svga->hwcursor.ysize = ((val & 1) ? 64 : 32);
svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = ((val & 1) ? 64 : 32);
}
break;
}
@@ -887,7 +887,7 @@ tgui_hwcursor_draw(svga_t *svga, int displine)
uint32_t dat[2];
int xx;
int offset = svga->hwcursor_latch.x + svga->hwcursor_latch.xoff;
int pitch = (svga->hwcursor_latch.xsize == 64) ? 16 : 8;
int pitch = (svga->hwcursor_latch.cur_xsize == 64) ? 16 : 8;
if (svga->interlace && svga->hwcursor_oddeven)
svga->hwcursor_latch.addr += pitch;

View File

@@ -154,9 +154,9 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t
case 0x09: /* Direct Cursor Control (RS value = 1001) */
ramdac->dcc = val;
if (ramdac->ccr & 0x80) {
svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 64;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
svga->dac_hwcursor.ena = !!(val & 0x03);
ramdac->mode = val & 0x03;
}
@@ -165,9 +165,9 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t
switch (ramdac->ind_idx) {
case 0x06: /* Indirect Cursor Control */
ramdac->ccr = val;
svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 64;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
svga->dac_hwcursor.ena = !!(val & 0x03);
ramdac->mode = val & 0x03;
break;
@@ -254,19 +254,19 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t
break;
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
break;
case 0x0d: /* Cursor X High Register (RS value = 1101) */
ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8);
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.xsize;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
break;
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
break;
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8);
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.ysize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
break;
}
@@ -464,10 +464,10 @@ tvp3026_hwcursor_draw(svga_t *svga, int displine)
/* The planes come in two parts, and each plane is 1bpp,
so a 32x32 cursor has 4 bytes per line, and a 64x64
cursor has 8 bytes per line. */
pitch = (svga->dac_hwcursor_latch.xsize >> 3); /* Bytes per line. */
pitch = (svga->dac_hwcursor_latch.cur_xsize >> 3); /* Bytes per line. */
/* A 32x32 cursor has 128 bytes per line, and a 64x64
cursor has 512 bytes per line. */
bppl = (pitch * svga->dac_hwcursor_latch.ysize); /* Bytes per plane. */
bppl = (pitch * svga->dac_hwcursor_latch.cur_ysize); /* Bytes per plane. */
mode = ramdac->mode;
if (svga->interlace && svga->dac_hwcursor_oddeven)
@@ -475,7 +475,7 @@ tvp3026_hwcursor_draw(svga_t *svga, int displine)
cd = (uint8_t *) ramdac->cursor64_data;
for (x = 0; x < svga->dac_hwcursor_latch.xsize; x += 16) {
for (x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += 16) {
dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) |
cd[svga->dac_hwcursor_latch.addr + 1];
dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) |

View File

@@ -547,12 +547,12 @@ static void banshee_recalctimings(svga_t *svga)
svga->overlay.x = voodoo->overlay.start_x;
svga->overlay.y = voodoo->overlay.start_y;
svga->overlay.xsize = voodoo->overlay.size_x;
svga->overlay.ysize = voodoo->overlay.size_y;
svga->overlay.cur_xsize = voodoo->overlay.size_x;
svga->overlay.cur_ysize = voodoo->overlay.size_y;
svga->overlay.pitch = (banshee->vidDesktopOverlayStride & VID_STRIDE_OVERLAY_MASK) >> VID_STRIDE_OVERLAY_SHIFT;
if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE)
svga->overlay.pitch *= 128*32;
if (svga->overlay.xsize <= 0 || svga->overlay.ysize <= 0)
if (svga->overlay.cur_xsize <= 0 || svga->overlay.cur_ysize <= 0)
svga->overlay.ena = 0;
if (svga->overlay.ena)
{
@@ -739,8 +739,8 @@ static void banshee_ext_outl(uint16_t addr, uint32_t val, void *p)
else
svga->hwcursor.yoff = 0;
svga->hwcursor.addr = (banshee->hwCurPatAddr & 0xfffff0) + (svga->hwcursor.yoff * 16);
svga->hwcursor.xsize = 64;
svga->hwcursor.ysize = 64;
svga->hwcursor.cur_xsize = 64;
svga->hwcursor.cur_ysize = 64;
// banshee_log("hwCurLoc %08x %i\n", val, svga->hwcursor.y);
break;
case Video_hwCurC0:
@@ -2103,7 +2103,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
OVERLAY_SAMPLE(banshee->overlay_buffer[1]);
if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE)
{
for (x = 0; x < svga->overlay_latch.xsize; x++)
for (x = 0; x < svga->overlay_latch.cur_xsize; x++)
{
unsigned int x_coeff = (src_x & 0xfffff) >> 4;
unsigned int coeffs[4] = {
@@ -2135,7 +2135,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
}
else
{
for (x = 0; x < svga->overlay_latch.xsize; x++)
for (x = 0; x < svga->overlay_latch.cur_xsize; x++)
{
uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20];
uint32_t samp1 = banshee->overlay_buffer[1][src_x >> 20];
@@ -2153,12 +2153,12 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
case VIDPROCCFG_FILTER_MODE_DITHER_4X4:
if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled)
{
uint8_t *fil = malloc((svga->overlay_latch.xsize) * 3);
uint8_t *fil3 = malloc((svga->overlay_latch.xsize) * 3);
uint8_t *fil = malloc((svga->overlay_latch.cur_xsize) * 3);
uint8_t *fil3 = malloc((svga->overlay_latch.cur_xsize) * 3);
if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) /* leilei HACK - don't know of real 4x1 hscaled behavior yet, double for now */
{
for (x=0; x<svga->overlay_latch.xsize;x++)
for (x=0; x<svga->overlay_latch.cur_xsize;x++)
{
fil[x*3] = ((banshee->overlay_buffer[0][src_x >> 20]));
fil[x*3+1] = ((banshee->overlay_buffer[0][src_x >> 20] >> 8));
@@ -2171,7 +2171,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
}
else
{
for (x=0; x<svga->overlay_latch.xsize;x++)
for (x=0; x<svga->overlay_latch.cur_xsize;x++)
{
fil[x*3] = ((banshee->overlay_buffer[0][x]));
fil[x*3+1] = ((banshee->overlay_buffer[0][x] >> 8));
@@ -2183,7 +2183,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
}
if (y % 2 == 0)
{
for (x=0; x<svga->overlay_latch.xsize;x++)
for (x=0; x<svga->overlay_latch.cur_xsize;x++)
{
fil[x*3] = banshee->voodoo->purpleline[fil[x*3+0]][0];
fil[x*3+1] = banshee->voodoo->purpleline[fil[x*3+1]][1];
@@ -2191,25 +2191,25 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
}
}
for (x=1; x<svga->overlay_latch.xsize;x++)
for (x=1; x<svga->overlay_latch.cur_xsize;x++)
{
fil3[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil[(x-1) *3]];
fil3[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil[(x-1) *3+1]];
fil3[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil[(x-1) *3+2]];
}
for (x=1; x<svga->overlay_latch.xsize;x++)
for (x=1; x<svga->overlay_latch.cur_xsize;x++)
{
fil[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil3[(x-1) *3]];
fil[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil3[(x-1) *3+1]];
fil[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil3[(x-1) *3+2]];
}
for (x=1; x<svga->overlay_latch.xsize;x++)
for (x=1; x<svga->overlay_latch.cur_xsize;x++)
{
fil3[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil[(x-1) *3]];
fil3[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil[(x-1) *3+1]];
fil3[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil[(x-1) *3+2]];
}
for (x=0; x<svga->overlay_latch.xsize;x++)
for (x=0; x<svga->overlay_latch.cur_xsize;x++)
{
fil[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil3[(x+1) *3]];
fil[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil3[(x+1) *3+1]];
@@ -2224,7 +2224,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
{
if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE)
{
for (x = 0; x < svga->overlay_latch.xsize; x++)
for (x = 0; x < svga->overlay_latch.cur_xsize; x++)
{
p[x] = banshee->overlay_buffer[0][src_x >> 20];
src_x += voodoo->overlay.vidOverlayDudx;
@@ -2232,7 +2232,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
}
else
{
for (x = 0; x < svga->overlay_latch.xsize; x++)
for (x = 0; x < svga->overlay_latch.cur_xsize; x++)
p[x] = banshee->overlay_buffer[0][x];
}
}
@@ -2241,18 +2241,18 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
case VIDPROCCFG_FILTER_MODE_DITHER_2X2:
if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled)
{
uint8_t *fil = malloc((svga->overlay_latch.xsize) * 3);
uint8_t *soak = malloc((svga->overlay_latch.xsize) * 3);
uint8_t *soak2 = malloc((svga->overlay_latch.xsize) * 3);
uint8_t *fil = malloc((svga->overlay_latch.cur_xsize) * 3);
uint8_t *soak = malloc((svga->overlay_latch.cur_xsize) * 3);
uint8_t *soak2 = malloc((svga->overlay_latch.cur_xsize) * 3);
uint8_t *samp1 = malloc((svga->overlay_latch.xsize) * 3);
uint8_t *samp2 = malloc((svga->overlay_latch.xsize) * 3);
uint8_t *samp3 = malloc((svga->overlay_latch.xsize) * 3);
uint8_t *samp4 = malloc((svga->overlay_latch.xsize) * 3);
uint8_t *samp1 = malloc((svga->overlay_latch.cur_xsize) * 3);
uint8_t *samp2 = malloc((svga->overlay_latch.cur_xsize) * 3);
uint8_t *samp3 = malloc((svga->overlay_latch.cur_xsize) * 3);
uint8_t *samp4 = malloc((svga->overlay_latch.cur_xsize) * 3);
src = &svga->vram[src_addr2 & svga->vram_mask];
OVERLAY_SAMPLE(banshee->overlay_buffer[1]);
for (x=0; x<svga->overlay_latch.xsize;x++)
for (x=0; x<svga->overlay_latch.cur_xsize;x++)
{
samp1[x*3] = ((banshee->overlay_buffer[0][x]));
samp1[x*3+1] = ((banshee->overlay_buffer[0][x] >> 8));
@@ -2289,7 +2289,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) /* 2x2 on a scaled low res */
{
for (x=0; x<svga->overlay_latch.xsize;x++)
for (x=0; x<svga->overlay_latch.cur_xsize;x++)
{
p[x] = (fil[(src_x >> 20)*3+2] << 16) | (fil[(src_x >> 20)*3+1] << 8) | fil[(src_x >> 20)*3];
src_x += voodoo->overlay.vidOverlayDudx;
@@ -2297,7 +2297,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
}
else
{
for (x=0; x<svga->overlay_latch.xsize;x++)
for (x=0; x<svga->overlay_latch.cur_xsize;x++)
{
p[x] = (fil[x*3+2] << 16) | (fil[x*3+1] << 8) | fil[x*3];
}
@@ -2315,7 +2315,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
{
if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE)
{
for (x = 0; x < svga->overlay_latch.xsize; x++)
for (x = 0; x < svga->overlay_latch.cur_xsize; x++)
{
p[x] = banshee->overlay_buffer[0][src_x >> 20];
@@ -2324,7 +2324,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
}
else
{
for (x = 0; x < svga->overlay_latch.xsize; x++)
for (x = 0; x < svga->overlay_latch.cur_xsize; x++)
p[x] = banshee->overlay_buffer[0][x];
}
}
@@ -2334,7 +2334,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
default:
if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE)
{
for (x = 0; x < svga->overlay_latch.xsize; x++)
for (x = 0; x < svga->overlay_latch.cur_xsize; x++)
{
p[x] = banshee->overlay_buffer[0][src_x >> 20];
@@ -2343,7 +2343,7 @@ static void banshee_overlay_draw(svga_t *svga, int displine)
}
else
{
for (x = 0; x < svga->overlay_latch.xsize; x++)
for (x = 0; x < svga->overlay_latch.cur_xsize; x++)
p[x] = banshee->overlay_buffer[0][x];
}
break;

View File

@@ -2048,7 +2048,7 @@ xga_hwcursor_draw(svga_t *svga, int displine)
x_pos = offset + svga->x_add;
p = buffer32->line[y_pos];
for (x = 0; x < xga->hwcursor_latch.xsize; x++) {
for (x = 0; x < xga->hwcursor_latch.cur_xsize; x++) {
if (x >= idx) {
if (!(x & 0x03))
dat = xga->sprite_data[xga->hwcursor_latch.addr & 0x3ff];
@@ -2476,13 +2476,13 @@ xga_poll(xga_t *xga, svga_t *svga)
if (!xga->linepos) {
if (xga->displine == xga->hwcursor_latch.y && xga->hwcursor_latch.ena) {
xga->hwcursor_on = xga->hwcursor_latch.ysize - (xga->cursor_data_on ? 32 : 0);
xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - (xga->cursor_data_on ? 32 : 0);
xga->hwcursor_oddeven = 0;
}
if (xga->displine == (xga->hwcursor_latch.y + 1) && xga->hwcursor_latch.ena &&
xga->interlace) {
xga->hwcursor_on = xga->hwcursor_latch.ysize - (xga->cursor_data_on ? 33 : 1);
xga->hwcursor_on = xga->hwcursor_latch.cur_ysize - (xga->cursor_data_on ? 33 : 1);
xga->hwcursor_oddeven = 1;
}
@@ -2702,8 +2702,8 @@ static void
xga->vram = calloc(xga->vram_size, 1);
xga->changedvram = calloc(xga->vram_size >> 12, 1);
xga->on = 0;
xga->hwcursor.xsize = 64;
xga->hwcursor.ysize = 64;
xga->hwcursor.cur_xsize = 64;
xga->hwcursor.cur_ysize = 64;
xga->bios_rom.sz = 0x8000;
f = rom_fopen(xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, "rb");

View File

@@ -48,6 +48,7 @@
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
*/
#include <stdatomic.h>
#define PNG_DEBUG 0
#include <png.h>
#include <stdarg.h>
@@ -68,6 +69,7 @@
#include <86box/timer.h>
#include <86box/path.h>
#include <86box/plat.h>
#include <86box/ui.h>
#include <86box/thread.h>
#include <86box/video.h>
#include <86box/vid_svga.h>
@@ -75,7 +77,7 @@
#include <minitrace/minitrace.h>
volatile int screenshots = 0;
bitmap_t *buffer32 = NULL;
//bitmap_t *buffer32 = NULL;
uint8_t fontdat[2048][8]; /* IBM CGA font */
uint8_t fontdatm[2048][16]; /* IBM MDA font */
uint8_t fontdatw[512][32]; /* Wyse700 font */
@@ -83,31 +85,15 @@ uint8_t fontdat8x12[256][16]; /* MDSI Genius font */
uint8_t fontdat12x18[256][36]; /* IM1024 font */
dbcs_font_t *fontdatksc5601 = NULL; /* Korean KSC-5601 font */
dbcs_font_t *fontdatksc5601_user = NULL; /* Korean KSC-5601 user defined font */
uint32_t pal_lookup[256];
int xsize = 1,
ysize = 1;
int cga_palette = 0,
herc_blend = 0;
int herc_blend = 0;
uint32_t *video_6to8 = NULL,
*video_8togs = NULL,
*video_8to32 = NULL,
*video_15to32 = NULL,
*video_16to32 = NULL;
int changeframecount = 2;
*video_16to32 = NULL;
int frames = 0;
int fullchange = 0;
uint8_t edatlookup[4][4];
int overscan_x = 0,
overscan_y = 0;
int video_timing_read_b = 0,
video_timing_read_w = 0,
video_timing_read_l = 0;
int video_timing_write_b = 0,
video_timing_write_w = 0,
video_timing_write_l = 0;
int video_res_x = 0,
video_res_y = 0,
video_bpp = 0;
static int video_force_resize;
int video_grayscale = 0;
int video_graytype = 0;
@@ -115,6 +101,10 @@ static int vid_type;
static const video_timings_t *vid_timings;
static uint32_t cga_2_table[16];
static uint8_t thread_run = 0;
monitor_t monitors[MONITORS_NUM];
monitor_settings_t monitor_settings[MONITORS_NUM];
atomic_bool doresize_monitors[MONITORS_NUM];
int monitor_index_global = 0;
#ifdef _WIN32
void * __cdecl (*video_copy)(void *_Dst, const void *_Src, size_t _Size) = memcpy;
@@ -251,10 +241,12 @@ const uint32_t shade[5][256] =
};
static struct {
static struct blit_data_struct {
int x, y, w, h;
int busy;
int buffer_in_use;
int thread_run;
int monitor_index;
thread_t *blit_thread;
event_t *wake_blit_thread;
@@ -263,7 +255,7 @@ static struct {
} blit_data;
static void (*blit_func)(int x, int y, int w, int h);
static void (*blit_func)(int x, int y, int w, int h, int monitor_index);
#ifdef ENABLE_VIDEO_LOG
@@ -287,7 +279,7 @@ video_log(const char *fmt, ...)
void
video_setblit(void(*blit)(int,int,int,int))
video_setblit(void(*blit)(int,int,int,int,int))
{
blit_func = blit;
}
@@ -296,41 +288,68 @@ video_setblit(void(*blit)(int,int,int,int))
void
video_blit_complete(void)
{
blit_data.buffer_in_use = 0;
thread_set_event(blit_data.buffer_not_in_use);
video_blit_complete_monitor(monitor_index_global);
}
void
video_wait_for_blit(void)
{
while (blit_data.busy)
thread_wait_event(blit_data.blit_complete, -1);
thread_reset_event(blit_data.blit_complete);
video_wait_for_blit_monitor(monitor_index_global);
}
void
video_wait_for_buffer(void)
{
while (blit_data.buffer_in_use)
thread_wait_event(blit_data.buffer_not_in_use, -1);
thread_reset_event(blit_data.buffer_not_in_use);
video_wait_for_buffer_monitor(monitor_index_global);
}
static png_structp png_ptr;
static png_infop info_ptr;
void
video_blit_complete_monitor(int monitor_index)
{
struct blit_data_struct* blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr;
blit_data_ptr->buffer_in_use = 0;
thread_set_event(blit_data_ptr->buffer_not_in_use);
}
void
video_wait_for_blit_monitor(int monitor_index)
{
struct blit_data_struct* blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr;
while (blit_data_ptr->busy)
thread_wait_event(blit_data_ptr->blit_complete, -1);
thread_reset_event(blit_data_ptr->blit_complete);
}
void
video_wait_for_buffer_monitor(int monitor_index)
{
struct blit_data_struct* blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr;
while (blit_data_ptr->buffer_in_use)
thread_wait_event(blit_data_ptr->buffer_not_in_use, -1);
thread_reset_event(blit_data_ptr->buffer_not_in_use);
}
static png_structp png_ptr[MONITORS_NUM];
static png_infop info_ptr[MONITORS_NUM];
static void
video_take_screenshot(const char *fn, uint32_t *buf, int start_x, int start_y, int row_len)
video_take_screenshot_monitor(const char *fn, uint32_t *buf, int start_x, int start_y, int row_len, int monitor_index)
{
int i, x, y;
png_bytep *b_rgb = NULL;
FILE *fp = NULL;
uint32_t temp = 0x00000000;
struct blit_data_struct* blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr;
/* create file */
fp = plat_fopen((char *) fn, (char *) "wb");
@@ -340,37 +359,37 @@ video_take_screenshot(const char *fn, uint32_t *buf, int start_x, int start_y, i
}
/* initialize stuff */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_ptr[monitor_index] = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
if (!png_ptr[monitor_index]) {
video_log("[video_take_screenshot] png_create_write_struct failed");
fclose(fp);
return;
}
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
info_ptr[monitor_index] = png_create_info_struct(png_ptr[monitor_index]);
if (!info_ptr[monitor_index]) {
video_log("[video_take_screenshot] png_create_info_struct failed");
fclose(fp);
return;
}
png_init_io(png_ptr, fp);
png_init_io(png_ptr[monitor_index], fp);
png_set_IHDR(png_ptr, info_ptr, blit_data.w, blit_data.h,
png_set_IHDR(png_ptr[monitor_index], info_ptr[monitor_index], blit_data_ptr->w, blit_data_ptr->h,
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * blit_data.h);
b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * blit_data_ptr->h);
if (b_rgb == NULL) {
video_log("[video_take_screenshot] Unable to Allocate RGB Bitmap Memory");
fclose(fp);
return;
}
for (y = 0; y < blit_data.h; ++y) {
b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr));
for (x = 0; x < blit_data.w; ++x) {
for (y = 0; y < blit_data_ptr->h; ++y) {
b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr[monitor_index], info_ptr[monitor_index]));
for (x = 0; x < blit_data_ptr->w; ++x) {
if (buf == NULL)
memset(&(b_rgb[y][x * 3]), 0x00, 3);
else {
@@ -382,14 +401,14 @@ video_take_screenshot(const char *fn, uint32_t *buf, int start_x, int start_y, i
}
}
png_write_info(png_ptr, info_ptr);
png_write_info(png_ptr[monitor_index], info_ptr[monitor_index]);
png_write_image(png_ptr, b_rgb);
png_write_image(png_ptr[monitor_index], b_rgb);
png_write_end(png_ptr, NULL);
png_write_end(png_ptr[monitor_index], NULL);
/* cleanup heap allocation */
for (i = 0; i < blit_data.h; i++)
for (i = 0; i < blit_data_ptr->h; i++)
if (b_rgb[i]) free(b_rgb[i]);
if (b_rgb) free(b_rgb);
@@ -399,9 +418,9 @@ video_take_screenshot(const char *fn, uint32_t *buf, int start_x, int start_y, i
void
video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len)
video_screenshot_monitor(uint32_t *buf, int start_x, int start_y, int row_len, int monitor_index)
{
char path[1024], fn[128];
char path[1024], fn[256];
memset(fn, 0, sizeof(fn));
memset(path, 0, sizeof(path));
@@ -409,19 +428,27 @@ video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len)
path_append_filename(path, usr_path, SCREENSHOT_PATH);
if (! plat_dir_check(path))
plat_dir_create(path);
plat_dir_create(path);
path_slash(path);
strcat(path, "Monitor_");
snprintf(&path[strlen(path)], 42, "%d_", monitor_index + 1);
plat_tempfile(fn, NULL, ".png");
strcat(path, fn);
video_log("taking screenshot to: %s\n", path);
video_take_screenshot((const char *) path, buf, start_x, start_y, row_len);
png_destroy_write_struct(&png_ptr, &info_ptr);
video_take_screenshot_monitor((const char *) path, buf, start_x, start_y, row_len, monitor_index);
png_destroy_write_struct(&png_ptr[monitor_index], &info_ptr[monitor_index]);
screenshots--;
monitors[monitor_index].mon_screenshots--;
}
void
video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len)
{
video_screenshot_monitor(buf, start_x, start_y, row_len, 0);
}
@@ -454,40 +481,48 @@ video_transform_copy(void *__restrict _Dst, const void *__restrict _Src, size_t
static
void blit_thread(void *param)
{
while (thread_run) {
thread_wait_event(blit_data.wake_blit_thread, -1);
thread_reset_event(blit_data.wake_blit_thread);
struct blit_data_struct* data = param;
while (data->thread_run) {
thread_wait_event(data->wake_blit_thread, -1);
thread_reset_event(data->wake_blit_thread);
MTR_BEGIN("video", "blit_thread");
if (blit_func)
blit_func(blit_data.x, blit_data.y, blit_data.w, blit_data.h);
blit_func(data->x, data->y, data->w, data->h, data->monitor_index);
blit_data.busy = 0;
data->busy = 0;
MTR_END("video", "blit_thread");
thread_set_event(blit_data.blit_complete);
thread_set_event(data->blit_complete);
}
}
void
video_blit_memtoscreen(int x, int y, int w, int h)
{
video_blit_memtoscreen_monitor(x, y, w, h, monitor_index_global);
}
void
video_blit_memtoscreen_monitor(int x, int y, int w, int h, int monitor_index)
{
MTR_BEGIN("video", "video_blit_memtoscreen");
if ((w <= 0) || (h <= 0))
return;
return;
video_wait_for_blit();
video_wait_for_blit_monitor(monitor_index);
blit_data.busy = 1;
blit_data.buffer_in_use = 1;
blit_data.x = x;
blit_data.y = y;
blit_data.w = w;
blit_data.h = h;
monitors[monitor_index].mon_blit_data_ptr->busy = 1;
monitors[monitor_index].mon_blit_data_ptr->buffer_in_use = 1;
monitors[monitor_index].mon_blit_data_ptr->x = x;
monitors[monitor_index].mon_blit_data_ptr->y = y;
monitors[monitor_index].mon_blit_data_ptr->w = w;
monitors[monitor_index].mon_blit_data_ptr->h = h;
thread_set_event(blit_data.wake_blit_thread);
thread_set_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread);
MTR_END("video", "video_blit_memtoscreen");
}
@@ -521,7 +556,7 @@ uint32_t pixel_to_color(uint8_t *pixels32, uint8_t pos)
void
video_blend(int x, int y)
video_blend_monitor(int x, int y, int monitor_index)
{
int xx;
uint32_t pixels32_1, pixels32_2;
@@ -529,152 +564,212 @@ video_blend(int x, int y)
static unsigned int carry = 0;
if (!herc_blend)
return;
return;
if (!x)
carry = 0;
carry = 0;
val1 = pixels8(&(buffer32->line[y][x]));
val1 = pixels8(&(monitors[monitor_index].target_buffer->line[y][x]));
val2 = (val1 >> 1) + carry;
carry = (val1 & 1) << 7;
pixels32_1 = cga_2_table[val1 >> 4] + cga_2_table[val2 >> 4];
pixels32_2 = cga_2_table[val1 & 0xf] + cga_2_table[val2 & 0xf];
for (xx = 0; xx < 4; xx++) {
buffer32->line[y][x + xx] = pixel_to_color((uint8_t *) &pixels32_1, xx);
buffer32->line[y][x + (xx | 4)] = pixel_to_color((uint8_t *) &pixels32_2, xx);
monitors[monitor_index].target_buffer->line[y][x + xx] = pixel_to_color((uint8_t *) &pixels32_1, xx);
monitors[monitor_index].target_buffer->line[y][x + (xx | 4)] = pixel_to_color((uint8_t *) &pixels32_2, xx);
}
}
void
video_blend(int x, int y)
{
video_blend_monitor(x, y, monitor_index_global);
}
void
video_blit_memtoscreen_8_monitor(int x, int y, int w, int h, int monitor_index)
{
int yy, xx;
if ((w > 0) && (h > 0)) {
for (yy = 0; yy < h; yy++) {
if ((y + yy) >= 0 && (y + yy) < monitors[monitor_index].target_buffer->h) {
for (xx = 0; xx < w; xx++) {
if (monitors[monitor_index].target_buffer->line[y + yy][x + xx] <= 0xff)
monitors[monitor_index].target_buffer->line[y + yy][x + xx] = monitors[monitor_index].mon_pal_lookup[monitors[monitor_index].target_buffer->line[y + yy][x + xx]];
else
monitors[monitor_index].target_buffer->line[y + yy][x + xx] = 0x00000000;
}
}
}
}
video_blit_memtoscreen_monitor(x, y, w, h, monitor_index);
}
void
video_blit_memtoscreen_8(int x, int y, int w, int h)
{
int yy, xx;
if ((w > 0) && (h > 0)) {
for (yy = 0; yy < h; yy++) {
if ((y + yy) >= 0 && (y + yy) < buffer32->h) {
for (xx = 0; xx < w; xx++) {
if (buffer32->line[y + yy][x + xx] <= 0xff)
buffer32->line[y + yy][x + xx] = pal_lookup[buffer32->line[y + yy][x + xx]];
else
buffer32->line[y + yy][x + xx] = 0x00000000;
}
}
}
}
video_blit_memtoscreen(x, y, w, h);
video_blit_memtoscreen_8_monitor(x, y, w, h, monitor_index_global);
}
void
cgapal_rebuild(void)
cgapal_rebuild_monitor(int monitor_index)
{
int c;
uint32_t* palette_lookup = monitors[monitor_index].mon_pal_lookup;
int cga_palette_monitor = 0;
/* We cannot do this (yet) if we have not been enabled yet. */
if (video_6to8 == NULL) return;
if (monitors[monitor_index].target_buffer == NULL ||
monitors[monitor_index].mon_cga_palette == NULL) return;
cga_palette_monitor = *monitors[monitor_index].mon_cga_palette;
for (c=0; c<256; c++) {
pal_lookup[c] = makecol(video_6to8[cgapal[c].r],
palette_lookup[c] = makecol(video_6to8[cgapal[c].r],
video_6to8[cgapal[c].g],
video_6to8[cgapal[c].b]);
}
if ((cga_palette > 1) && (cga_palette < 7)) {
if ((cga_palette_monitor > 1) && (cga_palette_monitor < 7)) {
if (vid_cga_contrast != 0) {
for (c = 0; c < 16; c++) {
pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r],
video_6to8[cgapal_mono[cga_palette - 2][c].g],
video_6to8[cgapal_mono[cga_palette - 2][c].b]);
pal_lookup[c+16] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r],
video_6to8[cgapal_mono[cga_palette - 2][c].g],
video_6to8[cgapal_mono[cga_palette - 2][c].b]);
pal_lookup[c+32] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r],
video_6to8[cgapal_mono[cga_palette - 2][c].g],
video_6to8[cgapal_mono[cga_palette - 2][c].b]);
pal_lookup[c+48] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r],
video_6to8[cgapal_mono[cga_palette - 2][c].g],
video_6to8[cgapal_mono[cga_palette - 2][c].b]);
palette_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]);
palette_lookup[c+16] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]);
palette_lookup[c+32] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]);
palette_lookup[c+48] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]);
}
} else {
for (c = 0; c < 16; c++) {
pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r],
video_6to8[cgapal_mono[cga_palette - 1][c].g],
video_6to8[cgapal_mono[cga_palette - 1][c].b]);
pal_lookup[c+16] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r],
video_6to8[cgapal_mono[cga_palette - 1][c].g],
video_6to8[cgapal_mono[cga_palette - 1][c].b]);
pal_lookup[c+32] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r],
video_6to8[cgapal_mono[cga_palette - 1][c].g],
video_6to8[cgapal_mono[cga_palette - 1][c].b]);
pal_lookup[c+48] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r],
video_6to8[cgapal_mono[cga_palette - 1][c].g],
video_6to8[cgapal_mono[cga_palette - 1][c].b]);
palette_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]);
palette_lookup[c+16] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]);
palette_lookup[c+32] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]);
palette_lookup[c+48] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]);
}
}
}
if (cga_palette == 7)
pal_lookup[0x16] = makecol(video_6to8[42],video_6to8[42],video_6to8[0]);
if (cga_palette_monitor == 7)
palette_lookup[0x16] = makecol(video_6to8[42],video_6to8[42],video_6to8[0]);
}
void
cgapal_rebuild(void)
{
cgapal_rebuild_monitor(monitor_index_global);
}
void
video_inform_monitor(int type, const video_timings_t *ptr, int monitor_index)
{
monitor_t* monitor = &monitors[monitor_index];
monitor->mon_vid_type = type;
monitor->mon_vid_timings = ptr;
}
void
video_inform(int type, const video_timings_t *ptr)
{
vid_type = type;
vid_timings = ptr;
video_inform_monitor(type, ptr, monitor_index_global);
}
int
video_get_type_monitor(int monitor_index)
{
return monitors[monitor_index].mon_vid_type;
}
int
video_get_type(void)
{
return vid_type;
return video_get_type_monitor(0);
}
void
video_update_timing(void)
{
if (!vid_timings)
return;
const video_timings_t* monitor_vid_timings = NULL;
int *vid_timing_read_b = NULL;
int *vid_timing_read_l = NULL;
int *vid_timing_read_w = NULL;
int *vid_timing_write_b = NULL;
int *vid_timing_write_l = NULL;
int *vid_timing_write_w = NULL;
int i = 0;
if (vid_timings->type == VIDEO_ISA) {
video_timing_read_b = ISA_CYCLES(vid_timings->read_b);
video_timing_read_w = ISA_CYCLES(vid_timings->read_w);
video_timing_read_l = ISA_CYCLES(vid_timings->read_l);
video_timing_write_b = ISA_CYCLES(vid_timings->write_b);
video_timing_write_w = ISA_CYCLES(vid_timings->write_w);
video_timing_write_l = ISA_CYCLES(vid_timings->write_l);
} else if (vid_timings->type == VIDEO_PCI) {
video_timing_read_b = (int)(pci_timing * vid_timings->read_b);
video_timing_read_w = (int)(pci_timing * vid_timings->read_w);
video_timing_read_l = (int)(pci_timing * vid_timings->read_l);
video_timing_write_b = (int)(pci_timing * vid_timings->write_b);
video_timing_write_w = (int)(pci_timing * vid_timings->write_w);
video_timing_write_l = (int)(pci_timing * vid_timings->write_l);
} else if (vid_timings->type == VIDEO_AGP) {
video_timing_read_b = (int)(agp_timing * vid_timings->read_b);
video_timing_read_w = (int)(agp_timing * vid_timings->read_w);
video_timing_read_l = (int)(agp_timing * vid_timings->read_l);
video_timing_write_b = (int)(agp_timing * vid_timings->write_b);
video_timing_write_w = (int)(agp_timing * vid_timings->write_w);
video_timing_write_l = (int)(agp_timing * vid_timings->write_l);
} else {
video_timing_read_b = (int)(bus_timing * vid_timings->read_b);
video_timing_read_w = (int)(bus_timing * vid_timings->read_w);
video_timing_read_l = (int)(bus_timing * vid_timings->read_l);
video_timing_write_b = (int)(bus_timing * vid_timings->write_b);
video_timing_write_w = (int)(bus_timing * vid_timings->write_w);
video_timing_write_l = (int)(bus_timing * vid_timings->write_l);
}
for (i = 0; i < MONITORS_NUM; i++) {
monitor_vid_timings = monitors[i].mon_vid_timings;
if (!monitor_vid_timings)
continue;
vid_timing_read_b = &monitors[i].mon_video_timing_read_b;
vid_timing_read_l = &monitors[i].mon_video_timing_read_l;
vid_timing_read_w = &monitors[i].mon_video_timing_read_w;
vid_timing_write_b = &monitors[i].mon_video_timing_write_b;
vid_timing_write_l = &monitors[i].mon_video_timing_write_l;
vid_timing_write_w = &monitors[i].mon_video_timing_write_w;
if (cpu_16bitbus) {
video_timing_read_l = video_timing_read_w * 2;
video_timing_write_l = video_timing_write_w * 2;
if (monitor_vid_timings->type == VIDEO_ISA) {
*vid_timing_read_b = ISA_CYCLES(monitor_vid_timings->read_b);
*vid_timing_read_w = ISA_CYCLES(monitor_vid_timings->read_w);
*vid_timing_read_l = ISA_CYCLES(monitor_vid_timings->read_l);
*vid_timing_write_b = ISA_CYCLES(monitor_vid_timings->write_b);
*vid_timing_write_w = ISA_CYCLES(monitor_vid_timings->write_w);
*vid_timing_write_l = ISA_CYCLES(monitor_vid_timings->write_l);
} else if (monitor_vid_timings->type == VIDEO_PCI) {
*vid_timing_read_b = (int)(pci_timing * monitor_vid_timings->read_b);
*vid_timing_read_w = (int)(pci_timing * monitor_vid_timings->read_w);
*vid_timing_read_l = (int)(pci_timing * monitor_vid_timings->read_l);
*vid_timing_write_b = (int)(pci_timing * monitor_vid_timings->write_b);
*vid_timing_write_w = (int)(pci_timing * monitor_vid_timings->write_w);
*vid_timing_write_l = (int)(pci_timing * monitor_vid_timings->write_l);
} else if (monitor_vid_timings->type == VIDEO_AGP) {
*vid_timing_read_b = (int)(agp_timing * monitor_vid_timings->read_b);
*vid_timing_read_w = (int)(agp_timing * monitor_vid_timings->read_w);
*vid_timing_read_l = (int)(agp_timing * monitor_vid_timings->read_l);
*vid_timing_write_b = (int)(agp_timing * monitor_vid_timings->write_b);
*vid_timing_write_w = (int)(agp_timing * monitor_vid_timings->write_w);
*vid_timing_write_l = (int)(agp_timing * monitor_vid_timings->write_l);
} else {
*vid_timing_read_b = (int)(bus_timing * monitor_vid_timings->read_b);
*vid_timing_read_w = (int)(bus_timing * monitor_vid_timings->read_w);
*vid_timing_read_l = (int)(bus_timing * monitor_vid_timings->read_l);
*vid_timing_write_b = (int)(bus_timing * monitor_vid_timings->write_b);
*vid_timing_write_w = (int)(bus_timing * monitor_vid_timings->write_w);
*vid_timing_write_l = (int)(bus_timing * monitor_vid_timings->write_l);
}
if (cpu_16bitbus) {
*vid_timing_read_l = *vid_timing_read_w * 2;
*vid_timing_write_l = *vid_timing_write_w * 2;
}
}
}
@@ -762,7 +857,7 @@ hline(bitmap_t *b, int x1, int y, int x2, uint32_t col)
{
int x;
if (y < 0 || y >= buffer32->h)
if (y < 0 || y >= b->h)
return;
for (x = x1; x < x2; x++)
@@ -820,6 +915,55 @@ create_bitmap(int x, int y)
return(b);
}
void
video_monitor_init(int index)
{
memset(&monitors[index], 0, sizeof(monitor_t));
monitors[index].mon_xsize = 640;
monitors[index].mon_ysize = 480;
monitors[index].mon_res_x = 640;
monitors[index].mon_res_y = 480;
monitors[index].mon_scrnsz_x = 640;
monitors[index].mon_scrnsz_y = 480;
monitors[index].mon_efscrnsz_y = 480;
monitors[index].mon_unscaled_size_x = 480;
monitors[index].mon_unscaled_size_y = 480;
monitors[index].mon_bpp = 8;
monitors[index].mon_changeframecount = 2;
monitors[index].target_buffer = create_bitmap(2048, 2048);
monitors[index].mon_blit_data_ptr = calloc(1, sizeof(struct blit_data_struct));
monitors[index].mon_blit_data_ptr->wake_blit_thread = thread_create_event();
monitors[index].mon_blit_data_ptr->blit_complete = thread_create_event();
monitors[index].mon_blit_data_ptr->buffer_not_in_use = thread_create_event();
monitors[index].mon_blit_data_ptr->thread_run = 1;
monitors[index].mon_blit_data_ptr->monitor_index = index;
monitors[index].mon_pal_lookup = calloc(sizeof(uint32_t), 256);
monitors[index].mon_cga_palette = calloc(1, sizeof(int));
monitors[index].mon_force_resize = 1;
monitors[index].mon_vid_type = VIDEO_FLAG_TYPE_NONE;
atomic_init(&doresize_monitors[index], 0);
if (index >= 1) ui_init_monitor(index);
monitors[index].mon_blit_data_ptr->blit_thread = thread_create(blit_thread, monitors[index].mon_blit_data_ptr);
}
void
video_monitor_close(int monitor_index)
{
if (monitors[monitor_index].target_buffer == NULL) { return; }
monitors[monitor_index].mon_blit_data_ptr->thread_run = 0;
thread_set_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread);
thread_wait(monitors[monitor_index].mon_blit_data_ptr->blit_thread);
if (monitor_index >= 1) ui_deinit_monitor(monitor_index);
thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->buffer_not_in_use);
thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->blit_complete);
thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread);
free(monitors[monitor_index].mon_blit_data_ptr);
if (!monitors[monitor_index].mon_pal_lookup_static) free(monitors[monitor_index].mon_pal_lookup);
if (!monitors[monitor_index].mon_cga_palette_static) free(monitors[monitor_index].mon_cga_palette);
destroy_bitmap(monitors[monitor_index].target_buffer);
monitors[monitor_index].target_buffer = NULL;
memset(&monitors[monitor_index], 0, sizeof(monitor_t));
}
void
video_init(void)
@@ -832,9 +976,6 @@ video_init(void)
(total[(c >> 1) & 1] << 16) | (total[(c >> 0) & 1] << 24);
}
/* Account for overscan. */
buffer32 = create_bitmap(2048, 2048);
for (c = 0; c < 64; c++) {
cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
cgapal[c + 64].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
@@ -878,23 +1019,15 @@ video_init(void)
for (c = 0; c < 65536; c++)
video_16to32[c] = calc_16to32(c);
blit_data.wake_blit_thread = thread_create_event();
blit_data.blit_complete = thread_create_event();
blit_data.buffer_not_in_use = thread_create_event();
thread_run = 1;
blit_data.blit_thread = thread_create(blit_thread, NULL);
memset(monitors, 0, sizeof(monitors));
video_monitor_init(0);
}
void
video_close(void)
{
thread_run = 0;
thread_set_event(blit_data.wake_blit_thread);
thread_wait(blit_data.blit_thread);
thread_destroy_event(blit_data.buffer_not_in_use);
thread_destroy_event(blit_data.blit_complete);
thread_destroy_event(blit_data.wake_blit_thread);
video_monitor_close(0);
free(video_16to32);
free(video_15to32);
@@ -902,8 +1035,6 @@ video_close(void)
free(video_8togs);
free(video_6to8);
destroy_bitmap(buffer32);
if (fontdatksc5601) {
free(fontdatksc5601);
fontdatksc5601 = NULL;
@@ -915,18 +1046,29 @@ video_close(void)
}
}
uint8_t
video_force_resize_get_monitor(int monitor_index)
{
return monitors[monitor_index].mon_force_resize;
}
uint8_t
video_force_resize_get(void)
{
return video_force_resize;
return monitors[monitor_index_global].mon_force_resize;
}
void
video_force_resize_set_monitor(uint8_t res, int monitor_index)
{
monitors[monitor_index].mon_force_resize = res;
}
void
video_force_resize_set(uint8_t res)
{
video_force_resize = res;
monitors[monitor_index_global].mon_force_resize = res;
}
void

View File

@@ -495,6 +495,9 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow)
return(1);
}
extern int gfxcard_2;
gfxcard_2 = 0;
/* Create console window. */
if (force_debug) {
CreateConsole(1);
@@ -552,11 +555,12 @@ main_thread(void *param)
Sleep(1);
/* If needed, handle a screen resize. */
if (!atomic_flag_test_and_set(&doresize) && !video_fullscreen && !is_quit) {
if (atomic_load(&doresize_monitors[0]) && !video_fullscreen && !is_quit) {
if (vid_resize & 2)
plat_resize(fixed_size_x, fixed_size_y);
else
plat_resize(scrnsz_x, scrnsz_y);
atomic_store(&doresize_monitors[0], 0);
}
}
@@ -1189,7 +1193,7 @@ plat_setfullscreen(int on)
video_fullscreen &= 1;
video_force_resize_set(1);
if (!(on & 1))
atomic_flag_clear(&doresize);
atomic_store(&doresize_monitors[0], 1);
win_mouse_init();

View File

@@ -871,14 +871,14 @@ static void opengl_main(void* param)
CoUninitialize();
}
static void opengl_blit(int x, int y, int w, int h)
static void opengl_blit(int x, int y, int w, int h, int monitor_index)
{
int row;
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (thread == NULL) ||
atomic_flag_test_and_set(&blit_info[write_pos].in_use))
atomic_flag_test_and_set(&blit_info[write_pos].in_use) || monitor_index >= 1)
{
video_blit_complete();
video_blit_complete_monitor(monitor_index);
return;
}

View File

@@ -229,13 +229,13 @@ sdl_stretch(int *w, int *h, int *x, int *y)
static void
sdl_blit(int x, int y, int w, int h)
sdl_blit(int x, int y, int w, int h, int monitor_index)
{
SDL_Rect r_src;
int ret;
if (!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) {
video_blit_complete();
if (!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL) || monitor_index >= 1) {
video_blit_complete_monitor(monitor_index);
return;
}
@@ -269,7 +269,7 @@ sdl_blit(int x, int y, int w, int h)
static void
sdl_blit_ex(int x, int y, int w, int h)
sdl_blit_ex(int x, int y, int w, int h, int monitor_index)
{
SDL_Rect r_src;
void *pixeldata;

View File

@@ -28,6 +28,7 @@
#include <86box/86box.h>
#include <86box/config.h>
#include <86box/plat.h>
#include <86box/video.h>
#include <86box/sound.h>
#include <86box/win.h>
@@ -133,7 +134,7 @@ SpecifyDimensionsDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM
scrnsz_x = fixed_size_x;
scrnsz_y = fixed_size_y;
atomic_flag_clear(&doresize);
atomic_store(&doresize_monitors[0], 1);
GetWindowRect(hwndMain, &r);

View File

@@ -8,6 +8,7 @@
#include <86box/plat.h>
#include <86box/resource.h>
#include <86box/ui.h>
#include <86box/video.h>
#include <86box/win.h>
HWND hwndRebar = NULL;

View File

@@ -646,7 +646,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
scrnsz_x = unscaled_size_x;
scrnsz_y = unscaled_size_y;
atomic_flag_clear(&doresize);
atomic_store(&doresize_monitors[0], 1);
config_save();
break;
@@ -745,7 +745,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
reset_screen_size();
device_force_redraw();
video_force_resize_set(1);
atomic_flag_clear(&doresize);
atomic_store(&doresize_monitors[0], 1);
config_save();
break;
@@ -760,7 +760,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case IDM_VID_HIDPI:
dpi_scale = !dpi_scale;
CheckMenuItem(hmenu, IDM_VID_HIDPI, dpi_scale ? MF_CHECKED : MF_UNCHECKED);
atomic_flag_clear(&doresize);
atomic_store(&doresize_monitors[0], 1);
config_save();
break;
@@ -860,7 +860,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* Main Window. */
ResizeWindowByClientArea(hwndMain, temp_x, temp_y + (hide_status_bar ? 0 : sbar_height) + (hide_tool_bar ? 0 : tbar_height));
} else if (!user_resize)
atomic_flag_clear(&doresize);
atomic_store(&doresize_monitors[0], 1);
break;
case WM_WINDOWPOSCHANGED:
@@ -909,13 +909,13 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
if (temp_x != scrnsz_x || temp_y != scrnsz_y) {
scrnsz_x = temp_x;
scrnsz_y = temp_y;
atomic_flag_clear(&doresize);
atomic_store(&doresize_monitors[0], 1);
}
} else {
if (rect.right != scrnsz_x || rect.bottom != scrnsz_y) {
scrnsz_x = rect.right;
scrnsz_y = rect.bottom;
atomic_flag_clear(&doresize);
atomic_store(&doresize_monitors[0], 1);
}
}
@@ -1092,7 +1092,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* If window is not resizable, then tell the main thread to
resize it, as sometimes, moves can mess up the window size. */
if (!vid_resize)
atomic_flag_clear(&doresize);
atomic_store(&doresize_monitors[0], 1);
break;
}
@@ -1580,3 +1580,6 @@ plat_mouse_capture(int on)
mouse_capture = 0;
}
}
void ui_init_monitor(int monitor_index) {}
void ui_deinit_monitor(int monitor_index) {}

View File

@@ -25,6 +25,7 @@
"network",
"vulkan",
"widgets",
"png",
"zstd"
]
},