From 3b07ba27e4a15fad0a6aa57a5c2660cc3b8b5460 Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Thu, 11 May 2006 07:51:32 +0000 Subject: [PATCH] Introduce a new video refresh function that uses smaller bounding boxes. This does not improve graphics performance but helps CPU because it reduces the number of bytes transfered to actual screen. I saw an improvement by up to 26% in frameskip 4 800x600x16 but also a hit by 3% with frameskip 0. The next step is to use NQD bounding boxes to help detecting dirty areas. So far, this is the best I can do without VOSF working (MacOS X performance bugs -- pitifully slow Mach syscalls) --- BasiliskII/src/SDL/video_sdl.cpp | 65 +++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/BasiliskII/src/SDL/video_sdl.cpp b/BasiliskII/src/SDL/video_sdl.cpp index 3f608bf8..5435fbf7 100644 --- a/BasiliskII/src/SDL/video_sdl.cpp +++ b/BasiliskII/src/SDL/video_sdl.cpp @@ -1984,6 +1984,65 @@ static void update_display_static(driver_window *drv) } } +// 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 @@ -2078,7 +2137,11 @@ static void video_refresh_window_static(void) 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)); } }