moved SDL2 video code to video_sdl2.cpp; restored SDL1 implementation of video_sdl.cpp

This commit is contained in:
David Ludwig 2017-09-04 12:18:52 -04:00
parent 22eaa317a8
commit f8682679c2
3 changed files with 2752 additions and 488 deletions

View File

@ -51,7 +51,6 @@
7539E1731F23B25A006B2DF2 /* scsi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7539E0701F23B25A006B2DF2 /* scsi.cpp */; };
7539E1741F23B25A006B2DF2 /* audio_sdl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7539E0721F23B25A006B2DF2 /* audio_sdl.cpp */; };
7539E1751F23B25A006B2DF2 /* keycodes in Resources */ = {isa = PBXBuildFile; fileRef = 7539E0731F23B25A006B2DF2 /* keycodes */; };
7539E1771F23B25A006B2DF2 /* video_sdl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7539E0761F23B25A006B2DF2 /* video_sdl.cpp */; };
7539E1781F23B25A006B2DF2 /* serial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7539E0771F23B25A006B2DF2 /* serial.cpp */; };
7539E18D1F23B25A006B2DF2 /* slot_rom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7539E0A21F23B25A006B2DF2 /* slot_rom.cpp */; };
7539E18E1F23B25A006B2DF2 /* sony.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7539E0A31F23B25A006B2DF2 /* sony.cpp */; };
@ -106,6 +105,7 @@
756C1B341F252FC100620917 /* utils_macosx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 756C1B331F252FC100620917 /* utils_macosx.mm */; };
756C1B391F25306A00620917 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 756C1B381F25306A00620917 /* AppKit.framework */; };
757A2BF01F5AF9D6003EDB01 /* user_strings_unix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 757A2BEF1F5AF9D6003EDB01 /* user_strings_unix.cpp */; };
75CBCF751F5DB3AD00830063 /* video_sdl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 75CBCF741F5DB3AD00830063 /* video_sdl2.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -288,7 +288,6 @@
7539E0701F23B25A006B2DF2 /* scsi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = scsi.cpp; path = ../scsi.cpp; sourceTree = "<group>"; };
7539E0721F23B25A006B2DF2 /* audio_sdl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audio_sdl.cpp; sourceTree = "<group>"; };
7539E0731F23B25A006B2DF2 /* keycodes */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = keycodes; sourceTree = "<group>"; };
7539E0761F23B25A006B2DF2 /* video_sdl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video_sdl.cpp; sourceTree = "<group>"; };
7539E0771F23B25A006B2DF2 /* serial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = serial.cpp; path = ../serial.cpp; sourceTree = "<group>"; };
7539E0A21F23B25A006B2DF2 /* slot_rom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = slot_rom.cpp; path = ../slot_rom.cpp; sourceTree = "<group>"; };
7539E0A31F23B25A006B2DF2 /* sony.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sony.cpp; path = ../sony.cpp; sourceTree = "<group>"; };
@ -376,6 +375,7 @@
756C1B331F252FC100620917 /* utils_macosx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = utils_macosx.mm; sourceTree = "<group>"; };
756C1B381F25306A00620917 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
757A2BEF1F5AF9D6003EDB01 /* user_strings_unix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_strings_unix.cpp; sourceTree = "<group>"; };
75CBCF741F5DB3AD00830063 /* video_sdl2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video_sdl2.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -584,7 +584,7 @@
752F27001F242BAF001032B4 /* prefs_sdl.cpp */,
7539E0721F23B25A006B2DF2 /* audio_sdl.cpp */,
7539E0731F23B25A006B2DF2 /* keycodes */,
7539E0761F23B25A006B2DF2 /* video_sdl.cpp */,
75CBCF741F5DB3AD00830063 /* video_sdl2.cpp */,
);
name = SDL;
path = ../SDL;
@ -1038,7 +1038,6 @@
7539E1A01F23B25A006B2DF2 /* memory.cpp in Sources */,
753253351F53688D0024025B /* readcpu.cpp in Sources */,
7539E1741F23B25A006B2DF2 /* audio_sdl.cpp in Sources */,
7539E1771F23B25A006B2DF2 /* video_sdl.cpp in Sources */,
753252EE1F535DD10024025B /* defs68k.c in Sources */,
7539E29F1F23C939006B2DF2 /* fpu_uae.cpp in Sources */,
7539E1E21F23B25A006B2DF2 /* video.cpp in Sources */,
@ -1056,6 +1055,7 @@
7539E1901F23B25A006B2DF2 /* basilisk_glue.cpp in Sources */,
7539E2801F23C4CA006B2DF2 /* main_unix.cpp in Sources */,
7539E1E11F23B25A006B2DF2 /* user_strings.cpp in Sources */,
75CBCF751F5DB3AD00830063 /* video_sdl2.cpp in Sources */,
752F27011F242BAF001032B4 /* prefs_sdl.cpp in Sources */,
7539E2971F23C5FD006B2DF2 /* newcpu.cpp in Sources */,
7539E12A1F23B25A006B2DF2 /* vm_alloc.cpp in Sources */,

631
BasiliskII/src/SDL/video_sdl.cpp Executable file → Normal file
View File

@ -51,7 +51,7 @@
#include <malloc.h> /* alloca() */
#endif
#include <cpu_emulation.h>
#include "cpu_emulation.h"
#include "main.h"
#include "adb.h"
#include "macos_util.h"
@ -87,8 +87,6 @@ static int display_type = DISPLAY_WINDOW; // See enum above
// Constants
#ifdef WIN32
const char KEYCODE_FILE_NAME[] = "BasiliskII_keycodes";
#elif __MACOSX__
const char KEYCODE_FILE_NAME[] = "BasiliskII_keycodes";
#else
const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
#endif
@ -129,18 +127,12 @@ static bool use_keycodes = false; // Flag: Use keycodes rather than keysyms
static int keycode_table[256]; // X keycode -> Mac keycode translation table
// SDL variables
SDL_Window * sdl_window = NULL; // Wraps an OS-native window
static SDL_Surface * host_surface = NULL; // Surface in host-OS display format
static SDL_Surface * guest_surface = NULL; // Surface in guest-OS display format
static SDL_Renderer * sdl_renderer = NULL; // Handle to SDL2 renderer
static SDL_threadID sdl_renderer_thread_id = 0; // Thread ID where the SDL_renderer was created, and SDL_renderer ops should run (for compatibility w/ d3d9)
static SDL_Texture * sdl_texture = NULL; // Handle to a GPU texture, with which to draw guest_surface to
static int screen_depth; // Depth of current screen
static SDL_Cursor *sdl_cursor = NULL; // Copy of Mac cursor
static SDL_Palette *sdl_palette = NULL; // Color palette to be used as CLUT and gamma table
static SDL_Cursor *sdl_cursor; // Copy of Mac cursor
static SDL_Color sdl_palette[256]; // Color palette to be used as CLUT and gamma table
static bool sdl_palette_changed = false; // Flag: Palette changed, redraw thread must set new colors
static bool toggle_fullscreen = false;
static bool did_add_event_watch = false;
static const int sdl_eventmask = SDL_MOUSEEVENTMASK | SDL_KEYEVENTMASK | SDL_VIDEOEXPOSEMASK | SDL_QUITMASK | SDL_ACTIVEEVENTMASK;
static bool mouse_grabbed = false;
@ -166,10 +158,6 @@ static void (*video_refresh)(void);
// Prototypes
static int redraw_func(void *arg);
static int update_sdl_video();
static int present_sdl_video();
static int SDLCALL on_sdl_event_generated(void *userdata, SDL_Event * event);
static bool is_fullscreen(SDL_Window *);
// From sys_unix.cpp
extern void SysMountFirstFloppy(void);
@ -181,7 +169,7 @@ extern void SysMountFirstFloppy(void);
#ifdef ENABLE_VOSF
#define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE) do { \
if (sdl_window && SDL_GetWindowFlags(sdl_window) & (SDL_WINDOW_FULLSCREEN)) \
if ((SURFACE)->flags & (SDL_HWSURFACE | SDL_FULLSCREEN)) \
the_host_buffer = (uint8 *)(SURFACE)->pixels; \
} while (0)
#else
@ -207,9 +195,6 @@ extern void SysMountFirstFloppy(void);
static void *vm_acquire_framebuffer(uint32 size)
{
#if __MACOSX__
return calloc(1, size);
#else
// always try to reallocate framebuffer at the same address
static void *fb = VM_MAP_FAILED;
if (fb != VM_MAP_FAILED) {
@ -223,16 +208,11 @@ static void *vm_acquire_framebuffer(uint32 size)
if (fb == VM_MAP_FAILED)
fb = vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT);
return fb;
#endif
}
static inline void vm_release_framebuffer(void *fb, uint32 size)
{
#if __MACOSX__
free(fb);
#else
vm_release(fb, size);
#endif
}
static inline int get_customized_color_depth(int default_depth)
@ -438,15 +418,25 @@ static int sdl_depth_of_video_depth(int video_depth)
// Get screen dimensions
static void sdl_display_dimensions(int &width, int &height)
{
SDL_DisplayMode desktop_mode;
const int display_index = 0; // TODO: try supporting multiple displays
if (SDL_GetDesktopDisplayMode(display_index, &desktop_mode) != 0) {
// TODO: report a warning, here?
width = height = 0;
return;
static int max_width, max_height;
if (max_width == 0 && max_height == 0) {
max_width = 640 ; max_height = 480;
SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
if (modes && modes != (SDL_Rect **)-1) {
// It turns out that on some implementations, and contrary to the documentation,
// the returned list is not sorted from largest to smallest (e.g. Windows)
for (int i = 0; modes[i] != NULL; i++) {
const int w = modes[i]->w;
const int h = modes[i]->h;
if (w > max_width && h > max_height) {
max_width = w;
max_height = h;
}
}
}
}
width = desktop_mode.w;
height = desktop_mode.h;
width = max_width;
height = max_height;
}
static inline int sdl_display_width(void)
@ -476,8 +466,10 @@ static bool has_mode(int type, int width, int height, int depth)
if (width > sdl_display_width() || height > sdl_display_height())
return false;
// Whatever size it is, beyond what we've checked, we'll scale to/from as appropriate.
return true;
// Rely on SDL capabilities
return SDL_VideoModeOK(width, height,
sdl_depth_of_video_depth(depth),
SDL_HWSURFACE | (type == DISPLAY_SCREEN ? SDL_FULLSCREEN : 0)) != 0;
}
// Add mode to list of supported modes
@ -530,20 +522,18 @@ static void set_mac_frame_buffer(SDL_monitor_desc &monitor, int depth, bool nati
// Set window name and class
static void set_window_name(int name)
{
if (!sdl_window) {
return;
const SDL_VideoInfo *vi = SDL_GetVideoInfo();
if (vi && vi->wm_available) {
const char *str = GetString(name);
SDL_WM_SetCaption(str, str);
}
const char *str = GetString(name);
SDL_SetWindowTitle(sdl_window, str);
}
// Set mouse grab mode
static void set_grab_mode(bool grab)
static SDL_GrabMode set_grab_mode(SDL_GrabMode mode)
{
if (!sdl_window) {
return;
}
SDL_SetWindowGrab(sdl_window, grab ? SDL_TRUE : SDL_FALSE);
const SDL_VideoInfo *vi = SDL_GetVideoInfo();
return (vi && vi->wm_available ? SDL_WM_GrabInput(mode) : SDL_GRAB_OFF);
}
// Migrate preferences items (XXX to be handled in MigratePrefs())
@ -647,256 +637,11 @@ driver_base::driver_base(SDL_monitor_desc &m)
the_buffer_copy = NULL;
}
static void delete_sdl_video_surfaces()
{
if (sdl_texture) {
SDL_DestroyTexture(sdl_texture);
sdl_texture = NULL;
}
if (host_surface) {
if (host_surface == guest_surface) {
guest_surface = NULL;
}
SDL_FreeSurface(host_surface);
host_surface = NULL;
}
if (guest_surface) {
SDL_FreeSurface(guest_surface);
guest_surface = NULL;
}
}
static void delete_sdl_video_window()
{
if (sdl_renderer) {
SDL_DestroyRenderer(sdl_renderer);
sdl_renderer = NULL;
}
if (sdl_window) {
SDL_DestroyWindow(sdl_window);
sdl_window = NULL;
}
}
static void shutdown_sdl_video()
{
delete_sdl_video_surfaces();
delete_sdl_video_window();
}
static SDL_Surface * init_sdl_video(int width, int height, int bpp, Uint32 flags)
{
if (guest_surface) {
delete_sdl_video_surfaces();
}
int window_width = width;
int window_height = height;
Uint32 window_flags = 0;
const int window_flags_to_monitor = SDL_WINDOW_FULLSCREEN;
if (flags & SDL_WINDOW_FULLSCREEN) {
SDL_DisplayMode desktop_mode;
if (SDL_GetDesktopDisplayMode(0, &desktop_mode) != 0) {
shutdown_sdl_video();
return NULL;
}
window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
window_width = desktop_mode.w;
window_height = desktop_mode.h;
}
if (sdl_window) {
int old_window_width, old_window_height, old_window_flags;
SDL_GetWindowSize(sdl_window, &old_window_width, &old_window_height);
old_window_flags = SDL_GetWindowFlags(sdl_window);
if (old_window_width != window_width ||
old_window_height != window_height ||
(old_window_flags & window_flags_to_monitor) != (window_flags & window_flags_to_monitor))
{
delete_sdl_video_window();
}
}
// Apply anti-aliasing, if and when appropriate (usually in fullscreen)
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
// Always use a resize-able window. This helps allow SDL to manage
// transitions involving fullscreen to or from windowed-mode.
window_flags |= SDL_WINDOW_RESIZABLE;
if (!sdl_window) {
sdl_window = SDL_CreateWindow(
"Basilisk II",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
window_width,
window_height,
window_flags);
if (!sdl_window) {
shutdown_sdl_video();
return NULL;
}
}
// Some SDL events (regarding some native-window events), need processing
// as they are generated. SDL2 has a facility, SDL_AddEventWatch(), which
// allows events to be processed as they are generated.
if (!did_add_event_watch) {
SDL_AddEventWatch(&on_sdl_event_generated, NULL);
did_add_event_watch = true;
}
if (!sdl_renderer) {
sdl_renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_ACCELERATED);
if (!sdl_renderer) {
shutdown_sdl_video();
return NULL;
}
sdl_renderer_thread_id = SDL_ThreadID();
}
SDL_assert(sdl_texture == NULL);
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, width, height);
if (!sdl_texture) {
shutdown_sdl_video();
return NULL;
}
SDL_assert(guest_surface == NULL);
SDL_assert(host_surface == NULL);
switch (bpp) {
case 8:
guest_surface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);
break;
case 16:
guest_surface = SDL_CreateRGBSurface(0, width, height, 16, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000);
break;
case 32:
guest_surface = SDL_CreateRGBSurface(0, width, height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
host_surface = guest_surface;
break;
default:
printf("WARNING: An unsupported bpp of %d was used\n", bpp);
break;
}
if (!guest_surface) {
shutdown_sdl_video();
return NULL;
}
if (!host_surface) {
Uint32 texture_format;
if (SDL_QueryTexture(sdl_texture, &texture_format, NULL, NULL, NULL) != 0) {
printf("ERROR: Unable to get the SDL texture's pixel format: %s\n", SDL_GetError());
shutdown_sdl_video();
return NULL;
}
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
if (!SDL_PixelFormatEnumToMasks(texture_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
printf("ERROR: Unable to determine format for host SDL_surface: %s\n", SDL_GetError());
shutdown_sdl_video();
return NULL;
}
host_surface = SDL_CreateRGBSurface(0, width, height, bpp, Rmask, Gmask, Bmask, Amask);
if (!host_surface) {
printf("ERROR: Unable to create host SDL_surface: %s\n", SDL_GetError());
shutdown_sdl_video();
return NULL;
}
}
if (SDL_RenderSetLogicalSize(sdl_renderer, width, height) != 0) {
printf("ERROR: Unable to set SDL rendeer's logical size (to %dx%d): %s\n",
width, height, SDL_GetError());
shutdown_sdl_video();
return NULL;
}
return guest_surface;
}
static int present_sdl_video()
{
if (!sdl_renderer || !sdl_texture || !guest_surface) {
printf("WARNING: A video mode does not appear to have been set.\n");
return -1;
}
// Some systems, such as D3D9, can fail if and when they are used across
// certain operations. To address this, only utilize SDL_Renderer in a
// single thread, preferably the main thread.
//
// This was added as part of a fix for https://github.com/DavidLudwig/macemu/issues/21
// "BasiliskII, Win32: resizing a window does not stretch "
SDL_assert(SDL_ThreadID() == sdl_renderer_thread_id);
// Make sure the display's internal (to SDL, possibly the OS) buffer gets
// cleared. Not doing so can, if and when letterboxing is applied (whereby
// colored bars are drawn on the screen's sides to help with aspect-ratio
// correction), the colored bars can be an unknown color.
SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 0); // Use black
SDL_RenderClear(sdl_renderer); // Clear the display
if (host_surface != guest_surface &&
host_surface != NULL &&
guest_surface != NULL)
{
SDL_Rect destRect = {0, 0, host_surface->w, host_surface->h};
if (SDL_BlitSurface(guest_surface, NULL, host_surface, &destRect) != 0) {
return -1;
}
}
if (SDL_UpdateTexture(sdl_texture, NULL, host_surface->pixels, host_surface->pitch) != 0) {
return -1;
}
SDL_Rect src_rect = {0, 0, host_surface->w, host_surface->h};
if (SDL_RenderCopy(sdl_renderer, sdl_texture, &src_rect, NULL) != 0) {
return -1;
}
SDL_RenderPresent(sdl_renderer);
return 0;
}
static int update_sdl_video()
{
// HACK, dludwig@pobox.com: for now, just update the whole screen, via
// VideoInterrupt(), which gets called on the main thread.
//
// TODO: make sure SDL_Renderer resources get displayed, if and when
// MacsBug is running (and VideoInterrupt() might not get called)
//
// TODO: cache rects to update, then use rects in present_sdl_video()
return 0;
}
static int update_sdl_video(SDL_Surface *s, int x, int y, int w, int h)
{
// HACK, dludwig@pobox.com: for now, just update the whole screen, via
// VideoInterrupt(), which gets called on the main thread.
//
// TODO: make sure SDL_Renderer resources get displayed, if and when
// MacsBug is running (and VideoInterrupt() might not get called)
//
// TODO: cache rects to update, then use rects in present_sdl_video()
return 0;
}
void driver_base::set_video_mode(int flags)
{
int depth = sdl_depth_of_video_depth(VIDEO_MODE_DEPTH);
if ((s = init_sdl_video(VIDEO_MODE_X, VIDEO_MODE_Y, depth, flags)) == NULL)
if ((s = SDL_SetVideoMode(VIDEO_MODE_X, VIDEO_MODE_Y, depth,
SDL_HWSURFACE | flags)) == NULL)
return;
#ifdef ENABLE_VOSF
the_host_buffer = (uint8 *)s->pixels;
@ -905,7 +650,7 @@ void driver_base::set_video_mode(int flags)
void driver_base::init()
{
set_video_mode(display_type == DISPLAY_SCREEN ? SDL_WINDOW_FULLSCREEN : 0);
set_video_mode(display_type == DISPLAY_SCREEN ? SDL_FULLSCREEN : 0);
int aligned_height = (VIDEO_MODE_Y + 15) & ~15;
#ifdef ENABLE_VOSF
@ -992,14 +737,8 @@ driver_base::~driver_base()
ungrab_mouse();
restore_mouse_accel();
// HACK: Just delete instances of SDL_Surface and SDL_Texture, rather
// than also the SDL_Window and SDL_Renderer. This fixes a bug whereby
// OSX hosts, when in fullscreen, will, on a guest OS resolution change,
// do a series of switches (using OSX's "Spaces" feature) to and from
// the Basilisk II desktop,
delete_sdl_video_surfaces(); // This deletes instances of SDL_Surface and SDL_Texture
//shutdown_sdl_video(); // This deletes SDL_Window, SDL_Renderer, in addition to
// instances of SDL_Surface and SDL_Texture.
if (s)
SDL_FreeSurface(s);
// the_buffer shall always be mapped through vm_acquire_framebuffer()
if (the_buffer != VM_MAP_FAILED) {
@ -1036,9 +775,8 @@ void driver_base::update_palette(void)
{
const VIDEO_MODE &mode = monitor.get_current_mode();
if ((int)VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT) {
SDL_SetSurfacePalette(s, sdl_palette);
}
if ((int)VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT)
SDL_SetPalette(s, SDL_PHYSPAL, sdl_palette, 0, 256);
}
// Disable mouse acceleration
@ -1060,24 +798,16 @@ void driver_base::toggle_mouse_grab(void)
grab_mouse();
}
static void update_mouse_grab()
{
if (mouse_grabbed) {
SDL_SetRelativeMouseMode(SDL_TRUE);
} else {
SDL_SetRelativeMouseMode(SDL_FALSE);
}
}
// Grab mouse, switch to relative mouse mode
void driver_base::grab_mouse(void)
{
if (!mouse_grabbed) {
mouse_grabbed = true;
update_mouse_grab();
set_window_name(STR_WINDOW_TITLE_GRABBED);
disable_mouse_accel();
ADBSetRelMouseMode(true);
SDL_GrabMode new_mode = set_grab_mode(SDL_GRAB_ON);
if (new_mode == SDL_GRAB_ON) {
set_window_name(STR_WINDOW_TITLE_GRABBED);
disable_mouse_accel();
ADBSetRelMouseMode(mouse_grabbed = true);
}
}
}
@ -1085,11 +815,12 @@ void driver_base::grab_mouse(void)
void driver_base::ungrab_mouse(void)
{
if (mouse_grabbed) {
mouse_grabbed = false;
update_mouse_grab();
set_window_name(STR_WINDOW_TITLE);
restore_mouse_accel();
ADBSetRelMouseMode(false);
SDL_GrabMode new_mode = set_grab_mode(SDL_GRAB_OFF);
if (new_mode == SDL_GRAB_OFF) {
set_window_name(STR_WINDOW_TITLE);
restore_mouse_accel();
ADBSetRelMouseMode(mouse_grabbed = false);
}
}
}
@ -1120,7 +851,8 @@ static void keycode_init(void)
keycode_table[i] = -1;
// Search for server vendor string, then read keycodes
const char * video_driver = SDL_GetCurrentVideoDriver();
char video_driver[256];
SDL_VideoDriverName(video_driver, sizeof(video_driver));
bool video_driver_found = false;
char line[256];
int n_keys = 0;
@ -1153,7 +885,7 @@ static void keycode_init(void)
static const char sdl_str[] = "sdl";
if (strncmp(line, sdl_str, sizeof(sdl_str) - 1) == 0) {
char *p = line + sizeof(sdl_str);
if (video_driver && strstr(video_driver, p) == video_driver)
if (strstr(video_driver, p) == video_driver)
video_driver_found = true;
}
}
@ -1166,12 +898,12 @@ static void keycode_init(void)
// Vendor not found? Then display warning
if (!video_driver_found) {
char str[256];
snprintf(str, sizeof(str), GetString(STR_KEYCODE_VENDOR_WARN), video_driver ? video_driver : "", kc_path ? kc_path : KEYCODE_FILE_NAME);
snprintf(str, sizeof(str), GetString(STR_KEYCODE_VENDOR_WARN), video_driver, kc_path ? kc_path : KEYCODE_FILE_NAME);
WarningAlert(str);
return;
}
D(bug("Using SDL/%s keycodes table, %d key mappings\n", video_driver ? video_driver : "", n_keys));
D(bug("Using SDL/%s keycodes table, %d key mappings\n", video_driver, n_keys));
}
}
@ -1212,7 +944,7 @@ bool SDL_monitor_desc::video_open(void)
// Start redraw/input thread
#ifndef USE_CPU_EMUL_SERVICES
redraw_thread_cancel = false;
redraw_thread_active = ((redraw_thread = SDL_CreateThread(redraw_func, "Redraw Thread", NULL)) != NULL);
redraw_thread_active = ((redraw_thread = SDL_CreateThread(redraw_func, NULL)) != NULL);
if (!redraw_thread_active) {
printf("FATAL: cannot create redraw thread\n");
return false;
@ -1290,11 +1022,7 @@ bool VideoInit(bool classic)
default_height = sdl_display_height();
// Mac screen depth follows X depth
screen_depth = 32;
SDL_DisplayMode desktop_mode;
if (SDL_GetDesktopDisplayMode(0, &desktop_mode) == 0) {
screen_depth = SDL_BITSPERPIXEL(desktop_mode.format);
}
screen_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
int default_depth;
switch (screen_depth) {
case 8:
@ -1351,6 +1079,8 @@ bool VideoInit(bool classic)
const int h = video_modes[i].h;
if (i > 0 && (w >= default_width || h >= default_height))
continue;
if (w == 512 && h == 384)
continue;
for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++)
add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)d), d);
}
@ -1490,18 +1220,18 @@ static void do_toggle_fullscreen(void)
while (!thread_stop_ack) ;
#endif
// Apply fullscreen
if (sdl_window) {
if (display_type == DISPLAY_SCREEN) {
display_type = DISPLAY_WINDOW;
SDL_SetWindowFullscreen(sdl_window, 0);
} else {
display_type = DISPLAY_SCREEN;
SDL_SetWindowFullscreen(sdl_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
}
}
// save the mouse position
int x, y;
SDL_GetMouseState(&x, &y);
// save the screen contents
SDL_Surface *tmp_surface = SDL_ConvertSurface(drv->s, drv->s->format,
drv->s->flags);
// switch modes
display_type = (display_type == DISPLAY_SCREEN) ? DISPLAY_WINDOW
: DISPLAY_SCREEN;
drv->set_video_mode(display_type == DISPLAY_SCREEN ? SDL_FULLSCREEN : 0);
drv->adapt_to_video_mode();
// reset the palette
@ -1510,12 +1240,20 @@ static void do_toggle_fullscreen(void)
#endif
drv->update_palette();
// restore the screen contents
SDL_BlitSurface(tmp_surface, NULL, drv->s, NULL);
SDL_FreeSurface(tmp_surface);
SDL_UpdateRect(drv->s, 0, 0, 0, 0);
// reset the video refresh handler
VideoRefreshInit();
// while SetVideoMode is happening, control key up may be missed
ADBKeyUp(0x36);
// restore the mouse position
SDL_WarpMouse(x, y);
// resume redraw thread
toggle_fullscreen = false;
#ifndef USE_CPU_EMUL_SERVICES
@ -1531,26 +1269,6 @@ static void do_toggle_fullscreen(void)
* Execute video VBL routine
*/
static bool is_fullscreen(SDL_Window * window)
{
#ifdef __MACOSX__
// On OSX, SDL, at least as of 2.0.5 (and possibly beyond), does not always
// report changes to fullscreen via the SDL_WINDOW_FULLSCREEN flag.
// (Example: https://bugzilla.libsdl.org/show_bug.cgi?id=3766 , which
// involves fullscreen/windowed toggles via window-manager UI controls).
// Until it does, or adds a facility to do so, we'll use a platform-specific
// code path to detect fullscreen changes.
extern bool is_fullscreen_osx(SDL_Window * window);
return is_fullscreen_osx(sdl_window);
#else
if (!window) {
return false;
}
const Uint32 sdl_window_flags = SDL_GetWindowFlags(sdl_window);
return (sdl_window_flags & SDL_WINDOW_FULLSCREEN) != 0;
#endif
}
#ifdef SHEEPSHAVER
void VideoVBL(void)
{
@ -1560,8 +1278,6 @@ void VideoVBL(void)
if (toggle_fullscreen)
do_toggle_fullscreen();
present_sdl_video();
// Temporarily give up frame buffer lock (this is the point where
// we are suspended when the user presses Ctrl-Tab)
@ -1585,8 +1301,6 @@ void VideoInterrupt(void)
if (toggle_fullscreen)
do_toggle_fullscreen();
present_sdl_video();
// Temporarily give up frame buffer lock (this is the point where
// we are suspended when the user presses Ctrl-Tab)
UNLOCK_FRAME_BUFFER;
@ -1627,12 +1341,7 @@ void SDL_monitor_desc::set_palette(uint8 *pal, int num_in)
// Convert colors to XColor array
int num_out = 256;
bool stretch = false;
if (!sdl_palette) {
sdl_palette = SDL_AllocPalette(num_out);
}
SDL_Color *p = sdl_palette->colors;
SDL_Color *p = sdl_palette;
for (int i=0; i<num_out; i++) {
int c = (stretch ? (i * num_in) / num_out : i);
p->r = pal[c*3 + 0] * 0x0101;
@ -1735,7 +1444,25 @@ bool video_can_change_cursor(void)
if (display_type != DISPLAY_WINDOW)
return false;
#if defined(__APPLE__)
static char driver[] = "Quartz?";
static int quartzok = -1;
if (quartzok < 0) {
if (SDL_VideoDriverName(driver, sizeof driver) == NULL || strncmp(driver, "Quartz", sizeof driver))
quartzok = true;
else {
// Quartz driver bug prevents cursor changing in SDL 1.2.11 to 1.2.14.
const SDL_version *vp = SDL_Linked_Version();
int version = SDL_VERSIONNUM(vp->major, vp->minor, vp->patch);
quartzok = (version <= SDL_VERSIONNUM(1, 2, 10) || version >= SDL_VERSIONNUM(1, 2, 15));
}
}
return quartzok;
#else
return true;
#endif
}
#endif
@ -1770,8 +1497,7 @@ void video_set_cursor(void)
if (visible) {
int x, y;
SDL_GetMouseState(&x, &y);
printf("WarpMouse to {%d,%d} via video_set_cursor\n", x, y);
SDL_WarpMouseGlobal(x, y);
SDL_WarpMouse(x, y);
}
}
}
@ -1787,25 +1513,27 @@ void video_set_cursor(void)
static bool is_modifier_key(SDL_KeyboardEvent const & e)
{
switch (e.keysym.sym) {
case SDLK_NUMLOCKCLEAR:
case SDLK_NUMLOCK:
case SDLK_CAPSLOCK:
case SDLK_SCROLLLOCK:
case SDLK_SCROLLOCK:
case SDLK_RSHIFT:
case SDLK_LSHIFT:
case SDLK_RCTRL:
case SDLK_LCTRL:
case SDLK_RALT:
case SDLK_LALT:
case SDLK_RGUI:
case SDLK_LGUI:
case SDLK_RMETA:
case SDLK_LMETA:
case SDLK_LSUPER:
case SDLK_RSUPER:
case SDLK_MODE:
case SDLK_APPLICATION:
case SDLK_COMPOSE:
return true;
}
return false;
}
static bool is_ctrl_down(SDL_Keysym const & ks)
static bool is_ctrl_down(SDL_keysym const & ks)
{
return ctrl_down || (ks.mod & KMOD_CTRL);
}
@ -1816,7 +1544,7 @@ static bool is_ctrl_down(SDL_Keysym const & ks)
* and -2 if the key was recognized as a hotkey
*/
static int kc_decode(SDL_Keysym const & ks, bool key_down)
static int kc_decode(SDL_keysym const & ks, bool key_down)
{
switch (ks.sym) {
case SDLK_a: return 0x00;
@ -1888,17 +1616,19 @@ static int kc_decode(SDL_Keysym const & ks, bool key_down)
#if (defined(__APPLE__) && defined(__MACH__))
case SDLK_LALT: return 0x3a;
case SDLK_RALT: return 0x3a;
case SDLK_LGUI: return 0x37;
case SDLK_RGUI: return 0x37;
case SDLK_LMETA: return 0x37;
case SDLK_RMETA: return 0x37;
#else
case SDLK_LALT: return 0x37;
case SDLK_RALT: return 0x37;
case SDLK_LGUI: return 0x3a;
case SDLK_RGUI: return 0x3a;
case SDLK_LMETA: return 0x3a;
case SDLK_RMETA: return 0x3a;
#endif
case SDLK_LSUPER: return 0x3a; // "Windows" key
case SDLK_RSUPER: return 0x3a;
case SDLK_MENU: return 0x32;
case SDLK_CAPSLOCK: return 0x39;
case SDLK_NUMLOCKCLEAR: return 0x47;
case SDLK_NUMLOCK: return 0x47;
case SDLK_UP: return 0x3e;
case SDLK_DOWN: return 0x3d;
@ -1911,7 +1641,7 @@ static int kc_decode(SDL_Keysym const & ks, bool key_down)
case SDLK_F2: return 0x78;
case SDLK_F3: return 0x63;
case SDLK_F4: return 0x76;
case SDLK_F5: return 0x60;
case SDLK_F5: if (is_ctrl_down(ks)) {if (!key_down) drv->toggle_mouse_grab(); return -2;} else return 0x60;
case SDLK_F6: return 0x61;
case SDLK_F7: return 0x62;
case SDLK_F8: return 0x64;
@ -1920,20 +1650,20 @@ static int kc_decode(SDL_Keysym const & ks, bool key_down)
case SDLK_F11: return 0x67;
case SDLK_F12: return 0x6f;
case SDLK_PRINTSCREEN: return 0x69;
case SDLK_SCROLLLOCK: return 0x6b;
case SDLK_PRINT: return 0x69;
case SDLK_SCROLLOCK: return 0x6b;
case SDLK_PAUSE: return 0x71;
case SDLK_KP_0: return 0x52;
case SDLK_KP_1: return 0x53;
case SDLK_KP_2: return 0x54;
case SDLK_KP_3: return 0x55;
case SDLK_KP_4: return 0x56;
case SDLK_KP_5: return 0x57;
case SDLK_KP_6: return 0x58;
case SDLK_KP_7: return 0x59;
case SDLK_KP_8: return 0x5b;
case SDLK_KP_9: return 0x5c;
case SDLK_KP0: return 0x52;
case SDLK_KP1: return 0x53;
case SDLK_KP2: return 0x54;
case SDLK_KP3: return 0x55;
case SDLK_KP4: return 0x56;
case SDLK_KP5: return 0x57;
case SDLK_KP6: return 0x58;
case SDLK_KP7: return 0x59;
case SDLK_KP8: return 0x5b;
case SDLK_KP9: return 0x5c;
case SDLK_KP_PERIOD: return 0x41;
case SDLK_KP_PLUS: return 0x45;
case SDLK_KP_MINUS: return 0x4e;
@ -1973,78 +1703,15 @@ static void force_complete_window_refresh()
* SDL event handling
*/
// possible return codes for SDL-registered event watches
enum : int {
EVENT_DROP_FROM_QUEUE = 0,
EVENT_ADD_TO_QUEUE = 1
};
// Some events need to be processed in the host-app's main thread, due to
// host-OS requirements.
//
// This function is called by SDL, whenever it generates an SDL_Event. It has
// the ability to process events, and optionally, to prevent them from being
// added to SDL's event queue (and retrieve-able via SDL_PeepEvents(), etc.)
static int SDLCALL on_sdl_event_generated(void *userdata, SDL_Event * event)
{
switch (event->type) {
case SDL_KEYUP: {
SDL_Keysym const & ks = event->key.keysym;
switch (ks.sym) {
case SDLK_F5: {
if (is_ctrl_down(ks)) {
drv->toggle_mouse_grab();
return EVENT_DROP_FROM_QUEUE;
}
} break;
}
} break;
case SDL_WINDOWEVENT: {
switch (event->window.event) {
case SDL_WINDOWEVENT_RESIZED: {
// Handle changes of fullscreen. This is done here, in
// on_sdl_event_generated() and not the main SDL_Event-processing
// loop, in order to perform this change on the main thread.
// (Some os'es UI APIs, such as OSX's NSWindow, are not
// thread-safe.)
const bool is_full = is_fullscreen(sdl_window);
const bool adjust_fullscreen = \
(display_type == DISPLAY_WINDOW && is_full) ||
(display_type == DISPLAY_SCREEN && !is_full);
if (adjust_fullscreen) {
do_toggle_fullscreen();
#if __MACOSX__
// HACK-FIX: on OSX hosts, make sure that the OSX menu
// bar does not show up in fullscreen mode, when the
// cursor is near the top of the screen, lest the
// guest OS' menu bar be obscured.
if (is_full) {
extern void set_menu_bar_visible_osx(bool);
set_menu_bar_visible_osx(false);
}
#endif
}
} break;
}
} break;
}
return EVENT_ADD_TO_QUEUE;
}
static void handle_events(void)
{
SDL_Event events[10];
const int n_max_events = sizeof(events) / sizeof(events[0]);
int n_events;
while ((n_events = SDL_PeepEvents(events, n_max_events, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) > 0) {
while ((n_events = SDL_PeepEvents(events, n_max_events, SDL_GETEVENT, sdl_eventmask)) > 0) {
for (int i = 0; i < n_events; i++) {
SDL_Event & event = events[i];
SDL_Event const & event = events[i];
switch (event.type) {
// Mouse button
@ -2143,28 +1810,24 @@ static void handle_events(void)
}
break;
}
case SDL_WINDOWEVENT: {
switch (event.window.event) {
// Hidden parts exposed, force complete refresh of window
case SDL_WINDOWEVENT_EXPOSED:
force_complete_window_refresh();
break;
// Force a complete window refresh when activating, to avoid redraw artifacts otherwise.
case SDL_WINDOWEVENT_RESTORED:
force_complete_window_refresh();
break;
}
// Hidden parts exposed, force complete refresh of window
case SDL_VIDEOEXPOSE:
force_complete_window_refresh();
break;
}
// Window "close" widget clicked
case SDL_QUIT:
ADBKeyDown(0x7f); // Power key
ADBKeyUp(0x7f);
break;
// Application activate/deactivate
case SDL_ACTIVEEVENT:
// Force a complete window refresh when activating, to avoid redraw artifacts otherwise.
if (event.active.gain && (event.active.state & SDL_APPACTIVE))
force_complete_window_refresh();
break;
}
}
}
@ -2261,7 +1924,7 @@ static void update_display_static(driver_base *drv)
SDL_UnlockSurface(drv->s);
// Refresh display
update_sdl_video(drv->s, x1, y1, wide, high);
SDL_UpdateRect(drv->s, x1, y1, wide, high);
}
} else {
@ -2317,7 +1980,7 @@ static void update_display_static(driver_base *drv)
SDL_UnlockSurface(drv->s);
// Refresh display
update_sdl_video(drv->s, x1, y1, wide, high);
SDL_UpdateRect(drv->s, x1, y1, wide, high);
}
}
}
@ -2380,8 +2043,8 @@ static void update_display_static_bbox(driver_base *drv)
// Refresh display
if (nr_boxes)
update_sdl_video();
}
SDL_UpdateRects(drv->s, nr_boxes, boxes);
}
// We suggest the compiler to inline the next two functions so that it

2601
BasiliskII/src/SDL/video_sdl2.cpp Executable file

File diff suppressed because it is too large Load Diff