GL: Eliminiate most redundant state setting calls at draw time
This commit is contained in:
@ -26,6 +26,7 @@ bool GPU_HW_OpenGL::Initialize(System* system, DMA* dma, InterruptController* in
|
||||
return false;
|
||||
|
||||
m_system->GetHostInterface()->SetDisplayTexture(m_display_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT, 1.0f);
|
||||
RestoreGraphicsAPIState();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -36,6 +37,37 @@ void GPU_HW_OpenGL::Reset()
|
||||
ClearFramebuffer();
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::ResetGraphicsAPIState()
|
||||
{
|
||||
GPU_HW::ResetGraphicsAPIState();
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_TRUE);
|
||||
glLineWidth(1.0f);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::RestoreGraphicsAPIState()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_vram_fbo);
|
||||
glViewport(0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight());
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
glLineWidth(static_cast<float>(m_resolution_scale));
|
||||
UpdateDrawingArea();
|
||||
|
||||
m_last_transparency_enable = false;
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
|
||||
glBindVertexArray(m_vao_id);
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::RenderStatistics()
|
||||
{
|
||||
GPU_HW::RenderStatistics();
|
||||
@ -156,6 +188,7 @@ void GPU_HW_OpenGL::CreateFramebuffer()
|
||||
linear_filter ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
glDeleteFramebuffers(1, &old_vram_fbo);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
old_vram_texture.reset();
|
||||
}
|
||||
|
||||
@ -187,15 +220,16 @@ void GPU_HW_OpenGL::CreateFramebuffer()
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_display_fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_display_texture->GetGLId(), 0);
|
||||
Assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_vram_fbo);
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::ClearFramebuffer()
|
||||
{
|
||||
// TODO: get rid of the FBO switches
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_vram_fbo);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
m_vram_read_texture_dirty = true;
|
||||
}
|
||||
|
||||
@ -305,7 +339,7 @@ bool GPU_HW_OpenGL::CompileProgram(GL::Program& prog, bool textured, bool blendi
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::SetProgram()
|
||||
void GPU_HW_OpenGL::SetDrawState()
|
||||
{
|
||||
const GL::Program& prog =
|
||||
m_render_programs[BoolToUInt32(m_batch.texture_enable)][BoolToUInt32(m_batch.texture_blending_enable)]
|
||||
@ -326,14 +360,30 @@ void GPU_HW_OpenGL::SetProgram()
|
||||
|
||||
if (m_batch.texture_enable)
|
||||
m_vram_read_texture->Bind();
|
||||
|
||||
if (m_last_transparency_enable != m_batch.transparency_enable ||
|
||||
(!m_last_transparency_enable && m_last_transparency_mode != m_batch.transparency_mode))
|
||||
{
|
||||
m_last_transparency_enable = m_batch.texture_enable;
|
||||
m_last_transparency_mode = m_batch.transparency_mode;
|
||||
|
||||
if (!m_batch.transparency_enable)
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
else
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquationSeparate(m_batch.transparency_mode == GPU::TransparencyMode::BackgroundMinusForeground ?
|
||||
GL_FUNC_REVERSE_SUBTRACT :
|
||||
GL_FUNC_ADD,
|
||||
GL_FUNC_ADD);
|
||||
glBlendFuncSeparate(GL_ONE, GL_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::SetViewport()
|
||||
{
|
||||
glViewport(0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight());
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::SetScissor()
|
||||
void GPU_HW_OpenGL::UpdateDrawingArea()
|
||||
{
|
||||
int left, top, right, bottom;
|
||||
CalcScissorRect(&left, &top, &right, &bottom);
|
||||
@ -347,22 +397,6 @@ void GPU_HW_OpenGL::SetScissor()
|
||||
glScissor(x, y, width, height);
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::SetBlendState()
|
||||
{
|
||||
if (!m_batch.transparency_enable)
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
return;
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquationSeparate(m_batch.transparency_mode == GPU::TransparencyMode::BackgroundMinusForeground ?
|
||||
GL_FUNC_REVERSE_SUBTRACT :
|
||||
GL_FUNC_ADD,
|
||||
GL_FUNC_ADD);
|
||||
glBlendFuncSeparate(GL_ONE, GL_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::UpdateDisplay()
|
||||
{
|
||||
GPU_HW::UpdateDisplay();
|
||||
@ -415,7 +449,9 @@ void GPU_HW_OpenGL::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer)
|
||||
glBlitFramebuffer(scaled_x, texture_height - scaled_y - height, scaled_x + scaled_width, scaled_y + scaled_height,
|
||||
0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_vram_downsample_fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_vram_fbo);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_buffer.data());
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -457,8 +493,6 @@ void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u16 color)
|
||||
width *= m_resolution_scale;
|
||||
height *= m_resolution_scale;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_vram_fbo);
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(x, m_vram_texture->GetHeight() - y - height, width, height);
|
||||
|
||||
@ -466,6 +500,7 @@ void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u16 color)
|
||||
glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
UpdateDrawingArea();
|
||||
InvalidateVRAMReadCache();
|
||||
}
|
||||
|
||||
@ -517,9 +552,9 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void*
|
||||
const u32 scaled_flipped_y = m_vram_texture->GetHeight() - scaled_y - scaled_height;
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_vram_downsample_fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_vram_fbo);
|
||||
glBlitFramebuffer(x, flipped_y, x + width, flipped_y + height, scaled_x, scaled_flipped_y, scaled_x + scaled_width,
|
||||
scaled_flipped_y + scaled_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
@ -540,6 +575,7 @@ void GPU_HW_OpenGL::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 wid
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_vram_fbo);
|
||||
glBlitFramebuffer(src_x, src_y, src_x + width, src_y + height, dst_x, dst_y, dst_x + width, dst_y + height,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
InvalidateVRAMReadCache();
|
||||
}
|
||||
@ -565,21 +601,9 @@ void GPU_HW_OpenGL::FlushRender()
|
||||
m_stats.num_batches++;
|
||||
m_stats.num_vertices += static_cast<u32>(m_batch.vertices.size());
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
glLineWidth(static_cast<float>(m_resolution_scale));
|
||||
SetProgram();
|
||||
SetViewport();
|
||||
SetScissor();
|
||||
SetBlendState();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_vram_fbo);
|
||||
glBindVertexArray(m_vao_id);
|
||||
SetDrawState();
|
||||
|
||||
Assert((m_batch.vertices.size() * sizeof(HWVertex)) <= VERTEX_BUFFER_SIZE);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, static_cast<GLsizei>(sizeof(HWVertex) * m_batch.vertices.size()),
|
||||
m_batch.vertices.data());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user