rasterizer: more correct texturing and alpha blending

This commit is contained in:
zeromus 2009-02-04 02:34:07 +00:00
parent ac68f0317f
commit 33be370fe6
7 changed files with 267 additions and 114 deletions

View File

@ -27,8 +27,6 @@
#include "OGLRender.h"
#include "debug.h"
//#define DEBUG_DUMP_TEXTURE
bool (*oglrender_init)() = 0;
bool (*oglrender_beginOpenGL)() = 0;
void (*oglrender_endOpenGL)() = 0;
@ -331,11 +329,9 @@ static void createShaders()
static void OGLReset()
{
int i;
//reset the texture cache
TexCache_Reset();
for (i = 0; i < MAX_TEXTURE; i++)
for (int i = 0; i < MAX_TEXTURE; i++)
texcache[i].id=oglTempTextureID[i];
// memset(GPU_screenStencil,0,sizeof(GPU_screenStencil));
@ -343,6 +339,9 @@ static void OGLReset()
needRefreshFramebuffer = false;
}
static void BindTexture(u32 tx)
{
glBindTexture(GL_TEXTURE_2D,(GLuint)texcache[tx].id);
@ -509,13 +508,11 @@ static void setTexture(unsigned int format, unsigned int texpal)
if (format==0)
{
// texcache_count=-1;
if(hasShaders && hasTexture) { glUniform1i(hasTexLoc, 0); hasTexture = false; }
return;
}
if (textureMode==0)
{
// texcache_count=-1;
if(hasShaders && hasTexture) { glUniform1i(hasTexLoc, 0); hasTexture = false; }
return;
}
@ -652,7 +649,7 @@ static void Control()
else glDisable (GL_TEXTURE_2D);
if(gfx3d.enableAlphaTest)
glAlphaFunc (GL_GREATER, gfx3d.alphaTestRef);
glAlphaFunc (GL_GREATER, gfx3d.alphaTestRef/31.f);
else
glAlphaFunc (GL_GREATER, 0);
@ -684,7 +681,13 @@ static void OGLRender()
glViewport(gfx3d.viewport.x,gfx3d.viewport.y,gfx3d.viewport.width,gfx3d.viewport.height);
//we're not using the alpha clear color right now
glClearColor(gfx3d.clearColor[0],gfx3d.clearColor[1],gfx3d.clearColor[2], gfx3d.clearColor[3]);
float clearColor[4] = {
((float)(gfx3d.clearColor&0x1F))/31.0f,
((float)((gfx3d.clearColor>>5)&0x1F))/31.0f,
((float)((gfx3d.clearColor>>10)&0x1F))/31.0f,
((float)((gfx3d.clearColor>>16)&0x1F))/31.0f,
};
glClearColor(clearColor[0],clearColor[1],clearColor[2],clearColor[3]);
glClearDepth(gfx3d.clearDepth);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

View File

@ -289,7 +289,7 @@ void gfx3d_reset()
GFX_FIFOclear();
}
void gfx3d_glViewPort(unsigned long v)
void gfx3d_glViewPort(u32 v)
{
//zero: NHerve messed with this in mod2 and mod3, but im still not sure its perfect. need to research this.
gfx3d.viewport.x = (v&0xFF);
@ -299,15 +299,13 @@ void gfx3d_glViewPort(unsigned long v)
}
void gfx3d_glClearColor(unsigned long v)
void gfx3d_glClearColor(u32 v)
{
gfx3d.clearColor[0] = ((float)(v&0x1F))/31.0f;
gfx3d.clearColor[1] = ((float)((v>>5)&0x1F))/31.0f;
gfx3d.clearColor[2] = ((float)((v>>10)&0x1F))/31.0f;
gfx3d.clearColor[3] = ((float)((v>>16)&0x1F))/31.0f;
gfx3d.clearColor = v;
}
void gfx3d_glFogColor(unsigned long v)
void gfx3d_glFogColor(u32 v)
{
gfx3d.fogColor[0] = ((float)((v )&0x1F))/31.0f;
gfx3d.fogColor[1] = ((float)((v>> 5)&0x1F))/31.0f;
@ -315,12 +313,12 @@ void gfx3d_glFogColor(unsigned long v)
gfx3d.fogColor[3] = ((float)((v>>16)&0x1F))/31.0f;
}
void gfx3d_glFogOffset (unsigned long v)
void gfx3d_glFogOffset (u32 v)
{
gfx3d.fogOffset = (float)(v&0xffff);
}
void gfx3d_glClearDepth(unsigned long v)
void gfx3d_glClearDepth(u32 v)
{
//Thanks to NHerve
v &= 0x7FFFF;
@ -328,7 +326,7 @@ void gfx3d_glClearDepth(unsigned long v)
gfx3d.clearDepth = depth24b / ((float)(1<<24));
}
void gfx3d_glMatrixMode(unsigned long v)
void gfx3d_glMatrixMode(u32 v)
{
mode = (v&3);
}
@ -374,7 +372,7 @@ BOOL gfx3d_glLoadMatrix4x3(signed long v)
return TRUE;
}
void gfx3d_glStoreMatrix(unsigned long v)
void gfx3d_glStoreMatrix(u32 v)
{
//this command always works on both pos and vector when either pos or pos-vector are the current mtx mode
short mymode = (mode==1?2:mode);
@ -388,7 +386,7 @@ void gfx3d_glStoreMatrix(unsigned long v)
MatrixStackLoadMatrix (&mtxStack[1], v&31, mtxCurrent[1]);
}
void gfx3d_glRestoreMatrix(unsigned long v)
void gfx3d_glRestoreMatrix(u32 v)
{
//this command always works on both pos and vector when either pos or pos-vector are the current mtx mode
short mymode = (mode==1?2:mode);
@ -550,7 +548,7 @@ BOOL gfx3d_glMultMatrix4x4(signed long v)
return TRUE;
}
void gfx3d_glBegin(unsigned long v)
void gfx3d_glBegin(u32 v)
{
vtxFormat = v&0x03;
triStripToggle = 0;
@ -563,7 +561,7 @@ void gfx3d_glEnd(void)
tempVertInfo.count = 0;
}
void gfx3d_glColor3b(unsigned long v)
void gfx3d_glColor3b(u32 v)
{
colorRGB[0] = (v&0x1F);
colorRGB[1] = ((v>>5)&0x1F);
@ -729,7 +727,7 @@ BOOL gfx3d_glVertex16b(unsigned int v)
return TRUE;
}
void gfx3d_glVertex10b(unsigned long v)
void gfx3d_glVertex10b(u32 v)
{
coord[0] = float10Table[v&1023];
coord[1] = float10Table[(v>>10)&1023];
@ -746,7 +744,7 @@ void gfx3d_glVertex3_cord(unsigned int one, unsigned int two, unsigned int v)
SetVertex ();
}
void gfx3d_glVertex_rel(unsigned long v)
void gfx3d_glVertex_rel(u32 v)
{
coord[0] += float10RelTable[v&1023];
coord[1] += float10RelTable[(v>>10)&1023];
@ -797,7 +795,7 @@ static void gfx3d_glPolygonAttrib_cache()
//polyID = (polyAttr>>24)&0x1F;
}
void gfx3d_glPolygonAttrib (unsigned long val)
void gfx3d_glPolygonAttrib (u32 val)
{
polyAttr = val;
gfx3d_glPolygonAttrib_cache();
@ -812,7 +810,7 @@ void gfx3d_glPolygonAttrib (unsigned long val)
21-25 Ambient Reflection Green
26-30 Ambient Reflection Blue
*/
void gfx3d_glMaterial0(unsigned long val)
void gfx3d_glMaterial0(u32 val)
{
dsDiffuse = val&0xFFFF;
dsAmbient = val>>16;
@ -825,13 +823,13 @@ void gfx3d_glMaterial0(unsigned long val)
}
}
void gfx3d_glMaterial1(unsigned long val)
void gfx3d_glMaterial1(u32 val)
{
dsSpecular = val&0xFFFF;
dsEmission = val>>16;
}
BOOL gfx3d_glShininess (unsigned long val)
BOOL gfx3d_glShininess (u32 val)
{
shininessTable[shininessInd++] = ((val & 0xFF) / 256.0f);
shininessTable[shininessInd++] = (((val >> 8) & 0xFF) / 256.0f);
@ -858,18 +856,18 @@ static void gfx3d_glTexImage_cache()
{
texCoordinateTransform = (textureFormat>>30);
}
void gfx3d_glTexImage(unsigned long val)
void gfx3d_glTexImage(u32 val)
{
textureFormat = val;
gfx3d_glTexImage_cache();
}
void gfx3d_glTexPalette(unsigned long val)
void gfx3d_glTexPalette(u32 val)
{
texturePalette = val;
}
void gfx3d_glTexCoord(unsigned long val)
void gfx3d_glTexCoord(u32 val)
{
_t = (s16)(val>>16);
_s = (s16)(val&0xFFFF);
@ -893,7 +891,7 @@ void gfx3d_glTexCoord(unsigned long val)
#define vec3dot(a, b) (((a[0]) * (b[0])) + ((a[1]) * (b[1])) + ((a[2]) * (b[2])))
void gfx3d_glNormal(unsigned long v)
void gfx3d_glNormal(u32 v)
{
int i,c;
ALIGN(16) float normal[3] = { normalTable[v&1023],
@ -1016,7 +1014,7 @@ static void gfx3d_glLightDirection_cache(int index)
20-29 Directional Vector's Z component (1bit sign + 9bit fractional part)
30-31 Light Number (0..3)
*/
void gfx3d_glLightDirection (unsigned long v)
void gfx3d_glLightDirection (u32 v)
{
int index = v>>30;
@ -1024,18 +1022,18 @@ void gfx3d_glLightDirection (unsigned long v)
gfx3d_glLightDirection_cache(index);
}
void gfx3d_glLightColor (unsigned long v)
void gfx3d_glLightColor (u32 v)
{
int index = v>>30;
lightColor[index] = v;
}
void gfx3d_glAlphaFunc(unsigned long v)
void gfx3d_glAlphaFunc(u32 v)
{
gfx3d.alphaTestRef = (v&31)/31.f;
gfx3d.alphaTestRef = v&31;
}
BOOL gfx3d_glBoxTest(unsigned long v)
BOOL gfx3d_glBoxTest(u32 v)
{
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
gxstat |= 0x00000001; // busy
@ -1051,7 +1049,7 @@ BOOL gfx3d_glBoxTest(unsigned long v)
return TRUE;
}
BOOL gfx3d_glPosTest(unsigned long v)
BOOL gfx3d_glPosTest(u32 v)
{
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
gxstat |= 0x00000001; // busy
@ -1079,7 +1077,7 @@ BOOL gfx3d_glPosTest(unsigned long v)
return TRUE;
}
void gfx3d_glVecTest(unsigned long v)
void gfx3d_glVecTest(u32 v)
{
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
gxstat &= 0xFFFFFFFE;
@ -1238,7 +1236,7 @@ static void gfx3d_FlushFIFO()
GFX_FIFOclear();
}
void gfx3d_glFlush(unsigned long v)
void gfx3d_glFlush(u32 v)
{
gfx3d_FlushFIFO();
@ -2014,7 +2012,7 @@ static void gfx3d_Control_cache()
}
}
void gfx3d_Control(unsigned long v)
void gfx3d_Control(u32 v)
{
control = v;
gfx3d_Control_cache();
@ -2114,12 +2112,12 @@ SFORMAT SF_GFX3D[]={
{ "GSSH", 4, 1, &gfx3d.shading},
{ "GSWB", 4, 1, &gfx3d.wbuffer},
{ "GSSM", 4, 1, &gfx3d.sortmode},
{ "GSAR", 4, 1, &gfx3d.alphaTestRef},
{ "GSAR", 1, 1, &gfx3d.alphaTestRef},
{ "GSVX", 4, 1, &gfx3d.viewport.x},
{ "GSVY", 4, 1, &gfx3d.viewport.y},
{ "GSVW", 4, 1, &gfx3d.viewport.width},
{ "GSVH", 4, 1, &gfx3d.viewport.height},
{ "GSCC", 4, 4, gfx3d.clearColor},
{ "GSCC", 4, 1, &gfx3d.clearColor},
{ "GSCD", 4, 1, &gfx3d.clearDepth},
{ "GSFC", 4, 4, gfx3d.fogColor},
{ "GSFO", 4, 1, &gfx3d.fogOffset},

View File

@ -117,8 +117,8 @@ struct GFX3D
, vertlist(0)
, alphaTestRef(0)
, clearDepth(1)
, clearColor(0)
{
clearColor[0] = clearColor[1] = clearColor[2] = clearColor[3] = 0;
fogColor[0] = fogColor[1] = fogColor[2] = fogColor[3] = 0;
fogOffset = 0;
}
@ -135,7 +135,7 @@ struct GFX3D
BOOL wbuffer, sortmode;
float alphaTestRef;
u8 alphaTestRef;
struct VIEWPORT {
VIEWPORT()
@ -144,7 +144,7 @@ struct GFX3D
int x, y, width, height;
} viewport;
float clearColor[4];
u32 clearColor;
float clearDepth;
float fogColor[4];
float fogOffset;

View File

@ -47,6 +47,92 @@ template<typename T> T max(T a, T b, T c) { return max(max(a,b),c); }
static u8 modulate_table[32][32];
//----texture cache---
//TODO - the texcache could ask for a buffer to generate into
//that would avoid us ever having to buffercopy..
struct TextureBuffers
{
static const int numTextures = MAX_TEXTURE+1;
u8* buffers[numTextures];
void clear() { memset(buffers,0,sizeof(buffers)); }
TextureBuffers()
{
clear();
}
void free()
{
for(int i=0;i<numTextures;i++)
delete[] buffers[i];
clear();
}
~TextureBuffers() {
free();
}
void setCurrent(int num)
{
currentData = buffers[num];
}
void create(int num, u8* data)
{
delete[] buffers[num];
int size = texcache[num].sizeX * texcache[num].sizeY * 4;
buffers[num] = new u8[size];
setCurrent(num);
memcpy(currentData,data,size);
}
u8* currentData;
} textures;
//called from the texture cache to change the active texture
static void BindTexture(u32 tx)
{
textures.setCurrent(tx);
}
//caled from the texture cache to change to a new texture
static void BindTextureData(u32 tx, u8* data)
{
textures.create(tx,data);
}
//---------------
struct PolyAttr
{
u32 val;
bool decalMode;
bool translucent;
bool translucentDepthWrite;
bool isVisible(bool backfacing)
{
switch((val>>6)&3) {
case 0: return false;
case 1: return backfacing;
case 2: return !backfacing;
case 3: return true;
default: assert(false); return false;
}
}
void setup(u32 polyAttr, bool translucent)
{
val = polyAttr;
decalMode = BIT14(val);
this->translucent = translucent;
translucentDepthWrite = BIT11(val);
}
} polyAttr;
struct Fragment
{
union Color {
@ -99,20 +185,20 @@ static struct
wrap = (format>>16)&0xF;
}
FORCEINLINE void clamp(int &val, int size, int sizemask){
FORCEINLINE void clamp(int &val, const int size, const int sizemask){
if(val<0) val = 0;
if(val>sizemask) val = sizemask;
}
FORCEINLINE void hclamp(int &val) { clamp(val,width,wmask); }
FORCEINLINE void vclamp(int &val) { clamp(val,height,hmask); }
FORCEINLINE void repeat(int &val, int size, int sizemask) {
FORCEINLINE void repeat(int &val, const int size, const int sizemask) {
val &= sizemask;
}
FORCEINLINE void hrepeat(int &val) { repeat(val,width,wmask); }
FORCEINLINE void vrepeat(int &val) { repeat(val,height,hmask); }
FORCEINLINE void flip(int &val, int size, int sizemask) {
FORCEINLINE void flip(int &val, const int size, const int sizemask) {
val &= ((size<<1)-1);
if(val>=size) val = (size<<1)-val-1;
}
@ -152,7 +238,7 @@ static struct
dowrap(iu,iv);
Fragment::Color color;
u32 col32 = ((u32*)TexCache_texMAP)[(iv<<wshift)+iu];
u32 col32 = ((u32*)textures.currentData)[(iv<<wshift)+iu];
//todo - teach texcache how to provide these already in 5555
col32 >>= 3;
col32 &= 0x1F1F1F1F;
@ -250,6 +336,42 @@ struct Interpolator
FORCEINLINE void incx(int count) { Z += dx*count; }
};
void alphaBlend(Fragment & dst, const Fragment & src)
{
if(gfx3d.enableAlphaBlending)
{
if(src.color.components.a == 0)
{
dst.color.components.a = max(src.color.components.a,dst.color.components.a);
}
else if(src.color.components.a == 31 || dst.color.components.a == 0)
{
dst.color = src.color;
dst.color.components.a = max(src.color.components.a,dst.color.components.a);
}
else
{
u8 alpha = src.color.components.a+1;
u8 invAlpha = 32 - alpha;
dst.color.components.r = (alpha*src.color.components.r + invAlpha*dst.color.components.r)>>5;
dst.color.components.g = (alpha*src.color.components.g + invAlpha*dst.color.components.g)>>5;
dst.color.components.b = (alpha*src.color.components.b + invAlpha*dst.color.components.b)>>5;
dst.color.components.a = max(src.color.components.a,dst.color.components.a);
}
}
else
{
if(src.color.components.a == 0)
{
//do nothing; the fragment is totally transparent
}
else
{
dst.color = src.color;
}
}
}
//http://www.devmaster.net/forums/showthread.php?t=1884&page=1
//todo - change to the tile-based renderer and try to apply some optimizations from that thread
static void triangle_from_devmaster()
@ -363,9 +485,16 @@ static void triangle_from_devmaster()
//this is just a temporary measure until we do proper clipping against the clip frustum.
//since we dont, we are receiving waaay out of bounds polys and so unless we do this we spend a lot of time calculating
//out of bounds pixels
i_color_r.incx(xaccum); i_color_g.incx(xaccum); i_color_b.incx(xaccum); i_color_a.incx(xaccum);
i_tex_invu.incx(xaccum); i_tex_invv.incx(xaccum);
i_w.incx(xaccum); i_invw.incx(xaccum);
//if(xaccum==1) {
// i_color_r.incx(); i_color_g.incx(); i_color_b.incx(); i_color_a.incx();
// i_tex_invu.incx(); i_tex_invv.incx();
// i_w.incx(); i_invw.incx();
//} else {
i_color_r.incx(xaccum); i_color_g.incx(xaccum); i_color_b.incx(xaccum); i_color_a.incx(xaccum);
i_tex_invu.incx(xaccum); i_tex_invv.incx(xaccum);
i_w.incx(xaccum); i_invw.incx(xaccum);
//}
xaccum = 0;
int adr = (y<<8)+x;
@ -373,8 +502,16 @@ static void triangle_from_devmaster()
//w-buffer depth test
int w = i_w.cur();
if(w>destFragment.depth)
goto rejected_fragment;
if(polyAttr.decalMode)
{
if(abs(w-destFragment.depth)>1)
goto rejected_fragment;
}
else
{
if(w>=destFragment.depth)
goto rejected_fragment;
}
shader.invw = i_invw.Z;
shader.invu = i_tex_invu.Z;
@ -396,24 +533,32 @@ static void triangle_from_devmaster()
Fragment shaderOutput;
shader.shade(shaderOutput);
//alpha blend
if(shaderOutput.color.components.a == 31)
//alpha test
if(gfx3d.enableAlphaTest)
{
destFragment.color = shaderOutput.color;
if(shaderOutput.color.components.a < gfx3d.alphaTestRef)
goto rejected_fragment;
}
//alpha blending
alphaBlend(destFragment, shaderOutput);
//depth writing
if(destFragment.color.components.a == 0)
{
//never update depth if the pixel is transparent
}
else
{
u8 alpha = shaderOutput.color.components.a+1;
u8 invAlpha = 32 - alpha;
destFragment.color.components.r = (alpha*shaderOutput.color.components.r + invAlpha*destFragment.color.components.r)>>5;
destFragment.color.components.g = (alpha*shaderOutput.color.components.g + invAlpha*destFragment.color.components.g)>>5;
destFragment.color.components.b = (alpha*shaderOutput.color.components.b + invAlpha*destFragment.color.components.b)>>5;
destFragment.color.components.a = max(shaderOutput.color.components.a,destFragment.color.components.a);
if(!polyAttr.translucent)
destFragment.depth = w;
else
if(polyAttr.translucent && polyAttr.translucentDepthWrite)
destFragment.depth = w;
}
destFragment.depth = w;
} else if(done) break;
rejected_fragment:
xaccum++;
@ -446,12 +591,18 @@ static char Init(void)
for(int j=0;j<32;j++)
modulate_table[i][j] = ((i+1)*(j+1)-1)>>5;
TexCache_Reset();
TexCache_BindTexture = BindTexture;
TexCache_BindTextureData = BindTextureData;
return 1;
}
static void Reset() {}
static void Close() {}
static void Close()
{
}
static void VramReconfigureSignal() {
TexCache_Invalidate();
@ -462,7 +613,7 @@ static void GetLine(int line, u16* dst, u8* dstAlpha)
Fragment* src = screen+((191-line)<<8);
for(int i=0;i<256;i++)
{
const bool testRenderAlpha = false;
u8 r = src->color.components.r;
u8 g = src->color.components.g;
u8 b = src->color.components.b;
@ -470,6 +621,13 @@ static void GetLine(int line, u16* dst, u8* dstAlpha)
if(src->color.components.a > 0)
*dst |= 0x8000;
*dstAlpha = alpha_5bit_to_4bit[src->color.components.a];
if(testRenderAlpha)
{
*dst = 0x8000 | R5G5B5TORGB15(src->color.components.a,src->color.components.a,src->color.components.a);
*dstAlpha = 16;
}
src++;
dst++;
dstAlpha++;
@ -487,9 +645,18 @@ static void Render()
//B. backface cull
//C. transforms
Fragment::Color clearColor;
clearColor.components.r = gfx3d.clearColor&0x1F;
clearColor.components.g = (gfx3d.clearColor>>5)&0x1F;
clearColor.components.b = (gfx3d.clearColor>>10)&0x1F;
clearColor.components.a = (gfx3d.clearColor>>16)&0x1F;
memset(screen,0,sizeof(screen));
for(int i=0;i<256*192;i++)
{
screen[i].depth = 0x007FFFFF;
screen[i].color = clearColor;
}
for(int i=0;i<gfx3d.vertlist->count;i++)
{
@ -518,6 +685,8 @@ static void Render()
type==4?&gfx3d.vertlist->list[poly->vertIndexes[3]]:0
};
polyAttr.setup(poly->polyAttr, poly->isTranslucent());
//HACK: backface culling
//this should be moved to gfx3d, but first we need to redo the way the lists are built
//because it is too convoluted right now.
@ -532,11 +701,14 @@ static void Render()
Vector3Cross(cross,ab,ac);
float view[3] = {0,0,1};
float dot = Vector3Dot(view,cross);
if(dot<0) {
bool backfacing = dot<0;
if(!polyAttr.isVisible(backfacing)) {
culled++;
continue;
}
if(i==0 || lastTextureFormat != poly->texParam || lastTexturePalette != poly->texPalette || lastPolyAttr != poly->polyAttr)
{
TexCache_SetTexture(poly->texParam,poly->texPalette);
@ -572,7 +744,6 @@ static void Render()
triangle_from_devmaster();
}
}
//printf("rendered %d of %d polys after backface culling\n",gfx3d.polylist->count-culled,gfx3d.polylist->count);

View File

@ -12,6 +12,8 @@
using std::min;
using std::max;
#define DEBUG_DUMP_TEXTURE
//This class represents a number of regions of memory which should be viewed as contiguous
class MemSpan
{
@ -129,35 +131,21 @@ static MemSpan MemSpan_TexPalette(u32 ofs, u32 len)
return ret;
}
//================================================= Textures
TextureCache texcache[MAX_TEXTURE+1];
//u32 texcache_count;
u32 texcache_start;
u32 texcache_stop;
u8 TexCache_texMAP[1024*2048*4];
//raw ds format poly attributes
//todo - make all color conversions go through a properly spread table!!
#if defined (DEBUG_DUMP_TEXTURE) && defined (WIN32)
#define DO_DEBUG_DUMP_TEXTURE
static void DebugDumpTexture(int which)
{
char fname[100];
sprintf(fname,"c:\\dump\\%d.bmp", which);
glBindTexture(GL_TEXTURE_2D,texcache[which].id);
glGetTexImage( GL_TEXTURE_2D ,
0,
GL_BGRA_EXT,
GL_UNSIGNED_BYTE,
TexCache_texMAP);
NDS_WriteBMP_32bppBuffer(texcache[which].sizeX,texcache[which].sizeY,TexCache_texMAP,fname);
}
#else
#define DebugDumpTexture(which) do { (void)which; } while (0)
#endif
@ -247,27 +235,26 @@ void TexCache_SetTexture(unsigned int format, unsigned int texpal)
if (!texcache[tx].suspectedInvalid) goto ACCEPT;
//if we couldnt cache this entire texture due to it being too large, then reject it
if (texSize+indexSize > (int)sizeof(texcache[tx].texture)) goto REJECT;
if (texSize+indexSize > (int)sizeof(texcache[tx].dump.texture)) goto REJECT;
//when the palettes dont match:
//note that we are considering 4x4 textures to have a palette size of 0.
//they really have a potentially HUGE palette, too big for us to handle like a normal palette,
//so they go through a different system
if (mspal.size != 0 && memcmp(texcache[tx].palette,pal,mspal.size)) goto REJECT;
if (mspal.size != 0 && memcmp(texcache[tx].dump.palette,pal,mspal.size)) goto REJECT;
//when the texture data doesn't match
if(ms.memcmp(texcache[tx].texture,sizeof(texcache[tx].texture))) goto REJECT;
if(ms.memcmp(texcache[tx].dump.texture,sizeof(texcache[tx].dump.texture))) goto REJECT;
//if the texture is 4x4 then the index data must match
if(textureMode == TEXMODE_4X4)
{
if(msIndex.memcmp(texcache[tx].texture + texcache[tx].textureSize,texcache[tx].indexSize)) goto REJECT;
if(msIndex.memcmp(texcache[tx].dump.texture + texcache[tx].dump.textureSize,texcache[tx].dump.indexSize)) goto REJECT;
}
ACCEPT:
texcache[tx].suspectedInvalid = false;
// texcache_count = tx;
if(lastTexture == -1 || (int)tx != lastTexture)
{
lastTexture = tx;
@ -303,27 +290,22 @@ REJECT:
texcache[tx].sizeY=sizeY;
texcache[tx].invSizeX=1.0f/((float)(sizeX));
texcache[tx].invSizeY=1.0f/((float)(sizeY));
texcache[tx].textureSize = ms.dump(texcache[tx].texture,sizeof(texcache[tx].texture));
texcache[tx].dump.textureSize = ms.dump(texcache[tx].dump.texture,sizeof(texcache[tx].dump.texture));
//dump palette data for cache keying
if ( palSize )
{
memcpy(texcache[tx].palette, pal, palSize*2);
memcpy(texcache[tx].dump.palette, pal, palSize*2);
}
//dump 4x4 index data for cache keying
texcache[tx].indexSize = 0;
texcache[tx].dump.indexSize = 0;
if(textureMode == TEXMODE_4X4)
{
texcache[tx].indexSize = min(msIndex.size,(int)sizeof(texcache[tx].texture) - texcache[tx].textureSize);
msIndex.dump(texcache[tx].texture+texcache[tx].textureSize,texcache[tx].indexSize);
texcache[tx].dump.indexSize = min(msIndex.size,(int)sizeof(texcache[tx].dump.texture) - texcache[tx].dump.textureSize);
msIndex.dump(texcache[tx].dump.texture+texcache[tx].dump.textureSize,texcache[tx].dump.indexSize);
}
//glMatrixMode (GL_TEXTURE);
//glLoadIdentity ();
//glScaled (texcache[tx].invSizeX, texcache[tx].invSizeY, 1.0f);
//INFO("Texture %03i - format=%08X; pal=%04X (mode %X, width %04i, height %04i)\n",i, texcache[i].frm, texcache[i].pal, texcache[i].mode, sizeX, sizeY);
//============================================================================ Texture conversion
@ -392,7 +374,6 @@ REJECT:
bits = ((*adr)>>4);
c = pal[bits];
*dwdst++ = RGB15TO32(c,(bits == 0) ? palZeroTransparent : 255);
adr++;
}
}
@ -563,25 +544,18 @@ REJECT:
if(TexCache_BindTextureData != 0)
TexCache_BindTextureData(tx,TexCache_texMAP);
#ifdef DO_DEBUG_DUMP_TEXTURE
DebugDumpTexture(tx);
//============================================================================================
// texcache_count=tx;
#endif
}
void TexCache_Reset()
{
memset(&texcache,0,sizeof(texcache));
memset(texcache,0,sizeof(texcache));
//texcache_count=0;
texcache_start=0;
texcache_stop=MAX_TEXTURE<<1;
for(int i=0;i<MAX_TEXTURE+1;i++)
texcache[i].suspectedInvalid = true;
}
TextureCache* TexCache_Curr()

View File

@ -18,9 +18,12 @@ struct ALIGN(8) TextureCache
u32 sizeY;
float invSizeX;
float invSizeY;
struct {
int textureSize, indexSize;
u8 texture[128*1024]; // 128Kb texture slot
u8 palette[256*2];
} dump;
//set if this texture is suspected be invalid due to a vram reconfigure
bool suspectedInvalid;

View File

@ -1082,6 +1082,10 @@
RelativePath="..\render3D.cpp"
>
</File>
<File
RelativePath="..\render3D.h"
>
</File>
<File
RelativePath="..\ROMReader.cpp"
>