GPU: Implement fill VRAM command
This commit is contained in:
parent
46870c6a7a
commit
851ef67814
|
@ -79,7 +79,7 @@ void Program::BindDefaultAttributes()
|
|||
BindAttribute(2, "a_color");
|
||||
}
|
||||
|
||||
void Program::BindFragData(GLuint index /*= 0*/, const char* name /*= "ocol0"*/)
|
||||
void Program::BindFragData(GLuint index /*= 0*/, const char* name /*= "o_col0"*/)
|
||||
{
|
||||
glBindFragDataLocation(m_program_id, index, name);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
void BindAttribute(GLuint index, const char* name);
|
||||
void BindDefaultAttributes();
|
||||
|
||||
void BindFragData(GLuint index = 0, const char* name = "ocol0");
|
||||
void BindFragData(GLuint index = 0, const char* name = "o_col0");
|
||||
|
||||
bool Link();
|
||||
|
||||
|
|
|
@ -116,18 +116,18 @@ void main()
|
|||
uniform sampler2D samp0;
|
||||
|
||||
in vec2 v_tex0;
|
||||
out vec4 ocol0;
|
||||
out vec4 o_col0;
|
||||
|
||||
void main()
|
||||
{
|
||||
ocol0 = texture(samp0, v_tex0);
|
||||
o_col0 = texture(samp0, v_tex0);
|
||||
}
|
||||
)";
|
||||
|
||||
if (!m_display_program.Compile(fullscreen_quad_vertex_shader, display_fragment_shader))
|
||||
return false;
|
||||
|
||||
m_display_program.BindFragData();
|
||||
m_display_program.BindFragData(0, "o_col0");
|
||||
if (!m_display_program.Link())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -157,6 +157,13 @@ void GPU::WriteGP0(u32 value)
|
|||
case 0x00: // NOP
|
||||
break;
|
||||
|
||||
case 0x02: // Fill Rectnagle
|
||||
{
|
||||
if (!HandleFillRectangleCommand())
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA0: // Copy Rectangle CPU->VRAM
|
||||
{
|
||||
if (!HandleCopyRectangleCPUToVRAMCommand())
|
||||
|
@ -345,6 +352,25 @@ bool GPU::HandleRenderCommand()
|
|||
ZeroExtend32(words_per_vertex));
|
||||
|
||||
DispatchRenderCommand(rc, num_vertices);
|
||||
UpdateDisplay();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GPU::HandleFillRectangleCommand()
|
||||
{
|
||||
if (m_GP0_command.size() < 3)
|
||||
return false;
|
||||
|
||||
const u32 color = (m_GP0_command[0] & UINT32_C(0x00FFFFFF)) | UINT32_C(0xFF000000);
|
||||
const u32 dst_x = m_GP0_command[1] & UINT32_C(0xFFFF);
|
||||
const u32 dst_y = m_GP0_command[1] >> 16;
|
||||
const u32 width = m_GP0_command[2] & UINT32_C(0xFFFF);
|
||||
const u32 height = m_GP0_command[2] >> 16;
|
||||
|
||||
Log_DebugPrintf("Fill VRAM rectangle offset=(%u,%u), size=(%u,%u)", dst_x, dst_y, width, height);
|
||||
|
||||
FillVRAM(dst_x, dst_y, width, height, color);
|
||||
UpdateDisplay();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -374,6 +400,7 @@ bool GPU::HandleCopyRectangleCPUToVRAMCommand()
|
|||
|
||||
FlushRender();
|
||||
UpdateVRAM(dst_x, dst_y, copy_width, copy_height, &m_GP0_command[3]);
|
||||
UpdateDisplay();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -411,6 +438,8 @@ void GPU::UpdateDisplay()
|
|||
m_system->IncrementFrameNumber();
|
||||
}
|
||||
|
||||
void GPU::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) {}
|
||||
|
||||
void GPU::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) {}
|
||||
|
||||
void GPU::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) {}
|
||||
|
|
|
@ -113,11 +113,13 @@ protected:
|
|||
|
||||
// Rendering commands, returns false if not enough data is provided
|
||||
bool HandleRenderCommand();
|
||||
bool HandleFillRectangleCommand();
|
||||
bool HandleCopyRectangleCPUToVRAMCommand();
|
||||
bool HandleCopyRectangleVRAMToCPUCommand();
|
||||
|
||||
// Rendering in the backend
|
||||
virtual void UpdateDisplay();
|
||||
virtual void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color);
|
||||
virtual void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data);
|
||||
virtual void DispatchRenderCommand(RenderCommand rc, u32 num_vertices);
|
||||
virtual void FlushRender();
|
||||
|
|
|
@ -245,7 +245,7 @@ void main()
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GPU_HW::GenerateTexturePageProgram(TextureColorMode mode)
|
||||
std::string GPU_HW::GenerateTexturePageFragmentShader(TextureColorMode mode)
|
||||
{
|
||||
const bool is_palette = (mode == GPU::TextureColorMode::Palette4Bit || mode == GPU::TextureColorMode::Palette8Bit);
|
||||
|
||||
|
@ -304,6 +304,24 @@ void main()
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GPU_HW::GenerateFillFragmentShader()
|
||||
{
|
||||
std::stringstream ss;
|
||||
GenerateShaderHeader(ss);
|
||||
|
||||
ss << R"(
|
||||
uniform vec4 fill_color;
|
||||
out vec4 o_col0;
|
||||
|
||||
void main()
|
||||
{
|
||||
o_col0 = fill_color;
|
||||
}
|
||||
)";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void GPU_HW::UpdateTexturePageTexture() {}
|
||||
|
||||
void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
|
||||
|
|
|
@ -19,13 +19,21 @@ protected:
|
|||
u16 texcoord;
|
||||
u16 padding;
|
||||
|
||||
static std::tuple<u8, u8> DecodeTexcoord(u16 texcoord)
|
||||
static constexpr 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); }
|
||||
static constexpr u16 EncodeTexcoord(u8 x, u8 y) { return ZeroExtend16(x) | (ZeroExtend16(y) << 8); }
|
||||
};
|
||||
|
||||
static constexpr std::tuple<float, float, float, float> RGBA8ToFloat(u32 rgba)
|
||||
{
|
||||
return std::make_tuple(static_cast<float>(rgba & UINT32_C(0xFF)) * (1.0f / 255.0f),
|
||||
static_cast<float>((rgba >> 16) & UINT32_C(0xFF)) * (1.0f / 255.0f),
|
||||
static_cast<float>((rgba >> 8) & UINT32_C(0xFF)) * (1.0f / 255.0f),
|
||||
static_cast<float>(rgba >> 24) * (1.0f / 255.0f));
|
||||
}
|
||||
|
||||
virtual void UpdateTexturePageTexture();
|
||||
|
||||
bool IsFlushed() const { return !m_batch_vertices.empty(); }
|
||||
|
@ -38,7 +46,8 @@ protected:
|
|||
std::string GenerateVertexShader(bool textured);
|
||||
std::string GenerateFragmentShader(bool textured, bool blending);
|
||||
std::string GenerateScreenQuadVertexShader();
|
||||
std::string GenerateTexturePageProgram(TextureColorMode mode);
|
||||
std::string GenerateTexturePageFragmentShader(TextureColorMode mode);
|
||||
std::string GenerateFillFragmentShader();
|
||||
|
||||
std::vector<HWVertex> m_batch_vertices;
|
||||
RenderCommand m_batch_command = {};
|
||||
|
|
|
@ -110,7 +110,7 @@ bool GPU_HW_OpenGL::CompilePrograms()
|
|||
const std::string screen_quad_vs = GenerateScreenQuadVertexShader();
|
||||
for (u32 palette_size = 0; palette_size < static_cast<u32>(m_texture_page_programs.size()); palette_size++)
|
||||
{
|
||||
const std::string fs = GenerateTexturePageProgram(static_cast<TextureColorMode>(palette_size));
|
||||
const std::string fs = GenerateTexturePageFragmentShader(static_cast<TextureColorMode>(palette_size));
|
||||
|
||||
GL::Program& prog = m_texture_page_programs[palette_size];
|
||||
if (!prog.Compile(screen_quad_vs.c_str(), fs.c_str()))
|
||||
|
@ -199,6 +199,19 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
|||
m_system->GetHostInterface()->SetDisplayTexture(m_framebuffer_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT);
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_fbo_id);
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(x, VRAM_HEIGHT - y - height, width, height);
|
||||
|
||||
const auto [r, g, b, a] = RGBA8ToFloat(color);
|
||||
glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data)
|
||||
{
|
||||
std::vector<u32> rgba_data;
|
||||
|
|
|
@ -18,6 +18,7 @@ public:
|
|||
|
||||
protected:
|
||||
void UpdateDisplay() override;
|
||||
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override;
|
||||
void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data) override;
|
||||
void UpdateTexturePageTexture() override;
|
||||
void FlushRender() override;
|
||||
|
|
Loading…
Reference in New Issue