diff --git a/BasiliskII/src/Unix/video_blit.cpp b/BasiliskII/src/Unix/video_blit.cpp index 7e249ae4..5e7c52f5 100644 --- a/BasiliskII/src/Unix/video_blit.cpp +++ b/BasiliskII/src/Unix/video_blit.cpp @@ -35,6 +35,9 @@ struct VisualFormat { }; static VisualFormat visualFormat; +// This holds the pixels values of the palette colors for 8->16/32-bit expansion +uint32 ExpandMap[256]; + /* -------------------------------------------------------------------------- */ /* --- Raw Copy / No conversion required --- */ /* -------------------------------------------------------------------------- */ @@ -258,6 +261,28 @@ static void Blit_Copy_Raw(uint8 * dest, const uint8 * source, uint32 length) #define FB_DEPTH 24 #include "video_blit.h" +/* -------------------------------------------------------------------------- */ +/* --- 8-bit indexed to 16-bit mode color expansion --- */ +/* -------------------------------------------------------------------------- */ + +static void Blit_Expand_8_To_16(uint8 * dest, const uint8 * p, uint32 length) +{ + uint16 *q = (uint16 *)dest; + for (int i=0; ired_mask; visualFormat.Gmask = visual_info->green_mask; visualFormat.Bmask = visual_info->blue_mask; - + // Compute RGB shift values visualFormat.Rshift = 0; for (uint32 Rmask = visualFormat.Rmask; Rmask && ((Rmask & 1) != 1); Rmask >>= 1) @@ -330,9 +355,21 @@ bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order, vide visualFormat.Bshift = 0; for (uint32 Bmask = visualFormat.Bmask; Bmask && ((Bmask & 1) != 1); Bmask >>= 1) ++visualFormat.Bshift; + + bool blitter_found = false; + + // 8-bit mode on 16/32-bit screen? + if (mac_depth == VDEPTH_8BIT && visualFormat.depth > 8) { + if (visual_info->depth <= 16) { + Screen_blit = Blit_Expand_8_To_16; + blitter_found = true; + } else { + Screen_blit = Blit_Expand_8_To_32; + blitter_found = true; + } + } // Search for an adequate blit function - bool blitter_found = false; const int blitters_count = sizeof(Screen_blitters)/sizeof(Screen_blitters[0]); for (int i = 0; !blitter_found && (i < blitters_count); i++) { if ( (visualFormat.depth == Screen_blitters[i].depth) diff --git a/BasiliskII/src/Unix/video_vosf.h b/BasiliskII/src/Unix/video_vosf.h index 91af9581..f6f77c5a 100644 --- a/BasiliskII/src/Unix/video_vosf.h +++ b/BasiliskII/src/Unix/video_vosf.h @@ -281,6 +281,7 @@ static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_addres // From video_blit.cpp extern void (*Screen_blit)(uint8 * dest, const uint8 * source, uint32 length); extern bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order, video_depth mac_depth); +extern uint32 ExpandMap[256]; /* How can we deal with array overrun conditions ? @@ -336,13 +337,11 @@ static inline void update_display_window_vosf(driver_window *drv) const int y2 = mainBuffer.pageInfo[page - 1].bottom; const int height = y2 - y1 + 1; - const int bytes_per_row = VideoMonitor.mode.bytes_per_row; - const int bytes_per_pixel = VideoMonitor.mode.bytes_per_row / VideoMonitor.mode.x; - int i = y1 * bytes_per_row, j; - if (VideoMonitor.mode.depth == VDEPTH_1BIT) { // Update the_host_buffer and copy of the_buffer + const int bytes_per_row = VideoMonitor.mode.bytes_per_row; + int i = y1 * bytes_per_row, j; for (j = y1; j <= y2; j++) { Screen_blit(the_host_buffer + i, the_buffer + i, VideoMonitor.mode.x >> 3); i += bytes_per_row; @@ -351,9 +350,14 @@ static inline void update_display_window_vosf(driver_window *drv) } else { // Update the_host_buffer and copy of the_buffer + const int src_bytes_per_row = VideoMonitor.mode.bytes_per_row; + const int dst_bytes_per_row = drv->img->bytes_per_line; + const int bytes_per_pixel = src_bytes_per_row / VideoMonitor.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 + i, the_buffer + i, bytes_per_pixel * VideoMonitor.mode.x); - i += bytes_per_row; + Screen_blit(the_host_buffer + i2, the_buffer + i1, bytes_per_pixel * VideoMonitor.mode.x); + i1 += src_bytes_per_row; + i2 += dst_bytes_per_row; } } diff --git a/BasiliskII/src/Unix/video_x.cpp b/BasiliskII/src/Unix/video_x.cpp index 88d667fa..48d2ae61 100644 --- a/BasiliskII/src/Unix/video_x.cpp +++ b/BasiliskII/src/Unix/video_x.cpp @@ -185,6 +185,12 @@ extern void SysMountFirstFloppy(void); * Utility functions */ +// Map RGB color to pixel value (this only works in TrueColor/DirectColor visuals) +static inline uint32 map_rgb(uint8 red, uint8 green, uint8 blue) +{ + return ((red >> rloss) << rshift) | ((green >> gloss) << gshift) | ((blue >> bloss) << bshift); +} + // Add mode to list of supported modes static void add_mode(uint32 width, uint32 height, uint32 resolution_id, uint32 bytes_per_row, video_depth depth) { @@ -479,7 +485,7 @@ driver_window::driver_window(const video_mode &mode) // Create normal X image if SHM doesn't work ("height + 2" for safety) if (!have_shm) { - int bytes_per_row = TrivialBytesPerRow(aligned_width, mode.depth); + int bytes_per_row = (mode.depth == VDEPTH_1BIT ? aligned_width/8 : TrivialBytesPerRow(aligned_width, DepthModeForPixelDepth(xdepth))); the_buffer_copy = (uint8 *)malloc((aligned_height + 2) * bytes_per_row); img = XCreateImage(x_display, vis, mode.depth == VDEPTH_1BIT ? 1 : xdepth, mode.depth == VDEPTH_1BIT ? XYBitmap : ZPixmap, 0, (char *)the_buffer_copy, aligned_width, aligned_height, 32, bytes_per_row); } @@ -1043,6 +1049,13 @@ static bool video_open(const video_mode &mode) XStoreColors(x_display, cmap[1], palette, num); } +#ifdef ENABLE_VOSF + // Load gray ramp to 8->16/32 expand map + if (!IsDirectMode(mode) && (vis->c_class == TrueColor || vis->c_class == DirectColor)) + for (int i=0; i<256; i++) + ExpandMap[i] = map_rgb(i, i, i); +#endif + // Create display driver object of requested type switch (display_type) { case DISPLAY_WINDOW: @@ -1233,7 +1246,7 @@ bool VideoInit(bool classic) int num = vis->map_entries; for (int i=0; i> rloss) << rshift) | ((c >> gloss) << gshift) | ((c >> bloss) << bshift); + palette[i].pixel = map_rgb(c, c, c); } } @@ -1282,20 +1295,29 @@ bool VideoInit(bool classic) add_mode(512, 384, 0x80, TrivialBytesPerRow(512, VDEPTH_1BIT), VDEPTH_1BIT); add_mode(640, 480, 0x81, TrivialBytesPerRow(640, VDEPTH_1BIT), VDEPTH_1BIT); add_mode(800, 600, 0x82, TrivialBytesPerRow(800, VDEPTH_1BIT), VDEPTH_1BIT); - add_mode(832, 624, 0x83, TrivialBytesPerRow(832, VDEPTH_1BIT), VDEPTH_1BIT); - add_mode(1024, 768, 0x84, TrivialBytesPerRow(1024, VDEPTH_1BIT), VDEPTH_1BIT); - add_mode(1152, 870, 0x85, TrivialBytesPerRow(1152, VDEPTH_1BIT), VDEPTH_1BIT); - add_mode(1280, 1024, 0x86, TrivialBytesPerRow(1280, VDEPTH_1BIT), VDEPTH_1BIT); - add_mode(1600, 1200, 0x87, TrivialBytesPerRow(1600, VDEPTH_1BIT), VDEPTH_1BIT); + add_mode(1024, 768, 0x83, TrivialBytesPerRow(1024, VDEPTH_1BIT), VDEPTH_1BIT); + add_mode(1152, 870, 0x84, TrivialBytesPerRow(1152, VDEPTH_1BIT), VDEPTH_1BIT); + add_mode(1280, 1024, 0x85, TrivialBytesPerRow(1280, VDEPTH_1BIT), VDEPTH_1BIT); + add_mode(1600, 1200, 0x86, TrivialBytesPerRow(1600, VDEPTH_1BIT), VDEPTH_1BIT); } +#ifdef ENABLE_VOSF + if (default_depth > VDEPTH_8BIT) { // 8-bit modes are also possible on 16/32-bit screens with VOSF blitters + add_mode(512, 384, 0x80, TrivialBytesPerRow(512, VDEPTH_8BIT), VDEPTH_8BIT); + add_mode(640, 480, 0x81, TrivialBytesPerRow(640, VDEPTH_8BIT), VDEPTH_8BIT); + add_mode(800, 600, 0x82, TrivialBytesPerRow(800, VDEPTH_8BIT), VDEPTH_8BIT); + add_mode(1024, 768, 0x83, TrivialBytesPerRow(1024, VDEPTH_8BIT), VDEPTH_8BIT); + add_mode(1152, 870, 0x84, TrivialBytesPerRow(1152, VDEPTH_8BIT), VDEPTH_8BIT); + add_mode(1280, 1024, 0x85, TrivialBytesPerRow(1280, VDEPTH_8BIT), VDEPTH_8BIT); + add_mode(1600, 1200, 0x86, TrivialBytesPerRow(1600, VDEPTH_8BIT), VDEPTH_8BIT); + } +#endif add_mode(512, 384, 0x80, TrivialBytesPerRow(512, default_depth), default_depth); add_mode(640, 480, 0x81, TrivialBytesPerRow(640, default_depth), default_depth); add_mode(800, 600, 0x82, TrivialBytesPerRow(800, default_depth), default_depth); - add_mode(832, 624, 0x83, TrivialBytesPerRow(832, default_depth), default_depth); - add_mode(1024, 768, 0x84, TrivialBytesPerRow(1024, default_depth), default_depth); - add_mode(1152, 870, 0x85, TrivialBytesPerRow(1152, default_depth), default_depth); - add_mode(1280, 1024, 0x86, TrivialBytesPerRow(1280, default_depth), default_depth); - add_mode(1600, 1200, 0x87, TrivialBytesPerRow(1600, default_depth), default_depth); + add_mode(1024, 768, 0x83, TrivialBytesPerRow(1024, default_depth), default_depth); + add_mode(1152, 870, 0x84, TrivialBytesPerRow(1152, default_depth), default_depth); + add_mode(1280, 1024, 0x85, TrivialBytesPerRow(1280, default_depth), default_depth); + add_mode(1600, 1200, 0x86, TrivialBytesPerRow(1600, default_depth), default_depth); } } else add_mode(default_width, default_height, 0x80, TrivialBytesPerRow(default_width, default_depth), default_depth); @@ -1446,6 +1468,20 @@ void video_set_palette(uint8 *pal) p++; } +#ifdef ENABLE_VOSF + // Recalculate pixel color expansion map + if (!IsDirectMode(VideoMonitor.mode) && (vis->c_class == TrueColor || vis->c_class == DirectColor)) { + for (int i=0; i<256; i++) + ExpandMap[i] = map_rgb(pal[i*3+0], pal[i*3+1], pal[i*3+2]); + + // We have to redraw everything because the interpretation of pixel values changed + LOCK_VOSF; + PFLAG_SET_ALL; + UNLOCK_VOSF; + memset(the_buffer_copy, 0, VideoMonitor.mode.bytes_per_row * VideoMonitor.mode.y); + } +#endif + // Tell redraw thread to change palette palette_changed = true;