From fc0560087fde6f517c4141a6fa674ad92fead081 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 14 Jun 2020 01:01:01 +1000 Subject: [PATCH] GPU: Skip primitives where clip area is invalid Fixes palettes being overwritten/menus being broken in Yoshimoto Mahjong Club Deluxe. --- src/core/gpu.h | 3 +++ src/core/gpu_hw.cpp | 12 ++++++++++++ src/core/gpu_sw.cpp | 10 +++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/core/gpu.h b/src/core/gpu.h index c29e04739..6aebc1abc 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -394,6 +394,9 @@ protected: BoolToUInt8(m_render_command.shading_enable); } + /// Returns true if the drawing area is valid (i.e. left <= right, top <= bottom). + ALWAYS_INLINE bool IsDrawingAreaIsValid() const { return m_drawing_area.Valid(); } + void AddCommandTicks(TickCount ticks); void WriteGP1(u32 value); diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index 569e49c45..edbe39b22 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -217,6 +217,9 @@ void GPU_HW::LoadVertices() if (rc.quad_polygon && m_resolution_scale > 1) HandleFlippedQuadTextureCoordinates(vertices.data()); + if (!IsDrawingAreaIsValid()) + return; + // Cull polygons which are too large. const s32 min_x_12 = std::min(vertices[1].x, vertices[2].x); const s32 max_x_12 = std::max(vertices[1].x, vertices[2].x); @@ -328,6 +331,9 @@ void GPU_HW::LoadVertices() // we can split the rectangle up into potentially 8 quads DebugAssert(GetBatchVertexSpace() >= MAX_VERTICES_FOR_RECTANGLE); + if (!IsDrawingAreaIsValid()) + return; + // Split the rectangle into multiple quads if it's greater than 256x256, as the texture page should repeat. u16 tex_top = orig_tex_top; for (s32 y_offset = 0; y_offset < rectangle_height;) @@ -395,6 +401,9 @@ void GPU_HW::LoadVertices() pos1.bits = m_fifo.Pop(); } + if (!IsDrawingAreaIsValid()) + return; + BatchVertex start, end; start.Set(m_drawing_offset.x + pos0.x, m_drawing_offset.y + pos0.y, color0, 0, 0); end.Set(m_drawing_offset.x + pos1.x, m_drawing_offset.y + pos1.y, color1, 0, 0); @@ -428,6 +437,9 @@ void GPU_HW::LoadVertices() const u32 num_vertices = GetPolyLineVertexCount(); DebugAssert(GetBatchVertexSpace() >= (num_vertices * 2)); + if (!IsDrawingAreaIsValid()) + return; + const u32 first_color = rc.color_for_first_vertex; const bool shaded = rc.shading_enable; diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index a129088d8..c058ece3e 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -248,6 +248,9 @@ void GPU_SW::DispatchRenderCommand() } } + if (!IsDrawingAreaIsValid()) + return; + const DrawTriangleFunction DrawFunction = GetDrawTriangleFunction( rc.shading_enable, rc.texture_enable, rc.raw_texture_enable, rc.transparency_enable, dithering_enable); @@ -296,6 +299,9 @@ void GPU_SW::DispatchRenderCommand() break; } + if (!IsDrawingAreaIsValid()) + return; + const DrawRectangleFunction DrawFunction = GetDrawRectangleFunction(rc.texture_enable, rc.raw_texture_enable, rc.transparency_enable); @@ -334,7 +340,9 @@ void GPU_SW::DispatchRenderCommand() p1->SetPosition(VertexPosition{m_fifo.Pop()}); } - (this->*DrawFunction)(p0, p1); + // down here because of the FIFO pops + if (IsDrawingAreaIsValid()) + (this->*DrawFunction)(p0, p1); // swap p0/p1 so that the last vertex is used as the first for the next line std::swap(p0, p1);