aboutsummaryrefslogtreecommitdiff
path: root/src/GPU3D_Soft.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/GPU3D_Soft.cpp')
-rw-r--r--src/GPU3D_Soft.cpp240
1 files changed, 121 insertions, 119 deletions
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp
index 894ac94..c96464a 100644
--- a/src/GPU3D_Soft.cpp
+++ b/src/GPU3D_Soft.cpp
@@ -42,14 +42,16 @@ void SoftRenderer::StopRenderThread()
}
}
-void SoftRenderer::SetupRenderThread()
+void SoftRenderer::SetupRenderThread(GPU& gpu)
{
if (Threaded)
{
if (!RenderThreadRunning.load(std::memory_order_relaxed))
{
RenderThreadRunning = true;
- RenderThread = Platform::Thread_Create(std::bind(&SoftRenderer::RenderThreadFunc, this));
+ RenderThread = Platform::Thread_Create([this, &gpu]() {
+ RenderThreadFunc(gpu);
+ });
}
// otherwise more than one frame can be queued up at once
@@ -71,8 +73,8 @@ void SoftRenderer::SetupRenderThread()
}
-SoftRenderer::SoftRenderer(melonDS::GPU& gpu, bool threaded) noexcept
- : Renderer3D(false), GPU(gpu), Threaded(threaded)
+SoftRenderer::SoftRenderer(bool threaded) noexcept
+ : Renderer3D(false), Threaded(threaded)
{
Sema_RenderStart = Platform::Semaphore_Create();
Sema_RenderDone = Platform::Semaphore_Create();
@@ -92,7 +94,7 @@ SoftRenderer::~SoftRenderer()
Platform::Semaphore_Free(Sema_ScanlineCount);
}
-void SoftRenderer::Reset()
+void SoftRenderer::Reset(GPU& gpu)
{
memset(ColorBuffer, 0, BufferSize * 2 * 4);
memset(DepthBuffer, 0, BufferSize * 2 * 4);
@@ -100,19 +102,19 @@ void SoftRenderer::Reset()
PrevIsShadowMask = false;
- SetupRenderThread();
+ SetupRenderThread(gpu);
}
-void SoftRenderer::SetThreaded(bool threaded) noexcept
+void SoftRenderer::SetThreaded(bool threaded, GPU& gpu) noexcept
{
if (Threaded != threaded)
{
Threaded = threaded;
- SetupRenderThread();
+ SetupRenderThread(gpu);
}
}
-void SoftRenderer::TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* color, u8* alpha) const
+void SoftRenderer::TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s, s16 t, u16* color, u8* alpha) const
{
u32 vramaddr = (texparam & 0xFFFF) << 3;
@@ -167,10 +169,10 @@ void SoftRenderer::TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* co
case 1: // A3I5
{
vramaddr += ((t * width) + s);
- u8 pixel = ReadVRAM_Texture<u8>(vramaddr);
+ u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
texpal <<= 4;
- *color = ReadVRAM_TexPal<u16>(texpal + ((pixel&0x1F)<<1));
+ *color = ReadVRAM_TexPal<u16>(texpal + ((pixel&0x1F)<<1), gpu);
*alpha = ((pixel >> 3) & 0x1C) + (pixel >> 6);
}
break;
@@ -178,12 +180,12 @@ void SoftRenderer::TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* co
case 2: // 4-color
{
vramaddr += (((t * width) + s) >> 2);
- u8 pixel = ReadVRAM_Texture<u8>(vramaddr);
+ u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
pixel >>= ((s & 0x3) << 1);
pixel &= 0x3;
texpal <<= 3;
- *color = ReadVRAM_TexPal<u16>(texpal + (pixel<<1));
+ *color = ReadVRAM_TexPal<u16>(texpal + (pixel<<1), gpu);
*alpha = (pixel==0) ? alpha0 : 31;
}
break;
@@ -191,12 +193,12 @@ void SoftRenderer::TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* co
case 3: // 16-color
{
vramaddr += (((t * width) + s) >> 1);
- u8 pixel = ReadVRAM_Texture<u8>(vramaddr);
+ u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
if (s & 0x1) pixel >>= 4;
else pixel &= 0xF;
texpal <<= 4;
- *color = ReadVRAM_TexPal<u16>(texpal + (pixel<<1));
+ *color = ReadVRAM_TexPal<u16>(texpal + (pixel<<1), gpu);
*alpha = (pixel==0) ? alpha0 : 31;
}
break;
@@ -204,10 +206,10 @@ void SoftRenderer::TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* co
case 4: // 256-color
{
vramaddr += ((t * width) + s);
- u8 pixel = ReadVRAM_Texture<u8>(vramaddr);
+ u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
texpal <<= 4;
- *color = ReadVRAM_TexPal<u16>(texpal + (pixel<<1));
+ *color = ReadVRAM_TexPal<u16>(texpal + (pixel<<1), gpu);
*alpha = (pixel==0) ? alpha0 : 31;
}
break;
@@ -221,30 +223,30 @@ void SoftRenderer::TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* co
if (vramaddr >= 0x40000)
slot1addr += 0x10000;
- u8 val = ReadVRAM_Texture<u8>(vramaddr);
+ u8 val = ReadVRAM_Texture<u8>(vramaddr, gpu);
val >>= (2 * (s & 0x3));
- u16 palinfo = ReadVRAM_Texture<u16>(slot1addr);
+ u16 palinfo = ReadVRAM_Texture<u16>(slot1addr, gpu);
u32 paloffset = (palinfo & 0x3FFF) << 2;
texpal <<= 4;
switch (val & 0x3)
{
case 0:
- *color = ReadVRAM_TexPal<u16>(texpal + paloffset);
+ *color = ReadVRAM_TexPal<u16>(texpal + paloffset, gpu);
*alpha = 31;
break;
case 1:
- *color = ReadVRAM_TexPal<u16>(texpal + paloffset + 2);
+ *color = ReadVRAM_TexPal<u16>(texpal + paloffset + 2, gpu);
*alpha = 31;
break;
case 2:
if ((palinfo >> 14) == 1)
{
- u16 color0 = ReadVRAM_TexPal<u16>(texpal + paloffset);
- u16 color1 = ReadVRAM_TexPal<u16>(texpal + paloffset + 2);
+ u16 color0 = ReadVRAM_TexPal<u16>(texpal + paloffset, gpu);
+ u16 color1 = ReadVRAM_TexPal<u16>(texpal + paloffset + 2, gpu);
u32 r0 = color0 & 0x001F;
u32 g0 = color0 & 0x03E0;
@@ -261,8 +263,8 @@ void SoftRenderer::TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* co
}
else if ((palinfo >> 14) == 3)
{
- u16 color0 = ReadVRAM_TexPal<u16>(texpal + paloffset);
- u16 color1 = ReadVRAM_TexPal<u16>(texpal + paloffset + 2);
+ u16 color0 = ReadVRAM_TexPal<u16>(texpal + paloffset, gpu);
+ u16 color1 = ReadVRAM_TexPal<u16>(texpal + paloffset + 2, gpu);
u32 r0 = color0 & 0x001F;
u32 g0 = color0 & 0x03E0;
@@ -278,20 +280,20 @@ void SoftRenderer::TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* co
*color = r | g | b;
}
else
- *color = ReadVRAM_TexPal<u16>(texpal + paloffset + 4);
+ *color = ReadVRAM_TexPal<u16>(texpal + paloffset + 4, gpu);
*alpha = 31;
break;
case 3:
if ((palinfo >> 14) == 2)
{
- *color = ReadVRAM_TexPal<u16>(texpal + paloffset + 6);
+ *color = ReadVRAM_TexPal<u16>(texpal + paloffset + 6, gpu);
*alpha = 31;
}
else if ((palinfo >> 14) == 3)
{
- u16 color0 = ReadVRAM_TexPal<u16>(texpal + paloffset);
- u16 color1 = ReadVRAM_TexPal<u16>(texpal + paloffset + 2);
+ u16 color0 = ReadVRAM_TexPal<u16>(texpal + paloffset, gpu);
+ u16 color1 = ReadVRAM_TexPal<u16>(texpal + paloffset + 2, gpu);
u32 r0 = color0 & 0x001F;
u32 g0 = color0 & 0x03E0;
@@ -320,10 +322,10 @@ void SoftRenderer::TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* co
case 6: // A5I3
{
vramaddr += ((t * width) + s);
- u8 pixel = ReadVRAM_Texture<u8>(vramaddr);
+ u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
texpal <<= 4;
- *color = ReadVRAM_TexPal<u16>(texpal + ((pixel&0x7)<<1));
+ *color = ReadVRAM_TexPal<u16>(texpal + ((pixel&0x7)<<1), gpu);
*alpha = (pixel >> 3);
}
break;
@@ -331,7 +333,7 @@ void SoftRenderer::TextureLookup(u32 texparam, u32 texpal, s16 s, s16 t, u16* co
case 7: // direct color
{
vramaddr += (((t * width) + s) << 1);
- *color = ReadVRAM_Texture<u16>(vramaddr);
+ *color = ReadVRAM_Texture<u16>(vramaddr, gpu);
*alpha = (*color & 0x8000) ? 31 : 0;
}
break;
@@ -388,7 +390,7 @@ bool DepthTest_LessThan_FrontFacing(s32 dstz, s32 z, u32 dstattr)
return false;
}
-u32 SoftRenderer::AlphaBlend(u32 srccolor, u32 dstcolor, u32 alpha) const noexcept
+u32 SoftRenderer::AlphaBlend(const GPU3D& gpu3d, u32 srccolor, u32 dstcolor, u32 alpha) const noexcept
{
u32 dstalpha = dstcolor >> 24;
@@ -399,7 +401,7 @@ u32 SoftRenderer::AlphaBlend(u32 srccolor, u32 dstcolor, u32 alpha) const noexce
u32 srcG = (srccolor >> 8) & 0x3F;
u32 srcB = (srccolor >> 16) & 0x3F;
- if (GPU.GPU3D.RenderDispCnt & (1<<3))
+ if (gpu3d.RenderDispCnt & (1<<3))
{
u32 dstR = dstcolor & 0x3F;
u32 dstG = (dstcolor >> 8) & 0x3F;
@@ -418,7 +420,7 @@ u32 SoftRenderer::AlphaBlend(u32 srccolor, u32 dstcolor, u32 alpha) const noexce
return srcR | (srcG << 8) | (srcB << 16) | (dstalpha << 24);
}
-u32 SoftRenderer::RenderPixel(const Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16 t) const
+u32 SoftRenderer::RenderPixel(const GPU& gpu, const Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16 t) const
{
u8 r, g, b, a;
@@ -428,7 +430,7 @@ u32 SoftRenderer::RenderPixel(const Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s
if (blendmode == 2)
{
- if (GPU.GPU3D.RenderDispCnt & (1<<1))
+ if (gpu.GPU3D.RenderDispCnt & (1<<1))
{
// highlight mode: color is calculated normally
// except all vertex color components are set
@@ -442,7 +444,7 @@ u32 SoftRenderer::RenderPixel(const Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s
{
// toon mode: vertex color is replaced by toon color
- u16 tooncolor = GPU.GPU3D.RenderToonTable[vr >> 1];
+ u16 tooncolor = gpu.GPU3D.RenderToonTable[vr >> 1];
vr = (tooncolor << 1) & 0x3E; if (vr) vr++;
vg = (tooncolor >> 4) & 0x3E; if (vg) vg++;
@@ -450,12 +452,12 @@ u32 SoftRenderer::RenderPixel(const Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s
}
}
- if ((GPU.GPU3D.RenderDispCnt & (1<<0)) && (((polygon->TexParam >> 26) & 0x7) != 0))
+ if ((gpu.GPU3D.RenderDispCnt & (1<<0)) && (((polygon->TexParam >> 26) & 0x7) != 0))
{
u8 tr, tg, tb;
u16 tcolor; u8 talpha;
- TextureLookup(polygon->TexParam, polygon->TexPalette, s, t, &tcolor, &talpha);
+ TextureLookup(gpu, polygon->TexParam, polygon->TexPalette, s, t, &tcolor, &talpha);
tr = (tcolor << 1) & 0x3E; if (tr) tr++;
tg = (tcolor >> 4) & 0x3E; if (tg) tg++;
@@ -503,9 +505,9 @@ u32 SoftRenderer::RenderPixel(const Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s
a = polyalpha;
}
- if ((blendmode == 2) && (GPU.GPU3D.RenderDispCnt & (1<<1)))
+ if ((blendmode == 2) && (gpu.GPU3D.RenderDispCnt & (1<<1)))
{
- u16 tooncolor = GPU.GPU3D.RenderToonTable[vr >> 1];
+ u16 tooncolor = gpu.GPU3D.RenderToonTable[vr >> 1];
vr = (tooncolor << 1) & 0x3E; if (vr) vr++;
vg = (tooncolor >> 4) & 0x3E; if (vg) vg++;
@@ -526,7 +528,7 @@ u32 SoftRenderer::RenderPixel(const Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s
return r | (g << 8) | (b << 16) | (a << 24);
}
-void SoftRenderer::PlotTranslucentPixel(u32 pixeladdr, u32 color, u32 z, u32 polyattr, u32 shadow)
+void SoftRenderer::PlotTranslucentPixel(const GPU3D& gpu3d, u32 pixeladdr, u32 color, u32 z, u32 polyattr, u32 shadow)
{
u32 dstattr = AttrBuffer[pixeladdr];
u32 attr = (polyattr & 0xE0F0) | ((polyattr >> 8) & 0xFF0000) | (1<<22) | (dstattr & 0xFF001F0F);
@@ -556,7 +558,7 @@ void SoftRenderer::PlotTranslucentPixel(u32 pixeladdr, u32 color, u32 z, u32 pol
if (!(dstattr & (1<<15)))
attr &= ~(1<<15);
- color = AlphaBlend(color, ColorBuffer[pixeladdr], color>>24);
+ color = AlphaBlend(gpu3d, color, ColorBuffer[pixeladdr], color>>24);
if (z != -1)
DepthBuffer[pixeladdr] = z;
@@ -672,7 +674,7 @@ void SoftRenderer::SetupPolygon(SoftRenderer::RendererPolygon* rp, Polygon* poly
}
}
-void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
+void SoftRenderer::RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon* rp, s32 y)
{
Polygon* polygon = rp->PolyData;
@@ -749,7 +751,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
std::swap(zl, zr);
// CHECKME: edge fill rules for swapped opaque shadow mask polygons
- if ((GPU.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (GPU.GPU3D.RenderDispCnt & (1<<3))) || wireframe)
+ if ((gpu3d.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (gpu3d.RenderDispCnt & (1<<3))) || wireframe)
{
l_filledge = true;
r_filledge = true;
@@ -777,7 +779,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
rp->SlopeR.EdgeParams<false>(&r_edgelen, &r_edgecov);
// CHECKME: edge fill rules for unswapped opaque shadow mask polygons
- if ((GPU.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (GPU.GPU3D.RenderDispCnt & (1<<3))) || wireframe)
+ if ((gpu3d.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (gpu3d.RenderDispCnt & (1<<3))) || wireframe)
{
l_filledge = true;
r_filledge = true;
@@ -798,7 +800,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
// similarly, we can perform alpha test early (checkme)
if (wireframe) polyalpha = 31;
- if (polyalpha <= GPU.GPU3D.RenderAlphaRef) return;
+ if (polyalpha <= gpu3d.RenderAlphaRef) return;
// in wireframe mode, there are special rules for equal Z (TODO)
@@ -900,7 +902,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
rp->XR = rp->SlopeR.Step();
}
-void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
+void SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s32 y)
{
Polygon* polygon = rp->PolyData;
@@ -984,7 +986,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
// edges are always filled if antialiasing/edgemarking are enabled,
// if the pixels are translucent and alpha blending is enabled, or if the polygon is wireframe
// checkme: do swapped line polygons exist?
- if ((GPU.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (GPU.GPU3D.RenderDispCnt & (1<<3))) || wireframe)
+ if ((gpu.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (gpu.GPU3D.RenderDispCnt & (1<<3))) || wireframe)
{
l_filledge = true;
r_filledge = true;
@@ -1019,7 +1021,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
// * edges are filled if both sides are identical and fully overlapping
// edges are always filled if antialiasing/edgemarking are enabled,
// if the pixels are translucent and alpha blending is enabled, or if the polygon is wireframe
- if ((GPU.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (GPU.GPU3D.RenderDispCnt & (1<<3))) || wireframe)
+ if ((gpu.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (gpu.GPU3D.RenderDispCnt & (1<<3))) || wireframe)
{
l_filledge = true;
r_filledge = true;
@@ -1118,17 +1120,17 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
s16 s = interpX.Interpolate(sl, sr);
s16 t = interpX.Interpolate(tl, tr);
- u32 color = RenderPixel(polygon, vr>>3, vg>>3, vb>>3, s, t);
+ u32 color = RenderPixel(gpu, polygon, vr>>3, vg>>3, vb>>3, s, t);
u8 alpha = color >> 24;
// alpha test
- if (alpha <= GPU.GPU3D.RenderAlphaRef) continue;
+ if (alpha <= gpu.GPU3D.RenderAlphaRef) continue;
if (alpha == 31)
{
u32 attr = polyattr | edge;
- if (GPU.GPU3D.RenderDispCnt & (1<<4))
+ if (gpu.GPU3D.RenderDispCnt & (1<<4))
{
// anti-aliasing: all edges are rendered
@@ -1158,11 +1160,11 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
else
{
if (!(polygon->Attr & (1<<11))) z = -1;
- PlotTranslucentPixel(pixeladdr, color, z, polyattr, polygon->IsShadow);
+ PlotTranslucentPixel(gpu.GPU3D, pixeladdr, color, z, polyattr, polygon->IsShadow);
// blend with bottom pixel too, if needed
if ((dstattr & 0xF) && (pixeladdr < BufferSize))
- PlotTranslucentPixel(pixeladdr+BufferSize, color, z, polyattr, polygon->IsShadow);
+ PlotTranslucentPixel(gpu.GPU3D, pixeladdr+BufferSize, color, z, polyattr, polygon->IsShadow);
}
}
@@ -1214,17 +1216,17 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
s16 s = interpX.Interpolate(sl, sr);
s16 t = interpX.Interpolate(tl, tr);
- u32 color = RenderPixel(polygon, vr>>3, vg>>3, vb>>3, s, t);
+ u32 color = RenderPixel(gpu, polygon, vr>>3, vg>>3, vb>>3, s, t);
u8 alpha = color >> 24;
// alpha test
- if (alpha <= GPU.GPU3D.RenderAlphaRef) continue;
+ if (alpha <= gpu.GPU3D.RenderAlphaRef) continue;
if (alpha == 31)
{
u32 attr = polyattr | edge;
- if ((GPU.GPU3D.RenderDispCnt & (1<<4)) && (attr & 0xF))
+ if ((gpu.GPU3D.RenderDispCnt & (1<<4)) && (attr & 0xF))
{
// anti-aliasing: all edges are rendered
@@ -1247,11 +1249,11 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
else
{
if (!(polygon->Attr & (1<<11))) z = -1;
- PlotTranslucentPixel(pixeladdr, color, z, polyattr, polygon->IsShadow);
+ PlotTranslucentPixel(gpu.GPU3D, pixeladdr, color, z, polyattr, polygon->IsShadow);
// blend with bottom pixel too, if needed
if ((dstattr & 0xF) && (pixeladdr < BufferSize))
- PlotTranslucentPixel(pixeladdr+BufferSize, color, z, polyattr, polygon->IsShadow);
+ PlotTranslucentPixel(gpu.GPU3D, pixeladdr+BufferSize, color, z, polyattr, polygon->IsShadow);
}
}
@@ -1306,17 +1308,17 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
s16 s = interpX.Interpolate(sl, sr);
s16 t = interpX.Interpolate(tl, tr);
- u32 color = RenderPixel(polygon, vr>>3, vg>>3, vb>>3, s, t);
+ u32 color = RenderPixel(gpu, polygon, vr>>3, vg>>3, vb>>3, s, t);
u8 alpha = color >> 24;
// alpha test
- if (alpha <= GPU.GPU3D.RenderAlphaRef) continue;
+ if (alpha <= gpu.GPU3D.RenderAlphaRef) continue;
if (alpha == 31)
{
u32 attr = polyattr | edge;
- if (GPU.GPU3D.RenderDispCnt & (1<<4))
+ if (gpu.GPU3D.RenderDispCnt & (1<<4))
{
// anti-aliasing: all edges are rendered
@@ -1346,11 +1348,11 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
else
{
if (!(polygon->Attr & (1<<11))) z = -1;
- PlotTranslucentPixel(pixeladdr, color, z, polyattr, polygon->IsShadow);
+ PlotTranslucentPixel(gpu.GPU3D, pixeladdr, color, z, polyattr, polygon->IsShadow);
// blend with bottom pixel too, if needed
if ((dstattr & 0xF) && (pixeladdr < BufferSize))
- PlotTranslucentPixel(pixeladdr+BufferSize, color, z, polyattr, polygon->IsShadow);
+ PlotTranslucentPixel(gpu.GPU3D, pixeladdr+BufferSize, color, z, polyattr, polygon->IsShadow);
}
}
@@ -1358,7 +1360,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
rp->XR = rp->SlopeR.Step();
}
-void SoftRenderer::RenderScanline(s32 y, int npolys)
+void SoftRenderer::RenderScanline(const GPU& gpu, s32 y, int npolys)
{
for (int i = 0; i < npolys; i++)
{
@@ -1368,19 +1370,19 @@ void SoftRenderer::RenderScanline(s32 y, int npolys)
if (y >= polygon->YTop && (y < polygon->YBottom || (y == polygon->YTop && polygon->YBottom == polygon->YTop)))
{
if (polygon->IsShadowMask)
- RenderShadowMaskScanline(rp, y);
+ RenderShadowMaskScanline(gpu.GPU3D, rp, y);
else
- RenderPolygonScanline(rp, y);
+ RenderPolygonScanline(gpu, rp, y);
}
}
}
-u32 SoftRenderer::CalculateFogDensity(u32 pixeladdr) const
+u32 SoftRenderer::CalculateFogDensity(const GPU3D& gpu3d, u32 pixeladdr) const
{
u32 z = DepthBuffer[pixeladdr];
u32 densityid, densityfrac;
- if (z < GPU.GPU3D.RenderFogOffset)
+ if (z < gpu3d.RenderFogOffset)
{
densityid = 0;
densityfrac = 0;
@@ -1392,8 +1394,8 @@ u32 SoftRenderer::CalculateFogDensity(u32 pixeladdr) const
// on hardware, the final value can overflow the 32-bit range with a shift big enough,
// causing fog to 'wrap around' and accidentally apply to larger Z ranges
- z -= GPU.GPU3D.RenderFogOffset;
- z = (z >> 2) << GPU.GPU3D.RenderFogShift;
+ z -= gpu3d.RenderFogOffset;
+ z = (z >> 2) << gpu3d.RenderFogShift;
densityid = z >> 17;
if (densityid >= 32)
@@ -1407,20 +1409,20 @@ u32 SoftRenderer::CalculateFogDensity(u32 pixeladdr) const
// checkme (may be too precise?)
u32 density =
- ((GPU.GPU3D.RenderFogDensityTable[densityid] * (0x20000-densityfrac)) +
- (GPU.GPU3D.RenderFogDensityTable[densityid+1] * densityfrac)) >> 17;
+ ((gpu3d.RenderFogDensityTable[densityid] * (0x20000-densityfrac)) +
+ (gpu3d.RenderFogDensityTable[densityid+1] * densityfrac)) >> 17;
if (density >= 127) density = 128;
return density;
}
-void SoftRenderer::ScanlineFinalPass(s32 y)
+void SoftRenderer::ScanlineFinalPass(const GPU3D& gpu3d, s32 y)
{
// to consider:
// clearing all polygon fog flags if the master flag isn't set?
// merging all final pass loops into one?
- if (GPU.GPU3D.RenderDispCnt & (1<<5))
+ if (gpu3d.RenderDispCnt & (1<<5))
{
// edge marking
// only applied to topmost pixels
@@ -1440,7 +1442,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
((polyid != (AttrBuffer[pixeladdr-ScanlineWidth] >> 24)) && (z < DepthBuffer[pixeladdr-ScanlineWidth])) ||
((polyid != (AttrBuffer[pixeladdr+ScanlineWidth] >> 24)) && (z < DepthBuffer[pixeladdr+ScanlineWidth])))
{
- u16 edgecolor = GPU.GPU3D.RenderEdgeTable[polyid >> 3];
+ u16 edgecolor = gpu3d.RenderEdgeTable[polyid >> 3];
u32 edgeR = (edgecolor << 1) & 0x3E; if (edgeR) edgeR++;
u32 edgeG = (edgecolor >> 4) & 0x3E; if (edgeG) edgeG++;
u32 edgeB = (edgecolor >> 9) & 0x3E; if (edgeB) edgeB++;
@@ -1453,7 +1455,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
}
}
- if (GPU.GPU3D.RenderDispCnt & (1<<7))
+ if (gpu3d.RenderDispCnt & (1<<7))
{
// fog
@@ -1466,12 +1468,12 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
// TODO: check the 'fog alpha glitch with small Z' GBAtek talks about
- bool fogcolor = !(GPU.GPU3D.RenderDispCnt & (1<<6));
+ bool fogcolor = !(gpu3d.RenderDispCnt & (1<<6));
- u32 fogR = (GPU.GPU3D.RenderFogColor << 1) & 0x3E; if (fogR) fogR++;
- u32 fogG = (GPU.GPU3D.RenderFogColor >> 4) & 0x3E; if (fogG) fogG++;
- u32 fogB = (GPU.GPU3D.RenderFogColor >> 9) & 0x3E; if (fogB) fogB++;
- u32 fogA = (GPU.GPU3D.RenderFogColor >> 16) & 0x1F;
+ u32 fogR = (gpu3d.RenderFogColor << 1) & 0x3E; if (fogR) fogR++;
+ u32 fogG = (gpu3d.RenderFogColor >> 4) & 0x3E; if (fogG) fogG++;
+ u32 fogB = (gpu3d.RenderFogColor >> 9) & 0x3E; if (fogB) fogB++;
+ u32 fogA = (gpu3d.RenderFogColor >> 16) & 0x1F;
for (int x = 0; x < 256; x++)
{
@@ -1481,7 +1483,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
u32 attr = AttrBuffer[pixeladdr];
if (attr & (1<<15))
{
- density = CalculateFogDensity(pixeladdr);
+ density = CalculateFogDensity(gpu3d, pixeladdr);
srccolor = ColorBuffer[pixeladdr];
srcR = srccolor & 0x3F;
@@ -1510,7 +1512,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
attr = AttrBuffer[pixeladdr];
if (!(attr & (1<<15))) continue;
- density = CalculateFogDensity(pixeladdr);
+ density = CalculateFogDensity(gpu3d, pixeladdr);
srccolor = ColorBuffer[pixeladdr];
srcR = srccolor & 0x3F;
@@ -1531,7 +1533,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
}
}
- if (GPU.GPU3D.RenderDispCnt & (1<<4))
+ if (gpu3d.RenderDispCnt & (1<<4))
{
// anti-aliasing
@@ -1584,10 +1586,10 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
}
}
-void SoftRenderer::ClearBuffers()
+void SoftRenderer::ClearBuffers(const GPU& gpu)
{
- u32 clearz = ((GPU.GPU3D.RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
- u32 polyid = GPU.GPU3D.RenderClearAttr1 & 0x3F000000; // this sets the opaque polygonID
+ u32 clearz = ((gpu.GPU3D.RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
+ u32 polyid = gpu.GPU3D.RenderClearAttr1 & 0x3F000000; // this sets the opaque polygonID
// fill screen borders for edge marking
@@ -1617,17 +1619,17 @@ void SoftRenderer::ClearBuffers()
// clear the screen
- if (GPU.GPU3D.RenderDispCnt & (1<<14))
+ if (gpu.GPU3D.RenderDispCnt & (1<<14))
{
- u8 xoff = (GPU.GPU3D.RenderClearAttr2 >> 16) & 0xFF;
- u8 yoff = (GPU.GPU3D.RenderClearAttr2 >> 24) & 0xFF;
+ u8 xoff = (gpu.GPU3D.RenderClearAttr2 >> 16) & 0xFF;
+ u8 yoff = (gpu.GPU3D.RenderClearAttr2 >> 24) & 0xFF;
for (int y = 0; y < ScanlineWidth*192; y+=ScanlineWidth)
{
for (int x = 0; x < 256; x++)
{
- u16 val2 = ReadVRAM_Texture<u16>(0x40000 + (yoff << 9) + (xoff << 1));
- u16 val3 = ReadVRAM_Texture<u16>(0x60000 + (yoff << 9) + (xoff << 1));
+ u16 val2 = ReadVRAM_Texture<u16>(0x40000 + (yoff << 9) + (xoff << 1), gpu);
+ u16 val3 = ReadVRAM_Texture<u16>(0x60000 + (yoff << 9) + (xoff << 1), gpu);
// TODO: confirm color conversion
u32 r = (val2 << 1) & 0x3E; if (r) r++;
@@ -1652,13 +1654,13 @@ void SoftRenderer::ClearBuffers()
else
{
// TODO: confirm color conversion
- u32 r = (GPU.GPU3D.RenderClearAttr1 << 1) & 0x3E; if (r) r++;
- u32 g = (GPU.GPU3D.RenderClearAttr1 >> 4) & 0x3E; if (g) g++;
- u32 b = (GPU.GPU3D.RenderClearAttr1 >> 9) & 0x3E; if (b) b++;
- u32 a = (GPU.GPU3D.RenderClearAttr1 >> 16) & 0x1F;
+ u32 r = (gpu.GPU3D.RenderClearAttr1 << 1) & 0x3E; if (r) r++;
+ u32 g = (gpu.GPU3D.RenderClearAttr1 >> 4) & 0x3E; if (g) g++;
+ u32 b = (gpu.GPU3D.RenderClearAttr1 >> 9) & 0x3E; if (b) b++;
+ u32 a = (gpu.GPU3D.RenderClearAttr1 >> 16) & 0x1F;
u32 color = r | (g << 8) | (b << 16) | (a << 24);
- polyid |= (GPU.GPU3D.RenderClearAttr1 & 0x8000);
+ polyid |= (gpu.GPU3D.RenderClearAttr1 & 0x8000);
for (int y = 0; y < ScanlineWidth*192; y+=ScanlineWidth)
{
@@ -1673,7 +1675,7 @@ void SoftRenderer::ClearBuffers()
}
}
-void SoftRenderer::RenderPolygons(bool threaded, Polygon** polygons, int npolys)
+void SoftRenderer::RenderPolygons(const GPU& gpu, bool threaded, Polygon** polygons, int npolys)
{
int j = 0;
for (int i = 0; i < npolys; i++)
@@ -1682,38 +1684,38 @@ void SoftRenderer::RenderPolygons(bool threaded, Polygon** polygons, int npolys)
SetupPolygon(&PolygonList[j++], polygons[i]);
}
- RenderScanline(0, j);
+ RenderScanline(gpu, 0, j);
for (s32 y = 1; y < 192; y++)
{
- RenderScanline(y, j);
- ScanlineFinalPass(y-1);
+ RenderScanline(gpu, y, j);
+ ScanlineFinalPass(gpu.GPU3D, y-1);
if (threaded)
Platform::Semaphore_Post(Sema_ScanlineCount);
}
- ScanlineFinalPass(191);
+ ScanlineFinalPass(gpu.GPU3D, 191);
if (threaded)
Platform::Semaphore_Post(Sema_ScanlineCount);
}
-void SoftRenderer::VCount144()
+void SoftRenderer::VCount144(GPU& gpu)
{
- if (RenderThreadRunning.load(std::memory_order_relaxed) && !GPU.GPU3D.AbortFrame)
+ if (RenderThreadRunning.load(std::memory_order_relaxed) && !gpu.GPU3D.AbortFrame)
Platform::Semaphore_Wait(Sema_RenderDone);
}
-void SoftRenderer::RenderFrame()
+void SoftRenderer::RenderFrame(GPU& gpu)
{
- auto textureDirty = GPU.VRAMDirty_Texture.DeriveState(GPU.VRAMMap_Texture, GPU);
- auto texPalDirty = GPU.VRAMDirty_TexPal.DeriveState(GPU.VRAMMap_TexPal, GPU);
+ auto textureDirty = gpu.VRAMDirty_Texture.DeriveState(gpu.VRAMMap_Texture, gpu);
+ auto texPalDirty = gpu.VRAMDirty_TexPal.DeriveState(gpu.VRAMMap_TexPal, gpu);
- bool textureChanged = GPU.MakeVRAMFlat_TextureCoherent(textureDirty);
- bool texPalChanged = GPU.MakeVRAMFlat_TexPalCoherent(texPalDirty);
+ bool textureChanged = gpu.MakeVRAMFlat_TextureCoherent(textureDirty);
+ bool texPalChanged = gpu.MakeVRAMFlat_TexPalCoherent(texPalDirty);
- FrameIdentical = !(textureChanged || texPalChanged) && GPU.GPU3D.RenderFrameIdentical;
+ FrameIdentical = !(textureChanged || texPalChanged) && gpu.GPU3D.RenderFrameIdentical;
if (RenderThreadRunning.load(std::memory_order_relaxed))
{
@@ -1721,17 +1723,17 @@ void SoftRenderer::RenderFrame()
}
else if (!FrameIdentical)
{
- ClearBuffers();
- RenderPolygons(false, &GPU.GPU3D.RenderPolygonRAM[0], GPU.GPU3D.RenderNumPolygons);
+ ClearBuffers(gpu);
+ RenderPolygons(gpu, false, &gpu.GPU3D.RenderPolygonRAM[0], gpu.GPU3D.RenderNumPolygons);
}
}
-void SoftRenderer::RestartFrame()
+void SoftRenderer::RestartFrame(GPU& gpu)
{
- SetupRenderThread();
+ SetupRenderThread(gpu);
}
-void SoftRenderer::RenderThreadFunc()
+void SoftRenderer::RenderThreadFunc(GPU& gpu)
{
for (;;)
{
@@ -1745,8 +1747,8 @@ void SoftRenderer::RenderThreadFunc()
}
else
{
- ClearBuffers();
- RenderPolygons(true, &GPU.GPU3D.RenderPolygonRAM[0], GPU.GPU3D.RenderNumPolygons);
+ ClearBuffers(gpu);
+ RenderPolygons(gpu, true, &gpu.GPU3D.RenderPolygonRAM[0], gpu.GPU3D.RenderNumPolygons);
}
Platform::Semaphore_Post(Sema_RenderDone);