Path: blob/master/libmupen64plus/mupen64plus-video-z64/src/rgl_geometry.cpp
2 views
/*1* z642*3* Copyright (C) 2007 ziggy4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License along16* with this program; if not, write to the Free Software Foundation, Inc.,17* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.18*19**/2021#include "rdp.h"22#include "rgl.h"2324#include <SDL.h>2526inline float _zscale(uint16_t z)27{28uint32_t res;29int e = z>>(16-3);30int m = (z>>2)&((1<<11)-1);3132static struct {33int shift;34long add;35} z_format[8] = {36{6, 0x00000},37{5, 0x20000},38{4, 0x30000},39{3, 0x38000},40{2, 0x3c000},41{1, 0x3e000},42{0, 0x3f000},43{0, 0x3f800},44};4546res = (m << z_format[e].shift) +47z_format[e].add;48return float(res)/0x3ffff;49}5051inline float zscale(uint16_t z)52{53return float(z)/0xffff;54}55//#define zscale _zscale5657float rglZscale(uint16_t z)58{59return _zscale(z);60}6162void rglTextureRectangle(rdpTexRect_t * rect, int flip)63{64int tilenum = rect->tilenum;65int x1,x2,y1,y2,z;66int s, t;67int dx, dy;6869// if (tilenum == 7) {70// LOG("Fixing tilenum from 7 to 0\n");71// tilenum = 0;72// }7374x1 = (rect->xh);75x2 = (rect->xl);76y1 = (rect->yh);77y2 = (rect->yl);78s = int(rect->s)<<5;79t = int(rect->t)<<5;8081DUMP("texrect %d x %d --> %d x %d s %d t %d flip %d\n",82x1, y1, x2, y2, s, t, flip);8384if (RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_FILL ||85RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_COPY)86{87rect->dsdx /= 4;88//s /= 4;89x2 += 4;90y2 += 4;91} else {92x2 += 1;93y2 += 1;94}9596x1 /= 4;97x2 /= 4;98y1 /= 4;99y2 /= 4;100101if (x2 < x1) x2 = x1+1; // black gauge in SCARS (E)102103int t1 = rglT1Usage(rdpState)? RGL_STRIP_TEX1:0;104int t2 = (rect->tilenum < 7 && rglT2Usage(rdpState))? RGL_STRIP_TEX2:0;105if (t1)106rglPrepareRendering(1, (tilenum==7 && RDP_GETOM_CYCLE_TYPE(rdpState.otherModes)==1)? 0:tilenum, y2-y1, 1);107if (t2)108rglPrepareRendering(1, tilenum+1, y2-y1, 1);109else if (!t1)110rglPrepareRendering(0, 0, 0, 1);111112// TO BE REMOVED when we implement depth texture writing113curRBuffer->flags |= RGL_RB_HASTRIANGLES;114115// TO CHECK should this before or after the rescaling above ?116// s -= (rdpTiles[tilenum].sl << 8);117// t -= (rdpTiles[tilenum].tl << 8);118// if (/*!tile.ms && */tile.mask_s)119// s &= (1<<tile.mask_s+10) - 1;120// if (/*!tile.mt && */tile.mask_t)121// t &= (1<<tile.mask_t+10) - 1;122123#define XSCALE(x) (float(x))124#define YSCALE(y) (float(y))125#define ZSCALE(z) (zscale(z))126#define SSCALE(s) (float(s)/(1 << 10))127#define TSCALE(s) (float(s)/(1 << 10))128// #define glTexCoord2f(s, t) printf("tex %g %g\n", s, t), glTexCoord2f(s, t)129// #define glVertex3f(s, t, z) printf("vert %g %g %g\n", s, t, z), glVertex3f(s, t, z)130131dx = x2 - x1;132dy = y2 - y1;133if (RDP_GETOM_Z_SOURCE_SEL(rdpState.otherModes))134z = rdpState.primitiveZ;135else136z = 0xffff;137// if (dump)138// fprintf(stderr, "fillrect cycle %d\n", other_modes.cycle_type);139140rglStrip_t * strip = strips + nbStrips++;141rglAssert(nbStrips < MAX_STRIPS);142curChunk->nbStrips++;143rglVertex_t * vtx = vtxs + nbVtxs;144145strip->flags = t1 | t2 | RGL_STRIP_ZBUFFER;146strip->vtxs = vtx;147strip->tilenum = tilenum;148149float s2, tr;150s2 = s+int(rect->dsdx)*dx;151tr = t+int(rect->dtdy)*dy;152//LOG("%d %d\n", rect->dsdx, rect->dtdy);153if (0 && RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) < 2)154{155//if (rect->dsdx == (1<<10))156{157s += 1<<9;158s2 -= 1<<9;159}160//if (rect->dtdy == (1<<10))161{162t += 1<<9;163tr -= 1<<9;164}165}166167if (flip) { vtx->t = SSCALE(s2); vtx->s = TSCALE(t);168} else { vtx->s = SSCALE(s2); vtx->t = TSCALE(t); }169vtx->x = XSCALE(x2); vtx->y = YSCALE(y1); vtx->z = ZSCALE(z); vtx++->w = 1;170if (flip) { vtx->t = SSCALE(s); vtx->s = TSCALE(t);171} else { vtx->s = SSCALE(s); vtx->t = TSCALE(t); }172vtx->x = XSCALE(x1); vtx->y = YSCALE(y1); vtx->z = ZSCALE(z); vtx++->w = 1;173if (flip) { vtx->t = SSCALE(s2); vtx->s = TSCALE(tr);174} else { vtx->s = SSCALE(s2); vtx->t = TSCALE(tr); }175vtx->x = XSCALE(x2); vtx->y = YSCALE(y2); vtx->z = ZSCALE(z); vtx++->w = 1;176if (flip) { vtx->t = SSCALE(s); vtx->s = TSCALE(tr);177} else { vtx->s = SSCALE(s); vtx->t = TSCALE(tr); }178vtx->x = XSCALE(x1); vtx->y = YSCALE(y2); vtx->z = ZSCALE(z); vtx++->w = 1;179180strip->nbVtxs = vtx - strip->vtxs;181nbVtxs = vtx - vtxs;182}183184void rglFillRectangle(rdpRect_t * rect)185{186int x1,x2,y1,y2,z;187//int s, t;188//int dx, dy;189190rglPrepareRendering(0, 0, 0, 1);191DUMP("fillrect curRBuffer->flags %x %x %x\n", curRBuffer->flags, curRBuffer->addressStart, rdpZbAddress);192// if (/*(curRBuffer->flags & RGL_RB_DEPTH) &&*/193// RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_FILL &&194// rect->xh-4 <= rdpState.clip.xh && rect->xl+8 >= rdpState.clip.xl &&195// rect->yh-4 <= rdpState.clip.yh && rect->yl+8 >= rdpState.clip.yl196// ) {197// curChunk->flags |= RGL_CHUNK_CLEAR;198// return;199// }200201x1 = (rect->xh / 4);202x2 = (rect->xl / 4);203y1 = (rect->yh / 4);204y2 = (rect->yl / 4);205206if (RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_FILL ||207RDP_GETOM_CYCLE_TYPE(rdpState.otherModes) == RDP_CYCLE_TYPE_COPY)208{209x2 += 1;210y2 += 1;211} else {212//rglAssert(!(curRBuffer->flags & RGL_RB_DEPTH));213// x2 -= 1;214// y2 -= 1;215}216217if (x2 < x1) x2 = x1+1; // black gauge in SCARS (E)218219#define XSCALE(x) (float(x))220#define YSCALE(y) (float(y))221#define ZSCALE(z) (zscale(z))222223if (RDP_GETOM_Z_SOURCE_SEL(rdpState.otherModes))224z = rdpState.primitiveZ;225else226z = 0xffff;227// if (dump)228// fprintf(stderr, "fillrect cycle %d\n", other_modes.cycle_type);229230rglStrip_t * strip = strips + nbStrips++;231rglAssert(nbStrips < MAX_STRIPS);232curChunk->nbStrips++;233rglVertex_t * vtx = vtxs + nbVtxs;234235strip->flags = RGL_STRIP_ZBUFFER;236strip->vtxs = vtx;237238vtx->x = XSCALE(x2); vtx->y = YSCALE(y1); vtx->z = ZSCALE(z); vtx++->w = 1;239vtx->x = XSCALE(x1); vtx->y = YSCALE(y1); vtx->z = ZSCALE(z); vtx++->w = 1;240vtx->x = XSCALE(x2); vtx->y = YSCALE(y2); vtx->z = ZSCALE(z); vtx++->w = 1;241vtx->x = XSCALE(x1); vtx->y = YSCALE(y2); vtx->z = ZSCALE(z); vtx++->w = 1;242243strip->nbVtxs = vtx - strip->vtxs;244nbVtxs = vtx - vtxs;245}246247void rglTriangle(uint32_t w1, uint32_t w2, int shade, int texture, int zbuffer,248uint32_t * rdp_cmd)249{250int tilenum = (w1 >> 16) & 0x7;251// if (tilenum == 7) {252// LOG("Fixing tilenum from 7 to 0\n");253// tilenum = 0;254// }255int j;256int xleft, xright, xleft_inc, xright_inc;257//int xstart, xend;258int r, g, b, a, z, s, t, w;259int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0;260int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0;261int flip = (w1 & 0x800000) ? 1 : 0;262263int32_t yl, ym, yh;264int32_t xl, xm, xh;265int64_t dxldy, dxhdy, dxmdy;266uint32_t w3, w4, w5, w6, w7, w8;267268uint32_t * shade_base = rdp_cmd + 8;269uint32_t * texture_base = rdp_cmd + 8;270uint32_t * zbuffer_base = rdp_cmd + 8;271272int t1 = (texture && rglT1Usage(rdpState))? RGL_STRIP_TEX1:0;273int t2 = (texture && tilenum < 7 && rglT2Usage(rdpState))? RGL_STRIP_TEX2:0;274if (t1)275rglPrepareRendering(1, (tilenum==7 && RDP_GETOM_CYCLE_TYPE(rdpState.otherModes)==1)? 0:tilenum, 0, zbuffer);276if (t2)277rglPrepareRendering(1, tilenum+1, 0, zbuffer);278else if (!t1)279rglPrepareRendering(0, 0, 0, zbuffer);280281curRBuffer->flags |= RGL_RB_HASTRIANGLES;282283if (shade)284{285texture_base += 16;286zbuffer_base += 16;287}288if (texture)289{290zbuffer_base += 16;291}292293w3 = rdp_cmd[2];294w4 = rdp_cmd[3];295w5 = rdp_cmd[4];296w6 = rdp_cmd[5];297w7 = rdp_cmd[6];298w8 = rdp_cmd[7];299300yl = (w1 & 0x3fff);301ym = ((w2 >> 16) & 0x3fff);302yh = ((w2 >> 0) & 0x3fff);303xl = (int32_t)(w3);304xh = (int32_t)(w5);305xm = (int32_t)(w7);306dxldy = (int32_t)(w4);307dxhdy = (int32_t)(w6);308dxmdy = (int32_t)(w8);309310if (yl & (0x800<<2)) yl |= 0xfffff000<<2;311if (ym & (0x800<<2)) ym |= 0xfffff000<<2;312if (yh & (0x800<<2)) yh |= 0xfffff000<<2;313314yh &= ~3;315316r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000;317318if (shade)319{320r = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff);321g = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff);322b = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff);323a = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff);324drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff);325dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff);326dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff);327dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff);328drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff);329dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff);330dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff);331dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff);332}333if (texture)334{335s = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff);336t = ((texture_base[0 ] << 16) & 0xffff0000) | (texture_base[4 ] & 0x0000ffff);337w = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff);338dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff);339dtdx = ((texture_base[2 ] << 16) & 0xffff0000) | (texture_base[6 ] & 0x0000ffff);340dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff);341dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff);342dtde = ((texture_base[8 ] << 16) & 0xffff0000) | (texture_base[12] & 0x0000ffff);343dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff);344}345if (zbuffer)346{347//rglAssert(!(curRBuffer->flags & RGL_RB_DEPTH));348349z = zbuffer_base[0];350dzdx = zbuffer_base[1];351dzde = zbuffer_base[2];352}353354xh <<= 2; xm <<= 2; xl <<= 2;355r <<= 2; g <<= 2; b <<= 2; a <<= 2;356dsde >>= 2; dtde >>= 2; dsdx >>= 2; dtdx >>= 2;357dzdx >>= 2; dzde >>= 2;358dwdx >>= 2; dwde >>= 2;359360361// #define tile rdpTiles[tilenum]362// s -= (rdpTiles[tilenum].sl << 8);363// t -= (rdpTiles[tilenum].tl << 8);364// if (/*!tile.ms && */tile.mask_s)365// s &= (1<<tile.mask_s+10) - 1;366// if (/*!tile.mt && */tile.mask_t)367// t &= (1<<tile.mask_t+10) - 1;368// #undef tile369370371xleft = xm;372xright = xh;373xleft_inc = dxmdy;374xright_inc = dxhdy;375376while (yh<ym &&377!((!flip && xleft < xright+0x10000) ||378(flip && xleft > xright-0x10000))) {379xleft += xleft_inc; xright += xright_inc;380s += dsde; t += dtde; w += dwde;381r += drde; g += dgde; b += dbde; a += dade;382z += dzde;383yh++;384}385386j = ym-yh;387//rglAssert(j >= 0);388#undef XSCALE389#undef YSCALE390#undef ZSCALE391#undef SSCALE392#undef TSCALE393#define XSCALE(x) (float(x)/(1<<18))394#define YSCALE(y) (float(y)/(1<<2))395#define ZSCALE(z) (RDP_GETOM_Z_SOURCE_SEL(rdpState.otherModes)? zscale(rdpState.primitiveZ) : zscale((z)>>16))396#define WSCALE(z) 1.0f/(RDP_GETOM_PERSP_TEX_EN(rdpState.otherModes)? (float(uint32_t(z) + 0x10000)/0xffff0000) : 1.0f)397//#define WSCALE(w) (RDP_GETOM_PERSP_TEX_EN(rdpState.otherModes)? 65536.0f*65536.0f/float((w+ 0x10000)) : 1.0f)398#define CSCALE(c) (((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18)399#define _PERSP(w) ( w )400#define PERSP(s, w) ( ((int64_t)(s) << 20) / (_PERSP(w)? _PERSP(w):1) )401#define SSCALE(s, _w) (RDP_GETOM_PERSP_TEX_EN(rdpState.otherModes)? float(PERSP(s, _w))/(1 << 10) : float(s)/(1<<21))402#define TSCALE(s, w) (RDP_GETOM_PERSP_TEX_EN(rdpState.otherModes)? float(PERSP(s, w))/(1 << 10) : float(s)/(1<<21))403404rglStrip_t * strip = strips + nbStrips++;405rglAssert(nbStrips < MAX_STRIPS);406curChunk->nbStrips++;407rglVertex_t * vtx = vtxs + nbVtxs;408409strip->flags = (shade? RGL_STRIP_SHADE : 0) | t1 | t2410| RGL_STRIP_ZBUFFER;411//| (zbuffer? RGL_STRIP_ZBUFFER : 0);412strip->vtxs = vtx;413strip->tilenum = tilenum;414415//int sw;416if (j > 0)417{418int dx = ((xleft-xright)>>16);419if ((!flip && xleft < xright) ||420(flip/* && xleft > xright*/))421{422if (shade) {423vtx->r = CSCALE(r+drdx*dx);424vtx->g = CSCALE(g+dgdx*dx);425vtx->b = CSCALE(b+dbdx*dx);426vtx->a = CSCALE(a+dadx*dx);427}428if (texture) {429vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);430vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);431}432vtx->x = XSCALE(xleft);433vtx->y = YSCALE(yh);434vtx->z = ZSCALE(z+dzdx*dx);435vtx->w = WSCALE(w+dwdx*dx);436vtx++;437}438if ((!flip/* && xleft < xright*/) ||439(flip && xleft > xright))440{441if (shade) {442vtx->r = CSCALE(r);443vtx->g = CSCALE(g);444vtx->b = CSCALE(b);445vtx->a = CSCALE(a);446}447if (texture) {448vtx->s = SSCALE(s, w);449vtx->t = TSCALE(t, w);450}451vtx->x = XSCALE(xright);452vtx->y = YSCALE(yh);453vtx->z = ZSCALE(z);454vtx->w = WSCALE(w);455vtx++;456}457}458xleft += xleft_inc*j; xright += xright_inc*j;459s += dsde*j; t += dtde*j; w += dwde*j;460r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;461z += dzde*j;462// render ...463464xleft = xl;465466//if (yl-ym > 0)467{468int dx = ((xleft-xright)>>16);469if ((!flip && xleft <= xright) ||470(flip/* && xleft >= xright*/))471{472if (shade) {473vtx->r = CSCALE(r+drdx*dx);474vtx->g = CSCALE(g+dgdx*dx);475vtx->b = CSCALE(b+dbdx*dx);476vtx->a = CSCALE(a+dadx*dx);477}478if (texture) {479vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);480vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);481}482vtx->x = XSCALE(xleft);483vtx->y = YSCALE(ym);484vtx->z = ZSCALE(z+dzdx*dx);485vtx->w = WSCALE(w+dwdx*dx);486vtx++;487}488if ((!flip/* && xleft <= xright*/) ||489(flip && xleft >= xright))490{491if (shade) {492vtx->r = CSCALE(r);493vtx->g = CSCALE(g);494vtx->b = CSCALE(b);495vtx->a = CSCALE(a);496}497if (texture) {498vtx->s = SSCALE(s, w);499vtx->t = TSCALE(t, w);500}501vtx->x = XSCALE(xright);502vtx->y = YSCALE(ym);503vtx->z = ZSCALE(z);504vtx->w = WSCALE(w);505vtx++;506}507}508xleft_inc = dxldy;509xright_inc = dxhdy;510511j = yl-ym;512//rglAssert(j >= 0);513//j--; // ?514xleft += xleft_inc*j; xright += xright_inc*j;515s += dsde*j; t += dtde*j; w += dwde*j;516r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;517z += dzde*j;518519while (yl>ym &&520!((!flip && xleft < xright+0x10000) ||521(flip && xleft > xright-0x10000))) {522xleft -= xleft_inc; xright -= xright_inc;523s -= dsde; t -= dtde; w -= dwde;524r -= drde; g -= dgde; b -= dbde; a -= dade;525z -= dzde;526j--;527yl--;528}529530// render ...531if (j >= 0) {532int dx = ((xleft-xright)>>16);533if ((!flip && xleft <= xright) ||534(flip/* && xleft >= xright*/))535{536if (shade) {537vtx->r = CSCALE(r+drdx*dx);538vtx->g = CSCALE(g+dgdx*dx);539vtx->b = CSCALE(b+dbdx*dx);540vtx->a = CSCALE(a+dadx*dx);541}542if (texture) {543vtx->s = SSCALE(s+dsdx*dx, w+dwdx*dx);544vtx->t = TSCALE(t+dtdx*dx, w+dwdx*dx);545}546vtx->x = XSCALE(xleft);547vtx->y = YSCALE(yl);548vtx->z = ZSCALE(z+dzdx*dx);549vtx->w = WSCALE(w+dwdx*dx);550vtx++;551}552if ((!flip/* && xleft <= xright*/) ||553(flip && xleft >= xright))554{555if (shade) {556vtx->r = CSCALE(r);557vtx->g = CSCALE(g);558vtx->b = CSCALE(b);559vtx->a = CSCALE(a);560}561if (texture) {562vtx->s = SSCALE(s, w);563vtx->t = TSCALE(t, w);564}565vtx->x = XSCALE(xright);566vtx->y = YSCALE(yl);567vtx->z = ZSCALE(z);568vtx->w = WSCALE(w);569vtx++;570}571}572573strip->nbVtxs = vtx - strip->vtxs;574nbVtxs = vtx - vtxs;575}576577578