GFX3D: Render states and geometry lists are now copied/swapped more consistently on flush. (Related to commit 8438a5a6.)

- Viewports are now processed on VIEWPORT register write instead of being processed at render time.
- CLEAR_DEPTH, CLRIMAGE_OFFSET, EDGE_COLOR, FOG_TABLE, and TOON_TABLE register writes are now handled more consistently.
- The fogDensityTable check for force-drawing clear images in gfx3d_VBlankEndSignal() has been removed. Changes done in commit 8438a5a6 will always causes this check to fail, and this commit will always cause this check to fail. Therefore, this check is now obsolete.
- Change a bunch of GFX3D-related structs from C++ style constructed structs into C-style POD structs.
This commit is contained in:
rogerman 2023-01-25 18:52:45 -08:00
parent be287de623
commit 5426509ede
12 changed files with 1018 additions and 670 deletions

View File

@ -2,7 +2,7 @@
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 Theo Berkau
Copyright (C) 2007 shash
Copyright (C) 2009-2022 DeSmuME team
Copyright (C) 2009-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -581,7 +581,7 @@ typedef union
u8 PolygonShading:1; // 1: Polygon shading mode, interacts with POLYGON_ATTR (0x40004A4); 0=Toon Shading, 1=Highlight Shading
u8 EnableAlphaTest:1; // 2: Perform alpha test, interacts with ALPHA_TEST_REF (0x4000340); 0=Disable, 1=Enable
u8 EnableAlphaBlending:1; // 3: Perform alpha blending, interacts with POLYGON_ATTR (0x40004A4); 0=Disable, 1=Enable
u8 EnableAntiAliasing:1; // 4: Render polygon edges with antialiasing; 0=Disable, 1=Enable
u8 EnableAntialiasing:1; // 4: Render polygon edges with antialiasing; 0=Disable, 1=Enable
u8 EnableEdgeMarking:1; // 5: Perform polygon edge marking, interacts with EDGE_COLOR (0x4000330); 0=Disable, 1=Enable
u8 FogOnlyAlpha:1; // 6: Apply fog to the alpha channel only, interacts with FOG_COLOR (0x4000358) / FOG_TABLE (0x4000360); 0=Color+Alpha, 1=Alpha
u8 EnableFog:1; // 7: Perform fog rendering, interacts with FOG_COLOR (0x4000358) / FOG_OFFSET (0x400035C) / FOG_TABLE (0x4000360);
@ -600,7 +600,7 @@ typedef union
// 0=Disable, 1=Enable
u8 FogOnlyAlpha:1; // 6: Apply fog to the alpha channel only, interacts with FOG_COLOR (0x4000358) / FOG_TABLE (0x4000360); 0=Color+Alpha, 1=Alpha
u8 EnableEdgeMarking:1; // 5: Perform polygon edge marking, interacts with EDGE_COLOR (0x4000330); 0=Disable, 1=Enable
u8 EnableAntiAliasing:1; // 4: Render polygon edges with antialiasing; 0=Disable, 1=Enable
u8 EnableAntialiasing:1; // 4: Render polygon edges with antialiasing; 0=Disable, 1=Enable
u8 EnableAlphaBlending:1; // 3: Perform alpha blending, interacts with POLYGON_ATTR (0x40004A4); 0=Disable, 1=Enable
u8 EnableAlphaTest:1; // 2: Perform alpha test, interacts with ALPHA_TEST_REF (0x4000340); 0=Disable, 1=Enable
u8 PolygonShading:1; // 1: Polygon shading mode, interacts with POLYGON_ATTR (0x40004A4); 0=Toon Shading, 1=Highlight Shading

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2007 shash
Copyright (C) 2007-2022 DeSmuME team
Copyright (C) 2007-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1830,13 +1830,28 @@ static void writereg_POWCNT1(const int size, const u32 adr, const u32 val)
if(wasGeomEnabled && !isGeomEnabled)
{
//kill the geometry data when the power goes off
//but save these tables, first. they shouldnt be cleared.
//so, so bad. we need to model this with hardware-like operations instead of c++ code
GFX3D_State prior = gfx3d.state;
reconstruct(&gfx3d.state);
memcpy(gfx3d.state.u16ToonTable, prior.u16ToonTable, sizeof(prior.u16ToonTable));
//dont think we should save this one: it's sent with 3d commands, not random bonus immediate register writes like the toon table
//memcpy(gfx3d.state.shininessTable, prior.shininessTable, sizeof(prior.shininessTable));
// TODO: Test which geometry data should be cleared on power off.
// The code below doesn't make any sense. You would think that only the data that
// is derived from geometry commands (either via GXFIFO or if writing to registers
// 0x04000440 - 0x040006A4) is what should be cleared. And that outside of geometry
// command data, other data (even if related to the 3D engine) shouldn't be touched.
// This will need further testing, but for now, we'll leave things as they are.
// - 2023/01/22, rogerman
gfx3d.pendingState.DISP3DCNT.value = 0;
gfx3d.pendingState.DISP3DCNT.EnableTexMapping = 1;
gfx3d.pendingState.DISP3DCNT.PolygonShading = PolygonShadingMode_Toon;
gfx3d.pendingState.DISP3DCNT.EnableAlphaTest = 1;
gfx3d.pendingState.DISP3DCNT.EnableAlphaBlending = 1;
gfx3d.pendingState.SWAP_BUFFERS.value = 0;
gfx3d.pendingState.alphaTestRef = 0;
gfx3d.pendingState.clearDepth = DS_DEPTH15TO24(0x7FFF);
gfx3d.pendingState.clearColor = 0;
gfx3d.pendingState.fogColor = 0;
gfx3d.pendingState.fogOffset = 0;
gfx3d.pendingState.fogShift = 0;
memset(gfx3d.pendingState.shininessTable, 0, sizeof(gfx3d.pendingState.shininessTable));
}
}
@ -3271,6 +3286,28 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
return;
}
switch (adr >> 4)
{
case 0x400033: // Edge Mark Color Table
MMU.ARM9_REG[adr & 0xFFF] = val;
gfx3d_UpdateEdgeMarkColorTable<u8>((u8)(adr & 0x0000000F), val);
return;
case 0x400036:
case 0x400037: // Fog Table
MMU.ARM9_REG[adr & 0xFFF] = val & 0x7F;
gfx3d_UpdateFogTable<u8>((u8)(adr & 0x0000001F), val & 0x7F); // Drop the highest bit of each 8-bit value to limit the range to [0...127]
return;
case 0x400038:
case 0x400039:
case 0x40003A:
case 0x40003B: // Toon Table
MMU.ARM9_REG[adr & 0xFFF] = val;
gfx3d_UpdateToonTable<u8>((u8)(adr & 0x0000003F), val);
return;
}
GPUEngineA *mainEngine = GPU->GetEngineMain();
GPUEngineB *subEngine = GPU->GetEngineSub();
@ -3615,18 +3652,6 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
case REG_DIVCNT+3: printf("ERROR 8bit DIVCNT+3 WRITE\n"); return;
#endif
//fog table: only write bottom 7 bits
case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x01: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x03:
case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x05: case eng_3D_FOG_TABLE+0x06: case eng_3D_FOG_TABLE+0x07:
case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x09: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0B:
case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0D: case eng_3D_FOG_TABLE+0x0E: case eng_3D_FOG_TABLE+0x0F:
case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x11: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x13:
case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x15: case eng_3D_FOG_TABLE+0x16: case eng_3D_FOG_TABLE+0x17:
case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x19: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1B:
case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1D: case eng_3D_FOG_TABLE+0x1E: case eng_3D_FOG_TABLE+0x1F:
val &= 0x7F;
break;
//ensata putchar port
case 0x04FFF000:
if(nds.ensataEmulation)
@ -3663,9 +3688,29 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
case eng_3D_CLEAR_COLOR+0: case eng_3D_CLEAR_COLOR+1:
case eng_3D_CLEAR_COLOR+2: case eng_3D_CLEAR_COLOR+3:
T1WriteByte((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val);
T1WriteByte((u8*)&gfx3d.pendingState.clearColor, adr-eng_3D_CLEAR_COLOR, val);
break;
case eng_3D_CLEAR_DEPTH:
HostWriteByte(MMU.ARM9_REG, 0x0354, val);
gfx3d_glClearDepth<u8, 0>(val);
return;
case eng_3D_CLEAR_DEPTH+1:
HostWriteByte(MMU.ARM9_REG, 0x0355, val);
gfx3d_glClearDepth<u8, 1>(val);
return;
case eng_3D_CLRIMAGE_OFFSET:
HostWriteByte(MMU.ARM9_REG, 0x0356, val);
gfx3d_glClearImageOffset<u8, 0>(val);
return;
case eng_3D_CLRIMAGE_OFFSET+1:
HostWriteByte(MMU.ARM9_REG, 0x0357, val);
gfx3d_glClearImageOffset<u8, 1>(val);
return;
case REG_VRAMCNTA:
case REG_VRAMCNTB:
case REG_VRAMCNTC:
@ -3761,13 +3806,23 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
switch (adr >> 4)
{
//toon table
case 0x0400038:
case 0x0400039:
case 0x040003A:
case 0x040003B:
((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF)>>1] = val;
gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val);
case 0x400033: // Edge Mark Color Table
((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u16) >> 1)] = val;
gfx3d_UpdateEdgeMarkColorTable<u16>((u8)(adr & 0x0000000F), val);
return;
case 0x400036:
case 0x400037: // Fog Table
((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u16) >> 1)] = val & 0x7F7F;
gfx3d_UpdateFogTable<u16>((u8)(adr & 0x0000001F), val & 0x7F7F); // Drop the highest bit of each 8-bit value to limit the range to [0...127]
return;
case 0x400038:
case 0x400039:
case 0x40003A:
case 0x40003B: // Toon Table
((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u16) >> 1)] = val;
gfx3d_UpdateToonTable<u16>((u8)(adr & 0x0000003F), val);
return;
}
@ -4262,14 +4317,6 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
MMU_new.gxstat.write(16,adr,val);
break;
//fog table: only write bottom 7 bits
case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x06:
case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0E:
case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x16:
case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1E:
val &= 0x7F7F;
break;
// Alpha test reference value - Parameters:1
case eng_3D_ALPHA_TEST_REF:
HostWriteWord(MMU.ARM9_REG, 0x0340, val);
@ -4278,13 +4325,18 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
case eng_3D_CLEAR_COLOR:
case eng_3D_CLEAR_COLOR+2:
T1WriteWord((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val);
T1WriteWord((u8 *)&gfx3d.pendingState.clearColor, adr-eng_3D_CLEAR_COLOR, val);
break;
// Clear background depth setup - Parameters:2
case eng_3D_CLEAR_DEPTH:
HostWriteWord(MMU.ARM9_REG, 0x0354, val);
gfx3d_glClearDepth(val);
gfx3d_glClearDepth<u16, 0>(val);
return;
case eng_3D_CLRIMAGE_OFFSET:
HostWriteWord(MMU.ARM9_REG, 0x0356, val);
gfx3d_glClearImageOffset<u16, 0>(val);
return;
// Fog Color - Parameters:4b
@ -4477,16 +4529,23 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
// lookups by the compiler
switch (adr >> 4)
{
case 0x400033: //edge color table
((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val;
case 0x400033: // Edge Mark Color Table
((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u32) >> 1)] = val;
gfx3d_UpdateEdgeMarkColorTable<u32>((u8)(adr & 0x0000000F), val);
return;
case 0x400036:
case 0x400037: // Fog Table
((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u32) >> 1)] = val & 0x7F7F7F7F;
gfx3d_UpdateFogTable<u32>((u8)(adr & 0x0000001F), val & 0x7F7F7F7F); // Drop the highest bit of each 8-bit value to limit the range to [0...127]
return;
case 0x400038:
case 0x400039:
case 0x40003A:
case 0x40003B: //toon table
((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val;
gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val);
case 0x40003B: // Toon Table
((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u32) >> 1)] = val;
gfx3d_UpdateToonTable<u32>((u8)(adr & 0x0000003F), val);
return;
case 0x400040:
@ -4790,12 +4849,6 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
case REG_POWCNT1: writereg_POWCNT1(32,adr,val); break;
//fog table: only write bottom 7 bits
case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0C:
case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1C:
val &= 0x7F7F7F7F;
break;
//ensata handshaking port?
case 0x04FFF010:
if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_ack && val == 0x13579bdf)
@ -4828,13 +4881,14 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
return;
case eng_3D_CLEAR_COLOR:
T1WriteLong((u8*)&gfx3d.state.clearColor,0,val);
T1WriteLong((u8 *)&gfx3d.pendingState.clearColor, 0, val);
break;
// Clear background depth setup - Parameters:2
case eng_3D_CLEAR_DEPTH:
HostWriteLong(MMU.ARM9_REG, 0x0354, val);
gfx3d_glClearDepth(val);
gfx3d_glClearDepth<u16, 0>((u16)(val & 0x0000FFFF));
gfx3d_glClearImageOffset<u16, 0>((u16)(val >> 16));
return;
// Fog Color - Parameters:4b

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2022 DeSmuME team
Copyright (C) 2008-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1777,7 +1777,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, c
const POLY &initialPoly = *clippedPolyList[firstIndex].poly;
TEXIMAGE_PARAM lastTexParams = initialPoly.texParam;
u32 lastTexPalette = initialPoly.texPalette;
u32 lastViewport = initialPoly.viewport;
GFX3D_Viewport lastViewport = initialPoly.viewport;
this->SetupTexture(initialPoly, firstIndex);
this->SetupViewport(initialPoly.viewport);
@ -1806,7 +1806,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, c
}
// Set up the viewport if it changed
if (lastViewport != thePoly.viewport)
if (lastViewport.value != thePoly.viewport.value)
{
lastViewport = thePoly.viewport;
this->SetupViewport(thePoly.viewport);
@ -1833,7 +1833,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, c
if (lastPolyAttr.value == nextPoly.attribute.value &&
lastTexParams.value == nextPoly.texParam.value &&
lastTexPalette == nextPoly.texPalette &&
lastViewport == nextPoly.viewport &&
lastViewport.value == nextPoly.viewport.value &&
polyPrimitive == oglPrimitiveType[nextPoly.vtxFormat] &&
polyPrimitive != GL_LINE_LOOP &&
polyPrimitive != GL_LINE_STRIP &&
@ -3874,7 +3874,7 @@ Render3DError OpenGLRenderer_1_2::DisableVertexAttributes()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
{
OGLRenderRef &OGLRef = *this->ref;
@ -3957,7 +3957,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const CPoly *clippedPolyList,
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(clippedPolyList, clippedPolyCount, this->_clippedPolyOpaqueCount, clippedPolyCount - 1, indexOffset, lastPolyAttr);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(clippedPolyList, clippedPolyCount, clippedPolyOpaqueCount, clippedPolyCount - 1, indexOffset, lastPolyAttr);
// Restore OpenGL states back to normal.
this->_geometryProgramFlags = oldGProgramFlags;
@ -4157,7 +4157,7 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList)
{
OGLRenderRef &OGLRef = *this->ref;
@ -4166,11 +4166,11 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
return OGLERROR_BEGINGL_FAILED;
}
this->_clippedPolyCount = engine.clippedPolyCount;
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
this->_clippedPolyList = engine.clippedPolyList;
this->_clippedPolyCount = renderGList.clippedPolyCount;
this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount;
this->_clippedPolyList = (CPoly *)renderGList.clippedPolyList;
this->_enableAlphaBlending = (engine.renderState.enableAlphaBlending) ? true : false;
this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false;
if (this->isVBOSupported)
{
@ -4178,14 +4178,14 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
// Only copy as much vertex data as we need to, since this can be a potentially large upload size.
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(VERT) * engine.vertListCount, engine.vertList);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(VERT) * renderGList.vertListCount, renderGList.vertList);
}
else
{
// If VBOs aren't supported, we need to use the client-side buffers here.
OGLRef.vtxPtrPosition = &engine.vertList[0].coord;
OGLRef.vtxPtrTexCoord = &engine.vertList[0].texcoord;
OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)&engine.vertList[0].color : OGLRef.color4fBuffer;
OGLRef.vtxPtrPosition = (GLvoid *)&renderGList.vertList[0].coord;
OGLRef.vtxPtrTexCoord = (GLvoid *)&renderGList.vertList[0].texcoord;
OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)&renderGList.vertList[0].color : OGLRef.color4fBuffer;
}
// Generate the clipped polygon list.
@ -4197,10 +4197,10 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
const size_t polyType = thePoly.type;
const VERT vert[4] = {
engine.vertList[thePoly.vertIndexes[0]],
engine.vertList[thePoly.vertIndexes[1]],
engine.vertList[thePoly.vertIndexes[2]],
engine.vertList[thePoly.vertIndexes[3]]
renderGList.vertList[thePoly.vertIndexes[0]],
renderGList.vertList[thePoly.vertIndexes[1]],
renderGList.vertList[thePoly.vertIndexes[2]],
renderGList.vertList[thePoly.vertIndexes[3]]
};
if (this->isShaderSupported)
@ -4238,7 +4238,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
// Consolidate the vertex color and the poly alpha to our internal color buffer
// so that OpenGL can use it.
const VERT *vertForAlpha = &engine.vertList[vertIndex];
const VERT *vertForAlpha = &renderGList.vertList[vertIndex];
OGLRef.color4fBuffer[colorIndex+0] = divide6bitBy63_LUT[vertForAlpha->color[0]];
OGLRef.color4fBuffer[colorIndex+1] = divide6bitBy63_LUT[vertForAlpha->color[1]];
OGLRef.color4fBuffer[colorIndex+2] = divide6bitBy63_LUT[vertForAlpha->color[2]];
@ -4289,29 +4289,29 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
}
// Set up rendering states that will remain constant for the entire frame.
this->_pendingRenderStates.enableAntialiasing = (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableFogAlphaOnly = (engine.renderState.enableFogAlphaOnly) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableAntialiasing = (renderState.DISP3DCNT.EnableAntialiasing) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableFogAlphaOnly = (renderState.DISP3DCNT.FogOnlyAlpha) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[engine.renderState.alphaTestRef];
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[renderState.alphaTestRef];
if (this->_enableFog && this->_deviceInfo.isFogSupported)
{
this->_fogProgramKey.key = 0;
this->_fogProgramKey.offset = engine.renderState.fogOffset & 0x7FFF;
this->_fogProgramKey.shift = engine.renderState.fogShift;
this->_fogProgramKey.offset = renderState.fogOffset & 0x7FFF;
this->_fogProgramKey.shift = renderState.fogShift;
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(engine.renderState.fogColor ) & 0x0000001F];
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(engine.renderState.fogColor >> 5) & 0x0000001F];
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(engine.renderState.fogColor >> 10) & 0x0000001F];
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(engine.renderState.fogColor >> 16) & 0x0000001F];
this->_pendingRenderStates.fogOffset = (GLfloat)(engine.renderState.fogOffset & 0x7FFF) / 32767.0f;
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> engine.renderState.fogShift) / 32767.0f;
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(renderState.fogColor ) & 0x0000001F];
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(renderState.fogColor >> 5) & 0x0000001F];
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(renderState.fogColor >> 10) & 0x0000001F];
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(renderState.fogColor >> 16) & 0x0000001F];
this->_pendingRenderStates.fogOffset = (GLfloat)(renderState.fogOffset & 0x7FFF) / 32767.0f;
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> renderState.fogShift) / 32767.0f;
u8 fogDensityTable[32];
for (size_t i = 0; i < 32; i++)
{
fogDensityTable[i] = (engine.renderState.fogDensityTable[i] == 127) ? 255 : engine.renderState.fogDensityTable[i] << 1;
fogDensityTable[i] = (renderState.fogDensityTable[i] == 127) ? 255 : renderState.fogDensityTable[i] << 1;
}
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
@ -4321,12 +4321,12 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
if (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported)
{
const u8 alpha8 = (engine.renderState.enableAntialiasing) ? 0x80 : 0xFF;
const u8 alpha8 = (renderState.DISP3DCNT.EnableAntialiasing) ? 0x80 : 0xFF;
FragmentColor edgeColor32[8];
for (size_t i = 0; i < 8; i++)
{
edgeColor32[i].color = COLOR555TO8888(engine.renderState.edgeMarkColorTable[i] & 0x7FFF, alpha8);
edgeColor32[i].color = COLOR555TO8888(renderState.edgeMarkColorTable[i] & 0x7FFF, alpha8);
}
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
@ -4337,10 +4337,10 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
if (this->isShaderSupported)
{
this->_geometryProgramFlags.value = 0;
this->_geometryProgramFlags.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0;
this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0;
this->_geometryProgramFlags.EnableWDepth = renderState.SWAP_BUFFERS.DepthMode;
this->_geometryProgramFlags.EnableAlphaTest = renderState.DISP3DCNT.EnableAlphaTest;
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0;
this->_geometryProgramFlags.ToonShadingMode = (engine.renderState.shading) ? 1 : 0;
this->_geometryProgramFlags.ToonShadingMode = renderState.DISP3DCNT.PolygonShading;
this->_geometryProgramFlags.EnableFog = (this->_enableFog && this->_deviceInfo.isFogSupported) ? 1 : 0;
this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ? 1 : 0;
this->_geometryProgramFlags.OpaqueDrawMode = (this->_isDepthLEqualPolygonFacingSupported) ? 1 : 0;
@ -4351,14 +4351,14 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
{
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, engine.renderState.u16ToonTable);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, renderState.toonTable16);
}
}
else
{
if (engine.renderState.enableAlphaTest && (engine.renderState.alphaTestRef > 0))
if (renderState.DISP3DCNT.EnableAlphaTest && (renderState.alphaTestRef > 0))
{
glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[engine.renderState.alphaTestRef]);
glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[renderState.alphaTestRef]);
}
else
{
@ -4426,7 +4426,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry()
this->SetupPolygon(firstPoly, true, false);
}
this->ZeroDstAlphaPass(this->_clippedPolyList, this->_clippedPolyCount, this->_enableAlphaBlending, indexOffset, lastPolyAttr);
this->ZeroDstAlphaPass(this->_clippedPolyList, this->_clippedPolyCount, this->_clippedPolyOpaqueCount, this->_enableAlphaBlending, indexOffset, lastPolyAttr);
if (this->_clippedPolyOpaqueCount > 0)
{
@ -4956,23 +4956,15 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, size_t polyR
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::SetupViewport(const u32 viewportValue)
Render3DError OpenGLRenderer_1_2::SetupViewport(const GFX3D_Viewport viewport)
{
const GLfloat wScalar = this->_framebufferWidth / (GLfloat)GPU_FRAMEBUFFER_NATIVE_WIDTH;
const GLfloat hScalar = this->_framebufferHeight / (GLfloat)GPU_FRAMEBUFFER_NATIVE_HEIGHT;
VIEWPORT viewport;
viewport.decode(viewportValue);
// The maximum viewport y-value is 191. Values above 191 need to wrap
// around and go negative.
//
// Test case: The Homie Rollerz character select screen sets the y-value
// to 253, which then wraps around to -2.
glViewport( viewport.x * wScalar,
(viewport.y > 191) ? (viewport.y - 0xFF) * hScalar : viewport.y * hScalar,
viewport.width * wScalar,
viewport.height * hScalar);
glViewport(viewport.x * wScalar,
viewport.y * hScalar,
viewport.width * wScalar,
viewport.height * hScalar);
return OGLERROR_NOERR;
}
@ -5446,7 +5438,7 @@ Render3DError OpenGLRenderer_2_0::DisableVertexAttributes()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList)
{
OGLRenderRef &OGLRef = *this->ref;
@ -5455,17 +5447,17 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
return OGLERROR_BEGINGL_FAILED;
}
this->_clippedPolyCount = engine.clippedPolyCount;
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
this->_clippedPolyList = engine.clippedPolyList;
this->_clippedPolyCount = renderGList.clippedPolyCount;
this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount;
this->_clippedPolyList = (CPoly *)renderGList.clippedPolyList;
this->_enableAlphaBlending = (engine.renderState.enableAlphaBlending) ? true : false;
this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false;
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
// Only copy as much vertex data as we need to, since this can be a potentially large upload size.
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * engine.vertListCount, engine.vertList);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * renderGList.vertListCount, renderGList.vertList);
// Generate the clipped polygon list.
bool renderNeedsToonTable = false;
@ -5476,10 +5468,10 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
const size_t polyType = thePoly.type;
const VERT vert[4] = {
engine.vertList[thePoly.vertIndexes[0]],
engine.vertList[thePoly.vertIndexes[1]],
engine.vertList[thePoly.vertIndexes[2]],
engine.vertList[thePoly.vertIndexes[3]]
renderGList.vertList[thePoly.vertIndexes[0]],
renderGList.vertList[thePoly.vertIndexes[1]],
renderGList.vertList[thePoly.vertIndexes[2]],
renderGList.vertList[thePoly.vertIndexes[3]]
};
for (size_t j = 0; j < polyType; j++)
@ -5527,29 +5519,29 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(OGLRef.vertIndexBuffer), OGLRef.vertIndexBuffer);
// Set up rendering states that will remain constant for the entire frame.
this->_pendingRenderStates.enableAntialiasing = (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableFogAlphaOnly = (engine.renderState.enableFogAlphaOnly) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableAntialiasing = (renderState.DISP3DCNT.EnableAntialiasing) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableFogAlphaOnly = (renderState.DISP3DCNT.FogOnlyAlpha) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[engine.renderState.alphaTestRef];
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[renderState.alphaTestRef];
if (this->_enableFog && this->_deviceInfo.isFogSupported)
{
this->_fogProgramKey.key = 0;
this->_fogProgramKey.offset = engine.renderState.fogOffset & 0x7FFF;
this->_fogProgramKey.shift = engine.renderState.fogShift;
this->_fogProgramKey.offset = renderState.fogOffset & 0x7FFF;
this->_fogProgramKey.shift = renderState.fogShift;
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(engine.renderState.fogColor ) & 0x0000001F];
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(engine.renderState.fogColor >> 5) & 0x0000001F];
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(engine.renderState.fogColor >> 10) & 0x0000001F];
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(engine.renderState.fogColor >> 16) & 0x0000001F];
this->_pendingRenderStates.fogOffset = (GLfloat)(engine.renderState.fogOffset & 0x7FFF) / 32767.0f;
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> engine.renderState.fogShift) / 32767.0f;
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(renderState.fogColor ) & 0x0000001F];
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(renderState.fogColor >> 5) & 0x0000001F];
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(renderState.fogColor >> 10) & 0x0000001F];
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(renderState.fogColor >> 16) & 0x0000001F];
this->_pendingRenderStates.fogOffset = (GLfloat)(renderState.fogOffset & 0x7FFF) / 32767.0f;
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> renderState.fogShift) / 32767.0f;
u8 fogDensityTable[32];
for (size_t i = 0; i < 32; i++)
{
fogDensityTable[i] = (engine.renderState.fogDensityTable[i] == 127) ? 255 : engine.renderState.fogDensityTable[i] << 1;
fogDensityTable[i] = (renderState.fogDensityTable[i] == 127) ? 255 : renderState.fogDensityTable[i] << 1;
}
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
@ -5559,12 +5551,12 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
if (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported)
{
const u8 alpha8 = (engine.renderState.enableAntialiasing) ? 0x80 : 0xFF;
const u8 alpha8 = (renderState.DISP3DCNT.EnableAntialiasing) ? 0x80 : 0xFF;
FragmentColor edgeColor32[8];
for (size_t i = 0; i < 8; i++)
{
edgeColor32[i].color = COLOR555TO8888(engine.renderState.edgeMarkColorTable[i] & 0x7FFF, alpha8);
edgeColor32[i].color = COLOR555TO8888(renderState.edgeMarkColorTable[i] & 0x7FFF, alpha8);
}
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
@ -5574,10 +5566,10 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
// Setup render states
this->_geometryProgramFlags.value = 0;
this->_geometryProgramFlags.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0;
this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0;
this->_geometryProgramFlags.EnableWDepth = renderState.SWAP_BUFFERS.DepthMode;
this->_geometryProgramFlags.EnableAlphaTest = renderState.DISP3DCNT.EnableAlphaTest;
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0;
this->_geometryProgramFlags.ToonShadingMode = (engine.renderState.shading) ? 1 : 0;
this->_geometryProgramFlags.ToonShadingMode = renderState.DISP3DCNT.PolygonShading;
this->_geometryProgramFlags.EnableFog = (this->_enableFog && this->_deviceInfo.isFogSupported) ? 1 : 0;
this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ? 1 : 0;
this->_geometryProgramFlags.OpaqueDrawMode = (this->_isDepthLEqualPolygonFacingSupported) ? 1 : 0;
@ -5588,7 +5580,7 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
{
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, engine.renderState.u16ToonTable);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, renderState.toonTable16);
}
glReadBuffer(GL_COLOROUT_ATTACHMENT_ID);

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2022 DeSmuME team
Copyright (C) 2008-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -323,7 +323,7 @@ enum OGLTextureUnitID
OGLTextureUnitID_DepthStencil,
OGLTextureUnitID_GPolyID,
OGLTextureUnitID_FogAttr,
OGLTextureUnitID_PolyStates,
OGLTextureUnitID_PolyStates,
OGLTextureUnitID_LookupTable,
};
@ -604,8 +604,6 @@ struct OGLRenderRef
};
struct GFX3D_State;
struct POLYLIST;
struct INDEXLIST;
struct POLY;
class OpenGLRenderer;
@ -876,13 +874,13 @@ protected:
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry();
virtual Render3DError ReadBackPixels();
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList);
virtual Render3DError RenderGeometry();
virtual Render3DError PostprocessFramebuffer();
virtual Render3DError EndRender();
@ -893,7 +891,7 @@ protected:
virtual void SetPolygonIndex(const size_t index);
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer);
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
virtual Render3DError SetupViewport(const u32 viewportValue);
virtual Render3DError SetupViewport(const GFX3D_Viewport viewport);
virtual Render3DError DrawShadowPolygon(const GLenum polyPrimitive, const GLsizei vertIndexCount, const GLushort *indexBufferPtr, const bool performDepthEqualTest, const bool enableAlphaDepthWrite, const bool isTranslucent, const u8 opaquePolyID);
@ -916,7 +914,7 @@ protected:
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList);
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
};

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2022 DeSmuME team
Copyright (C) 2008-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1758,7 +1758,7 @@ Render3DError OpenGLRenderer_3_2::DisableVertexAttributes()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
{
OGLRenderRef &OGLRef = *this->ref;
@ -1816,7 +1816,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const CPoly *clippedPolyList,
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(clippedPolyList, clippedPolyCount, this->_clippedPolyOpaqueCount, clippedPolyCount - 1, indexOffset, lastPolyAttr);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(clippedPolyList, clippedPolyCount, clippedPolyOpaqueCount, clippedPolyCount - 1, indexOffset, lastPolyAttr);
// Restore OpenGL states back to normal.
this->_geometryProgramFlags = oldGProgramFlags;
@ -1973,7 +1973,7 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList)
{
OGLRenderRef &OGLRef = *this->ref;
@ -1982,11 +1982,11 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
return OGLERROR_BEGINGL_FAILED;
}
this->_clippedPolyCount = engine.clippedPolyCount;
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
this->_clippedPolyList = engine.clippedPolyList;
this->_clippedPolyCount = renderGList.clippedPolyCount;
this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount;
this->_clippedPolyList = (CPoly *)renderGList.clippedPolyList;
this->_enableAlphaBlending = (engine.renderState.enableAlphaBlending) ? true : false;
this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false;
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
@ -1999,9 +1999,9 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
glDeleteSync(this->_syncBufferSetup);
}
const size_t vtxBufferSize = sizeof(VERT) * engine.vertListCount;
const size_t vtxBufferSize = sizeof(VERT) * renderGList.vertListCount;
VERT *vtxPtr = (VERT *)glMapBufferRange(GL_ARRAY_BUFFER, 0, vtxBufferSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
memcpy(vtxPtr, engine.vertList, vtxBufferSize);
memcpy(vtxPtr, renderGList.vertList, vtxBufferSize);
glUnmapBuffer(GL_ARRAY_BUFFER);
this->_syncBufferSetup = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
@ -2025,10 +2025,10 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
const size_t polyType = thePoly.type;
const VERT vert[4] = {
engine.vertList[thePoly.vertIndexes[0]],
engine.vertList[thePoly.vertIndexes[1]],
engine.vertList[thePoly.vertIndexes[2]],
engine.vertList[thePoly.vertIndexes[3]]
renderGList.vertList[thePoly.vertIndexes[0]],
renderGList.vertList[thePoly.vertIndexes[1]],
renderGList.vertList[thePoly.vertIndexes[2]],
renderGList.vertList[thePoly.vertIndexes[3]]
};
for (size_t j = 0; j < polyType; j++)
@ -2075,19 +2075,19 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(OGLRef.vertIndexBuffer), OGLRef.vertIndexBuffer);
// Set up rendering states that will remain constant for the entire frame.
this->_pendingRenderStates.enableAntialiasing = (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableFogAlphaOnly = (engine.renderState.enableFogAlphaOnly) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableAntialiasing = (renderState.DISP3DCNT.EnableAntialiasing) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.enableFogAlphaOnly = (renderState.DISP3DCNT.FogOnlyAlpha) ? GL_TRUE : GL_FALSE;
this->_pendingRenderStates.clearPolyID = this->_clearAttributes.opaquePolyID;
this->_pendingRenderStates.clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF;
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[engine.renderState.alphaTestRef];
this->_pendingRenderStates.alphaTestRef = divide5bitBy31_LUT[renderState.alphaTestRef];
if (renderNeedsToonTable)
{
for (size_t i = 0; i < 32; i++)
{
this->_pendingRenderStates.toonColor[i].r = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] ) & 0x001F];
this->_pendingRenderStates.toonColor[i].g = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.toonColor[i].b = divide5bitBy31_LUT[(engine.renderState.u16ToonTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.toonColor[i].r = divide5bitBy31_LUT[(renderState.toonTable16[i] ) & 0x001F];
this->_pendingRenderStates.toonColor[i].g = divide5bitBy31_LUT[(renderState.toonTable16[i] >> 5) & 0x001F];
this->_pendingRenderStates.toonColor[i].b = divide5bitBy31_LUT[(renderState.toonTable16[i] >> 10) & 0x001F];
this->_pendingRenderStates.toonColor[i].a = 1.0f;
}
}
@ -2095,20 +2095,20 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
if (this->_enableFog)
{
this->_fogProgramKey.key = 0;
this->_fogProgramKey.offset = engine.renderState.fogOffset & 0x7FFF;
this->_fogProgramKey.shift = engine.renderState.fogShift;
this->_fogProgramKey.offset = renderState.fogOffset & 0x7FFF;
this->_fogProgramKey.shift = renderState.fogShift;
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(engine.renderState.fogColor ) & 0x0000001F];
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(engine.renderState.fogColor >> 5) & 0x0000001F];
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(engine.renderState.fogColor >> 10) & 0x0000001F];
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(engine.renderState.fogColor >> 16) & 0x0000001F];
this->_pendingRenderStates.fogOffset = (GLfloat)(engine.renderState.fogOffset & 0x7FFF) / 32767.0f;
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> engine.renderState.fogShift) / 32767.0f;
this->_pendingRenderStates.fogColor.r = divide5bitBy31_LUT[(renderState.fogColor ) & 0x0000001F];
this->_pendingRenderStates.fogColor.g = divide5bitBy31_LUT[(renderState.fogColor >> 5) & 0x0000001F];
this->_pendingRenderStates.fogColor.b = divide5bitBy31_LUT[(renderState.fogColor >> 10) & 0x0000001F];
this->_pendingRenderStates.fogColor.a = divide5bitBy31_LUT[(renderState.fogColor >> 16) & 0x0000001F];
this->_pendingRenderStates.fogOffset = (GLfloat)(renderState.fogOffset & 0x7FFF) / 32767.0f;
this->_pendingRenderStates.fogStep = (GLfloat)(0x0400 >> renderState.fogShift) / 32767.0f;
u8 fogDensityTable[32];
for (size_t i = 0; i < 32; i++)
{
fogDensityTable[i] = (engine.renderState.fogDensityTable[i] == 127) ? 255 : engine.renderState.fogDensityTable[i] << 1;
fogDensityTable[i] = (renderState.fogDensityTable[i] == 127) ? 255 : renderState.fogDensityTable[i] << 1;
}
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
@ -2117,12 +2117,12 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
if (this->_enableEdgeMark)
{
const GLfloat edgeColorAlpha = (engine.renderState.enableAntialiasing) ? (16.0f/31.0f) : 1.0f;
const GLfloat edgeColorAlpha = (renderState.DISP3DCNT.EnableAntialiasing) ? (16.0f/31.0f) : 1.0f;
for (size_t i = 0; i < 8; i++)
{
this->_pendingRenderStates.edgeColor[i].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] ) & 0x001F];
this->_pendingRenderStates.edgeColor[i].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.edgeColor[i].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.edgeColor[i].r = divide5bitBy31_LUT[(renderState.edgeMarkColorTable[i] ) & 0x001F];
this->_pendingRenderStates.edgeColor[i].g = divide5bitBy31_LUT[(renderState.edgeMarkColorTable[i] >> 5) & 0x001F];
this->_pendingRenderStates.edgeColor[i].b = divide5bitBy31_LUT[(renderState.edgeMarkColorTable[i] >> 10) & 0x001F];
this->_pendingRenderStates.edgeColor[i].a = edgeColorAlpha;
}
}
@ -2176,10 +2176,10 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
// Set up the default draw call states.
this->_geometryProgramFlags.value = 0;
this->_geometryProgramFlags.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0;
this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0;
this->_geometryProgramFlags.EnableWDepth = renderState.SWAP_BUFFERS.DepthMode;
this->_geometryProgramFlags.EnableAlphaTest = renderState.DISP3DCNT.EnableAlphaTest;
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0;
this->_geometryProgramFlags.ToonShadingMode = (engine.renderState.shading) ? 1 : 0;
this->_geometryProgramFlags.ToonShadingMode = renderState.DISP3DCNT.PolygonShading;
this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0;
this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0;
this->_geometryProgramFlags.OpaqueDrawMode = 1;

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2019 DeSmuME team
Copyright (C) 2008-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -98,11 +98,11 @@ protected:
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry();
virtual Render3DError ReadBackPixels();
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList);
virtual Render3DError PostprocessFramebuffer();
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2008-2022 DeSmuME team
Copyright (C) 2008-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -144,6 +144,57 @@ void gfx3d_init();
void gfx3d_deinit();
void gfx3d_reset();
typedef union
{
u16 value;
struct
{
#ifndef MSB_FIRST
u8 XOffset;
u8 YOffset;
#else
u8 YOffset;
u8 XOffset;
#endif
};
} IOREG_CLRIMAGE_OFFSET;
typedef union
{
u8 cmd[4]; // 0- 7: Unpacked command OR packed command #1
// 8-15: Packed command #2
// 16-23: Packed command #3
// 24-31: Packed command #4
u32 command; // 8-bit unpacked command
u32 param; // Parameter(s) for previous command(s)
} IOREG_GXFIFO; // 0x04000400: Geometry command/parameter sent to FIFO
typedef union
{
#ifndef MSB_FIRST
u8 MtxMode:2; // 0- 1: Set matrix mode;
// 0=Projection
// 1=Position
// 2=Position+Vector
// 3=Texture
u8 :6; // 2- 7: Unused bits
u32 :24; // 8-31: Unused bits
#else
u8 :6; // 2- 7: Unused bits
u8 MtxMode:2; // 0- 1: Set matrix mode;
// 0=Projection
// 1=Position
// 2=Position+Vector
// 3=Texture
u32 :24; // 8-31: Unused bits
#endif
} IOREG_MTX_MODE; // 0x04000440: MTX_MODE command port
typedef union
{
u32 value;
@ -230,7 +281,7 @@ typedef union
u8 LightMask:4; // 0- 3: Light enable mask
#endif
};
} POLYGON_ATTR;
} POLYGON_ATTR; // 0x040004A4: POLYGON_ATTR command port
typedef union
{
@ -301,7 +352,173 @@ typedef union
u16 :16;
#endif
};
} TEXIMAGE_PARAM;
} TEXIMAGE_PARAM; // 0x040004A8: TEXIMAGE_PARAM command port
typedef union
{
u32 value;
struct
{
#ifndef MSB_FIRST
u8 YSortMode:1; // 0: Translucent polygon Y-sorting mode; 0=Auto-sort, 1=Manual-sort
u8 DepthMode:1; // 1: Depth buffering select; 0=Z 1=W
u8 :6; // 2- 7: Unused bits
u32 :24; // 8-31: Unused bits
#else
u8 :6; // 2- 7: Unused bits
u8 DepthMode:1; // 1: Depth buffering select; 0=Z 1=W
u8 YSortMode:1; // 0: Translucent polygon Y-sorting mode; 0=Auto-sort, 1=Manual-sort
u32 :24; // 8-31: Unused bits
#endif
};
} IOREG_SWAP_BUFFERS; // 0x04000540: SWAP_BUFFERS command port
typedef union
{
u32 value;
struct
{
// Coordinate (0,0) represents the bottom-left of the screen.
// Coordinate (255,191) represents the top-right of the screen.
u8 X1; // 0- 7: First X-coordinate; 0...255
u8 Y1; // 8-15: First Y-coordinate; 0...191
u8 X2; // 16-23: Second X-coordinate; 0...255
u8 Y2; // 24-31: Second Y-coordinate; 0...191
};
} IOREG_VIEWPORT; // 0x04000580: VIEWPORT command port
typedef union
{
u32 value;
struct
{
u8 TestBusy:1;
u8 BoxTestResult:1;
u8 :6;
u8 PosVecMtxStackLevel:5;
u8 ProjMtxStackLevel:1;
u8 MtxStackBusy:1;
u8 AckMtxStackError:1;
u16 CommandListCount:9;
u8 CommandListLessThanHalf:1;
u8 CommandListEmpty:1;
u8 EngineBusy:1;
u8 :2;
u8 CommandListIRQ:2;
};
} IOREG_GXSTAT; // 0x04000600: Geometry engine status
typedef union
{
u32 value;
struct
{
u16 PolygonCount; // 0-15: Number of polygons currently stored in polygon list RAM; 0...2048
u16 VertexCount; // 16-31: Number of vertices currently stored in vertex RAM; 0...6144
};
} IOREG_RAM_COUNT; // 0x04000604: Polygon list and vertex RAM count
struct GFX3D_IOREG
{
u8 RDLINES_COUNT; // 0x04000320
u8 __unused1[15];
u16 EDGE_COLOR[8]; // 0x04000330
u8 ALPHA_TEST_REF; // 0x04000340
u8 __unused2[15];
u32 CLEAR_COLOR; // 0x04000350
u16 CLEAR_DEPTH; // 0x04000354
IOREG_CLRIMAGE_OFFSET CLRIMAGE_OFFSET; // 0x04000356
u32 FOG_COLOR; // 0x04000358
u16 FOG_OFFSET; // 0x0400035C
u8 __unused3[2];
u8 FOG_TABLE[32]; // 0x04000360
u16 TOON_TABLE[32]; // 0x04000380
u8 __unused4[64];
IOREG_GXFIFO GXFIFO; // 0x04000400
u8 __unused5[60];
// Geometry command ports
u32 MTX_MODE; // 0x04000440
u32 MTX_PUSH; // 0x04000444
u32 MTX_POP; // 0x04000448
u32 MTX_STORE; // 0x0400044C
u32 MTX_RESTORE; // 0x04000450
u32 MTX_IDENTITY; // 0x04000454
u32 MTX_LOAD_4x4; // 0x04000458
u32 MTX_LOAD_4x3; // 0x0400045C
u32 MTX_MULT_4x4; // 0x04000460
u32 MTX_MULT_4x3; // 0x04000464
u32 MTX_MULT_3x3; // 0x04000468
u32 MTX_SCALE; // 0x0400046C
u32 MTX_TRANS; // 0x04000470
u8 __unused6[12];
u32 COLOR; // 0x04000480
u32 NORMAL; // 0x04000484
u32 TEXCOORD; // 0x04000488
u32 VTX_16; // 0x0400048C
u32 VTX_10; // 0x04000490
u32 VTX_XY; // 0x04000494
u32 VTX_XZ; // 0x04000498
u32 VTX_YZ; // 0x0400049C
u32 VTX_DIFF; // 0x040004A0
u32 POLYGON_ATTR; // 0x040004A4
u32 TEXIMAGE_PARAM; // 0x040004A8
u32 PLTT_BASE; // 0x040004AC
u8 __unused7[16];
u32 DIF_AMB; // 0x040004C0
u32 SPE_EMI; // 0x040004C4
u32 LIGHT_VECTOR; // 0x040004C8
u32 LIGHT_COLOR; // 0x040004CC
u32 SHININESS; // 0x040004D0
u8 __unused8[44];
u32 BEGIN_VTXS; // 0x04000500
u32 END_VTXS; // 0x04000504
u8 __unused9[56];
IOREG_SWAP_BUFFERS SWAP_BUFFERS; // 0x04000540
u8 __unused10[60];
IOREG_VIEWPORT VIEWPORT; // 0x04000580
u8 __unused11[60];
u32 BOX_TEST; // 0x040005C0
u32 POS_TEST; // 0x040005C4
u32 VEC_TEST; // 0x040005C8
u8 __unused12[52];
IOREG_GXSTAT GXSTAT; // 0x04000600
IOREG_RAM_COUNT RAM_COUNT; // 0x04000604
u8 __unused13[8];
u16 DISP_1DOT_DEPTH; // 0x04000610
u8 __unused14[14];
u32 POS_RESULT[4]; // 0x04000620
u16 VEC_RESULT[3]; // 0x04000630
u8 __unused15[10];
u8 CLIPMTX_RESULT[64]; // 0x04000640
u8 VECMTX_RESULT[36]; // 0x04000680
};
typedef struct GFX3D_IOREG GFX3D_IOREG; // 0x04000320 - 0x040006A4
union GFX3D_Viewport
{
u64 value;
struct
{
s16 x;
s16 y;
u16 width;
u16 height;
};
};
typedef union GFX3D_Viewport GFX3D_Viewport;
struct POLY {
PolygonType type; //tri or quad
@ -310,7 +527,8 @@ struct POLY {
POLYGON_ATTR attribute;
TEXIMAGE_PARAM texParam;
u32 texPalette; //the hardware rendering params
u32 viewport;
GFX3D_Viewport viewport;
IOREG_VIEWPORT viewportLegacySave; // Exists for save state compatibility.
float miny, maxy;
void setVertIndexes(int a, int b, int c, int d=-1)
@ -360,12 +578,7 @@ struct POLY {
#define POLYLIST_SIZE 20000
#define VERTLIST_SIZE (POLYLIST_SIZE * 4)
struct POLYLIST {
POLY list[POLYLIST_SIZE];
size_t count;
size_t opaqueCount;
};
#define INDEXLIST_SIZE (POLYLIST_SIZE * 4)
//just a vert with a 4 float position
struct VERT_POS4f
@ -483,17 +696,6 @@ union VtxTexCoord16
};
typedef union VtxTexCoord16 VtxTexCoord16;
#define INDEXLIST_SIZE (POLYLIST_SIZE * 4)
struct INDEXLIST {
int list[INDEXLIST_SIZE];
};
struct VIEWPORT {
u8 x, y;
u16 width, height;
void decode(u32 v);
};
//ok, imagine the plane that cuts diagonally across a cube such that it clips
//out to be a hexagon. within that plane, draw a quad such that it cuts off
//four corners of the hexagon, and you will observe a decagon
@ -513,6 +715,7 @@ struct CPoly
POLY *poly;
VERT clipVerts[MAX_CLIPPED_VERTS];
};
typedef struct CPoly CPoly;
class GFX3D_Clipper
{
@ -536,103 +739,94 @@ public:
//used to communicate state to the renderer
struct GFX3D_State
{
GFX3D_State()
: enableTexturing(true)
, enableAlphaTest(true)
, enableAlphaBlending(true)
, enableAntialiasing(false)
, enableEdgeMarking(false)
, enableClearImage(false)
, enableFog(false)
, enableFogAlphaOnly(false)
, shading(PolygonShadingMode_Toon)
, alphaTestRef(0)
, activeFlushCommand(0)
, pendingFlushCommand(0)
, clearDepth(DS_DEPTH15TO24(0x7FFF))
, clearColor(0)
, fogColor(0)
, fogOffset(0)
, fogShift(0)
, invalidateToon(true)
{
for(u32 i=0;i<ARRAY_SIZE(shininessTable);i++)
shininessTable[i] = 0;
for(u32 i=0;i<ARRAY_SIZE(u16ToonTable);i++)
u16ToonTable[i] = 0;
}
IOREG_DISP3DCNT savedDISP3DCNT;
IOREG_DISP3DCNT DISP3DCNT;
u8 fogShift;
BOOL enableTexturing, enableAlphaTest, enableAlphaBlending,
enableAntialiasing, enableEdgeMarking, enableClearImage, enableFog, enableFogAlphaOnly;
u32 shading;
BOOL wbuffer, sortmode;
u8 alphaTestRef;
u32 clearColor; // Not an RGBA8888 color. This uses its own packed format.
u32 clearDepth;
IOREG_CLRIMAGE_OFFSET clearImageOffset;
u32 fogColor; // Not an RGBA8888 color. This uses its own packed format.
u16 fogOffset;
IOREG_SWAP_BUFFERS SWAP_BUFFERS;
CACHE_ALIGN u16 edgeMarkColorTable[8];
CACHE_ALIGN u8 fogDensityTable[32];
CACHE_ALIGN u16 toonTable16[32];
CACHE_ALIGN u8 shininessTable[128];
};
typedef struct GFX3D_State GFX3D_State;
struct GFX3D_GeometryList
{
PAGE_ALIGN VERT vertList[VERTLIST_SIZE];
PAGE_ALIGN POLY polyList[POLYLIST_SIZE];
PAGE_ALIGN CPoly clippedPolyList[POLYLIST_SIZE];
size_t vertListCount;
size_t polyCount;
size_t polyOpaqueCount;
size_t clippedPolyCount;
size_t clippedPolyOpaqueCount;
};
typedef struct GFX3D_GeometryList GFX3D_GeometryList;
struct LegacyGFX3DStateSFormat
{
u32 enableTexturing;
u32 enableAlphaTest;
u32 enableAlphaBlending;
u32 enableAntialiasing;
u32 enableEdgeMarking;
u32 enableClearImage;
u32 enableFog;
u32 enableFogAlphaOnly;
u32 fogShift;
u32 toonShadingMode;
u32 enableWDepth;
u32 polygonTransparentSortMode;
u32 alphaTestRef;
u32 clearColor;
u32 clearDepth;
u32 fogColor[4]; //for savestate compatibility as of 26-jul-09
u32 fogOffset;
u16 toonTable16[32];
u8 shininessTable[128];
u32 activeFlushCommand;
u32 pendingFlushCommand;
u32 clearDepth;
u32 clearColor;
#include "PACKED.h"
struct {
u32 fogColor;
u32 pad[3]; //for savestate compatibility as of 26-jul-09
};
#include "PACKED_END.h"
u32 fogOffset;
u32 fogShift;
bool invalidateToon;
CACHE_ALIGN u16 u16ToonTable[32];
u8 shininessTable[128];
//TODO: copy these in instead of this sloppy memory mapping
u8 *fogDensityTable; // Alias to MMU.ARM9_REG+0x0360
u16 *edgeMarkColorTable; // Alias to MMU.ARM9_REG+0x0330
};
typedef struct LegacyGFX3D_StateSFormat LegacyGFX3D_StateSFormat;
struct Viewer3d_State
struct Viewer3D_State
{
int frameNumber;
GFX3D_State state;
VERT vertList[VERTLIST_SIZE];
POLYLIST polylist;
INDEXLIST indexlist;
size_t vertListCount;
GFX3D_GeometryList gList;
int indexList[INDEXLIST_SIZE];
};
typedef struct Viewer3D_State Viewer3D_State;
extern Viewer3d_State* viewer3d_state;
extern Viewer3D_State viewer3D;
struct GFX3D
{
GFX3D()
: polylist(NULL)
, vertList(NULL)
, render3DFrameCount(0) {
}
//currently set values
GFX3D_State state;
//values used for the currently-rendered frame (committed with each flush)
GFX3D_State renderState;
POLYLIST *polylist;
VERT *vertList;
INDEXLIST indexlist;
GFX3D_State pendingState;
GFX3D_State appliedState;
GFX3D_GeometryList gList[2];
size_t clippedPolyCount;
size_t clippedPolyOpaqueCount;
CPoly *clippedPolyList;
size_t vertListCount;
u8 pendingListIndex;
u8 appliedListIndex;
u32 render3DFrameCount; // Increments when gfx3d_doFlush() is called. Resets every 60 video frames.
};
typedef struct GFX3D GFX3D;
extern GFX3D gfx3d;
//---------------------
@ -646,12 +840,14 @@ void gfx3d_glFlush(u32 v);
void gfx3d_glFogColor(u32 v);
void gfx3d_glFogOffset (u32 v);
void gfx3d_glClearDepth(u32 v);
template<typename T, size_t ADDROFFSET> void gfx3d_glClearDepth(const T val);
template<typename T, size_t ADDROFFSET> void gfx3d_glClearImageOffset(const T val);
void gfx3d_glSwapScreen(u32 screen);
int gfx3d_GetNumPolys();
int gfx3d_GetNumVertex();
void gfx3d_UpdateToonTable(u8 offset, u16 val);
void gfx3d_UpdateToonTable(u8 offset, u32 val);
u32 gfx3d_GetNumPolys();
u32 gfx3d_GetNumVertex();
template<typename T> void gfx3d_UpdateEdgeMarkColorTable(const u8 offset, const T val);
template<typename T> void gfx3d_UpdateFogTable(const u8 offset, const T val);
template<typename T> void gfx3d_UpdateToonTable(const u8 offset, const T val);
s32 gfx3d_GetClipMatrix (const u32 index);
s32 gfx3d_GetDirectionalMatrix(const u32 index);
void gfx3d_glAlphaFunc(u32 v);
@ -678,6 +874,7 @@ void gfx3d_FinishLoadStateBufferRead();
void gfx3d_ClearStack();
void gfx3d_parseCurrentDISP3DCNT();
const GFX3D_IOREG& GFX3D_GetIORegisterMap();
void ParseReg_DISP3DCNT();
#endif //_GFX3D_H_

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2009-2022 DeSmuME team
Copyright (C) 2009-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -313,25 +313,25 @@ FORCEINLINE int edge_fx_fl::Step() {
static FORCEINLINE void alphaBlend(FragmentColor &dst, const FragmentColor src)
static FORCEINLINE void alphaBlend(const bool isAlphaBlendingEnabled, const FragmentColor inSrc, FragmentColor &outDst)
{
if (src.a == 0)
if (inSrc.a == 0)
{
return;
}
if (src.a == 31 || dst.a == 0 || !gfx3d.renderState.enableAlphaBlending)
if (inSrc.a == 31 || outDst.a == 0 || !isAlphaBlendingEnabled)
{
dst = src;
outDst = inSrc;
}
else
{
const u8 alpha = src.a + 1;
const u8 alpha = inSrc.a + 1;
const u8 invAlpha = 32 - alpha;
dst.r = (alpha*src.r + invAlpha*dst.r) >> 5;
dst.g = (alpha*src.g + invAlpha*dst.g) >> 5;
dst.b = (alpha*src.b + invAlpha*dst.b) >> 5;
dst.a = max(src.a, dst.a);
outDst.r = (alpha*inSrc.r + invAlpha*outDst.r) >> 5;
outDst.g = (alpha*inSrc.g + invAlpha*outDst.g) >> 5;
outDst.b = (alpha*inSrc.b + invAlpha*outDst.b) >> 5;
outDst.a = max(inSrc.a, outDst.a);
}
}
@ -424,6 +424,8 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_shade(const PolygonMode polygonMode,
return;
}
const GFX3D_State &renderState = *this->_softRender->currentRenderState;
static const FragmentColor colorWhite = MakeFragmentColor(0x3F, 0x3F, 0x3F, 0x1F);
const FragmentColor mainTexColor = (this->_currentTexture->IsSamplingEnabled()) ? this->_sample(texCoordU, texCoordV) : colorWhite;
@ -468,7 +470,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_shade(const PolygonMode polygonMode,
{
const FragmentColor toonColor = this->_softRender->toonColor32LUT[src.r >> 1];
if (gfx3d.renderState.shading == PolygonShadingMode_Highlight)
if (renderState.DISP3DCNT.PolygonShading == PolygonShadingMode_Highlight)
{
// Tested in the "Shadows of Almia" logo in the Pokemon Ranger: Shadows of Almia title screen.
// Also tested in Advance Wars: Dual Strike and Advance Wars: Days of Ruin when tiles highlight
@ -502,6 +504,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_shade(const PolygonMode polygonMode,
template<bool RENDERER> template<bool ISFRONTFACING, bool ISSHADOWPOLYGON>
FORCEINLINE void RasterizerUnit<RENDERER>::_pixel(const POLYGON_ATTR polyAttr, const bool isTranslucent, const size_t fragmentIndex, FragmentColor &dstColor, float r, float g, float b, float invu, float invv, float z, float w)
{
const GFX3D_State &renderState = *this->_softRender->currentRenderState;
FragmentColor newDstColor32;
FragmentColor shaderOutput;
bool isOpaquePixel;
@ -522,7 +525,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_pixel(const POLYGON_ATTR polyAttr, c
// Note that an IEEE-754 single-precision float uses a 23-bit significand. Therefore, we will multiply the
// Z-depth by a 22-bit significand for safety.
const u32 newDepth = (gfx3d.renderState.wbuffer) ? u32floor(w * 4096.0f) : u32floor(z * 4194303.0f) << 2;
const u32 newDepth = (renderState.SWAP_BUFFERS.DepthMode) ? u32floor(w * 4096.0f) : u32floor(z * 4194303.0f) << 2;
// run the depth test
bool depthFail = false;
@ -642,7 +645,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_pixel(const POLYGON_ATTR polyAttr, c
dstAttributeTranslucentPolyID = polyAttr.PolygonID;
//alpha blending and write color
alphaBlend(dstColor, shaderOutput);
alphaBlend((renderState.DISP3DCNT.EnableAlphaBlending != 0), shaderOutput, dstColor);
dstAttributeIsFogged = (dstAttributeIsFogged && polyAttr.Fog_Enable);
}
@ -779,6 +782,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_drawscanline(const POLYGON_ATTR poly
template<bool RENDERER> template<bool ISFRONTFACING, bool ISSHADOWPOLYGON>
FORCEINLINE void RasterizerUnit<RENDERER>::_pixel_SSE2(const POLYGON_ATTR polyAttr, const bool isTranslucent, const size_t fragmentIndex, FragmentColor &dstColor, const __m128 &srcColorf, float invu, float invv, float z, float w)
{
const GFX3D_State &renderState = *this->_softRender->currentRenderState;
FragmentColor newDstColor32;
FragmentColor shaderOutput;
bool isOpaquePixel;
@ -799,7 +803,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_pixel_SSE2(const POLYGON_ATTR polyAt
// Note that an IEEE-754 single-precision float uses a 23-bit significand. Therefore, we will multiply the
// Z-depth by a 22-bit significand for safety.
const u32 newDepth = (gfx3d.renderState.wbuffer) ? u32floor(w * 4096.0f) : u32floor(z * 4194303.0f) << 2;
const u32 newDepth = (renderState.SWAP_BUFFERS.DepthMode) ? u32floor(w * 4096.0f) : u32floor(z * 4194303.0f) << 2;
// run the depth test
bool depthFail = false;
@ -891,7 +895,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_pixel_SSE2(const POLYGON_ATTR polyAt
this->_shade<ISSHADOWPOLYGON>((PolygonMode)polyAttr.Mode, newDstColor32, shaderOutput, invu * w, invv * w);
// handle alpha test
if ( shaderOutput.a == 0 || (this->_softRender->currentRenderState->enableAlphaTest && shaderOutput.a < this->_softRender->currentRenderState->alphaTestRef) )
if ( shaderOutput.a == 0 || (renderState.DISP3DCNT.EnableAlphaTest && (shaderOutput.a < renderState.alphaTestRef)) )
{
return;
}
@ -917,7 +921,7 @@ FORCEINLINE void RasterizerUnit<RENDERER>::_pixel_SSE2(const POLYGON_ATTR polyAt
dstAttributeTranslucentPolyID = polyAttr.PolygonID;
//alpha blending and write color
alphaBlend(dstColor, shaderOutput);
alphaBlend((renderState.DISP3DCNT.EnableAlphaBlending != 0), shaderOutput, dstColor);
dstAttributeIsFogged = (dstAttributeIsFogged && polyAttr.Fog_Enable);
}
@ -1910,21 +1914,13 @@ void SoftRasterizerRenderer::_TransformVertices()
vert.fcolor[2] /= vertw;
//viewport transformation
VIEWPORT viewport;
viewport.decode(poly.poly->viewport);
vert.coord[0] *= viewport.width;
vert.coord[0] += viewport.x;
// The maximum viewport y-value is 191. Values above 191 need to wrap
// around and go negative.
//
// Test case: The Homie Rollerz character select screen sets the y-value
// to 253, which then wraps around to -2.
vert.coord[1] *= viewport.height;
vert.coord[1] += (viewport.y > 191) ? (viewport.y - 0xFF) : viewport.y;
vert.coord[1] = 192 - vert.coord[1];
vert.coord[0] *= poly.poly->viewport.width;
vert.coord[0] += poly.poly->viewport.x;
vert.coord[0] *= wScalar;
vert.coord[1] *= poly.poly->viewport.height;
vert.coord[1] += poly.poly->viewport.y;
vert.coord[1] = 192 - vert.coord[1];
vert.coord[1] *= hScalar;
//here is a hack which needs to be removed.
@ -2010,7 +2006,7 @@ Render3DError SoftRasterizerRenderer::ApplyRenderingSettings(const GFX3D_State &
return Render3D::ApplyRenderingSettings(renderState);
}
Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D &engine)
Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList)
{
// Force all threads to finish before rendering with new data
for (size_t i = 0; i < this->_threadCount; i++)
@ -2019,10 +2015,10 @@ Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D &engine)
}
// Keep the current render states for later use
this->currentRenderState = (GFX3D_State *)&engine.renderState;
this->_clippedPolyCount = engine.clippedPolyCount;
this->_clippedPolyOpaqueCount = engine.clippedPolyOpaqueCount;
memcpy(this->_clippedPolyList, engine.clippedPolyList, this->_clippedPolyCount * sizeof(CPoly));
this->currentRenderState = (GFX3D_State *)&renderState;
this->_clippedPolyCount = renderGList.clippedPolyCount;
this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount;
memcpy(this->_clippedPolyList, renderGList.clippedPolyList, this->_clippedPolyCount * sizeof(CPoly));
const bool doMultithreadedStateSetup = (this->_threadCount >= 2);
@ -2038,16 +2034,16 @@ Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D &engine)
}
// Convert the toon table colors
ColorspaceConvertBuffer555To6665Opaque<false, false, BESwapDst>(engine.renderState.u16ToonTable, (u32 *)this->toonColor32LUT, 32);
ColorspaceConvertBuffer555To6665Opaque<false, false, BESwapDst>(renderState.toonTable16, (u32 *)this->toonColor32LUT, 32);
if (this->_enableEdgeMark)
{
this->_UpdateEdgeMarkColorTable(this->currentRenderState->edgeMarkColorTable);
this->_UpdateEdgeMarkColorTable(renderState.edgeMarkColorTable);
}
if (this->_enableFog)
{
this->_UpdateFogTable(this->currentRenderState->fogDensityTable);
this->_UpdateFogTable(renderState.fogDensityTable);
}
if (doMultithreadedStateSetup)
@ -2107,7 +2103,7 @@ void SoftRasterizerRenderer::_UpdateEdgeMarkColorTable(const u16 *edgeMarkColorT
//we can do this by rendering a 3d frame and then freezing the system, but only changing the edge mark colors
for (size_t i = 0; i < 8; i++)
{
this->_edgeMarkTable[i].color = LE_TO_LOCAL_32( COLOR555TO6665(edgeMarkColorTable[i] & 0x7FFF, (this->currentRenderState->enableAntialiasing) ? 0x10 : 0x1F) );
this->_edgeMarkTable[i].color = LE_TO_LOCAL_32( COLOR555TO6665(edgeMarkColorTable[i] & 0x7FFF, (this->currentRenderState->DISP3DCNT.EnableAntialiasing) ? 0x10 : 0x1F) );
//zero 20-jun-2013 - this doesnt make any sense. at least, it should be related to the 0x8000 bit. if this is undocumented behaviour, lets write about which scenario proves it here, or which scenario is requiring this code.
//// this seems to be the only thing that selectively disables edge marking
@ -2390,7 +2386,7 @@ Render3DError SoftRasterizerRenderer::EndRender()
this->_threadPostprocessParam[0].enableEdgeMarking = this->_enableEdgeMark;
this->_threadPostprocessParam[0].enableFog = this->_enableFog;
this->_threadPostprocessParam[0].fogColor = this->currentRenderState->fogColor;
this->_threadPostprocessParam[0].fogAlphaOnly = this->currentRenderState->enableFogAlphaOnly;
this->_threadPostprocessParam[0].fogAlphaOnly = (this->currentRenderState->DISP3DCNT.FogOnlyAlpha != 0);
this->RenderEdgeMarkingAndFog(this->_threadPostprocessParam[0]);
}
@ -2426,7 +2422,7 @@ Render3DError SoftRasterizerRenderer::RenderFinish()
this->_threadPostprocessParam[i].enableEdgeMarking = this->_enableEdgeMark;
this->_threadPostprocessParam[i].enableFog = this->_enableFog;
this->_threadPostprocessParam[i].fogColor = this->currentRenderState->fogColor;
this->_threadPostprocessParam[i].fogAlphaOnly = this->currentRenderState->enableFogAlphaOnly;
this->_threadPostprocessParam[i].fogAlphaOnly = (this->currentRenderState->DISP3DCNT.FogOnlyAlpha != 0);
this->_task[i].execute(&SoftRasterizer_RunRenderEdgeMarkAndFog, &this->_threadPostprocessParam[i]);
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2009-2022 DeSmuME team
Copyright (C) 2009-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -176,7 +176,7 @@ protected:
void _GetPolygonStates();
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList);
virtual Render3DError RenderGeometry();
virtual Render3DError EndRender();

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2022 DeSmuME team
Copyright (C) 2008-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -412,12 +412,12 @@ size_t Render3D::GetClippedPolyCount() const
Render3DError Render3D::ApplyRenderingSettings(const GFX3D_State &renderState)
{
this->_enableEdgeMark = (CommonSettings.GFX3D_EdgeMark) ? renderState.enableEdgeMarking : false;
this->_enableFog = (CommonSettings.GFX3D_Fog) ? renderState.enableFog : false;
this->_enableEdgeMark = (CommonSettings.GFX3D_EdgeMark) ? (renderState.DISP3DCNT.EnableEdgeMarking != 0) : false;
this->_enableFog = (CommonSettings.GFX3D_Fog) ? (renderState.DISP3DCNT.EnableFog != 0) : false;
this->_enableTextureSmoothing = CommonSettings.GFX3D_Renderer_TextureSmoothing;
this->_prevEnableTextureSampling = this->_enableTextureSampling;
this->_enableTextureSampling = (CommonSettings.GFX3D_Texture) ? renderState.enableTexturing : false;
this->_enableTextureSampling = (CommonSettings.GFX3D_Texture) ? (renderState.DISP3DCNT.EnableTexMapping != 0) : false;
this->_prevEnableTextureDeposterize = this->_enableTextureDeposterize;
this->_enableTextureDeposterize = CommonSettings.GFX3D_Renderer_TextureDeposterize;
@ -436,7 +436,7 @@ Render3DError Render3D::ApplyRenderingSettings(const GFX3D_State &renderState)
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::BeginRender(const GFX3D &engine)
Render3DError Render3D::BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList)
{
return RENDER3DERROR_NOERR;
}
@ -579,15 +579,14 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State &renderState)
{
Render3DError error = RENDER3DERROR_NOERR;
if (renderState.enableClearImage)
if (renderState.DISP3DCNT.RearPlaneMode)
{
//the lion, the witch, and the wardrobe (thats book 1, suck it you new-school numberers)
//uses the scroll registers in the main game engine
const u16 *__restrict clearColorBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[2];
const u16 *__restrict clearDepthBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[3];
const u16 scrollBits = T1ReadWord(MMU.ARM9_REG, 0x356); //CLRIMAGE_OFFSET
const u8 xScroll = scrollBits & 0xFF;
const u8 yScroll = (scrollBits >> 8) & 0xFF;
const u8 xScroll = renderState.clearImageOffset.XOffset;
const u8 yScroll = renderState.clearImageOffset.YOffset;
if (xScroll == 0 && yScroll == 0)
{
@ -649,7 +648,7 @@ Render3DError Render3D::SetupTexture(const POLY &thePoly, size_t polyRenderIndex
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::SetupViewport(const u32 viewportValue)
Render3DError Render3D::SetupViewport(const GFX3D_Viewport viewport)
{
return RENDER3DERROR_NOERR;
}
@ -688,12 +687,12 @@ Render3DError Render3D::RenderPowerOff()
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::Render(const GFX3D &engine)
Render3DError Render3D::Render(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList)
{
Render3DError error = RENDER3DERROR_NOERR;
this->_isPoweredOn = true;
const u32 clearColorSwapped = LE_TO_LOCAL_32(engine.renderState.clearColor);
const u32 clearColorSwapped = LE_TO_LOCAL_32(renderState.clearColor);
this->_clearColor6665.color = LE_TO_LOCAL_32( COLOR555TO6665(clearColorSwapped & 0x7FFF, (clearColorSwapped >> 16) & 0x1F) );
this->_clearAttributes.opaquePolyID = (clearColorSwapped >> 24) & 0x3F;
@ -701,20 +700,20 @@ Render3DError Render3D::Render(const GFX3D &engine)
//I am not sure whether it is right, though. previously this was cleared to 0, as a guess,
//but in spiderman2 some fires with polyid 0 try to render on top of the background
this->_clearAttributes.translucentPolyID = kUnsetTranslucentPolyID;
this->_clearAttributes.depth = engine.renderState.clearDepth;
this->_clearAttributes.depth = renderState.clearDepth;
this->_clearAttributes.stencil = 0;
this->_clearAttributes.isTranslucentPoly = 0;
this->_clearAttributes.polyFacing = PolyFacing_Unwritten;
this->_clearAttributes.isFogged = BIT15(clearColorSwapped);
error = this->BeginRender(engine);
error = this->BeginRender(renderState, renderGList);
if (error != RENDER3DERROR_NOERR)
{
this->EndRender();
return error;
}
error = this->ClearFramebuffer(engine.renderState);
error = this->ClearFramebuffer(renderState);
if (error != RENDER3DERROR_NOERR)
{
this->EndRender();

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2006-2007 shash
Copyright (C) 2007-2022 DeSmuME team
Copyright (C) 2007-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -198,7 +198,7 @@ protected:
u16 *__restrict outColor16, u32 *__restrict outDepth24, u8 *__restrict outFog);
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList);
virtual Render3DError RenderGeometry();
virtual Render3DError PostprocessFramebuffer();
virtual Render3DError EndRender();
@ -208,7 +208,7 @@ protected:
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes);
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
virtual Render3DError SetupViewport(const u32 viewportValue);
virtual Render3DError SetupViewport(const GFX3D_Viewport viewport);
public:
static void* operator new(size_t size);
@ -232,7 +232,7 @@ public:
virtual Render3DError RenderPowerOff(); // Called when the renderer needs to handle a power-off condition by clearing its framebuffers.
virtual Render3DError Render(const GFX3D &engine); // Called when the renderer should do its job and render the current display lists.
virtual Render3DError Render(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList); // Called whenever the 3D renderer needs to render the geometry lists.
virtual Render3DError RenderFinish(); // Called whenever 3D rendering needs to finish. This function should block the calling thread
// and only release the block when 3D rendering is finished. (Before reading the 3D layer, be