diff --git a/BasiliskII/src/Unix/video_blit.cpp b/BasiliskII/src/Unix/video_blit.cpp index d12c1c72..23298927 100644 --- a/BasiliskII/src/Unix/video_blit.cpp +++ b/BasiliskII/src/Unix/video_blit.cpp @@ -344,9 +344,25 @@ static void Blit_Expand_4_To_8(uint8 * dest, const uint8 * p, uint32 length) } /* -------------------------------------------------------------------------- */ -/* --- 2/4/8-bit indexed to 16-bit mode color expansion --- */ +/* --- 1/2/4/8-bit indexed to 16-bit mode color expansion --- */ /* -------------------------------------------------------------------------- */ +static void Blit_Expand_1_To_16(uint8 * dest, const uint8 * p, uint32 length) +{ + uint16 *q = (uint16 *)dest; + for (uint32 i=0; i> 7); + *q++ = -((c >> 6) & 1); + *q++ = -((c >> 5) & 1); + *q++ = -((c >> 4) & 1); + *q++ = -((c >> 3) & 1); + *q++ = -((c >> 2) & 1); + *q++ = -((c >> 1) & 1); + *q++ = -(c & 1); + } +} + static void Blit_Expand_2_To_16(uint8 * dest, const uint8 * p, uint32 length) { uint16 *q = (uint16 *)dest; @@ -377,9 +393,25 @@ static void Blit_Expand_8_To_16(uint8 * dest, const uint8 * p, uint32 length) } /* -------------------------------------------------------------------------- */ -/* --- 2/4/8-bit indexed to 32-bit mode color expansion --- */ +/* --- 1/2/4/8-bit indexed to 32-bit mode color expansion --- */ /* -------------------------------------------------------------------------- */ +static void Blit_Expand_1_To_32(uint8 * dest, const uint8 * p, uint32 length) +{ + uint32 *q = (uint32 *)dest; + for (uint32 i=0; i> 7); + *q++ = -((c >> 6) & 1); + *q++ = -((c >> 5) & 1); + *q++ = -((c >> 4) & 1); + *q++ = -((c >> 3) & 1); + *q++ = -((c >> 2) & 1); + *q++ = -((c >> 1) & 1); + *q++ = -(c & 1); + } +} + static void Blit_Expand_2_To_32(uint8 * dest, const uint8 * p, uint32 length) { uint32 *q = (uint32 *)dest; @@ -466,9 +498,9 @@ bool Screen_blitter_init(VisualFormat const & visual_format, bool native_byte_or const bool use_sdl_video = false; #endif #if REAL_ADDRESSING || DIRECT_ADDRESSING - if (!use_sdl_video && mac_depth == 1) { + if (mac_depth == 1 && !use_sdl_video && !visual_format.fullscreen) { - // 1-bit mode uses a 1-bit X image, so there's no need for special blitting routines + // Windowed 1-bit mode uses a 1-bit X image, so there's no need for special blitting routines Screen_blit = Blit_Copy_Raw; } else { @@ -498,6 +530,7 @@ bool Screen_blitter_init(VisualFormat const & visual_format, bool native_byte_or case 15: case 16: switch (mac_depth) { + case 1: Screen_blit = Blit_Expand_1_To_16; break; case 2: Screen_blit = Blit_Expand_2_To_16; break; case 4: Screen_blit = Blit_Expand_4_To_16; break; case 8: Screen_blit = Blit_Expand_8_To_16; break; @@ -506,6 +539,7 @@ bool Screen_blitter_init(VisualFormat const & visual_format, bool native_byte_or case 24: case 32: switch (mac_depth) { + case 1: Screen_blit = Blit_Expand_1_To_32; break; case 2: Screen_blit = Blit_Expand_2_To_32; break; case 4: Screen_blit = Blit_Expand_4_To_32; break; case 8: Screen_blit = Blit_Expand_8_To_32; break; diff --git a/BasiliskII/src/Unix/video_blit.h b/BasiliskII/src/Unix/video_blit.h index 1a5005bd..353268a4 100644 --- a/BasiliskII/src/Unix/video_blit.h +++ b/BasiliskII/src/Unix/video_blit.h @@ -25,6 +25,7 @@ // Format of the target visual struct VisualFormat { + bool fullscreen; // Full screen mode? int depth; // Screen depth uint32 Rmask, Gmask, Bmask; // RGB mask values uint32 Rshift, Gshift, Bshift; // RGB shift values diff --git a/BasiliskII/src/Unix/video_vosf.h b/BasiliskII/src/Unix/video_vosf.h index f264ca44..a92b7b8b 100644 --- a/BasiliskII/src/Unix/video_vosf.h +++ b/BasiliskII/src/Unix/video_vosf.h @@ -60,6 +60,7 @@ // 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 @@ -393,35 +394,16 @@ static inline void update_display_window_vosf(VIDEO_DRV_INIT) const int y2 = mainBuffer.pageInfo[page - 1].bottom; const int height = y2 - y1 + 1; + // Update the_host_buffer VIDEO_DRV_LOCK_PIXELS; - - if ((int)VIDEO_MODE_DEPTH < VIDEO_DEPTH_8BIT) { - - // Update the_host_buffer and copy of the_buffer - const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES; - const int dst_bytes_per_row = VIDEO_DRV_ROW_BYTES; - const int pixels_per_byte = VIDEO_MODE_X / src_bytes_per_row; - int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j; - for (j = y1; j <= y2; j++) { - Screen_blit(the_host_buffer + i2, the_buffer + i1, VIDEO_MODE_X / pixels_per_byte); - i1 += src_bytes_per_row; - i2 += dst_bytes_per_row; - } - - } else { - - // Update the_host_buffer and copy of the_buffer - const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES; - const int dst_bytes_per_row = VIDEO_DRV_ROW_BYTES; - const int bytes_per_pixel = src_bytes_per_row / VIDEO_MODE_X; - int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j; - for (j = y1; j <= y2; j++) { - Screen_blit(the_host_buffer + i2, the_buffer + i1, bytes_per_pixel * VIDEO_MODE_X); - i1 += src_bytes_per_row; - i2 += dst_bytes_per_row; - } + const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES; + const int dst_bytes_per_row = VIDEO_DRV_ROW_BYTES; + int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j; + for (j = y1; j <= y2; j++) { + Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row); + i1 += src_bytes_per_row; + i2 += dst_bytes_per_row; } - VIDEO_DRV_UNLOCK_PIXELS; #ifdef USE_SDL_VIDEO @@ -447,7 +429,9 @@ static inline void update_display_dga_vosf(void) { VIDEO_MODE_INIT; + int i, j; int page = 0; + for (;;) { const unsigned first_page = find_next_page_set(page); if (first_page >= mainBuffer.pageCount) @@ -464,48 +448,73 @@ static inline void update_display_dga_vosf(void) // I am sure that y2 >= y1 and depth != 1 const int y1 = mainBuffer.pageInfo[first_page].top; const int y2 = mainBuffer.pageInfo[page - 1].bottom; - + + // 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; - const int bytes_per_pixel = VIDEO_MODE_ROW_BYTES / VIDEO_MODE_X; - int i, j; - - // Check for first column from left and first column - // from right that have changed - int x1 = VIDEO_MODE_X * bytes_per_pixel - 1; + assert((bytes_per_row % chunk_size) == 0); + + int b1 = bytes_per_row / chunk_size; for (j = y1; j <= y2; j++) { - uint8 * const p1 = &the_buffer[j * bytes_per_row]; - uint8 * const p2 = &the_buffer_copy[j * bytes_per_row]; - for (i = 0; i < x1; i++) { + 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]) { - x1 = i; + b1 = i; break; } } } - x1 /= bytes_per_pixel; - - int x2 = x1 * bytes_per_pixel; + + int b2 = b1; for (j = y2; j >= y1; j--) { - uint8 * const p1 = &the_buffer[j * bytes_per_row]; - uint8 * const p2 = &the_buffer_copy[j * bytes_per_row]; - for (i = VIDEO_MODE_X * bytes_per_pixel - 1; i > x2; i--) { + 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 = (bytes_per_row / chunk_size) - 1; i > b2; i--) { if (p1[i] != p2[i]) { - x2 = i; + b2 = i; break; } } } - x2 /= bytes_per_pixel; - + 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 - // There should be at least one pixel to copy VIDEO_DRV_LOCK_PIXELS; - const int width = x2 - x1 + 1; - i = y1 * bytes_per_row + x1 * bytes_per_pixel; for (j = y1; j <= y2; j++) { - Screen_blit(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width); - memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * width); - i += bytes_per_row; + 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; } diff --git a/BasiliskII/src/Unix/video_x.cpp b/BasiliskII/src/Unix/video_x.cpp index 8da6f7cf..4f6b8c38 100644 --- a/BasiliskII/src/Unix/video_x.cpp +++ b/BasiliskII/src/Unix/video_x.cpp @@ -735,7 +735,8 @@ 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_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line); + the_host_buffer_row_bytes = img->bytes_per_line; + the_buffer_size = page_extend((aligned_height + 2) * the_host_buffer_row_bytes); 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)); @@ -1130,7 +1131,8 @@ 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_buffer_size = page_extend((height + 2) * bytes_per_row); + the_host_buffer_row_bytes = bytes_per_row; + the_buffer_size = page_extend((height + 2) * the_host_buffer_row_bytes); the_buffer_copy = (uint8 *)malloc(the_buffer_size); the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size); } @@ -1270,7 +1272,8 @@ 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_buffer_size = page_extend((height + 2) * bytes_per_row); + the_host_buffer_row_bytes = bytes_per_row; + the_buffer_size = page_extend((height + 2) * the_host_buffer_row_bytes); the_buffer_copy = (uint8 *)malloc(the_buffer_size); the_buffer = (uint8 *)vm_acquire_mac(the_buffer_size); } @@ -1412,6 +1415,7 @@ bool X11_monitor_desc::video_open(void) } // Build up visualFormat structure + visualFormat.fullscreen = (display_type == DISPLAY_DGA); visualFormat.depth = visualInfo.depth; visualFormat.Rmask = visualInfo.red_mask; visualFormat.Gmask = visualInfo.green_mask;