diff --git a/BasiliskII/src/SDL/video_sdl2.cpp b/BasiliskII/src/SDL/video_sdl2.cpp index 7f27557d..7d059dfd 100644 --- a/BasiliskII/src/SDL/video_sdl2.cpp +++ b/BasiliskII/src/SDL/video_sdl2.cpp @@ -700,6 +700,10 @@ static void shutdown_sdl_video() delete_sdl_video_window(); } +static uint16 last_gamma_red[256]; +static uint16 last_gamma_green[256]; +static uint16 last_gamma_blue[256]; + static SDL_Surface * init_sdl_video(int width, int height, int bpp, Uint32 flags) { if (guest_surface) { @@ -1739,9 +1743,37 @@ void SDL_monitor_desc::set_palette(uint8 *pal, int num_in) { const VIDEO_MODE &mode = get_current_mode(); - // FIXME: how can we handle the gamma ramp? - if ((int)VIDEO_MODE_DEPTH > VIDEO_DEPTH_8BIT) + if ((int)VIDEO_MODE_DEPTH > VIDEO_DEPTH_8BIT) { + // handle the gamma ramp + + uint16 red[256]; + uint16 green[256]; + uint16 blue[256]; + + for (int i = 0; i < 256; i++) { + red[i] = pal[i*3 + 0] << 8; + green[i] = pal[i*3 + 1] << 8; + blue[i] = pal[i*3 + 2] << 8; + } + + bool changed = (memcmp(red, last_gamma_red, 512) != 0 || + memcmp(green, last_gamma_green, 512) != 0 || + memcmp(blue, last_gamma_blue, 512) != 0); + + if (changed) { + int result = SDL_SetWindowGammaRamp(sdl_window, red, green, blue); + + if (result < 0) { + printf("SDL_SetWindowGammaRamp returned %d, SDL error:", result, SDL_GetError()); + } + + memcpy(last_gamma_red, red, 512); + memcpy(last_gamma_green, green, 512); + memcpy(last_gamma_blue, blue, 512); + } + return; + } LOCK_PALETTE; diff --git a/SheepShaver/src/video.cpp b/SheepShaver/src/video.cpp index d0eda93d..fc884e65 100644 --- a/SheepShaver/src/video.cpp +++ b/SheepShaver/src/video.cpp @@ -211,6 +211,10 @@ static bool allocate_gamma_table(VidLocals *csSave, uint32 size) return true; } + static inline uint8 max(uint8 a, uint8 b) { + return a > b? a : b; + } + static int16 set_gamma(VidLocals *csSave, uint32 gamma) { if (gamma == 0) { // Build linear ramp, 256 entries @@ -229,8 +233,11 @@ static int16 set_gamma(VidLocals *csSave, uint32 gamma) // Build the linear ramp uint32 p = csSave->gammaTable + gFormulaData; - for (int i=0; i<256; i++) + + for (int i=0; i<256; i++) { WriteMacInt8(p + i, i); + mac_pal[i].red = mac_pal[i].green = mac_pal[i].blue = i; + } } else { // User-supplied gamma table @@ -256,7 +263,41 @@ static int16 set_gamma(VidLocals *csSave, uint32 gamma) // Copy table Mac2Mac_memcpy(csSave->gammaTable, gamma, size); + + // Save new gamma data for video impl + if (data_width != 8) { + // FIXME: handle bit-packed data + } else { + uint32 p = csSave->gammaTable + gFormulaData + gFormulaSize; + + uint32 p_red; + uint32 p_green; + uint32 p_blue; + + // make values increasing as some implementations really don't like it when gamma tables aren't + uint8 max_red = 0; + uint8 max_green = 0; + uint8 max_blue = 0; + + if (chan_cnt == 3) { + p_red = p; + p_green = p + data_cnt; + p_blue = p + data_cnt * 2; + } else { + p_red = p_green = p_blue = p; + } + for (int i=0; i < data_cnt; i++) { + max_red = max(max_red, ReadMacInt8(p_red++)); + max_green = max(max_green, ReadMacInt8(p_green++)); + max_blue = max(max_blue, ReadMacInt8(p_blue++)); + mac_pal[i].red = max_red; + mac_pal[i].green = max_green; + mac_pal[i].blue = max_blue; + } + } } + + video_set_palette(); return noErr; }