Implemented Voodoo mipmapping. Probably buggy.
This commit is contained in:
parent
1802996443
commit
2624745c67
1 changed files with 124 additions and 17 deletions
141
src/vid_voodoo.c
141
src/vid_voodoo.c
|
|
@ -844,9 +844,11 @@ typedef struct voodoo_state_t
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int64_t base_s, base_t, base_w;
|
int64_t base_s, base_t, base_w;
|
||||||
|
int lod;
|
||||||
} tmu[1];
|
} tmu[1];
|
||||||
int64_t base_w;
|
int64_t base_w;
|
||||||
int lod;
|
int lod;
|
||||||
|
int lod_min, lod_max;
|
||||||
int dx1, dx2;
|
int dx1, dx2;
|
||||||
int y, yend, ydir;
|
int y, yend, ydir;
|
||||||
int32_t dxAB, dxAC, dxBC;
|
int32_t dxAB, dxAC, dxBC;
|
||||||
|
|
@ -854,8 +856,8 @@ typedef struct voodoo_state_t
|
||||||
int tex_s, tex_t;
|
int tex_s, tex_t;
|
||||||
int clamp_s, clamp_t;
|
int clamp_s, clamp_t;
|
||||||
|
|
||||||
uint8_t *tex;
|
uint8_t *tex[LOD_MAX+1];
|
||||||
uint16_t *tex_w;
|
uint16_t *tex_w[LOD_MAX+1];
|
||||||
int tformat;
|
int tformat;
|
||||||
|
|
||||||
rgba_u *palette;
|
rgba_u *palette;
|
||||||
|
|
@ -867,6 +869,74 @@ typedef struct voodoo_state_t
|
||||||
|
|
||||||
static int voodoo_output = 0;
|
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)
|
static inline int fls(uint16_t val)
|
||||||
{
|
{
|
||||||
int num = 0;
|
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)
|
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
|
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)
|
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;
|
_t &= texture_state->h_mask;
|
||||||
}
|
}
|
||||||
if (state->tformat & 8)
|
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
|
else
|
||||||
dat[c] = state->tex[_s + (_t << texture_state->tex_shift)];
|
dat[c] = state->tex[state->lod][_s + (_t << texture_state->tex_shift)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (state->tformat & 8)
|
if (state->tformat & 8)
|
||||||
{
|
{
|
||||||
dat[0] = state->tex_w[s + (t << texture_state->tex_shift)];
|
dat[0] = state->tex_w[state->lod][s + (t << texture_state->tex_shift)];
|
||||||
dat[1] = state->tex_w[s + 1 + (t << texture_state->tex_shift)];
|
dat[1] = state->tex_w[state->lod][s + 1 + (t << texture_state->tex_shift)];
|
||||||
dat[2] = state->tex_w[s + ((t + 1) << texture_state->tex_shift)];
|
dat[2] = state->tex_w[state->lod][s + ((t + 1) << texture_state->tex_shift)];
|
||||||
dat[3] = state->tex_w[s + 1 + ((t + 1) << texture_state->tex_shift)];
|
dat[3] = state->tex_w[state->lod][s + 1 + ((t + 1) << texture_state->tex_shift)];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dat[0] = state->tex[s + (t << texture_state->tex_shift)];
|
dat[0] = state->tex[state->lod][s + (t << texture_state->tex_shift)];
|
||||||
dat[1] = state->tex[s + 1 + (t << texture_state->tex_shift)];
|
dat[1] = state->tex[state->lod][s + 1 + (t << texture_state->tex_shift)];
|
||||||
dat[2] = state->tex[s + ((t + 1) << texture_state->tex_shift)];
|
dat[2] = state->tex[state->lod][s + ((t + 1) << texture_state->tex_shift)];
|
||||||
dat[3] = state->tex[s + 1 + ((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 a_ref = params->alphaMode >> 24;
|
||||||
int depth_op = (params->fbzMode >> 5) & 7;
|
int depth_op = (params->fbzMode >> 5) & 7;
|
||||||
int dither = params->fbzMode & FBZ_DITHER;*/
|
int dither = params->fbzMode & FBZ_DITHER;*/
|
||||||
|
int c;
|
||||||
|
|
||||||
state->clamp_s = params->textureMode & TEXTUREMODE_TCLAMPS;
|
state->clamp_s = params->textureMode & TEXTUREMODE_TCLAMPS;
|
||||||
state->clamp_t = params->textureMode & TEXTUREMODE_TCLAMPT;
|
state->clamp_t = params->textureMode & TEXTUREMODE_TCLAMPT;
|
||||||
// int last_x;
|
// 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);
|
// 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];
|
for (c = 0; c <= LOD_MAX; c++)
|
||||||
state->tex = &voodoo->tex_mem[params->tex_base[state->lod] & 0x1fffff];
|
{
|
||||||
|
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;
|
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_s = (int32_t)((tmu0_s * _w) >> 30);
|
||||||
state->tex_t = (int32_t)((tmu0_t * _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
|
else
|
||||||
{
|
{
|
||||||
state->tex_s = (int32_t)(tmu0_s >> 14);
|
state->tex_s = (int32_t)(tmu0_s >> 14);
|
||||||
state->tex_t = (int32_t)(tmu0_t >> 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);
|
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 vertexCy_adjusted;
|
||||||
int dx, dy;
|
int dx, dy;
|
||||||
|
|
||||||
|
uint64_t tempdx, tempdy;
|
||||||
|
uint64_t tempLOD;
|
||||||
|
int LOD;
|
||||||
|
int lodbias;
|
||||||
|
|
||||||
voodoo->tri_count++;
|
voodoo->tri_count++;
|
||||||
|
|
||||||
dx = 8 - ((params->vertexAx + 7) & 0xf);
|
dx = 8 - ((params->vertexAx + 7) & 0xf);
|
||||||
|
|
@ -2115,7 +2203,10 @@ static void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params)
|
||||||
else
|
else
|
||||||
state.dxBC = 0;
|
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.xstart = state.xend = params->vertexAx << 8;
|
||||||
state.xdir = params->sign ? -1 : 1;
|
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.tmu[0].base_w = params->tmu[0].startW;
|
||||||
state.base_w = params->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)
|
switch (params->tformat)
|
||||||
{
|
{
|
||||||
case TEX_PAL8: case TEX_APAL88:
|
case TEX_PAL8: case TEX_APAL88:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue