diff --git a/src/pse/gpu.cpp b/src/pse/gpu.cpp index 23d28eee7..7a2edc668 100644 --- a/src/pse/gpu.cpp +++ b/src/pse/gpu.cpp @@ -322,7 +322,7 @@ bool GPU::HandleRenderCommand() case Primitive::Rectangle: { words_per_vertex = - 1 + BoolToUInt8(rc.texture_enable) + BoolToUInt8(rc.rectangle_size == DrawRectangleSize::Variable); + 2 + BoolToUInt8(rc.texture_enable) + BoolToUInt8(rc.rectangle_size == DrawRectangleSize::Variable); num_vertices = 1; total_words = words_per_vertex; } diff --git a/src/pse/gpu_hw.cpp b/src/pse/gpu_hw.cpp index eaf602d37..f0b941f00 100644 --- a/src/pse/gpu_hw.cpp +++ b/src/pse/gpu_hw.cpp @@ -8,6 +8,7 @@ GPU_HW::~GPU_HW() = default; void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices) { + // TODO: Move this to the GPU.. switch (rc.primitive) { case Primitive::Polygon: @@ -48,6 +49,53 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices) } break; + case Primitive::Rectangle: + { + u32 buffer_pos = 1; + + const bool textured = rc.texture_enable; + const u32 color = rc.color_for_first_vertex; + const VertexPosition vp{m_GP0_command[buffer_pos++]}; + const s32 pos_left = vp.x(); + const s32 pos_top = vp.y(); + const auto [tex_left, tex_top] = + HWVertex::DecodeTexcoord(rc.texture_enable ? Truncate16(m_GP0_command[buffer_pos++]) : 0); + s32 rectangle_width; + s32 rectangle_height; + switch (rc.rectangle_size) + { + case DrawRectangleSize::R1x1: + rectangle_width = 1; + rectangle_height = 1; + break; + case DrawRectangleSize::R8x8: + rectangle_width = 8; + rectangle_height = 8; + break; + case DrawRectangleSize::R16x16: + rectangle_width = 16; + rectangle_height = 16; + break; + default: + rectangle_width = static_cast(m_GP0_command[buffer_pos] & UINT32_C(0xFFFF)); + rectangle_height = static_cast(m_GP0_command[buffer_pos] >> 16); + break; + } + + // TODO: This should repeat the texcoords instead of stretching + const s32 pos_right = pos_left + (rectangle_width - 1); + const s32 pos_bottom = pos_top + (rectangle_height - 1); + const u8 tex_right = static_cast(tex_left + (rectangle_width - 1)); + const u8 tex_bottom = static_cast(tex_top + (rectangle_height - 1)); + + m_batch_vertices.push_back(HWVertex{pos_left, pos_top, color, HWVertex::EncodeTexcoord(tex_left, tex_top)}); + m_batch_vertices.push_back(HWVertex{pos_right, pos_top, color, HWVertex::EncodeTexcoord(tex_right, tex_top)}); + m_batch_vertices.push_back(HWVertex{pos_left, pos_bottom, color, HWVertex::EncodeTexcoord(tex_left, tex_bottom)}); + m_batch_vertices.push_back( + HWVertex{pos_right, pos_bottom, color, HWVertex::EncodeTexcoord(tex_right, tex_bottom)}); + } + break; + default: UnreachableCode(); break; @@ -272,6 +320,12 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) else m_texture_config.SetFromPolygonTexcoord(m_GP0_command[2], m_GP0_command[4]); } + + case Primitive::Rectangle: + { + m_texture_config.SetFromRectangleTexcoord(m_GP0_command[2]); + m_texture_config.SetFromPageAttribute(Truncate16(m_GPUSTAT.bits)); + } break; default: diff --git a/src/pse/gpu_hw.h b/src/pse/gpu_hw.h index 3a8f96f5b..aa054f4bb 100644 --- a/src/pse/gpu_hw.h +++ b/src/pse/gpu_hw.h @@ -1,7 +1,7 @@ #pragma once #include "gpu.h" -#include #include +#include #include class GPU_HW : public GPU @@ -18,6 +18,12 @@ protected: u32 color; u16 texcoord; u16 padding; + + static std::tuple DecodeTexcoord(u16 texcoord) + { + return std::make_tuple(static_cast(texcoord), static_cast(texcoord >> 8)); + } + static u16 EncodeTexcoord(u8 x, u8 y) { return ZeroExtend16(x) | (ZeroExtend16(y) << 8); } }; virtual void UpdateTexturePageTexture(); @@ -42,4 +48,3 @@ private: void LoadVertices(RenderCommand rc, u32 num_vertices); }; - diff --git a/src/pse/gpu_hw_opengl.cpp b/src/pse/gpu_hw_opengl.cpp index 2aa1d854b..256498564 100644 --- a/src/pse/gpu_hw_opengl.cpp +++ b/src/pse/gpu_hw_opengl.cpp @@ -283,8 +283,9 @@ void GPU_HW_OpenGL::FlushRender() glVertexAttribPointer(2, 2, GL_UNSIGNED_BYTE, true, sizeof(HWVertex), reinterpret_cast(offsetof(HWVertex, texcoord))); - glDrawArrays(m_batch_command.quad_polygon ? GL_TRIANGLE_STRIP : GL_TRIANGLES, 0, - static_cast(m_batch_vertices.size())); + const bool is_strip = ((m_batch_command.primitive == Primitive::Polygon && m_batch_command.quad_polygon) || + m_batch_command.primitive == Primitive::Rectangle); + glDrawArrays(is_strip ? GL_TRIANGLE_STRIP : GL_TRIANGLES, 0, static_cast(m_batch_vertices.size())); m_batch_vertices.clear(); }