From f2a42ccf7ee24e80e965c46cc0168d8f96f113fc Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 22 Feb 2017 20:49:54 +0000 Subject: [PATCH] Voodoo screen filter improvements. Patch from leilei. --- src/vid_voodoo.c | 299 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 252 insertions(+), 47 deletions(-) diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index 0f700dc..b4f675a 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -385,7 +385,7 @@ typedef struct voodoo_t uint8_t thefilterb[256][256]; // for blue /* the voodoo adds purple lines for some reason */ - uint16_t purpleline[1024]; + uint16_t purpleline[256][3]; texture_t texture_cache[2][TEX_CACHE_MAX]; uint8_t texture_present[2][4096]; @@ -6515,11 +6515,16 @@ static void voodoo_calc_clutData(voodoo_t *voodoo) static int FILTCAP, FILTCAPG, FILTCAPB = 0; /* color filter threshold values */ -static void voodoo_generate_filter(voodoo_t *voodoo) +static void voodoo_generate_filter_v1(voodoo_t *voodoo) { int g, h; float difference, diffg, diffb; float thiscol, thiscolg, thiscolb, lined; + float fcr, fcg, fcb; + + fcr = FILTCAP * 5; + fcg = FILTCAPG * 6; + fcb = FILTCAPB * 5; for (g=0;g FILTCAP) difference = FILTCAP; if (difference < -FILTCAP) @@ -6543,10 +6550,18 @@ static void voodoo_generate_filter(voodoo_t *voodoo) diffb = FILTCAPB; if (diffb < -FILTCAPB) diffb = -FILTCAPB; - - thiscol = g + (difference / 2); - thiscolg = g + (diffg / 2); /* need these divides so we can actually undither! */ - thiscolb = g + (diffb / 2); + + // hack - to make it not bleed onto black + //if (g == 0){ + //difference = diffg = diffb = 0; + //} + + if ((difference < fcr) || (-difference > -fcr)) + thiscol = g + (difference / 2); + if ((diffg < fcg) || (-diffg > -fcg)) + thiscolg = g + (diffg / 2); /* need these divides so we can actually undither! */ + if ((diffb < fcb) || (-diffb > -fcb)) + thiscolb = g + (diffb / 2); if (thiscol < 0) thiscol = 0; @@ -6568,10 +6583,115 @@ static void voodoo_generate_filter(voodoo_t *voodoo) voodoo->thefilterb[g][h] = thiscolb; } + lined = g + 4; + if (lined > 255) + lined = 255; + voodoo->purpleline[g][0] = lined; + voodoo->purpleline[g][2] = lined; + + lined = g + 0; + if (lined > 255) + lined = 255; + voodoo->purpleline[g][1] = lined; + } +} + +static void voodoo_generate_filter_v2(voodoo_t *voodoo) +{ + int g, h; + float difference; + float thiscol, thiscolg, thiscolb, lined; + float clr, clg, clb = 0; + float fcr, fcg, fcb = 0; + + // pre-clamping + + fcr = FILTCAP; + fcg = FILTCAPG; + fcb = FILTCAPB; + + if (fcr > 32) fcr = 32; + if (fcg > 32) fcg = 32; + if (fcb > 32) fcb = 32; + + for (g=0;g<256;g++) // pixel 1 - our target pixel we want to bleed into + { + for (h=0;h<256;h++) // pixel 2 - our main pixel + { + float avg; + float avgdiff; + + difference = (float)(g - h); + avg = (float)((g + g + g + g + h) / 5); + avgdiff = avg - (float)((g + h + h + h + h) / 5); + if (avgdiff < 0) avgdiff *= -1; + if (difference < 0) difference *= -1; + + thiscol = thiscolg = thiscolb = g; + + // try lighten + if (h > g) + { + clr = clg = clb = avgdiff; + + if (clr>fcr) clr=fcr; + if (clg>fcg) clg=fcg; + if (clb>fcb) clb=fcb; + + + thiscol = g + clr; + thiscolg = g + clg; + thiscolb = g + clb; + + if (thiscol>g+FILTCAP) + thiscol=g+FILTCAP; + if (thiscolg>g+FILTCAPG) + thiscolg=g+FILTCAPG; + if (thiscolb>g+FILTCAPB) + thiscolb=g+FILTCAPB; + + + if (thiscol>g+avgdiff) + thiscol=g+avgdiff; + if (thiscolg>g+avgdiff) + thiscolg=g+avgdiff; + if (thiscolb>g+avgdiff) + thiscolb=g+avgdiff; + + } + + if (difference > FILTCAP) + thiscol = g; + if (difference > FILTCAPG) + thiscolg = g; + if (difference > FILTCAPB) + thiscolb = g; + + // clamp + if (thiscol < 0) thiscol = 0; + if (thiscolg < 0) thiscolg = 0; + if (thiscolb < 0) thiscolb = 0; + + if (thiscol > 255) thiscol = 255; + if (thiscolg > 255) thiscolg = 255; + if (thiscolb > 255) thiscolb = 255; + + // add to the table + voodoo->thefilter[g][h] = (thiscol); + voodoo->thefilterg[g][h] = (thiscolg); + voodoo->thefilterb[g][h] = (thiscolb); + + // debug the ones that don't give us much of a difference + //if (difference < FILTCAP) + //pclog("Voodoofilter: %ix%i - %f difference, %f average difference, R=%f, G=%f, B=%f\n", g, h, difference, avgdiff, thiscol, thiscolg, thiscolb); + } + lined = g + 3; if (lined > 255) lined = 255; - voodoo->purpleline[g] = lined; + voodoo->purpleline[g][0] = lined; + voodoo->purpleline[g][1] = 0; + voodoo->purpleline[g][2] = lined; } } @@ -6596,51 +6716,32 @@ static void voodoo_threshold_check(voodoo_t *voodoo) pclog("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b); voodoo->scrfilterThresholdOld = voodoo->scrfilterThreshold; - voodoo_generate_filter(voodoo); + + if (voodoo->type == VOODOO_2) + voodoo_generate_filter_v2(voodoo); + else + voodoo_generate_filter_v1(voodoo); } } -static void voodoo_filterline(voodoo_t *voodoo, uint16_t *fil, int column, uint16_t *src, int line) +static void voodoo_filterline_v1(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line) { int x; + // Scratchpad for avoiding feedback streaks + uint8_t fil3[(voodoo->h_disp) * 3]; + /* 16 to 32-bit */ for (x=0; x> 5) & 63) << 2); /* Shift to 32-bit */ - fil[x*3+2] = (((src[x] >> 11) & 31) << 3); - } + fil[x*3] = ((src[x] & 31) << 3); + fil[x*3+1] = (((src[x] >> 5) & 63) << 2); + fil[x*3+2] = (((src[x] >> 11) & 31) << 3); - fil[x*3] = 0; - fil[x*3+1] = 0; /* Keep the compiler happy */ - fil[x*3+2] = 0; - - /* filtering time */ - - for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; - fil[(x-1)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; - fil[(x-1)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; - } - for (x=0; xthefilterb[fil[x*3]][fil[ (x+1) *3]]; - fil[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x+1) *3+1]]; - fil[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x+1) *3+2]]; - } - for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; - fil[(x-1)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; - fil[(x-1)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; - } - for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; - fil[(x-1)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; - fil[(x-1)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; + // Copy to our scratchpads + fil3[x*3+0] = fil[x*3+0]; + fil3[x*3+1] = fil[x*3+1]; + fil3[x*3+2] = fil[x*3+2]; } @@ -6650,12 +6751,110 @@ static void voodoo_filterline(voodoo_t *voodoo, uint16_t *fil, int column, uint1 { for (x=0; xpurpleline[fil[x*3]]; - fil[x*3+2] = voodoo->purpleline[fil[x*3+2]]; + fil[x*3] = voodoo->purpleline[fil[x*3]][0]; + fil[x*3+1] = voodoo->purpleline[fil[x*3+1]][1]; + fil[x*3+2] = voodoo->purpleline[fil[x*3+2]][2]; } } + + + /* filtering time */ + + for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; + fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; + fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; + } + + for (x=1; xthefilterb[fil3[x*3]][fil3[ (x-1) *3]]; + fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x-1) *3+1]]; + fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x-1) *3+2]]; + } + + for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; + fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; + fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; + } + + for (x=0; xthefilterb[fil3[x*3]][fil3[ (x+1) *3]]; + fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x+1) *3+1]]; + fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x+1) *3+2]]; + } } + +static void voodoo_filterline_v2(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line) +{ + int x; + + // Scratchpad for blending filter + uint8_t fil3[(voodoo->h_disp) * 3]; + + /* 16 to 32-bit */ + for (x=0; x> 5) & 63) << 2); + fil3[x*3+2] = fil[x*3+2] = (((src[x] >> 11) & 31) << 3); + } + + /* filtering time */ + + for (x=1; xthefilterb [((src[x+3] & 31) << 3)] [((src[x] & 31) << 3)]; + fil3[(x+3)*3+1] = voodoo->thefilterg [(((src[x+3] >> 5) & 63) << 2)] [(((src[x] >> 5) & 63) << 2)]; + fil3[(x+3)*3+2] = voodoo->thefilter [(((src[x+3] >> 11) & 31) << 3)] [(((src[x] >> 11) & 31) << 3)]; + + fil[(x+2)*3] = voodoo->thefilterb [fil3[(x+2)*3]][((src[x] & 31) << 3)]; + fil[(x+2)*3+1] = voodoo->thefilterg [fil3[(x+2)*3+1]][(((src[x] >> 5) & 63) << 2)]; + fil[(x+2)*3+2] = voodoo->thefilter [fil3[(x+2)*3+2]][(((src[x] >> 11) & 31) << 3)]; + + fil3[(x+1)*3] = voodoo->thefilterb [fil[(x+1)*3]][((src[x] & 31) << 3)]; + fil3[(x+1)*3+1] = voodoo->thefilterg [fil[(x+1)*3+1]][(((src[x] >> 5) & 63) << 2)]; + fil3[(x+1)*3+2] = voodoo->thefilter [fil[(x+1)*3+2]][(((src[x] >> 11) & 31) << 3)]; + + fil[(x-1)*3] = voodoo->thefilterb [fil3[(x-1)*3]][((src[x] & 31) << 3)]; + fil[(x-1)*3+1] = voodoo->thefilterg [fil3[(x-1)*3+1]][(((src[x] >> 5) & 63) << 2)]; + fil[(x-1)*3+2] = voodoo->thefilter [fil3[(x-1)*3+2]][(((src[x] >> 11) & 31) << 3)]; + } + + // unroll for edge cases + + fil3[(column-3)*3] = voodoo->thefilterb [((src[column-3] & 31) << 3)] [((src[column] & 31) << 3)]; + fil3[(column-3)*3+1] = voodoo->thefilterg [(((src[column-3] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; + fil3[(column-3)*3+2] = voodoo->thefilter [(((src[column-3] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; + + fil3[(column-2)*3] = voodoo->thefilterb [((src[column-2] & 31) << 3)] [((src[column] & 31) << 3)]; + fil3[(column-2)*3+1] = voodoo->thefilterg [(((src[column-2] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; + fil3[(column-2)*3+2] = voodoo->thefilter [(((src[column-2] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; + + fil3[(column-1)*3] = voodoo->thefilterb [((src[column-1] & 31) << 3)] [((src[column] & 31) << 3)]; + fil3[(column-1)*3+1] = voodoo->thefilterg [(((src[column-1] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; + fil3[(column-1)*3+2] = voodoo->thefilter [(((src[column-1] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; + + fil[(column-2)*3] = voodoo->thefilterb [fil3[(column-2)*3]][((src[column] & 31) << 3)]; + fil[(column-2)*3+1] = voodoo->thefilterg [fil3[(column-2)*3+1]][(((src[column] >> 5) & 63) << 2)]; + fil[(column-2)*3+2] = voodoo->thefilter [fil3[(column-2)*3+2]][(((src[column] >> 11) & 31) << 3)]; + + fil[(column-1)*3] = voodoo->thefilterb [fil3[(column-1)*3]][((src[column] & 31) << 3)]; + fil[(column-1)*3+1] = voodoo->thefilterg [fil3[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)]; + fil[(column-1)*3+2] = voodoo->thefilter [fil3[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)]; + + fil3[(column-1)*3] = voodoo->thefilterb [fil[(column-1)*3]][((src[column] & 31) << 3)]; + fil3[(column-1)*3+1] = voodoo->thefilterg [fil[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)]; + fil3[(column-1)*3+2] = voodoo->thefilter [fil[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)]; +} + + void voodoo_callback(void *p) { voodoo_t *voodoo = (voodoo_t *)p; @@ -6683,9 +6882,12 @@ void voodoo_callback(void *p) if (voodoo->scrfilter && voodoo->scrfilterEnabled) { int j, offset; - uint16_t fil[(voodoo->h_disp + 1) * 3]; /* interleaved 24-bit RGB */ + uint8_t fil[(voodoo->h_disp) * 3]; /* interleaved 24-bit RGB */ - voodoo_filterline(voodoo, fil, voodoo->h_disp, src, voodoo->line); + if (voodoo->type == VOODOO_2) + voodoo_filterline_v2(voodoo, fil, voodoo->h_disp, src, voodoo->line); + else + voodoo_filterline_v1(voodoo, fil, voodoo->h_disp, src, voodoo->line); for (x = 0; x < voodoo->h_disp; x++) { @@ -6833,7 +7035,10 @@ void *voodoo_init() break; } - voodoo_generate_filter(voodoo); /*generate filter lookup tables*/ + if (voodoo->type == VOODOO_2) /*generate filter lookup tables*/ + voodoo_generate_filter_v2(voodoo); + else + voodoo_generate_filter_v1(voodoo); pci_add(voodoo_pci_read, voodoo_pci_write, voodoo);