SDL2: added experimental fullscreen mode support

This commit is contained in:
Volker Ruppert 2014-07-03 20:17:19 +00:00
parent 816f5cc2d7
commit 2bfd78fa45

View File

@ -46,7 +46,9 @@ public:
bx_sdl2_gui_c() {}
DECLARE_GUI_VIRTUAL_METHODS()
DECLARE_GUI_NEW_VIRTUAL_METHODS()
virtual void set_display_mode(disp_mode_t newmode);
virtual void statusbar_setitem_specific(int element, bx_bool active, bx_bool w);
virtual void get_capabilities(Bit16u *xres, Bit16u *yres, Bit16u *bpp);
virtual void set_mouse_mode_absxy(bx_bool mode);
#if BX_SHOW_IPS
virtual void show_ips(Bit32u ips_count);
@ -90,7 +92,9 @@ static struct {
unsigned bx_headerbar_entries = 0;
static SDL_Window *window;
SDL_Surface *sdl_screen = NULL;
SDL_Surface *sdl_screen, *sdl_fullscreen;
SDL_DisplayMode sdl_maxres;
int sdl_fullscreen_toggle;
int sdl_grab;
unsigned res_x, res_y;
unsigned half_res_x, half_res_y;
@ -159,7 +163,7 @@ static void sdl_set_status_text(int element, const char *text, bx_bool active, b
int x, xleft, xsize;
statusitem_active[element] = active;
if(!sdl_screen) return;
if (!sdl_screen) return;
disp = sdl_screen->pitch/4;
xleft = statusitem_pos[element] + 2;
xsize = statusitem_pos[element+1] - xleft - 1;
@ -343,6 +347,27 @@ static Bit32u sdl_sym_to_bx_key(SDL_Keycode sym)
}
void switch_to_windowed(void)
{
SDL_SetWindowFullscreen(window, 0);
SDL_SetWindowSize(window, res_x, res_y + headerbar_height + statusbar_height);
sdl_screen = SDL_GetWindowSurface(window);
sdl_fullscreen = NULL;
bx_gui->show_headerbar();
DEV_vga_redraw_area(0, 0, res_x, res_y);
}
void switch_to_fullscreen(void)
{
SDL_SetWindowSize(window, res_x, res_y);
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
sdl_fullscreen = SDL_GetWindowSurface(window);
sdl_screen = NULL;
DEV_vga_redraw_area(0, 0, res_x, res_y);
}
#if BX_SHOW_IPS
#if defined(__MINGW32__) || defined(_MSC_VER)
Uint32 sdlTimer(Uint32 interval, void *param)
@ -391,10 +416,6 @@ void bx_sdl2_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y)
for(j=0;j<8;j++)
menufont[i][j] = sdl_font8x8[i][j];
if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get()) {
BX_INFO(("private_colormap option ignored."));
}
flags = SDL_INIT_VIDEO;
#if BX_SHOW_IPS
#if defined(__MINGW32__) || defined(_MSC_VER)
@ -407,6 +428,30 @@ void bx_sdl2_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y)
return;
}
atexit(SDL_Quit);
SDL_GetDisplayMode(0, 0, &sdl_maxres);
BX_INFO(("maximum host resolution: x=%d y=%d", sdl_maxres.w, sdl_maxres.h));
window = SDL_CreateWindow(
BOCHS_WINDOW_NAME,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_SHOWN
);
if (window == NULL) {
LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
BX_PANIC(("Unable to create SDL2 window"));
return;
}
sdl_screen = NULL;
sdl_fullscreen_toggle = 0;
dimension_update(640, 480);
SDL_WarpMouseInWindow(window, half_res_x, half_res_y);
icon_id = create_bitmap(bochs_icon_bits, bochs_icon_width, bochs_icon_height);
SDL_SetWindowIcon(window, sdl_bitmaps[icon_id]->surface);
#ifndef WIN32
// redirect notify callback to SDL2 specific code
@ -423,7 +468,10 @@ void bx_sdl2_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y)
// parse sdl specific options
if (argc > 1) {
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "nokeyrepeat")) {
if (!strcmp(argv[i], "fullscreen")) {
sdl_fullscreen_toggle = 1;
switch_to_fullscreen();
} else if (!strcmp(argv[i], "nokeyrepeat")) {
BX_INFO(("disabled host keyboard repeat"));
sdl_nokeyrepeat = 1;
#if BX_DEBUGGER && BX_DEBUGGER_GUI
@ -452,31 +500,6 @@ void bx_sdl2_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y)
}
}
window = SDL_CreateWindow(
BOCHS_WINDOW_NAME,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_SHOWN
);
dimension_update(640, 480);
SDL_WarpMouseInWindow(window, half_res_x, half_res_y);
headerbar_fg = SDL_MapRGB(
sdl_screen->format,
BX_HEADERBAR_FG_RED,
BX_HEADERBAR_FG_GREEN,
BX_HEADERBAR_FG_BLUE);
headerbar_bg = SDL_MapRGB(
sdl_screen->format,
BX_HEADERBAR_BG_RED,
BX_HEADERBAR_BG_GREEN,
BX_HEADERBAR_BG_BLUE);
icon_id = create_bitmap(bochs_icon_bits, bochs_icon_width, bochs_icon_height);
SDL_SetWindowIcon(window, sdl_bitmaps[icon_id]->surface);
new_gfx_api = 1;
#ifdef WIN32
if (gui_ci) {
@ -508,7 +531,6 @@ void bx_sdl2_gui_c::text_update(Bit8u *old_text, Bit8u *new_text,
bx_bool blink_mode, blink_state;
Uint32 text_palette[16];
if (!sdl_screen) return;
forceUpdate = 0;
blink_mode = (tm_info->blink_flags & BX_TEXT_BLINK_MODE) > 0;
blink_state = (tm_info->blink_flags & BX_TEXT_BLINK_STATE) > 0;
@ -532,8 +554,13 @@ void bx_sdl2_gui_c::text_update(Bit8u *old_text, Bit8u *new_text,
forceUpdate = 1;
line_compare = tm_info->line_compare;
}
disp = sdl_screen->pitch/4;
buf_row = (Uint32 *)sdl_screen->pixels + headerbar_height * disp;
if (sdl_screen) {
disp = sdl_screen->pitch/4;
buf_row = (Uint32 *)sdl_screen->pixels + headerbar_height * disp;
} else {
disp = sdl_fullscreen->pitch/4;
buf_row = (Uint32 *)sdl_fullscreen->pixels;
}
// first invalidate character at previous and new cursor location
if ((prev_cursor_y < text_rows) && (prev_cursor_x < text_cols)) {
curs = prev_cursor_y * tm_info->line_offset + prev_cursor_x * 2;
@ -691,11 +718,15 @@ void bx_sdl2_gui_c::graphics_tile_update(Bit8u *snapshot, unsigned x, unsigned y
{
Uint32 *buf, disp;
Uint32 *buf_row;
int i,j;
int i, j;
if (!sdl_screen) return;
disp = sdl_screen->pitch/4;
buf = (Uint32 *)sdl_screen->pixels + (headerbar_height+y)*disp + x;
if (sdl_screen) {
disp = sdl_screen->pitch/4;
buf = (Uint32 *)sdl_screen->pixels + (headerbar_height + y) * disp + x;
} else {
disp = sdl_fullscreen->pitch/4;
buf = (Uint32 *)sdl_fullscreen->pixels + y * disp + x;
}
i = y_tilesize;
if(i + y > res_y) i = res_y - y;
@ -786,7 +817,7 @@ void bx_sdl2_gui_c::handle_events(void)
toggle_mouse_enable();
}
break;
} else if (sdl_event.button.y < headerbar_height) {
} else if (!sdl_fullscreen_toggle && (sdl_event.button.y < headerbar_height)) {
headerbar_click(sdl_event.button.x);
break;
}
@ -849,6 +880,17 @@ void bx_sdl2_gui_c::handle_events(void)
toggle_mouse_enable();
}
// Window/Fullscreen toggle-check
if (sdl_event.key.keysym.sym == SDLK_SCROLLLOCK) {
sdl_fullscreen_toggle = ~sdl_fullscreen_toggle;
if (sdl_fullscreen_toggle == 0) {
switch_to_windowed();
} else {
switch_to_fullscreen();
}
break;
}
if (sdl_nokeyrepeat && sdl_event.key.repeat) {
break;
}
@ -884,22 +926,25 @@ void bx_sdl2_gui_c::handle_events(void)
mouse_toggle_check(BX_MT_KEY_F12, 0);
}
// convert sym->bochs code
if (!SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) {
key_event = sdl_sym_to_bx_key(sdl_event.key.keysym.sym);
} else {
/* use mapping */
BXKeyEntry *entry = bx_keymap.findHostKey(sdl_event.key.keysym.sym);
if (!entry) {
BX_ERROR(("host key %d (0x%x) not mapped!",
(unsigned) sdl_event.key.keysym.sym,
(unsigned) sdl_event.key.keysym.sym));
break;
// filter out release of Windows/Fullscreen toggle
if (sdl_event.key.keysym.sym != SDLK_SCROLLLOCK) {
// convert sym->bochs code
if (!SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) {
key_event = sdl_sym_to_bx_key(sdl_event.key.keysym.sym);
} else {
/* use mapping */
BXKeyEntry *entry = bx_keymap.findHostKey(sdl_event.key.keysym.sym);
if (!entry) {
BX_ERROR(("host key %d (0x%x) not mapped!",
(unsigned) sdl_event.key.keysym.sym,
(unsigned) sdl_event.key.keysym.sym));
break;
}
key_event = entry->baseKey;
}
key_event = entry->baseKey;
if (key_event == BX_KEY_UNHANDLED) break;
DEV_kbd_gen_scancode(key_event | BX_KEY_RELEASED);
}
if (key_event == BX_KEY_UNHANDLED) break;
DEV_kbd_gen_scancode(key_event | BX_KEY_RELEASED);
break;
case SDL_QUIT:
@ -930,10 +975,16 @@ void bx_sdl2_gui_c::clear_screen(void)
Uint32 *buf, *buf_row;
Uint32 disp;
if (!sdl_screen) return;
color = SDL_MapRGB(sdl_screen->format, 0,0,0);
disp = sdl_screen->pitch/4;
buf = (Uint32 *)sdl_screen->pixels + headerbar_height*disp;
if (sdl_screen) {
color = SDL_MapRGB(sdl_screen->format, 0, 0, 0);
disp = sdl_screen->pitch/4;
buf = (Uint32 *)sdl_screen->pixels + headerbar_height * disp;
} else if (sdl_fullscreen) {
color = SDL_MapRGB(sdl_fullscreen->format, 0, 0, 0);
disp = sdl_fullscreen->pitch/4;
buf = (Uint32 *)sdl_fullscreen->pixels;
}
else return;
do {
buf_row = buf;
@ -948,9 +999,11 @@ void bx_sdl2_gui_c::clear_screen(void)
bx_bool bx_sdl2_gui_c::palette_change(Bit8u index, Bit8u red, Bit8u green, Bit8u blue)
{
if (sdl_screen) {
if (sdl_screen)
sdl_palette[index] = SDL_MapRGB(sdl_screen->format, red, green, blue);
}
else if (sdl_fullscreen)
sdl_palette[index] = SDL_MapRGB(sdl_fullscreen->format, red, green, blue);
return 1;
}
@ -975,8 +1028,27 @@ void bx_sdl2_gui_c::dimension_update(unsigned x, unsigned y,
if ((x == res_x) && (y == res_y)) return;
SDL_SetWindowSize(window, x, y + headerbar_height + statusbar_height);
sdl_screen = SDL_GetWindowSurface(window);
if (((int)x > sdl_maxres.w) || ((int)y > sdl_maxres.h)) {
BX_PANIC(("dimension_update(): resolution of out of display bounds"));
return;
}
if (sdl_fullscreen_toggle == 0) {
SDL_SetWindowSize(window, x, y + headerbar_height + statusbar_height);
sdl_screen = SDL_GetWindowSurface(window);
headerbar_fg = SDL_MapRGB(
sdl_screen->format,
BX_HEADERBAR_FG_RED,
BX_HEADERBAR_FG_GREEN,
BX_HEADERBAR_FG_BLUE);
headerbar_bg = SDL_MapRGB(
sdl_screen->format,
BX_HEADERBAR_BG_RED,
BX_HEADERBAR_BG_GREEN,
BX_HEADERBAR_BG_BLUE);
} else {
SDL_SetWindowSize(window, x, y);
sdl_fullscreen = SDL_GetWindowSurface(window);
}
res_x = x;
res_y = y;
@ -1094,8 +1166,8 @@ void bx_sdl2_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
{
SDL_Rect hb_dst;
unsigned old_id;
if (!sdl_screen) return;
if (!sdl_screen) return;
old_id = hb_entry[hbar_id].bmp_id;
hb_dst = sdl_bitmaps[old_id]->dst;
sdl_bitmaps[old_id]->dst.x = -1;
@ -1212,6 +1284,8 @@ void bx_sdl2_gui_c::mouse_enabled_changed_specific(bx_bool val)
void bx_sdl2_gui_c::exit(void)
{
SDL_ShowCursor(1);
SDL_SetWindowGrab(window, SDL_FALSE);
while (n_sdl_bitmaps) {
SDL_FreeSurface(sdl_bitmaps[n_sdl_bitmaps-1]->surface);
n_sdl_bitmaps--;
@ -1222,16 +1296,27 @@ void bx_sdl2_gui_c::exit(void)
bx_svga_tileinfo_t *bx_sdl2_gui_c::graphics_tile_info(bx_svga_tileinfo_t *info)
{
if (!sdl_screen) return NULL;
info->bpp = sdl_screen->format->BitsPerPixel;
info->pitch = sdl_screen->pitch;
info->red_shift = sdl_screen->format->Rshift + 8 - sdl_screen->format->Rloss;
info->green_shift = sdl_screen->format->Gshift + 8 - sdl_screen->format->Gloss;
info->blue_shift = sdl_screen->format->Bshift + 8 - sdl_screen->format->Bloss;
info->red_mask = sdl_screen->format->Rmask;
info->green_mask = sdl_screen->format->Gmask;
info->blue_mask = sdl_screen->format->Bmask;
info->is_indexed = (sdl_screen->format->palette != NULL);
if (sdl_screen) {
info->bpp = sdl_screen->format->BitsPerPixel;
info->pitch = sdl_screen->pitch;
info->red_shift = sdl_screen->format->Rshift + 8 - sdl_screen->format->Rloss;
info->green_shift = sdl_screen->format->Gshift + 8 - sdl_screen->format->Gloss;
info->blue_shift = sdl_screen->format->Bshift + 8 - sdl_screen->format->Bloss;
info->red_mask = sdl_screen->format->Rmask;
info->green_mask = sdl_screen->format->Gmask;
info->blue_mask = sdl_screen->format->Bmask;
info->is_indexed = (sdl_screen->format->palette != NULL);
} else {
info->bpp = sdl_fullscreen->format->BitsPerPixel;
info->pitch = sdl_fullscreen->pitch;
info->red_shift = sdl_fullscreen->format->Rshift + 8 - sdl_fullscreen->format->Rloss;
info->green_shift = sdl_fullscreen->format->Gshift + 8 - sdl_fullscreen->format->Gloss;
info->blue_shift = sdl_fullscreen->format->Bshift + 8 - sdl_fullscreen->format->Bloss;
info->red_mask = sdl_fullscreen->format->Rmask;
info->green_mask = sdl_fullscreen->format->Gmask;
info->blue_mask = sdl_fullscreen->format->Bmask;
info->is_indexed = (sdl_fullscreen->format->palette != NULL);
}
#ifdef BX_LITTLE_ENDIAN
info->is_little_endian = 1;
#else
@ -1243,7 +1328,6 @@ bx_svga_tileinfo_t *bx_sdl2_gui_c::graphics_tile_info(bx_svga_tileinfo_t *info)
Bit8u *bx_sdl2_gui_c::graphics_tile_get(unsigned x0, unsigned y0, unsigned *w, unsigned *h)
{
if (!sdl_screen) return NULL;
if (x0+x_tilesize > res_x) {
*w = res_x - x0;
} else {
@ -1256,9 +1340,15 @@ Bit8u *bx_sdl2_gui_c::graphics_tile_get(unsigned x0, unsigned y0, unsigned *w, u
*h = y_tilesize;
}
return (Bit8u *)sdl_screen->pixels +
sdl_screen->pitch*(headerbar_height+y0) +
sdl_screen->format->BytesPerPixel*x0;
if (sdl_screen) {
return (Bit8u *)sdl_screen->pixels +
sdl_screen->pitch*(headerbar_height+y0) +
sdl_screen->format->BytesPerPixel*x0;
} else {
return (Bit8u *)sdl_fullscreen->pixels +
sdl_fullscreen->pitch * y0 +
sdl_fullscreen->format->BytesPerPixel * x0;
}
}
@ -1270,11 +1360,43 @@ void bx_sdl2_gui_c::graphics_tile_update_in_place(unsigned x0, unsigned y0,
// Optional bx_gui_c methods
void bx_sdl2_gui_c::set_display_mode(disp_mode_t newmode)
{
// if no mode change, do nothing.
if (disp_mode == newmode) return;
// remember the display mode for next time
disp_mode = newmode;
// If fullscreen mode is on, we must switch back to windowed mode if
// the user needs to see the text console.
if (sdl_fullscreen_toggle) {
switch (newmode) {
case DISP_MODE_CONFIG:
BX_DEBUG(("switch to configuration mode (windowed)"));
switch_to_windowed();
break;
case DISP_MODE_SIM:
BX_DEBUG(("switch to simulation mode (fullscreen)"));
switch_to_fullscreen();
break;
}
}
}
void bx_sdl2_gui_c::statusbar_setitem_specific(int element, bx_bool active, bx_bool w)
{
sdl_set_status_text(element+1, statusitem[element].text, active, w);
}
void bx_sdl2_gui_c::get_capabilities(Bit16u *xres, Bit16u *yres, Bit16u *bpp)
{
*xres = sdl_maxres.w;
*yres = sdl_maxres.h;
*bpp = 32;
}
void bx_sdl2_gui_c::set_mouse_mode_absxy(bx_bool mode)
{
sdl_mouse_mode_absxy = mode;