From 31f80e338b78d8823305d2d6a55fe3511767ecfe Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Thu, 12 May 2005 11:09:31 +0000 Subject: [PATCH] Fix DGA when visible screen is smaller than virtual display, aka fix fullscreen mode when VidMode extension is enabled. Also fix SDL fullscreen to really update the screen as this is necessary by default on Linux since simple windowed is used (and not DGA for fullscreen). Always prefer the 64 pixel chunks update code. Rearrange B2 video_x.cpp to match video_vosf.h updates --- BasiliskII/src/Unix/video_vosf.h | 133 +++++++++++-------------------- BasiliskII/src/Unix/video_x.cpp | 65 ++++++++++----- 2 files changed, 90 insertions(+), 108 deletions(-) diff --git a/BasiliskII/src/Unix/video_vosf.h b/BasiliskII/src/Unix/video_vosf.h index 0f9ebcf3..9a7682ac 100644 --- a/BasiliskII/src/Unix/video_vosf.h +++ b/BasiliskII/src/Unix/video_vosf.h @@ -33,21 +33,26 @@ // Glue for SDL and X11 support #ifdef USE_SDL_VIDEO #define MONITOR_INIT SDL_monitor_desc &monitor -#define VIDEO_DRV_INIT driver_window *drv -#define VIDEO_DRV_ROW_BYTES drv->s->pitch +#define VIDEO_DRV_WIN_INIT driver_window *drv #define VIDEO_DRV_LOCK_PIXELS if (SDL_MUSTLOCK(drv->s)) SDL_LockSurface(drv->s) #define VIDEO_DRV_UNLOCK_PIXELS if (SDL_MUSTLOCK(drv->s)) SDL_UnlockSurface(drv->s) +#define VIDEO_DRV_DEPTH drv->s->format->BitsPerPixel +#define VIDEO_DRV_WIDTH drv->s->w +#define VIDEO_DRV_HEIGHT drv->s->h +#define VIDEO_DRV_ROW_BYTES drv->s->pitch #else #ifdef SHEEPSHAVER #define MONITOR_INIT /* nothing */ -#define VIDEO_DRV_INIT /* nothing */ +#define VIDEO_DRV_WIN_INIT /* nothing */ +#define VIDEO_DRV_DGA_INIT /* nothing */ #define VIDEO_DRV_WINDOW the_win #define VIDEO_DRV_GC the_gc #define VIDEO_DRV_IMAGE img #define VIDEO_DRV_HAVE_SHM have_shm #else #define MONITOR_INIT X11_monitor_desc &monitor -#define VIDEO_DRV_INIT driver_window *drv +#define VIDEO_DRV_WIN_INIT driver_window *drv +#define VIDEO_DRV_DGA_INIT driver_dga *drv #define VIDEO_DRV_WINDOW drv->w #define VIDEO_DRV_GC drv->gc #define VIDEO_DRV_IMAGE drv->img @@ -55,12 +60,14 @@ #endif #define VIDEO_DRV_LOCK_PIXELS /* nothing */ #define VIDEO_DRV_UNLOCK_PIXELS /* nothing */ +#define VIDEO_DRV_DEPTH VIDEO_DRV_IMAGE->depth +#define VIDEO_DRV_WIDTH VIDEO_DRV_IMAGE->width +#define VIDEO_DRV_HEIGHT VIDEO_DRV_IMAGE->height #define VIDEO_DRV_ROW_BYTES VIDEO_DRV_IMAGE->bytes_per_line #endif // Variables for Video on SEGV support static uint8 *the_host_buffer; // Host frame buffer in VOSF mode -static uint32 the_host_buffer_row_bytes; // Host frame buffer number of bytes per row struct ScreenPageInfo { int top, bottom; // Mapping between this virtual page and Mac scanlines @@ -377,7 +384,7 @@ There are two cases to check: than pageCount. */ -static inline void update_display_window_vosf(VIDEO_DRV_INIT) +static inline void update_display_window_vosf(VIDEO_DRV_WIN_INIT) { VIDEO_MODE_INIT; @@ -431,20 +438,44 @@ static inline void update_display_window_vosf(VIDEO_DRV_INIT) */ #if REAL_ADDRESSING || DIRECT_ADDRESSING -static inline void update_display_dga_vosf(void) +static inline void update_display_dga_vosf(VIDEO_DRV_DGA_INIT) { VIDEO_MODE_INIT; + // Compute number of bytes per row, take care to virtual screens + const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES; + const int dst_bytes_per_row = TrivialBytesPerRow(VIDEO_MODE_X, DepthModeForPixelDepth(VIDEO_DRV_DEPTH)); + const int scr_bytes_per_row = VIDEO_DRV_ROW_BYTES; + assert(dst_bytes_per_row <= scr_bytes_per_row); + const int scr_bytes_left = scr_bytes_per_row - dst_bytes_per_row; + + // Full screen update requested? if (mainBuffer.very_dirty) { PFLAG_CLEAR_ALL; vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ); - VIDEO_DRV_LOCK_PIXELS; memcpy(the_buffer_copy, the_buffer, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y); - Screen_blit(the_host_buffer, the_buffer, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y); + VIDEO_DRV_LOCK_PIXELS; + int i1 = 0, i2 = 0; + for (int j = 0; j < VIDEO_MODE_Y; j++) { + Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row); + i1 += src_bytes_per_row; + i2 += scr_bytes_per_row; + } +#ifdef USE_SDL_VIDEO + SDL_UpdateRect(drv->s, 0, 0, VIDEO_MODE_X, VIDEO_MODE_Y); +#endif VIDEO_DRV_UNLOCK_PIXELS; return; } + // Setup partial blitter (use 64-pixel wide chunks) + const int n_pixels = 64; + const int n_chunks = VIDEO_MODE_X / n_pixels; + const int src_chunk_size = src_bytes_per_row / n_chunks; + const int dst_chunk_size = dst_bytes_per_row / n_chunks; + const int src_chunk_size_left = src_bytes_per_row - (n_chunks * src_chunk_size); + const int dst_chunk_size_left = dst_bytes_per_row - (n_chunks * dst_chunk_size); + int page = 0; for (;;) { const unsigned first_page = find_next_page_set(page); @@ -463,24 +494,18 @@ static inline void update_display_dga_vosf(void) const int y1 = mainBuffer.pageInfo[first_page].top; const int y2 = mainBuffer.pageInfo[page - 1].bottom; -#ifndef USE_SDL_VIDEO - // Update the_host_buffer and copy of the_buffer (use 64 bytes chunks) - const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES; - const int dst_bytes_per_row = the_host_buffer_row_bytes; - const int n_pixels = 64; - const int n_chunks = VIDEO_MODE_X / n_pixels; - const int src_chunk_size = src_bytes_per_row / n_chunks; - const int dst_chunk_size = dst_bytes_per_row / n_chunks; - const int src_chunk_size_left = src_bytes_per_row - (n_chunks * src_chunk_size); - const int dst_chunk_size_left = dst_bytes_per_row - (n_chunks * dst_chunk_size); + // Update the_host_buffer and copy of the_buffer int i1 = y1 * src_bytes_per_row; - int i2 = y1 * dst_bytes_per_row; + int i2 = y1 * scr_bytes_per_row; VIDEO_DRV_LOCK_PIXELS; for (int j = y1; j <= y2; j++) { for (int i = 0; i < n_chunks; i++) { if (memcmp(the_buffer_copy + i1, the_buffer + i1, src_chunk_size) != 0) { memcpy(the_buffer_copy + i1, the_buffer + i1, src_chunk_size); Screen_blit(the_host_buffer + i2, the_buffer + i1, src_chunk_size); +#ifdef USE_SDL_VIDEO + SDL_UpdateRect(drv->s, i * n_pixels, j, n_pixels, 1); +#endif } i1 += src_chunk_size; i2 += dst_chunk_size; @@ -493,75 +518,9 @@ static inline void update_display_dga_vosf(void) i1 += src_chunk_size_left; i2 += dst_chunk_size_left; } + i2 += scr_bytes_left; } VIDEO_DRV_UNLOCK_PIXELS; -#else - // Check for first chunk from left and first chunk from right that have changed - typedef uint64 chunk_t; - const int chunk_size = sizeof(chunk_t); - const int bytes_per_row = VIDEO_MODE_ROW_BYTES; - - int i, j; - int b1 = bytes_per_row / chunk_size; - int b2 = 0; - for (j = y1; j <= y2; j++) { - chunk_t * const p1 = (chunk_t *)(the_buffer + (j * bytes_per_row)); - chunk_t * const p2 = (chunk_t *)(the_buffer_copy + (j * bytes_per_row)); - for (i = 0; i < b1; i++) { - if (p1[i] != p2[i]) { - b1 = i; - break; - } - } - if (b1 > b2) - b2 = b1; - for (i = (bytes_per_row / chunk_size) - 1; i > b2; i--) { - if (p1[i] != p2[i]) { - b2 = i; - break; - } - } - } - b2++; - - // Convert to pixel information - int x1, x2; - switch (VIDEO_MODE_DEPTH) { - case VIDEO_DEPTH_1BIT: x1 = (b1 * chunk_size) << 3; x2 = (b2 * chunk_size) << 3; break; - case VIDEO_DEPTH_2BIT: x1 = (b1 * chunk_size) << 2; x2 = (b2 * chunk_size) << 2; break; - case VIDEO_DEPTH_4BIT: x1 = (b1 * chunk_size) << 1; x2 = (b2 * chunk_size) << 1; break; - case VIDEO_DEPTH_8BIT: x1 = b1 * chunk_size; x2 = b2 * chunk_size; break; - case VIDEO_DEPTH_16BIT: x1 = (b1 * chunk_size) >> 1; x2 = (b2 * chunk_size) >> 1; break; - case VIDEO_DEPTH_32BIT: x1 = (b1 * chunk_size) >> 2; x2 = (b2 * chunk_size) >> 2; break; - } - const int width = x2 - x1; - - // Normalize bounds for for the next blit - const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES; - const int dst_bytes_per_row = the_host_buffer_row_bytes; - const int dst_bytes_per_pixel = dst_bytes_per_row / VIDEO_MODE_X; - int i2 = y1 * dst_bytes_per_row + x1 * dst_bytes_per_pixel; - int i1, n_bytes; - if ((int)VIDEO_MODE_DEPTH < VIDEO_DEPTH_8BIT) { - const int src_pixels_per_byte = VIDEO_MODE_X / src_bytes_per_row; - i1 = y1 * src_bytes_per_row + x1 / src_pixels_per_byte; - n_bytes = width / src_pixels_per_byte; - } else { - const int src_bytes_per_pixel = src_bytes_per_row / VIDEO_MODE_X; - i1 = y1 * src_bytes_per_row + x1 * src_bytes_per_pixel; - n_bytes = width * src_bytes_per_pixel; - } - - // Update the_host_buffer and copy of the_buffer - VIDEO_DRV_LOCK_PIXELS; - for (j = y1; j <= y2; j++) { - Screen_blit(the_host_buffer + i2, the_buffer + i1, n_bytes); - memcpy(the_buffer_copy + i1, the_buffer + i1, n_bytes); - i1 += src_bytes_per_row; - i2 += dst_bytes_per_row; - } - VIDEO_DRV_UNLOCK_PIXELS; -#endif } mainBuffer.dirty = false; } diff --git a/BasiliskII/src/Unix/video_x.cpp b/BasiliskII/src/Unix/video_x.cpp index 4f6b8c38..238fdc07 100644 --- a/BasiliskII/src/Unix/video_x.cpp +++ b/BasiliskII/src/Unix/video_x.cpp @@ -542,6 +542,36 @@ private: int mouse_last_x, mouse_last_y; // Last mouse position (for relative mode) }; +class driver_dga; +static void update_display_dga_vosf(driver_dga *drv); + +class driver_dga : public driver_base { + friend void update_display_dga_vosf(driver_dga *drv); + +public: + driver_dga(X11_monitor_desc &monitor); + ~driver_dga(); + + void suspend(void); + void resume(void); + +protected: + struct FakeXImage { + int width, height; // size of image + int depth; // depth of image + int bytes_per_line; // accelerator to next line + + FakeXImage(int w, int h, int d) + : width(w), height(h), depth(d) + { bytes_per_line = TrivialBytesPerRow(width, DepthModeForPixelDepth(depth)); } + }; + FakeXImage *img; + +private: + Window suspend_win; // "Suspend" information window + void *fb_save; // Saved frame buffer for suspend/resume +}; + static driver_base *drv = NULL; // Pointer to currently used driver object #ifdef ENABLE_VOSF @@ -735,8 +765,7 @@ driver_window::driver_window(X11_monitor_desc &m) use_vosf = true; // Allocate memory for frame buffer (SIZE is extended to page-boundary) the_host_buffer = the_buffer_copy; - the_host_buffer_row_bytes = img->bytes_per_line; - the_buffer_size = page_extend((aligned_height + 2) * the_host_buffer_row_bytes); + the_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line); the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size); the_buffer_copy = (uint8 *)malloc(the_buffer_size); D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); @@ -884,21 +913,8 @@ void driver_window::mouse_moved(int x, int y) * DGA display driver base class */ -class driver_dga : public driver_base { -public: - driver_dga(X11_monitor_desc &monitor); - ~driver_dga(); - - void suspend(void); - void resume(void); - -private: - Window suspend_win; // "Suspend" information window - void *fb_save; // Saved frame buffer for suspend/resume -}; - driver_dga::driver_dga(X11_monitor_desc &m) - : driver_base(m), suspend_win(0), fb_save(NULL) + : driver_base(m), suspend_win(0), fb_save(NULL), img(NULL) { } @@ -906,6 +922,9 @@ driver_dga::~driver_dga() { XUngrabPointer(x_display, CurrentTime); XUngrabKeyboard(x_display, CurrentTime); + + if (img) + delete img; } // Suspend emulation @@ -1131,10 +1150,12 @@ driver_fbdev::driver_fbdev(X11_monitor_desc &m) : driver_dga(m) if (use_vosf) { // Allocate memory for frame buffer (SIZE is extended to page-boundary) the_host_buffer = the_buffer; - the_host_buffer_row_bytes = bytes_per_row; - the_buffer_size = page_extend((height + 2) * the_host_buffer_row_bytes); + the_buffer_size = page_extend((height + 2) * bytes_per_row); the_buffer_copy = (uint8 *)malloc(the_buffer_size); the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size); + + // Fake image for DGA/VOSF mode to know about display bounds + img = new FakeXImage(width, height, depth_of_video_mode(mode)); } #else use_vosf = false; @@ -1272,10 +1293,12 @@ driver_xf86dga::driver_xf86dga(X11_monitor_desc &m) if (use_vosf) { // Allocate memory for frame buffer (SIZE is extended to page-boundary) the_host_buffer = the_buffer; - the_host_buffer_row_bytes = bytes_per_row; - the_buffer_size = page_extend((height + 2) * the_host_buffer_row_bytes); + the_buffer_size = page_extend((height + 2) * bytes_per_row); the_buffer_copy = (uint8 *)malloc(the_buffer_size); the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size); + + // Fake image for DGA/VOSF mode to know about display bounds + img = new FakeXImage((v_width + 7) & ~7, height, depth_of_video_mode(mode)); } #else use_vosf = false; @@ -2471,7 +2494,7 @@ static void video_refresh_dga_vosf(void) tick_counter = 0; if (mainBuffer.dirty) { LOCK_VOSF; - update_display_dga_vosf(); + update_display_dga_vosf(static_cast(drv)); UNLOCK_VOSF; } }