--- BasiliskII/src/SDL/video_sdl.cpp 2005/06/06 21:20:28 1.19 +++ BasiliskII/src/SDL/video_sdl.cpp 2006/05/13 16:58:44 1.26 @@ -101,10 +101,14 @@ static uint8 *the_buffer_copy = NULL; static uint32 the_buffer_size; // Size of allocated the_buffer static bool redraw_thread_active = false; // Flag: Redraw thread installed +#ifndef USE_CPU_EMUL_SERVICES static volatile bool redraw_thread_cancel; // Flag: Cancel Redraw thread static SDL_Thread *redraw_thread = NULL; // Redraw thread +#ifdef SHEEPSHAVER static volatile bool thread_stop_req = false; static volatile bool thread_stop_ack = false; // Acknowledge for thread_stop_req +#endif +#endif #ifdef ENABLE_VOSF static bool use_vosf = false; // Flag: VOSF enabled @@ -131,6 +135,11 @@ static SDL_Color sdl_palette[256]; / static bool sdl_palette_changed = false; // Flag: Palette changed, redraw thread must set new colors static const int sdl_eventmask = SDL_MOUSEBUTTONDOWNMASK | SDL_MOUSEBUTTONUPMASK | SDL_MOUSEMOTIONMASK | SDL_KEYUPMASK | SDL_KEYDOWNMASK | SDL_VIDEOEXPOSEMASK | SDL_QUITMASK; +// Mutex to protect SDL events +static SDL_mutex *sdl_events_lock = NULL; +#define LOCK_EVENTS SDL_LockMutex(sdl_events_lock) +#define UNLOCK_EVENTS SDL_UnlockMutex(sdl_events_lock) + // Mutex to protect palette static SDL_mutex *sdl_palette_lock = NULL; #define LOCK_PALETTE SDL_LockMutex(sdl_palette_lock) @@ -154,20 +163,37 @@ extern void SysMountFirstFloppy(void); /* + * SDL surface locking glue + */ + +#ifdef ENABLE_VOSF +#define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE) do { \ + if ((SURFACE)->flags & (SDL_HWSURFACE | SDL_FULLSCREEN)) \ + the_host_buffer = (uint8 *)(SURFACE)->pixels; \ +} while (0) +#else +#define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE) +#endif + +#define SDL_VIDEO_LOCK_SURFACE(SURFACE) do { \ + if (SDL_MUSTLOCK(SURFACE)) { \ + SDL_LockSurface(SURFACE); \ + SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE); \ + } \ +} while (0) + +#define SDL_VIDEO_UNLOCK_SURFACE(SURFACE) do { \ + if (SDL_MUSTLOCK(SURFACE)) \ + SDL_UnlockSurface(SURFACE); \ +} while (0) + + +/* * Framebuffer allocation routines */ static void *vm_acquire_framebuffer(uint32 size) { -#ifdef SHEEPSHAVER -#ifdef DIRECT_ADDRESSING_HACK - const uint32 FRAME_BUFFER_BASE = 0x61000000; - uint8 *fb = Mac2HostAddr(FRAME_BUFFER_BASE); - if (vm_acquire_fixed(fb, size) < 0) - fb = VM_MAP_FAILED; - return fb; -#endif -#endif return vm_acquire(size); } @@ -178,6 +204,44 @@ static inline void vm_release_framebuffe /* + * Windows message handler + */ + +#ifdef WIN32 +#include +static WNDPROC sdl_window_proc = NULL; // Window proc used by SDL + +extern void SysMediaArrived(void); +extern void SysMediaRemoved(void); +extern HWND GetMainWindowHandle(void); + +static LRESULT CALLBACK windows_message_handler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_DEVICECHANGE: + if (wParam == DBT_DEVICEREMOVECOMPLETE) { + DEV_BROADCAST_HDR *p = (DEV_BROADCAST_HDR *)lParam; + if (p->dbch_devicetype == DBT_DEVTYP_VOLUME) + SysMediaRemoved(); + } + else if (wParam == DBT_DEVICEARRIVAL) { + DEV_BROADCAST_HDR *p = (DEV_BROADCAST_HDR *)lParam; + if (p->dbch_devicetype == DBT_DEVTYP_VOLUME) + SysMediaArrived(); + } + return 0; + + default: + if (sdl_window_proc) + return CallWindowProc(sdl_window_proc, hwnd, msg, wParam, lParam); + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} +#endif + + +/* * SheepShaver glue */ @@ -222,69 +286,21 @@ static vector VideoMonit // Find Apple mode matching best specified dimensions static int find_apple_resolution(int xsize, int ysize) { - int apple_id; - if (xsize < 800) - apple_id = APPLE_640x480; - else if (xsize < 1024) - apple_id = APPLE_800x600; - else if (xsize < 1152) - apple_id = APPLE_1024x768; - else if (xsize < 1280) { - if (ysize < 900) - apple_id = APPLE_1152x768; - else - apple_id = APPLE_1152x900; - } - else if (xsize < 1600) - apple_id = APPLE_1280x1024; - else - apple_id = APPLE_1600x1200; - return apple_id; -} - -// Set parameters to specified Apple mode -static void set_apple_resolution(int apple_id, int &xsize, int &ysize) -{ - switch (apple_id) { - case APPLE_640x480: - xsize = 640; - ysize = 480; - break; - case APPLE_800x600: - xsize = 800; - ysize = 600; - break; - case APPLE_1024x768: - xsize = 1024; - ysize = 768; - break; - case APPLE_1152x768: - xsize = 1152; - ysize = 768; - break; - case APPLE_1152x900: - xsize = 1152; - ysize = 900; - break; - case APPLE_1280x1024: - xsize = 1280; - ysize = 1024; - break; - case APPLE_1600x1200: - xsize = 1600; - ysize = 1200; - break; - default: - abort(); - } -} - -// Match Apple mode matching best specified dimensions -static int match_apple_resolution(int &xsize, int &ysize) -{ - int apple_id = find_apple_resolution(xsize, ysize); - set_apple_resolution(apple_id, xsize, ysize); - return apple_id; + if (xsize == 640 && ysize == 480) + return APPLE_640x480; + if (xsize == 800 && ysize == 600) + return APPLE_800x600; + if (xsize == 1024 && ysize == 768) + return APPLE_1024x768; + if (xsize == 1152 && ysize == 768) + return APPLE_1152x768; + if (xsize == 1152 && ysize == 900) + return APPLE_1152x900; + if (xsize == 1280 && ysize == 1024) + return APPLE_1280x1024; + if (xsize == 1600 && ysize == 1200) + return APPLE_1600x1200; + return APPLE_CUSTOM; } // Display error alert @@ -391,69 +407,74 @@ static int sdl_depth_of_video_depth(int return (video_depth <= VIDEO_DEPTH_8BIT) ? 8 : mac_depth_of_video_depth(video_depth); } +// Get screen dimensions +static void sdl_display_dimensions(int &width, int &height) +{ + 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 = max_width; + height = max_height; +} + +static inline int sdl_display_width(void) +{ + int width, height; + sdl_display_dimensions(width, height); + return width; +} + +static inline int sdl_display_height(void) +{ + int width, height; + sdl_display_dimensions(width, height); + return height; +} + // Check wether specified mode is available -static bool has_mode(int type, int width, int height) +static bool has_mode(int type, int width, int height, int depth) { #ifdef SHEEPSHAVER - // Filter out Classic resolutiosn + // Filter out Classic resolutions if (width == 512 && height == 384) return false; +#endif - // "screen" prefs items always succeeds - if (PrefsFindString("screen")) - return true; - - // Read window & screen modes prefs - static uint32 window_modes = 0; - static uint32 screen_modes = 0; - if (window_modes == 0 || screen_modes == 0) { - window_modes = PrefsFindInt32("windowmodes"); - screen_modes = PrefsFindInt32("screenmodes"); - if (window_modes == 0 || screen_modes == 0) - window_modes |= 3; // Allow at least 640x480 and 800x600 window modes - } - - int test_modes; - switch (type) { - case DISPLAY_WINDOW: - test_modes = window_modes; - break; - case DISPLAY_SCREEN: - test_modes = screen_modes; - break; - default: - test_modes = 0; - break; - } + // Filter out out-of-bounds resolutions + if (width > sdl_display_width() || height > sdl_display_height()) + return false; - int apple_mask; - switch (find_apple_resolution(width, height)) { - case APPLE_640x480: apple_mask = 0x01; break; - case APPLE_800x600: apple_mask = 0x02; break; - case APPLE_1024x768: apple_mask = 0x04; break; - case APPLE_1152x768: apple_mask = 0x40; break; - case APPLE_1152x900: apple_mask = 0x08; break; - case APPLE_1280x1024: apple_mask = 0x10; break; - case APPLE_1600x1200: apple_mask = 0x20; break; - default: apple_mask = 0x00; break; - } - return (test_modes & apple_mask); -#endif - 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)); } // Add mode to list of supported modes static void add_mode(int type, int width, int height, int resolution_id, int bytes_per_row, int depth) { // Filter out unsupported modes - if (!has_mode(type, width, height)) + if (!has_mode(type, width, height, depth)) return; // Fill in VideoMode entry VIDEO_MODE mode; #ifdef SHEEPSHAVER - // Recalculate dimensions to fit Apple modes - resolution_id = match_apple_resolution(width, height); + resolution_id = find_apple_resolution(width, height); mode.viType = type; #endif VIDEO_MODE_X = width; @@ -464,19 +485,6 @@ static void add_mode(int type, int width VideoModes.push_back(mode); } -// Add standard list of windowed modes for given color depth -static void add_window_modes(int depth) -{ - video_depth vdepth = (video_depth)depth; - add_mode(DISPLAY_WINDOW, 512, 384, 0x80, TrivialBytesPerRow(512, vdepth), depth); - add_mode(DISPLAY_WINDOW, 640, 480, 0x81, TrivialBytesPerRow(640, vdepth), depth); - add_mode(DISPLAY_WINDOW, 800, 600, 0x82, TrivialBytesPerRow(800, vdepth), depth); - add_mode(DISPLAY_WINDOW, 1024, 768, 0x83, TrivialBytesPerRow(1024, vdepth), depth); - add_mode(DISPLAY_WINDOW, 1152, 870, 0x84, TrivialBytesPerRow(1152, vdepth), depth); - add_mode(DISPLAY_WINDOW, 1280, 1024, 0x85, TrivialBytesPerRow(1280, vdepth), depth); - add_mode(DISPLAY_WINDOW, 1600, 1200, 0x86, TrivialBytesPerRow(1600, vdepth), depth); -} - // Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac) static void set_mac_frame_buffer(SDL_monitor_desc &monitor, int depth, bool native_byte_order) { @@ -520,6 +528,55 @@ static SDL_GrabMode set_grab_mode(SDL_Gr return (vi && vi->wm_available ? SDL_WM_GrabInput(mode) : SDL_GRAB_OFF); } +// Migrate preferences items (XXX to be handled in MigratePrefs()) +static void migrate_screen_prefs(void) +{ +#ifdef SHEEPSHAVER + // Look-up priorities are: "screen", "screenmodes", "windowmodes". + if (PrefsFindString("screen")) + return; + + uint32 window_modes = PrefsFindInt32("windowmodes"); + uint32 screen_modes = PrefsFindInt32("screenmodes"); + int width = 0, height = 0; + if (screen_modes) { + static const struct { + int id; + int width; + int height; + } + modes[] = { + { 1, 640, 480 }, + { 2, 800, 600 }, + { 4, 1024, 768 }, + { 64, 1152, 768 }, + { 8, 1152, 900 }, + { 16, 1280, 1024 }, + { 32, 1600, 1200 }, + { 0, } + }; + for (int i = 0; modes[i].id != 0; i++) { + if (screen_modes & modes[i].id) { + if (width < modes[i].width && height < modes[i].height) { + width = modes[i].width; + height = modes[i].height; + } + } + } + } else { + if (window_modes & 1) + width = 640, height = 480; + if (window_modes & 2) + width = 800, height = 600; + } + if (width && height) { + char str[32]; + sprintf(str, "%s/%d/%d", screen_modes ? "dga" : "win", width, height); + PrefsReplaceString("screen", str); + } +#endif +} + /* * Display "driver" classes @@ -999,6 +1056,13 @@ bool SDL_monitor_desc::video_open(void) return false; } +#ifdef WIN32 + // Chain in a new message handler for WM_DEVICECHANGE + HWND the_window = GetMainWindowHandle(); + sdl_window_proc = (WNDPROC)GetWindowLongPtr(the_window, GWLP_WNDPROC); + SetWindowLongPtr(the_window, GWLP_WNDPROC, (LONG_PTR)windows_message_handler); +#endif + // Initialize VideoRefresh function VideoRefreshInit(); @@ -1006,12 +1070,16 @@ bool SDL_monitor_desc::video_open(void) LOCK_FRAME_BUFFER; // Start redraw/input thread +#ifndef USE_CPU_EMUL_SERVICES redraw_thread_cancel = false; redraw_thread_active = ((redraw_thread = SDL_CreateThread(redraw_func, NULL)) != NULL); if (!redraw_thread_active) { printf("FATAL: cannot create redraw thread\n"); return false; } +#else + redraw_thread_active = true; +#endif return true; } @@ -1032,6 +1100,8 @@ bool VideoInit(bool classic) #endif // Create Mutexes + if ((sdl_events_lock = SDL_CreateMutex()) == NULL) + return false; if ((sdl_palette_lock = SDL_CreateMutex()) == NULL) return false; if ((frame_buffer_lock = SDL_CreateMutex()) == NULL) @@ -1046,6 +1116,7 @@ bool VideoInit(bool classic) mouse_wheel_lines = PrefsFindInt32("mousewheellines"); // Get screen mode from preferences + migrate_screen_prefs(); const char *mode_str = NULL; if (classic_mode) mode_str = "win/512/342"; @@ -1069,28 +1140,14 @@ bool VideoInit(bool classic) else if (sscanf(mode_str, "dga/%d/%d", &default_width, &default_height) == 2) display_type = DISPLAY_SCREEN; } - int 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; - } - } - if (default_width > max_width) - default_width = max_width; - if (default_height > max_height) - default_height = max_height; - } if (default_width <= 0) - default_width = max_width; + default_width = sdl_display_width(); + else if (default_width > sdl_display_width()) + default_width = sdl_display_width(); if (default_height <= 0) - default_height = max_height; + default_height = sdl_display_height(); + else if (default_height > sdl_display_height()) + default_height = sdl_display_height(); // Mac screen depth follows X depth screen_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel; @@ -1110,47 +1167,51 @@ bool VideoInit(bool classic) break; } + // Initialize list of video modes to try + struct { + int w; + int h; + int resolution_id; + } + video_modes[] = { + { -1, -1, 0x80 }, + { 512, 384, 0x80 }, + { 640, 480, 0x81 }, + { 800, 600, 0x82 }, + { 1024, 768, 0x83 }, + { 1152, 870, 0x84 }, + { 1280, 1024, 0x85 }, + { 1600, 1200, 0x86 }, + { 0, } + }; + video_modes[0].w = default_width; + video_modes[0].h = default_height; + // Construct list of supported modes if (display_type == DISPLAY_WINDOW) { if (classic) add_mode(display_type, 512, 342, 0x80, 64, VIDEO_DEPTH_1BIT); else { - for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++) { - int bpp = sdl_depth_of_video_depth(d); - if (SDL_VideoModeOK(max_width, max_height, bpp, SDL_HWSURFACE)) - add_window_modes(video_depth(d)); + for (int i = 0; video_modes[i].w != 0; i++) { + const int w = video_modes[i].w; + const int h = video_modes[i].h; + if (i > 0 && (w >= default_width || h >= default_height)) + 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); } } } else if (display_type == DISPLAY_SCREEN) { - struct { - int w; - int h; - int resolution_id; - } - video_modes[] = { - { -1, -1, 0x80 }, - { 640, 480, 0x81 }, - { 800, 600, 0x82 }, - { 1024, 768, 0x83 }, - { 1152, 870, 0x84 }, - { 1280, 1024, 0x85 }, - { 1600, 1200, 0x86 }, - { 0, } - }; - video_modes[0].w = default_width; - video_modes[0].h = default_height; - for (int i = 0; video_modes[i].w != 0; i++) { const int w = video_modes[i].w; const int h = video_modes[i].h; if (i > 0 && (w >= default_width || h >= default_height)) continue; + if (w == 512 && h == 384) + continue; #ifdef ENABLE_VOSF - for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++) { - int bpp = sdl_depth_of_video_depth(d); - if (SDL_VideoModeOK(w, h, bpp, SDL_HWSURFACE | SDL_FULLSCREEN)) - add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)d), d); - } + 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); #else add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)default_depth), default_depth); #endif @@ -1227,11 +1288,19 @@ void SDL_monitor_desc::video_close(void) { D(bug("video_close()\n")); +#ifdef WIN32 + // Remove message handler for WM_DEVICECHANGE + HWND the_window = GetMainWindowHandle(); + SetWindowLongPtr(the_window, GWLP_WNDPROC, (LONG_PTR)sdl_window_proc); +#endif + // Stop redraw thread +#ifndef USE_CPU_EMUL_SERVICES if (redraw_thread_active) { redraw_thread_cancel = true; SDL_WaitThread(redraw_thread, NULL); } +#endif redraw_thread_active = false; // Unlock frame buffer @@ -1255,6 +1324,8 @@ void VideoExit(void) SDL_DestroyMutex(frame_buffer_lock); if (sdl_palette_lock) SDL_DestroyMutex(sdl_palette_lock); + if (sdl_events_lock) + SDL_DestroyMutex(sdl_events_lock); } @@ -1424,8 +1495,10 @@ int16 video_mode_change(VidLocals *csSav void SDL_monitor_desc::switch_to_current_mode(void) { // Close and reopen display + LOCK_EVENTS; video_close(); video_open(); + UNLOCK_EVENTS; if (drv == NULL) { ErrorAlert(STR_OPEN_WINDOW_ERR); @@ -1911,6 +1984,65 @@ static void update_display_static(driver } } +// Static display update (fixed frame rate, bounding boxes based) +// XXX use NQD bounding boxes to help detect dirty areas? +static void update_display_static_bbox(driver_window *drv) +{ + const VIDEO_MODE &mode = drv->mode; + + // Allocate bounding boxes for SDL_UpdateRects() + const int N_PIXELS = 64; + const int n_x_boxes = (VIDEO_MODE_X + N_PIXELS - 1) / N_PIXELS; + const int n_y_boxes = (VIDEO_MODE_Y + N_PIXELS - 1) / N_PIXELS; + SDL_Rect *boxes = (SDL_Rect *)alloca(sizeof(SDL_Rect) * n_x_boxes * n_y_boxes); + int nr_boxes = 0; + + // Lock surface, if required + if (SDL_MUSTLOCK(drv->s)) + SDL_LockSurface(drv->s); + + // Update the surface from Mac screen + const int bytes_per_row = VIDEO_MODE_ROW_BYTES; + const int bytes_per_pixel = bytes_per_row / VIDEO_MODE_X; + int x, y; + for (y = 0; y < VIDEO_MODE_Y; y += N_PIXELS) { + int h = N_PIXELS; + if (h > VIDEO_MODE_Y - y) + h = VIDEO_MODE_Y - y; + for (x = 0; x < VIDEO_MODE_X; x += N_PIXELS) { + int w = N_PIXELS; + if (w > VIDEO_MODE_X - x) + w = VIDEO_MODE_X - x; + const int xs = w * bytes_per_pixel; + const int xb = x * bytes_per_pixel; + bool dirty = false; + for (int j = y; j < (y + h); j++) { + const int yb = j * bytes_per_row; + if (memcmp(&the_buffer[yb + xb], &the_buffer_copy[yb + xb], xs) != 0) { + memcpy(&the_buffer_copy[yb + xb], &the_buffer[yb + xb], xs); + Screen_blit((uint8 *)drv->s->pixels + yb + xb, the_buffer + yb + xb, xs); + dirty = true; + } + } + if (dirty) { + boxes[nr_boxes].x = x; + boxes[nr_boxes].y = y; + boxes[nr_boxes].w = w; + boxes[nr_boxes].h = h; + nr_boxes++; + } + } + } + + // Unlock surface, if required + if (SDL_MUSTLOCK(drv->s)) + SDL_UnlockSurface(drv->s); + + // Refresh display + if (nr_boxes) + SDL_UpdateRects(drv->s, nr_boxes, boxes); +} + // We suggest the compiler to inline the next two functions so that it // may specialise the code according to the current screen depth and @@ -2005,7 +2137,11 @@ static void video_refresh_window_static( static int tick_counter = 0; if (++tick_counter >= frame_skip) { tick_counter = 0; - update_display_static(static_cast(drv)); + const VIDEO_MODE &mode = drv->mode; + if ((int)VIDEO_MODE_DEPTH >= VIDEO_DEPTH_8BIT) + update_display_static_bbox(static_cast(drv)); + else + update_display_static(static_cast(drv)); } } @@ -2035,9 +2171,47 @@ static void VideoRefreshInit(void) } } +static inline void do_video_refresh(void) +{ + // Handle SDL events + handle_events(); + + // Update display + video_refresh(); + +#ifdef SHEEPSHAVER + // Set new cursor image if it was changed + if (cursor_changed && sdl_cursor) { + cursor_changed = false; + LOCK_EVENTS; + SDL_FreeCursor(sdl_cursor); + sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, MacCursor[2], MacCursor[3]); + if (sdl_cursor) + SDL_SetCursor(sdl_cursor); + UNLOCK_EVENTS; + } +#endif + + // Set new palette if it was changed + handle_palette_changes(); +} + +// This function is called on non-threaded platforms from a timer interrupt +void VideoRefresh(void) +{ + // We need to check redraw_thread_active to inhibit refreshed during + // mode changes on non-threaded platforms + if (!redraw_thread_active) + return; + + // Process pending events and update display + do_video_refresh(); +} + const int VIDEO_REFRESH_HZ = 60; const int VIDEO_REFRESH_DELAY = 1000000 / VIDEO_REFRESH_HZ; +#ifndef USE_CPU_EMUL_SERVICES static int redraw_func(void *arg) { uint64 start = GetTicks_usec(); @@ -2063,28 +2237,36 @@ static int redraw_func(void *arg) } #endif - // Handle SDL events - handle_events(); + // Process pending events and update display + do_video_refresh(); + } - // Refresh display - video_refresh(); + uint64 end = GetTicks_usec(); + D(bug("%lld refreshes in %lld usec = %f refreshes/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); + return 0; +} +#endif + + +/* + * Record dirty area from NQD + */ #ifdef SHEEPSHAVER - // Set new cursor image if it was changed - if (cursor_changed && sdl_cursor) { - cursor_changed = false; - SDL_FreeCursor(sdl_cursor); - sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, MacCursor[2], MacCursor[3]); - if (sdl_cursor) - SDL_SetCursor(sdl_cursor); - } -#endif +void video_set_dirty_area(int x, int y, int w, int h) +{ + const VIDEO_MODE &mode = drv->mode; + const int screen_width = VIDEO_MODE_X; + const int screen_height = VIDEO_MODE_Y; + const int bytes_per_row = VIDEO_MODE_ROW_BYTES; - // Set new palette if it was changed - handle_palette_changes(); +#ifdef ENABLE_VOSF + if (use_vosf) { + vosf_set_dirty_area(x, y, w, h, screen_width, bytes_per_row); + return; } +#endif - uint64 end = GetTicks_usec(); - D(bug("%lld refreshes in %lld usec = %f refreshes/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); - return 0; + // XXX handle dirty bounding boxes for non-VOSF modes } +#endif