From 3aa4219067e71a28407983837d6469ab0c51b9e6 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 1 Nov 2019 23:11:37 +1000 Subject: [PATCH] GPU: Implement dithering on software backend --- src/core/gpu.h | 9 +++++++++ src/core/gpu_sw.cpp | 23 +++++++++++++++-------- src/core/gpu_sw.h | 2 +- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/core/gpu.h b/src/core/gpu.h index 9c7fa158a..9b8f8b180 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -243,6 +243,15 @@ protected: (static_cast(c_) << 15); } + void SetRGB24Dithered(u32 x, u32 y, u8 r8, u8 g8, u8 b8, bool c_ = false) + { + const s32 offset = DITHER_MATRIX[y & 3][x & 3]; + r8 = static_cast(std::clamp(static_cast(ZeroExtend32(r8)) + offset, 0, 255)); + g8 = static_cast(std::clamp(static_cast(ZeroExtend32(g8)) + offset, 0, 255)); + b8 = static_cast(std::clamp(static_cast(ZeroExtend32(b8)) + offset, 0, 255)); + SetRGB24(r8, g8, b8, c_); + } + u32 ToRGB24() const { const u32 r_ = ZeroExtend32(r.GetValue()); diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index d85ce6762..1cd2e3bcf 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -357,7 +357,8 @@ void GPU_SW::DrawTriangle(RenderCommand rc, const SWVertex* v0, const SWVertex* const u8 texcoord_x = Interpolate(v0->texcoord_x, v1->texcoord_x, v2->texcoord_x, b0, b1, b2, ws); const u8 texcoord_y = Interpolate(v0->texcoord_y, v1->texcoord_y, v2->texcoord_y, b0, b1, b2, ws); - ShadePixel(rc, static_cast(x), static_cast(y), r, g, b, texcoord_x, texcoord_y); + ShadePixel(rc, static_cast(x), static_cast(y), r, g, b, texcoord_x, texcoord_y, + rc.IsDitheringEnabled() && m_GPUSTAT.dither_enable); } row_w0 += a12; @@ -395,13 +396,13 @@ void GPU_SW::DrawRectangle(RenderCommand rc, s32 origin_x, s32 origin_y, u32 wid const u8 texcoord_x = Truncate8(ZeroExtend32(origin_texcoord_x) + offset_x); - ShadePixel(rc, static_cast(x), static_cast(y), r, g, b, texcoord_x, texcoord_y); + ShadePixel(rc, static_cast(x), static_cast(y), r, g, b, texcoord_x, texcoord_y, false); } } } void GPU_SW::ShadePixel(RenderCommand rc, u32 x, u32 y, u8 color_r, u8 color_g, u8 color_b, u8 texcoord_x, - u8 texcoord_y) + u8 texcoord_y, bool dithering) { VRAMPixel color; bool transparent = true; @@ -461,15 +462,21 @@ void GPU_SW::ShadePixel(RenderCommand rc, u32 x, u32 y, u8 color_r, u8 color_g, } else { - color.SetRGB24( - Truncate8(std::min((ZeroExtend16(texture_color.GetR8()) * ZeroExtend16(color_r)) >> 7, 0xFF)), - Truncate8(std::min((ZeroExtend16(texture_color.GetG8()) * ZeroExtend16(color_g)) >> 7, 0xFF)), - Truncate8(std::min((ZeroExtend16(texture_color.GetB8()) * ZeroExtend16(color_b)) >> 7, 0xFF))); + const u8 r = Truncate8(std::min((ZeroExtend16(texture_color.GetR8()) * ZeroExtend16(color_r)) >> 7, 0xFF)); + const u8 g = Truncate8(std::min((ZeroExtend16(texture_color.GetG8()) * ZeroExtend16(color_g)) >> 7, 0xFF)); + const u8 b = Truncate8(std::min((ZeroExtend16(texture_color.GetB8()) * ZeroExtend16(color_b)) >> 7, 0xFF)); + if (dithering) + color.SetRGB24Dithered(x, y, r, g, b); + else + color.SetRGB24(r, g, b); } } else { - color.SetRGB24(color_r, color_g, color_b); + if (dithering) + color.SetRGB24Dithered(x, y, color_r, color_g, color_b); + else + color.SetRGB24(color_r, color_g, color_b); } if (rc.transparency_enable && transparent) diff --git a/src/core/gpu_sw.h b/src/core/gpu_sw.h index 2a164d29e..0275cc740 100644 --- a/src/core/gpu_sw.h +++ b/src/core/gpu_sw.h @@ -58,7 +58,7 @@ protected: static bool IsClockwiseWinding(const SWVertex* v0, const SWVertex* v1, const SWVertex* v2); - void ShadePixel(RenderCommand rc, u32 x, u32 y, u8 color_r, u8 color_g, u8 color_b, u8 texcoord_x, u8 texcoord_y); + void ShadePixel(RenderCommand rc, u32 x, u32 y, u8 color_r, u8 color_g, u8 color_b, u8 texcoord_x, u8 texcoord_y, bool dithering); void DrawTriangle(RenderCommand rc, const SWVertex* v0, const SWVertex* v1, const SWVertex* v2); void DrawRectangle(RenderCommand rc, s32 origin_x, s32 origin_y, u32 width, u32 height, u8 r, u8 g, u8 b, u8 origin_texcoord_x, u8 origin_texcoord_y);