(svn r11342) -Fix: [OSX] The cocoa driver incorrectly assumed that the blitter always was 8bpp. Now both 8bpp and 32bpp blitters can be used. The driver will check the blitter screen depth. In fullscreen it will select a proper video mode for this depth, and in windowed mode it will simply skip doing fake 8bpp.

This commit is contained in:
egladil 2007-10-25 23:45:03 +00:00
parent 287a4a8049
commit 134227aa8c
2 changed files with 113 additions and 47 deletions

View File

@ -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,33 +104,56 @@ 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;
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);
}
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;
}
_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;
}
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;
}
_cur_palette[0xff].r = 0;
_cur_palette[0xff].g = 0;
_cur_palette[0xff].b = 0;
_pal_first_dirty = 0;
_pal_count_dirty = 256;
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(f);
return;

View File

@ -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);