From a65a6c6db22d7844dcfc80cc261322fd92833fde Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Sun, 18 Apr 2004 23:03:53 +0000 Subject: [PATCH] Start Native QuickDraw acceleration --- SheepShaver/src/BeOS/video_beos.cpp | 16 +- SheepShaver/src/Unix/video_x.cpp | 152 +++++++++++++------ SheepShaver/src/include/thunks.h | 7 + SheepShaver/src/include/video.h | 9 ++ SheepShaver/src/include/video_defs.h | 12 +- SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp | 23 +++ SheepShaver/src/thunks.cpp | 14 ++ 7 files changed, 169 insertions(+), 64 deletions(-) diff --git a/SheepShaver/src/BeOS/video_beos.cpp b/SheepShaver/src/BeOS/video_beos.cpp index 44054969..df94bdd5 100644 --- a/SheepShaver/src/BeOS/video_beos.cpp +++ b/SheepShaver/src/BeOS/video_beos.cpp @@ -561,7 +561,7 @@ static bool accl_bitblt_hook(accl_params *p) p->src_row_bytes > 0 && ((uint32 *)p)[0x15c >> 2] > 0) { // Yes, set function pointer - p->draw_proc = accl_bitblt; + p->draw_proc = (uint32)accl_bitblt; return true; } return false; @@ -629,15 +629,15 @@ static bool accl_fillrect_hook(accl_params *p) if (p->transfer_mode == 8) { // Fill if (p->dest_pixel_size == 8 && fillrect8_hook != NULL) { - p->draw_proc = accl_fillrect8; + p->draw_proc = (uint32)accl_fillrect8; return true; } else if (p->dest_pixel_size == 32 && fillrect32_hook != NULL) { - p->draw_proc = accl_fillrect32; + p->draw_proc = (uint32)accl_fillrect32; return true; } } else if (p->transfer_mode == 10 && invrect_hook != NULL) { // Invert - p->draw_proc = accl_invrect; + p->draw_proc = (uint32)accl_invrect; return true; } } @@ -664,10 +664,10 @@ static bool accl_foobar_hook(accl_params *p) printf(" val5 %08x\n", ((uint32 *)p)[0x160 >> 2]); printf(" val6 %08x\n", ((uint32 *)p)[0x1b4 >> 2]); printf(" val7 %08x\n", ((uint32 *)p)[0x284 >> 2]); - p->draw_proc = do_nothing; + p->draw_proc = (uint32)do_nothing; return true; } -static struct accl_hook_info foobar_hook_info = {accl_foobar_hook, accl_sync_hook, 6}; +static struct accl_hook_info foobar_hook_info = {(uint32)accl_foobar_hook, (uint32)accl_sync_hook, 6}; */ // Wait for graphics operation to finish @@ -679,8 +679,8 @@ static bool accl_sync_hook(void *arg) return true; } -static struct accl_hook_info bitblt_hook_info = {accl_bitblt_hook, accl_sync_hook, ACCL_BITBLT}; -static struct accl_hook_info fillrect_hook_info = {accl_fillrect_hook, accl_sync_hook, ACCL_FILLRECT}; +static struct accl_hook_info bitblt_hook_info = {(uint32)accl_bitblt_hook, (uint32)accl_sync_hook, ACCL_BITBLT}; +static struct accl_hook_info fillrect_hook_info = {(uint32)accl_fillrect_hook, (uint32)accl_sync_hook, ACCL_FILLRECT}; void VideoInstallAccel(void) { diff --git a/SheepShaver/src/Unix/video_x.cpp b/SheepShaver/src/Unix/video_x.cpp index ef90a58e..9d07600a 100644 --- a/SheepShaver/src/Unix/video_x.cpp +++ b/SheepShaver/src/Unix/video_x.cpp @@ -195,10 +195,30 @@ static int palette_size(int mode) } } +// Return bits per pixel for requested depth +static inline int bytes_per_pixel(int depth) +{ + int bpp; + switch (depth) { + case 8: + bpp = 1; + break; + case 15: case 16: + bpp = 2; + break; + case 24: case 32: + bpp = 4; + break; + default: + abort(); + } + return bpp; +} + // Map video_mode depth ID to numerical depth value static inline int depth_of_video_mode(int mode) { - int depth = -1; + int depth; switch (mode) { case APPLE_1_BIT: depth = 1; @@ -1592,44 +1612,6 @@ void VideoVBL(void) */ #if 0 -// Rectangle blitting -static void accl_bitblt(accl_params *p) -{ - D(bug("accl_bitblt\n")); - - // Get blitting parameters - int16 src_X = p->src_rect[1] - p->src_bounds[1]; - int16 src_Y = p->src_rect[0] - p->src_bounds[0]; - int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; - int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; - int16 width = p->dest_rect[3] - p->dest_rect[1] - 1; - int16 height = p->dest_rect[2] - p->dest_rect[0] - 1; - D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y)); - D(bug(" width %d, height %d\n", width, height)); - - // And perform the blit - bitblt_hook(src_X, src_Y, dest_X, dest_Y, width, height); -} - -static bool accl_bitblt_hook(accl_params *p) -{ - D(bug("accl_draw_hook %p\n", p)); - - // Check if we can accelerate this bitblt - if (p->src_base_addr == screen_base && p->dest_base_addr == screen_base && - display_type == DIS_SCREEN && bitblt_hook != NULL && - ((uint32 *)p)[0x18 >> 2] + ((uint32 *)p)[0x128 >> 2] == 0 && - ((uint32 *)p)[0x130 >> 2] == 0 && - p->transfer_mode == 0 && - p->src_row_bytes > 0 && ((uint32 *)p)[0x15c >> 2] > 0) { - - // Yes, set function pointer - p->draw_proc = accl_bitblt; - return true; - } - return false; -} - // Rectangle filling/inversion static void accl_fillrect8(accl_params *p) { @@ -1707,25 +1689,95 @@ static bool accl_fillrect_hook(accl_params *p) return false; } -// Wait for graphics operation to finish -static bool accl_sync_hook(void *arg) -{ - D(bug("accl_sync_hook %p\n", arg)); - if (sync_hook != NULL) - sync_hook(); - return true; -} - -static struct accl_hook_info bitblt_hook_info = {accl_bitblt_hook, accl_sync_hook, ACCL_BITBLT}; static struct accl_hook_info fillrect_hook_info = {accl_fillrect_hook, accl_sync_hook, ACCL_FILLRECT}; #endif +// Rectangle blitting +// TODO: optimize for VOSF and target pixmap == screen +void NQD_bitblt(uint32 arg) +{ + D(bug("accl_bitblt %08x\n", arg)); + accl_params *p = (accl_params *)arg; + + // Get blitting parameters + int16 src_X = p->src_rect[1] - p->src_bounds[1]; + int16 src_Y = p->src_rect[0] - p->src_bounds[0]; + int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; + int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; + int16 width = p->dest_rect[3] - p->dest_rect[1]; + int16 height = p->dest_rect[2] - p->dest_rect[0]; + D(bug(" src addr %08x, dest addr %08x\n", p->src_base_addr, p->dest_base_addr)); + D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y)); + D(bug(" width %d, height %d\n", width, height)); + + // And perform the blit + const int bpp = bytes_per_pixel(p->src_pixel_size); + width *= bpp; + if (p->src_row_bytes > 0) { + const int src_row_bytes = p->src_row_bytes; + const int dst_row_bytes = p->dest_row_bytes; + uint8 *src = (uint8 *)p->src_base_addr + (src_Y * src_row_bytes) + (src_X * bpp); + uint8 *dst = (uint8 *)p->dest_base_addr + (dest_Y * dst_row_bytes) + (dest_X * bpp); + for (int i = 0; i < height; i++) { + memcpy(dst, src, width); + src += src_row_bytes; + dst += dst_row_bytes; + } + } + else { + const int src_row_bytes = -p->src_row_bytes; + const int dst_row_bytes = -p->dest_row_bytes; + uint8 *src = (uint8 *)p->src_base_addr + ((src_Y + height - 1) * src_row_bytes) + (src_X * bpp); + uint8 *dst = (uint8 *)p->dest_base_addr + ((dest_Y + height - 1) * dst_row_bytes) + (dest_X * bpp); + for (int i = height - 1; i >= 0; i--) { + memcpy(dst, src, width); + src -= src_row_bytes; + dst -= dst_row_bytes; + } + } +} + +bool NQD_bitblt_hook(uint32 arg) +{ + D(bug("accl_draw_hook %08x\n", arg)); + accl_params *p = (accl_params *)arg; + + // Check if we can accelerate this bitblt + if (((uint32 *)p)[0x18 >> 2] + ((uint32 *)p)[0x128 >> 2] == 0 && + ((uint32 *)p)[0x130 >> 2] == 0 && + p->src_pixel_size >= 8 && p->src_pixel_size == p->dest_pixel_size && + ((p->src_row_bytes ^ p->dest_row_bytes) >> 31) == 0 && + p->transfer_mode == 0 && + ((uint32 *)p)[0x15c >> 2] > 0) { + + // Yes, set function pointer + p->draw_proc = NativeTVECT(NATIVE_BITBLT); + return true; + } + return false; +} + +// Wait for graphics operation to finish +bool NQD_sync_hook(uint32 arg) +{ + D(bug("accl_sync_hook %08x\n", arg)); + return true; +} + void VideoInstallAccel(void) { // Install acceleration hooks if (PrefsFindBool("gfxaccel")) { D(bug("Video: Installing acceleration hooks\n")); -//!! NQDMisc(6, &bitblt_hook_info); + uint32 base; + + SheepVar bitblt_hook_info(sizeof(accl_hook_info)); + base = bitblt_hook_info.addr(); + WriteMacInt32(base + 0, NativeTVECT(NATIVE_BITBLT_HOOK)); + WriteMacInt32(base + 4, NativeTVECT(NATIVE_SYNC_HOOK)); + WriteMacInt32(base + 8, ACCL_BITBLT); + NQDMisc(6, bitblt_hook_info.ptr()); + // NQDMisc(6, &fillrect_hook_info); } } diff --git a/SheepShaver/src/include/thunks.h b/SheepShaver/src/include/thunks.h index 0495b68d..0fd340c9 100644 --- a/SheepShaver/src/include/thunks.h +++ b/SheepShaver/src/include/thunks.h @@ -55,6 +55,13 @@ enum { NATIVE_ENABLE_INTERRUPT, NATIVE_MAKE_EXECUTABLE, NATIVE_CHECK_LOAD_INVOC, + NATIVE_SYNC_HOOK, + NATIVE_BITBLT_HOOK, + NATIVE_FILLRECT_HOOK, + NATIVE_BITBLT, + NATIVE_INVRECT, + NATIVE_FILLRECT_8, + NATIVE_FILLRECT_32, NATIVE_OP_MAX }; diff --git a/SheepShaver/src/include/video.h b/SheepShaver/src/include/video.h index 595a69a2..777b5f91 100644 --- a/SheepShaver/src/include/video.h +++ b/SheepShaver/src/include/video.h @@ -143,6 +143,15 @@ extern int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr); extern int16 VSLDoInterruptService(uint32 arg1); extern void NQDMisc(uint32 arg1, void *arg2); +// Native QuickDraw acceleration callbacks +extern bool NQD_sync_hook(uint32); +extern bool NQD_bitblt_hook(uint32); +//extern bool NQD_fillrect_hook(uint32); +extern void NQD_bitblt(uint32); +//extern void NQD_invrect(uint32); +//extern void NQD_fillrect8(uint32); +//extern void NQD_fillrect32(uint32); + extern bool keyfile_valid; #endif diff --git a/SheepShaver/src/include/video_defs.h b/SheepShaver/src/include/video_defs.h index 84af87be..5e6356ae 100644 --- a/SheepShaver/src/include/video_defs.h +++ b/SheepShaver/src/include/video_defs.h @@ -307,7 +307,7 @@ enum { // CursorImage struct * Structures for graphics acceleration */ -typedef void *CTabHandle; +typedef uint32 CTabHandle; // Parameter block passed to acceleration hooks struct accl_params { @@ -324,7 +324,7 @@ struct accl_params { uint32 unknown2[3]; uint32 src_base_addr; - uint32 src_row_bytes; + int32 src_row_bytes; int16 src_bounds[4]; uint32 src_unknown1; uint32 src_pixel_type; @@ -337,7 +337,7 @@ struct accl_params { uint32 src_unknown4; uint32 dest_base_addr; - uint32 dest_row_bytes; + int32 dest_row_bytes; int16 dest_bounds[4]; uint32 dest_unknown1; uint32 dest_pixel_type; @@ -356,14 +356,14 @@ struct accl_params { uint32 unknown4[38]; - void (*draw_proc)(accl_params *); + uint32 draw_proc; // Argument for accl_sync_hook at offset 0x4f8 }; // Hook info for NQDMisc struct accl_hook_info { - bool (*draw_func)(accl_params *); - bool (*sync_func)(void *); + uint32 draw_func; + uint32 sync_func; uint32 code; }; diff --git a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp index f8e92c17..d72d15ce 100644 --- a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp +++ b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp @@ -985,6 +985,29 @@ static void NativeOp(int selector) case NATIVE_ETHER_RSRV: GPR(3) = ether_rsrv((queue_t *)GPR(3)); break; + case NATIVE_SYNC_HOOK: + GPR(3) = NQD_sync_hook(GPR(3)); + break; + case NATIVE_BITBLT_HOOK: + GPR(3) = NQD_bitblt_hook(GPR(3)); + break; + case NATIVE_BITBLT: + NQD_bitblt(GPR(3)); + break; +#if 0 + case NATIVE_FILLRECT_HOOK: + GPR(3) = NQD_fillrect_hook(GPR(3)); + break; + case NATIVE_INVRECT: + NQD_invrect(GPR(3)); + break; + case NATIVE_FILLRECT_8: + NQD_fillrect8(GPR(3)); + break; + case NATIVE_FILLRECT_32: + NQD_fillrect32(GPR(3)); + break; +#endif #else case NATIVE_ETHER_INIT: // FIXME: needs more complicated thunks diff --git a/SheepShaver/src/thunks.cpp b/SheepShaver/src/thunks.cpp index 3cd1e87d..d516a14d 100644 --- a/SheepShaver/src/thunks.cpp +++ b/SheepShaver/src/thunks.cpp @@ -84,6 +84,13 @@ uint32 NativeOpcode(int selector) case NATIVE_GET_1_IND_RESOURCE: case NATIVE_R_GET_RESOURCE: case NATIVE_MAKE_EXECUTABLE: + case NATIVE_SYNC_HOOK: + case NATIVE_BITBLT_HOOK: + case NATIVE_FILLRECT_HOOK: + case NATIVE_BITBLT: + case NATIVE_INVRECT: + case NATIVE_FILLRECT_8: + case NATIVE_FILLRECT_32: opcode = POWERPC_NATIVE_OP(1, selector); break; default: @@ -247,6 +254,13 @@ bool ThunksInit(void) DEFINE_NATIVE_OP(NATIVE_SERIAL_STATUS, SerialStatus); DEFINE_NATIVE_OP(NATIVE_SERIAL_CLOSE, SerialClose); DEFINE_NATIVE_OP(NATIVE_MAKE_EXECUTABLE, MakeExecutable); + DEFINE_NATIVE_OP(NATIVE_SYNC_HOOK, NQD_sync_hook); + DEFINE_NATIVE_OP(NATIVE_BITBLT_HOOK, NQD_bitblt_hook); +// DEFINE_NATIVE_OP(NATIVE_FILLRECT_HOOK, NQD_fillrect_hook); + DEFINE_NATIVE_OP(NATIVE_BITBLT, NQD_bitblt); +// DEFINE_NATIVE_OP(NATIVE_INVRECT, NQD_invrect); +// DEFINE_NATIVE_OP(NATIVE_FILLRECT_8, NQD_fillrect8); +// DEFINE_NATIVE_OP(NATIVE_FILLRECT_32, NQD_fillrect32); #undef DEFINE_NATIVE_OP #endif