From 2624745c67b458ace79d4c9499c722518aacd647 Mon Sep 17 00:00:00 2001 From: TomW Date: Sat, 9 May 2015 20:03:41 +0100 Subject: [PATCH] Implemented Voodoo mipmapping. Probably buggy. --- src/vid_voodoo.c | 141 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 124 insertions(+), 17 deletions(-) diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index 639afd8..932e12a 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -844,9 +844,11 @@ typedef struct voodoo_state_t struct { int64_t base_s, base_t, base_w; + int lod; } tmu[1]; int64_t base_w; int lod; + int lod_min, lod_max; int dx1, dx2; int y, yend, ydir; int32_t dxAB, dxAC, dxBC; @@ -854,8 +856,8 @@ typedef struct voodoo_state_t int tex_s, tex_t; int clamp_s, clamp_t; - uint8_t *tex; - uint16_t *tex_w; + uint8_t *tex[LOD_MAX+1]; + uint16_t *tex_w[LOD_MAX+1]; int tformat; rgba_u *palette; @@ -867,6 +869,74 @@ typedef struct voodoo_state_t static int voodoo_output = 0; +static uint8_t logtable[256] = +{ + 0x00,0x01,0x02,0x04,0x05,0x07,0x08,0x09,0x0b,0x0c,0x0e,0x0f,0x10,0x12,0x13,0x15, + 0x16,0x17,0x19,0x1a,0x1b,0x1d,0x1e,0x1f,0x21,0x22,0x23,0x25,0x26,0x27,0x28,0x2a, + 0x2b,0x2c,0x2e,0x2f,0x30,0x31,0x33,0x34,0x35,0x36,0x38,0x39,0x3a,0x3b,0x3d,0x3e, + 0x3f,0x40,0x41,0x43,0x44,0x45,0x46,0x47,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x50,0x51, + 0x52,0x53,0x54,0x55,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x60,0x61,0x62,0x63, + 0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74, + 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x83,0x84,0x85, + 0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94, + 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0,0xa1,0xa2,0xa2,0xa3, + 0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xad,0xae,0xaf,0xb0,0xb1,0xb2, + 0xb3,0xb4,0xb5,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbc,0xbd,0xbe,0xbf,0xc0, + 0xc1,0xc2,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xcd, + 0xce,0xcf,0xd0,0xd1,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd6,0xd7,0xd8,0xd9,0xda,0xda, + 0xdb,0xdc,0xdd,0xde,0xde,0xdf,0xe0,0xe1,0xe1,0xe2,0xe3,0xe4,0xe5,0xe5,0xe6,0xe7, + 0xe8,0xe8,0xe9,0xea,0xeb,0xeb,0xec,0xed,0xee,0xef,0xef,0xf0,0xf1,0xf2,0xf2,0xf3, + 0xf4,0xf5,0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xfa,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff +}; + +static inline int fastlog(uint64_t val) +{ + uint64_t oldval = val; + int exp = 63; + int frac; + + if (!val || val & (1ULL << 63)) + return 0x80000000; + + if (!(val & 0xffffffff00000000)) + { + exp -= 32; + val <<= 32; + } + if (!(val & 0xffff000000000000)) + { + exp -= 16; + val <<= 16; + } + if (!(val & 0xff00000000000000)) + { + exp -= 8; + val <<= 8; + } + if (!(val & 0xf000000000000000)) + { + exp -= 4; + val <<= 4; + } + if (!(val & 0xc000000000000000)) + { + exp -= 2; + val <<= 2; + } + if (!(val & 0x8000000000000000)) + { + exp -= 1; + val <<= 1; + } + + if (exp >= 8) + frac = (oldval >> (exp - 8)) & 0xff; + else + frac = (oldval << (8 - exp)) & 0xff; + + return (exp << 8) | logtable[frac]; +} + static inline int fls(uint16_t val) { int num = 0; @@ -933,9 +1003,9 @@ static inline void tex_read(voodoo_state_t *state, voodoo_texture_state_t *textu } if (state->tformat & 8) - dat = state->tex_w[texture_state->s + (texture_state->t << texture_state->tex_shift)]; + dat = state->tex_w[state->lod][texture_state->s + (texture_state->t << texture_state->tex_shift)]; else - dat = state->tex[texture_state->s + (texture_state->t << texture_state->tex_shift)]; + dat = state->tex[state->lod][texture_state->s + (texture_state->t << texture_state->tex_shift)]; switch (state->tformat) { @@ -1052,26 +1122,26 @@ static inline void tex_read_4(voodoo_state_t *state, voodoo_texture_state_t *tex _t &= texture_state->h_mask; } if (state->tformat & 8) - dat[c] = state->tex_w[_s + (_t << texture_state->tex_shift)]; + dat[c] = state->tex_w[state->lod][_s + (_t << texture_state->tex_shift)]; else - dat[c] = state->tex[_s + (_t << texture_state->tex_shift)]; + dat[c] = state->tex[state->lod][_s + (_t << texture_state->tex_shift)]; } } else { if (state->tformat & 8) { - dat[0] = state->tex_w[s + (t << texture_state->tex_shift)]; - dat[1] = state->tex_w[s + 1 + (t << texture_state->tex_shift)]; - dat[2] = state->tex_w[s + ((t + 1) << texture_state->tex_shift)]; - dat[3] = state->tex_w[s + 1 + ((t + 1) << texture_state->tex_shift)]; + dat[0] = state->tex_w[state->lod][s + (t << texture_state->tex_shift)]; + dat[1] = state->tex_w[state->lod][s + 1 + (t << texture_state->tex_shift)]; + dat[2] = state->tex_w[state->lod][s + ((t + 1) << texture_state->tex_shift)]; + dat[3] = state->tex_w[state->lod][s + 1 + ((t + 1) << texture_state->tex_shift)]; } else { - dat[0] = state->tex[s + (t << texture_state->tex_shift)]; - dat[1] = state->tex[s + 1 + (t << texture_state->tex_shift)]; - dat[2] = state->tex[s + ((t + 1) << texture_state->tex_shift)]; - dat[3] = state->tex[s + 1 + ((t + 1) << texture_state->tex_shift)]; + dat[0] = state->tex[state->lod][s + (t << texture_state->tex_shift)]; + dat[1] = state->tex[state->lod][s + 1 + (t << texture_state->tex_shift)]; + dat[2] = state->tex[state->lod][s + ((t + 1) << texture_state->tex_shift)]; + dat[3] = state->tex[state->lod][s + 1 + ((t + 1) << texture_state->tex_shift)]; } } @@ -1277,14 +1347,18 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood int a_ref = params->alphaMode >> 24; int depth_op = (params->fbzMode >> 5) & 7; int dither = params->fbzMode & FBZ_DITHER;*/ + int c; state->clamp_s = params->textureMode & TEXTUREMODE_TCLAMPS; state->clamp_t = params->textureMode & TEXTUREMODE_TCLAMPT; // int last_x; // pclog("voodoo_triangle : bottom-half %X %X %X %X %X %i %i %i %i\n", xstart, xend, dx1, dx2, dx2 * 36, xdir, y, yend, ydir); - state->tex_w = &voodoo->tex_mem_w[(params->tex_base[state->lod] >> 1) & 0xfffff]; - state->tex = &voodoo->tex_mem[params->tex_base[state->lod] & 0x1fffff]; + for (c = 0; c <= LOD_MAX; c++) + { + state->tex_w[c] = &voodoo->tex_mem_w[(params->tex_base[c] >> 1) & 0xfffff]; + state->tex[c] = &voodoo->tex_mem[params->tex_base[c] & 0x1fffff]; + } state->tformat = params->tformat; @@ -1524,12 +1598,21 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood state->tex_s = (int32_t)((tmu0_s * _w) >> 30); state->tex_t = (int32_t)((tmu0_t * _w) >> 30); +// state->lod = state->tmu[0].lod + (int)(log2((double)_w / (double)(1 << 19)) * 256.0); + state->lod = state->tmu[0].lod + (fastlog(_w) - (19 << 8)); } else { state->tex_s = (int32_t)(tmu0_s >> 14); state->tex_t = (int32_t)(tmu0_t >> 14); + state->lod = state->tmu[0].lod; } + + if (state->lod < state->lod_min) + state->lod = state->lod_min; + else if (state->lod > state->lod_max) + state->lod = state->lod_max; + state->lod >>= 8; voodoo_get_texture(voodoo, params, state); @@ -2054,6 +2137,11 @@ static void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params) int vertexCy_adjusted; int dx, dy; + uint64_t tempdx, tempdy; + uint64_t tempLOD; + int LOD; + int lodbias; + voodoo->tri_count++; dx = 8 - ((params->vertexAx + 7) & 0xf); @@ -2115,7 +2203,10 @@ static void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params) else state.dxBC = 0; - state.lod = (params->tLOD >> 2) & 15; + state.lod_min = (params->tLOD & 0x3f) << 6; + state.lod_max = ((params->tLOD >> 6) & 0x3f) << 6; + if (state.lod_max > 0x800) + state.lod_max = 0x800; state.xstart = state.xend = params->vertexAx << 8; state.xdir = params->sign ? -1 : 1; @@ -2132,6 +2223,22 @@ static void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params) state.tmu[0].base_w = params->tmu[0].startW; state.base_w = params->startW; + tempdx = params->tmu[0].dSdX * params->tmu[0].dSdX + params->tmu[0].dTdX * params->tmu[0].dTdX; + tempdy = params->tmu[0].dSdY * params->tmu[0].dSdY + params->tmu[0].dTdY * params->tmu[0].dTdY; + + if (tempdx > tempdy) + tempLOD = tempdx; + else + tempLOD = tempdy; + + LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256); + LOD >>= 2; + + lodbias = (params->tLOD >> 12) & 0x3f; + if (lodbias & 0x20) + lodbias |= ~0x3f; + state.tmu[0].lod = LOD + (lodbias << 6); + switch (params->tformat) { case TEX_PAL8: case TEX_APAL88: