diff options
-rw-r--r-- | src/os/macosx/splash.cpp | 60 | ||||
-rw-r--r-- | src/video/cocoa_v.mm | 96 |
2 files changed, 111 insertions, 45 deletions
diff --git a/src/os/macosx/splash.cpp b/src/os/macosx/splash.cpp index 30eed880d..45973c781 100644 --- a/src/os/macosx/splash.cpp +++ b/src/os/macosx/splash.cpp @@ -8,6 +8,7 @@ #include "../../functions.h" #include "../../gfx.h" #include "../../fileio.h" +#include "../../blitter/factory.hpp" #include "splash.h" @@ -36,7 +37,7 @@ void DisplaySplashImage() png_colorp palette; int num_palette; png_bytep *row_pointers; - uint8 *src, *dst; + uint8 *src; uint y; uint xoff, yoff; int i; @@ -103,32 +104,55 @@ void DisplaySplashImage() row_pointers = png_get_rows(png_ptr, info_ptr); - memset(_screen.dst_ptr, 0xff, _screen.pitch * _screen.height); - if (width > (uint) _screen.width) width = _screen.width; if (height > (uint) _screen.height) height = _screen.height; xoff = (_screen.width - width) / 2; yoff = (_screen.height - height) / 2; - for (y = 0; y < height; y++) { - src = row_pointers[y]; - dst = ((uint8 *) _screen.dst_ptr) + (yoff + y) * _screen.pitch + xoff; - memcpy(dst, src, width); - } + switch (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth()) { + case 8: { + uint8 *dst; - for (i = 0; i < num_palette; i++) { - _cur_palette[i].r = palette[i].red; - _cur_palette[i].g = palette[i].green; - _cur_palette[i].b = palette[i].blue; - } + memset(_screen.dst_ptr, 0xff, _screen.pitch * _screen.height); + + for (y = 0; y < height; y++) { + src = row_pointers[y]; + dst = ((uint8 *) _screen.dst_ptr) + (yoff + y) * _screen.pitch + xoff; + + memcpy(dst, src, width); + } - _cur_palette[0xff].r = 0; - _cur_palette[0xff].g = 0; - _cur_palette[0xff].b = 0; + for (i = 0; i < num_palette; i++) { + _cur_palette[i].r = palette[i].red; + _cur_palette[i].g = palette[i].green; + _cur_palette[i].b = palette[i].blue; + } - _pal_first_dirty = 0; - _pal_count_dirty = 256; + _cur_palette[0xff].r = 0; + _cur_palette[0xff].g = 0; + _cur_palette[0xff].b = 0; + + _pal_first_dirty = 0; + _pal_count_dirty = 256; + } + break; + case 32: { + uint32 *dst; + int x; + + memset(_screen.dst_ptr, 0xff000000, _screen.pitch * _screen.height * 4); + + for (y = 0; y < height; y++) { + src = row_pointers[y]; + dst = ((uint32 *) _screen.dst_ptr) + (yoff + y) * _screen.pitch + xoff; + + for (x = 0; x < width; x++) + dst[x] = palette[src[x]].blue | (palette[src[x]].green << 8) | (palette[src[x]].red << 16) | 0xff000000; + } + } + break; + } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); diff --git a/src/video/cocoa_v.mm b/src/video/cocoa_v.mm index 0b9ec1786..0a23871dc 100644 --- a/src/video/cocoa_v.mm +++ b/src/video/cocoa_v.mm @@ -157,12 +157,14 @@ static struct CocoaVideoData { CFArrayRef mode_list; /* list of available fullscreen modes */ CGDirectPaletteRef palette; /* palette of an 8-bit display */ + uint32 blitter_bpp; + uint32 device_width; uint32 device_height; uint32 device_bpp; void *realpixels; - uint8 *pixels; + void *pixels; uint32 width; uint32 height; uint32 pitch; @@ -900,7 +902,7 @@ static void QZ_SetPortAlphaOpaque() /* Allocate new buffer */ free(_cocoa_video_data.pixels); - _cocoa_video_data.pixels = (uint8*)malloc(newViewFrame.size.width * newViewFrame.size.height); + _cocoa_video_data.pixels = malloc(newViewFrame.size.width * newViewFrame.size.height * _cocoa_video_data.blitter_bpp / 8); assert(_cocoa_video_data.pixels != NULL); @@ -1019,28 +1021,54 @@ static void QZ_UpdateWindowPalette(uint start, uint count) static inline void QZ_WindowBlitIndexedPixelsToView32(uint left, uint top, uint right, uint bottom) { - const uint32* pal = _cocoa_video_data.palette32; - const uint8* src = _cocoa_video_data.pixels; uint32* dst = (uint32*)_cocoa_video_data.realpixels; uint width = _cocoa_video_data.width; uint pitch = _cocoa_video_data.pitch / 4; uint x; uint y; - for (y = top; y < bottom; y++) { - for (x = left; x < right; x++) { - dst[y * pitch + x] = pal[src[y * width + x]]; - } + switch (_cocoa_video_data.blitter_bpp) { + case 8: { + const uint32* pal = _cocoa_video_data.palette32; + const uint8* src = (uint8*) _cocoa_video_data.pixels; + + for (y = top; y < bottom; y++) { + for (x = left; x < right; x++) { + dst[y * pitch + x] = pal[src[y * width + x]]; + } + } + } + break; + case 32: { + const uint32* src = (uint32*) _cocoa_video_data.pixels; + + dst += top * pitch + left; + src += top * width + left; + + for (y = top; y < bottom; y++, dst+= pitch, src+= width) + memcpy(dst, src, (right - left) * 4); + } + break; } } +/** + * This function copies pixels from the screen buffer in 16bpp windowed mode. It assumes + * that the blitter is 8bpp since the driver only supports 8 and 32 bpp blitters, and we + * don't allow a blitter with a higer bpp than the display in windowed mode. + * + * @param left The x coord for the left edge of the box to blit. + * @param top The y coord for the top edge of the box to blit. + * @param right The x coord for the right edge of the box to blit. + * @param bottom The y coord for the bottom edge of the box to blit. + */ static inline void QZ_WindowBlitIndexedPixelsToView16(uint left, uint top, uint right, uint bottom) { - const uint16* pal = _cocoa_video_data.palette16; - const uint8* src = _cocoa_video_data.pixels; - uint16* dst = (uint16*)_cocoa_video_data.realpixels; - uint width = _cocoa_video_data.width; - uint pitch = _cocoa_video_data.pitch / 2; + const uint16* pal = _cocoa_video_data.palette16; + const uint8* src = (uint8*) _cocoa_video_data.pixels; + uint16* dst = (uint16*)_cocoa_video_data.realpixels; + uint width = _cocoa_video_data.width; + uint pitch = _cocoa_video_data.pitch / 2; uint x; uint y; @@ -1164,6 +1192,10 @@ static const char* QZ_SetVideoWindowed(uint width, uint height) NSRect contentRect; BOOL isCustom = NO; + if (_cocoa_video_data.blitter_bpp > _cocoa_video_data.device_bpp) { + error("Cocoa: Cannot use a blitter with a higer screen depth than the display when running in windowed mode."); + } + if (width > _cocoa_video_data.device_width) width = _cocoa_video_data.device_width; if (height > _cocoa_video_data.device_height) @@ -1251,7 +1283,7 @@ static const char* QZ_SetVideoWindowed(uint width, uint height) } free(_cocoa_video_data.pixels); - _cocoa_video_data.pixels = (uint8*)malloc(width * height); + _cocoa_video_data.pixels = malloc(width * height * _cocoa_video_data.blitter_bpp / 8); if (_cocoa_video_data.pixels == NULL) return "Failed to allocate 8-bit buffer"; _cocoa_video_data.fullscreen = false; @@ -1362,13 +1394,13 @@ static const char* QZ_SetVideoFullScreen(int width, int height) if (_cocoa_video_data.isset) QZ_UnsetVideoMode(); /* See if requested mode exists */ - _cocoa_video_data.mode = CGDisplayBestModeForParameters(_cocoa_video_data.display_id, 8, width, height, &exact_match); + _cocoa_video_data.mode = CGDisplayBestModeForParameters(_cocoa_video_data.display_id, _cocoa_video_data.blitter_bpp, width, height, &exact_match); /* If the mode wasn't an exact match, check if it has the right bpp, and update width and height */ if (!exact_match) { number = (const __CFNumber*) CFDictionaryGetValue(_cocoa_video_data.mode, kCGDisplayBitsPerPixel); CFNumberGetValue(number, kCFNumberSInt32Type, &bpp); - if (bpp != 8) { + if ((uint) bpp != _cocoa_video_data.blitter_bpp) { errstr = "Failed to find display resolution"; goto ERR_NO_MATCH; } @@ -1397,7 +1429,7 @@ static const char* QZ_SetVideoFullScreen(int width, int height) goto ERR_NO_SWITCH; } - _cocoa_video_data.realpixels = (uint8*)CGDisplayBaseAddress(_cocoa_video_data.display_id); + _cocoa_video_data.realpixels = CGDisplayBaseAddress(_cocoa_video_data.display_id); _cocoa_video_data.pitch = CGDisplayBytesPerRow(_cocoa_video_data.display_id); _cocoa_video_data.width = CGDisplayPixelsWide(_cocoa_video_data.display_id); @@ -1405,13 +1437,13 @@ static const char* QZ_SetVideoFullScreen(int width, int height) _cocoa_video_data.fullscreen = true; /* Setup double-buffer emulation */ - _cocoa_video_data.pixels = (uint8*)malloc(width * height); + _cocoa_video_data.pixels = malloc(width * height * _cocoa_video_data.blitter_bpp / 8); if (_cocoa_video_data.pixels == NULL) { errstr = "Failed to allocate memory for double buffering"; goto ERR_DOUBLEBUF; } - if (!CGDisplayCanSetPalette(_cocoa_video_data.display_id)) { + if (_cocoa_video_data.blitter_bpp == 8 && !CGDisplayCanSetPalette(_cocoa_video_data.display_id)) { errstr = "Not an indexed display mode."; goto ERR_NOT_INDEXED; } @@ -1507,11 +1539,12 @@ static void QZ_WaitForVerticalBlank() static void QZ_DrawScreen() { - const uint8* src = _cocoa_video_data.pixels; - uint8* dst = (uint8*)_cocoa_video_data.realpixels; - uint pitch = _cocoa_video_data.pitch; - uint width = _cocoa_video_data.width; - uint num_dirty = _cocoa_video_data.num_dirty_rects; + const uint8* src = (uint8*) _cocoa_video_data.pixels; + uint8* dst = (uint8*)_cocoa_video_data.realpixels; + uint pitch = _cocoa_video_data.pitch; + uint width = _cocoa_video_data.width; + uint num_dirty = _cocoa_video_data.num_dirty_rects; + uint bytesperpixel = _cocoa_video_data.blitter_bpp / 8; uint i; /* Check if we need to do anything */ @@ -1534,7 +1567,7 @@ static void QZ_DrawScreen() uint bottom = _cocoa_video_data.dirty_rects[i].bottom; for (; y < bottom; y++) { - memcpy(dst + y * pitch + left, src + y * width + left, length); + memcpy(dst + y * pitch + left * bytesperpixel, src + y * width * bytesperpixel + left * bytesperpixel, length * bytesperpixel); } } @@ -1563,7 +1596,7 @@ static int QZ_ListFullscreenModes(OTTDPoint* mode_list, int max_modes) number = (const __CFNumber*)CFDictionaryGetValue(onemode, kCGDisplayBitsPerPixel); CFNumberGetValue (number, kCFNumberSInt32Type, &bpp); - if (bpp != 8) continue; + if ((uint) bpp != _cocoa_video_data.blitter_bpp) continue; number = (const __CFNumber*)CFDictionaryGetValue(onemode, kCGDisplayWidth); CFNumberGetValue(number, kCFNumberSInt32Type, &intvalue); @@ -1774,10 +1807,19 @@ static const char* QZ_SetVideoModeAndRestoreOnFailure(uint width, uint height, b static void QZ_VideoInit() { - if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 0) error("Can't use a blitter that blits 0 bpp for normal visuals"); memset(&_cocoa_video_data, 0, sizeof(_cocoa_video_data)); + _cocoa_video_data.blitter_bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(); + DEBUG(driver, 1, "Cocoa: Blitter bpp %d", _cocoa_video_data.blitter_bpp); + + if (_cocoa_video_data.blitter_bpp == 0) error("Can't use a blitter that blits 0 bpp for normal visuals"); + + + if (_cocoa_video_data.blitter_bpp != 8 && _cocoa_video_data.blitter_bpp != 32) { + error("Cocoa: This video driver only supports 8 and 32 bpp blitters."); + } + /* Initialize the video settings; this data persists between mode switches */ _cocoa_video_data.display_id = kCGDirectMainDisplay; _cocoa_video_data.save_mode = CGDisplayCurrentMode(_cocoa_video_data.display_id); |