From c8e8113c8175bca3e64fd990db7f076b5cb02a53 Mon Sep 17 00:00:00 2001 From: Romain Dolbeau Date: Mon, 16 May 2022 16:40:05 +0200 Subject: [PATCH] preliminary support for pattern-to-screen, reusing single-byte rectfill --- .../NuBusFPGAInit/NuBusFPGAInit.c | 121 +++++++++++++----- .../NuBusFPGAInit/NuBusFPGA_HW.h | 3 +- nubus-to-ztex-gateware/blit.c | 11 +- nubus-to-ztex-gateware/goblin_accel.py | 22 +++- 4 files changed, 117 insertions(+), 40 deletions(-) diff --git a/nubus-to-ztex-gateware/NuBusFPGAInit/NuBusFPGAInit.c b/nubus-to-ztex-gateware/NuBusFPGAInit/NuBusFPGAInit.c index 5a46ad1..d34d81d 100644 --- a/nubus-to-ztex-gateware/NuBusFPGAInit/NuBusFPGAInit.c +++ b/nubus-to-ztex-gateware/NuBusFPGAInit/NuBusFPGAInit.c @@ -344,7 +344,7 @@ struct qdstuff { uint16_t PATROW; // (must follow PATHMASK) // PATHMASK-2 uint16_t PATHMASK; // (must follow PATVMASK) // PATVMASK-2 uint16_t PATVMASK; // (must follow expat) // EXPAT-2 - uint32_t EXPAT; // YES // STACKFREE-4 + uint32_t* EXPAT; // YES // STACKFREE-4 // SET UP FOR BITBLT FOR RGNBLT // (CALLED BY STRETCHBITS, RGNBLT, BITBLT, DRAWARC, DRAWLINE) @@ -383,13 +383,13 @@ int hwblit(char* stack, char* p_fb_base, /* short dstshift, */ short mode, Patte short height = qdstack->MINRECT.bottom - qdstack->MINRECT.top; short dstshift = qdstack->DSTSHIFT; - if (mode != 0) { // only copy handled for now -#if 0 //def QEMU + if ((mode != 0) && (mode != 8)) { // only copy handled for now +#ifdef QEMU bt->debug = -2L; bt->debug = mode; if (mode == 8) { bt->debug = qdstack->PATROW; - bt->debug = -2L; +#if 0 bt->debug = pat->pat[0]; bt->debug = pat->pat[1]; bt->debug = pat->pat[2]; @@ -398,11 +398,33 @@ int hwblit(char* stack, char* p_fb_base, /* short dstshift, */ short mode, Patte bt->debug = pat->pat[5]; bt->debug = pat->pat[6]; bt->debug = pat->pat[7]; +#endif } #endif return 0; } + if (mode == 8) { + register int i; + register unsigned long expat0 = qdstack->EXPAT[0]; + if (qdstack->PATROW != 0) { + bt->debug = -6L; + return 0; + } + if ((expat0 & 0xFFFF) != ((expat0 >> 16) & 0xFFFF)) + return 0; + if ((expat0 & 0xFF) != ((expat0 >> 8) & 0xFF)) + return 0; + for (i = 1 ; i < 16 ; i++) + if (expat0 != qdstack->EXPAT[i]) { + bt->debug = -7L; + return 0; + } + } if (dstshift < 3) { // only 8/16/32 bits for now +#ifdef QEMU + bt->debug = -3L; + bt->debug = dstshift; +#endif return 0; } dstshift -= 3; @@ -411,9 +433,17 @@ int hwblit(char* stack, char* p_fb_base, /* short dstshift, */ short mode, Patte } if (dstpix->baseAddr != p_fb_base) { // we're not destination +#ifdef QEMU + bt->debug = -4L; + bt->debug = (unsigned long)dstpix->baseAddr; +#endif return 0; } if (srcpix->baseAddr != p_fb_base) { // we're not source +#ifdef QEMU + bt->debug = -5L; + bt->debug = (unsigned long)srcpix->baseAddr; +#endif return 0; } @@ -440,48 +470,75 @@ int hwblit(char* stack, char* p_fb_base, /* short dstshift, */ short mode, Patte realrect.left += (srcrect->left - dstrect->left); /* A2 */ /* qdstack->MINRECT is A3 */ - srcv.top = realrect.top - srcpix->bounds.top; - srcv.left = realrect.left - srcpix->bounds.left; + srcv.top = realrect.top - srcpix->bounds.top; + srcv.left = realrect.left - srcpix->bounds.left; - dstv.top = qdstack->MINRECT.top - dstpix->bounds.top; - dstv.left = qdstack->MINRECT.left - dstpix->bounds.left; + dstv.top = qdstack->MINRECT.top - dstpix->bounds.top; + dstv.left = qdstack->MINRECT.left - dstpix->bounds.left; - /* if .baseAddr of both pix are different, no overlap */ - /* - // the HW can handle that for us - if (dstpix->baseAddr == srcpix->baseAddr) { - - } - */ + /* if .baseAddr of both pix are different, no overlap */ + /* + // the HW can handle that for us + if (dstpix->baseAddr == srcpix->baseAddr) { + + } + */ #ifdef QEMU - bt->debug = srcv.top; - bt->debug = srcv.left; +#if 0 + if ((mode == 8) && (qdstack->PATROW == 0)) { + bt->debug = 0x87654321; + bt->debug = qdstack->EXPAT[ 0]; + bt->debug = qdstack->EXPAT[ 1]; + bt->debug = qdstack->EXPAT[ 2]; + bt->debug = qdstack->EXPAT[ 3]; + bt->debug = qdstack->EXPAT[ 4]; + bt->debug = qdstack->EXPAT[ 5]; + bt->debug = qdstack->EXPAT[ 6]; + bt->debug = qdstack->EXPAT[ 7]; + bt->debug = qdstack->EXPAT[ 8]; + bt->debug = qdstack->EXPAT[ 9]; + bt->debug = qdstack->EXPAT[10]; + bt->debug = qdstack->EXPAT[11]; + bt->debug = qdstack->EXPAT[12]; + bt->debug = qdstack->EXPAT[13]; + bt->debug = qdstack->EXPAT[14]; + bt->debug = qdstack->EXPAT[15]; + } +#endif + bt->debug = -1L; + bt->debug = srcv.top; + bt->debug = srcv.left; - bt->debug = height; - bt->debug = width; + bt->debug = height; + bt->debug = width; - bt->debug = dstv.top; - bt->debug = dstv.left; + bt->debug = dstv.top; + bt->debug = dstv.left; - bt->debug = (long)dstpix->baseAddr; - bt->debug = (long)srcpix->baseAddr; + bt->debug = (long)dstpix->baseAddr; + bt->debug = (long)srcpix->baseAddr; return 0; #else - WAIT_FOR_HW(accel); + WAIT_FOR_HW(accel); - accel->reg_width = brev(width); - accel->reg_height = brev(height); + accel->reg_width = brev(width); + accel->reg_height = brev(height); + accel->reg_bitblt_dst_x = brev(dstv.left << dstshift); + accel->reg_bitblt_dst_y = brev(dstv.top); + + if (mode == 0) { accel->reg_bitblt_src_x = brev(srcv.left << dstshift); accel->reg_bitblt_src_y = brev(srcv.top); - accel->reg_bitblt_dst_x = brev(dstv.left << dstshift); - accel->reg_bitblt_dst_y = brev(dstv.top); + accel->reg_cmd = brev(1<reg_fgcolor = qdstack->EXPAT[0]; + accel->reg_cmd = brev(1<reg_cmd = brev(1<reg_width, fbc->reg_height, fbc->reg_bitblt_dst_x, fbc->reg_bitblt_dst_y, 0xFF, 0x3); // GXcopy - } + } break; + case FUN_FILL: { + rectfill(fbc->reg_bitblt_dst_x, fbc->reg_bitblt_dst_y, + fbc->reg_width, fbc->reg_height, + fbc->reg_fgcolor); + } break; default: break; } diff --git a/nubus-to-ztex-gateware/goblin_accel.py b/nubus-to-ztex-gateware/goblin_accel.py index 0ef3c52..6a0d569 100644 --- a/nubus-to-ztex-gateware/goblin_accel.py +++ b/nubus-to-ztex-gateware/goblin_accel.py @@ -18,9 +18,9 @@ class GoblinAccel(Module): # AutoCSR ? reg_cmd = Signal(32) # 1 reg_r5_cmd = Signal(32) # 2, to communicate with Vex # 3 resv0 - reg_width = Signal(COORD_BITS) - reg_height = Signal(COORD_BITS) - # 6 resv1 + reg_width = Signal(COORD_BITS) # 4 + reg_height = Signal(COORD_BITS) # 5 + reg_fgcolor = Signal(32) # 6 # 7 resv2 reg_bitblt_src_x = Signal(COORD_BITS) # 8 reg_bitblt_src_y = Signal(COORD_BITS) # 9 @@ -29,9 +29,11 @@ class GoblinAccel(Module): # AutoCSR ? # do-some-work flags do_blit = Signal() + do_fill = Signal() # cmd register reg_cmd DO_BLIT_BIT = 0 + DO_FILL_BIT = 1 # global status register reg_status WORK_IN_PROGRESS_BIT = 0 @@ -48,12 +50,14 @@ class GoblinAccel(Module): # AutoCSR ? 0: [ NextValue(reg_status, bus.dat_w) ], # debug, remove me 1: [ NextValue(reg_cmd, bus.dat_w), NextValue(do_blit, bus.dat_w[DO_BLIT_BIT] & ~reg_status[WORK_IN_PROGRESS_BIT]), + NextValue(do_fill, bus.dat_w[DO_FILL_BIT] & ~reg_status[WORK_IN_PROGRESS_BIT]), ], 2: [ NextValue(reg_r5_cmd, bus.dat_w) ], # 3 4: [ NextValue(reg_width, bus.dat_w) ], 5: [ NextValue(reg_height, bus.dat_w) ], - # 6,7 + 6: [ NextValue(reg_fgcolor, bus.dat_w) ], + # 7 8: [ NextValue(reg_bitblt_src_x, bus.dat_w) ], 9: [ NextValue(reg_bitblt_src_y, bus.dat_w) ], 10: [ NextValue(reg_bitblt_dst_x, bus.dat_w) ], @@ -69,7 +73,8 @@ class GoblinAccel(Module): # AutoCSR ? # 3 4: [ NextValue(bus.dat_r, reg_width) ], 5: [ NextValue(bus.dat_r, reg_height) ], - # 6, 7 + 6: [ NextValue(bus.dat_r, reg_fgcolor) ], + # 7 8: [ NextValue(bus.dat_r, reg_bitblt_src_x) ], 9: [ NextValue(bus.dat_r, reg_bitblt_src_y) ], 10: [ NextValue(bus.dat_r, reg_bitblt_dst_x) ], @@ -84,6 +89,7 @@ class GoblinAccel(Module): # AutoCSR ? # also in blit.c, for r5-cmd FUN_DONE_BIT = 31 FUN_BLIT_BIT = 0 + FUN_FILL_BIT = 1 # to hold the Vex in reset local_reset = Signal(reset = 1) @@ -99,6 +105,12 @@ class GoblinAccel(Module): # AutoCSR ? reg_status[WORK_IN_PROGRESS_BIT].eq(1), local_reset.eq(0), #timeout.eq(timeout_rst), + ).Elif(do_fill & ~reg_status[WORK_IN_PROGRESS_BIT], + do_fill.eq(0), + reg_r5_cmd[FUN_FILL_BIT].eq(1), + reg_status[WORK_IN_PROGRESS_BIT].eq(1), + local_reset.eq(0), + #timeout.eq(timeout_rst), ) ]