GPU: Implement basic rectangle rendering

This commit is contained in:
Connor McLaughlin 2019-09-14 16:27:24 +10:00
parent f47d44c151
commit 46870c6a7a
4 changed files with 65 additions and 5 deletions

View file

@ -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;
}

View file

@ -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<s32>(m_GP0_command[buffer_pos] & UINT32_C(0xFFFF));
rectangle_height = static_cast<s32>(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<u8>(tex_left + (rectangle_width - 1));
const u8 tex_bottom = static_cast<u8>(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:

View file

@ -1,7 +1,7 @@
#pragma once
#include "gpu.h"
#include <string>
#include <sstream>
#include <string>
#include <vector>
class GPU_HW : public GPU
@ -18,6 +18,12 @@ protected:
u32 color;
u16 texcoord;
u16 padding;
static std::tuple<u8, u8> DecodeTexcoord(u16 texcoord)
{
return std::make_tuple(static_cast<u8>(texcoord), static_cast<u8>(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);
};

View file

@ -283,8 +283,9 @@ void GPU_HW_OpenGL::FlushRender()
glVertexAttribPointer(2, 2, GL_UNSIGNED_BYTE, true, sizeof(HWVertex),
reinterpret_cast<void*>(offsetof(HWVertex, texcoord)));
glDrawArrays(m_batch_command.quad_polygon ? GL_TRIANGLE_STRIP : GL_TRIANGLES, 0,
static_cast<GLsizei>(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<GLsizei>(m_batch_vertices.size()));
m_batch_vertices.clear();
}