--- BasiliskII/src/SDL/video_sdl.cpp 2006/05/13 16:58:44 1.26 +++ BasiliskII/src/SDL/video_sdl.cpp 2008/01/01 09:40:32 1.34 @@ -1,7 +1,7 @@ /* * video_sdl.cpp - Video/graphics emulation, SDL specific stuff * - * Basilisk II (C) 1997-2005 Christian Bauer + * Basilisk II (C) 1997-2008 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,16 +27,15 @@ * Ctrl-F5 = grab mouse (in windowed mode) * * FIXMEs and TODOs: + * - Windows requires an extra mouse event to update the actual cursor image? * - Ctr-Tab for suspend/resume but how? SDL does not support that for non-Linux * - Ctrl-Fn doesn't generate SDL_KEYDOWN events (SDL bug?) * - Mouse acceleration, there is no API in SDL yet for that * - Force relative mode in Grab mode even if SDL provides absolute coordinates? - * - Fullscreen mode * - Gamma tables support is likely to be broken here * - Events processing is bound to the general emulation thread as SDL requires * to PumpEvents() within the same thread as the one that called SetVideoMode(). * Besides, there can't seem to be a way to call SetVideoMode() from a child thread. - * - Refresh performance is still slow. Use SDL_CreateRGBSurface()? * - Backport hw cursor acceleration to Basilisk II? * - Factor out code */ @@ -49,6 +48,10 @@ #include #include +#ifdef WIN32 +#include /* alloca() */ +#endif + #include "cpu_emulation.h" #include "main.h" #include "adb.h" @@ -194,7 +197,19 @@ extern void SysMountFirstFloppy(void); static void *vm_acquire_framebuffer(uint32 size) { - return vm_acquire(size); + // always try to reallocate framebuffer at the same address + static void *fb = VM_MAP_FAILED; + if (fb != VM_MAP_FAILED) { + if (vm_acquire_fixed(fb, size) < 0) { +#ifndef SHEEPSHAVER + printf("FATAL: Could not reallocate framebuffer at previous address\n"); +#endif + fb = VM_MAP_FAILED; + } + } + if (fb == VM_MAP_FAILED) + fb = vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT); + return fb; } static inline void vm_release_framebuffer(void *fb, uint32 size) @@ -716,6 +731,8 @@ void driver_base::restore_mouse_accel(vo * Windowed display driver */ +static bool SDL_display_opened = false; + // Open display driver_window::driver_window(SDL_monitor_desc &m) : driver_base(m), mouse_grabbed(false) @@ -727,11 +744,23 @@ driver_window::driver_window(SDL_monitor // Set absolute mouse mode ADBSetRelMouseMode(mouse_grabbed); + // This is ugly: + // If we're switching resolutions (ie, not setting it for the first time), + // there's a bug in SDL where the SDL_Surface created will not be properly + // setup. The solution is to SDL_QuitSubSystem(SDL_INIT_VIDEO) before calling + // SDL_SetVideoMode for the second time (SDL_SetVideoMode will call SDL_Init() + // and all will be well). Without this, the video becomes corrupted (at least + // on Mac OS X), after the resolution switch. + if (SDL_display_opened) + SDL_QuitSubSystem(SDL_INIT_VIDEO); + // Create surface int depth = sdl_depth_of_video_depth(VIDEO_MODE_DEPTH); if ((s = SDL_SetVideoMode(width, height, depth, SDL_HWSURFACE)) == NULL) return; + SDL_display_opened = true; + #ifdef ENABLE_VOSF use_vosf = true; // Allocate memory for frame buffer (SIZE is extended to page-boundary) @@ -2186,8 +2215,19 @@ static inline void do_video_refresh(void LOCK_EVENTS; SDL_FreeCursor(sdl_cursor); sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, MacCursor[2], MacCursor[3]); - if (sdl_cursor) + if (sdl_cursor) { SDL_SetCursor(sdl_cursor); +#ifdef WIN32 + // XXX Windows apparently needs an extra mouse event to + // make the new cursor image visible + int visible = SDL_ShowCursor(-1); + if (visible) { + int x, y; + SDL_GetMouseState(&x, &y); + SDL_WarpMouse(x, y); + } +#endif + } UNLOCK_EVENTS; } #endif @@ -2262,7 +2302,7 @@ void video_set_dirty_area(int x, int y, #ifdef ENABLE_VOSF if (use_vosf) { - vosf_set_dirty_area(x, y, w, h, screen_width, bytes_per_row); + vosf_set_dirty_area(x, y, w, h, screen_width, screen_height, bytes_per_row); return; } #endif