GPU: Implement transparency mode

This commit is contained in:
Connor McLaughlin 2019-09-19 00:55:06 +10:00
parent 23ef1cafbd
commit d84bffead1
5 changed files with 52 additions and 19 deletions

View file

@ -304,6 +304,7 @@ void SDLInterface::RenderDisplay()
return; return;
glViewport(0, 0, m_window_width, m_window_height - 20); glViewport(0, 0, m_window_width, m_window_height - 20);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);

View file

@ -388,7 +388,6 @@ void GPU::WriteGP0(u32 value)
m_GPUSTAT.texture_disable = (param & (UINT32_C(1) << 11)) != 0; m_GPUSTAT.texture_disable = (param & (UINT32_C(1) << 11)) != 0;
m_texture_config.x_flip = (param & (UINT32_C(1) << 12)) != 0; m_texture_config.x_flip = (param & (UINT32_C(1) << 12)) != 0;
m_texture_config.y_flip = (param & (UINT32_C(1) << 13)) != 0; m_texture_config.y_flip = (param & (UINT32_C(1) << 13)) != 0;
m_texture_config.SetColorMode(m_GPUSTAT.texture_color_mode);
Log_DebugPrintf("Set draw mode %08X", param); Log_DebugPrintf("Set draw mode %08X", param);
} }
break; break;
@ -749,18 +748,6 @@ void GPU::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) {}
void GPU::FlushRender() {} void GPU::FlushRender() {}
void GPU::TextureConfig::SetColorMode(TextureColorMode new_color_mode)
{
if (new_color_mode == TextureColorMode::Reserved_Direct16Bit)
new_color_mode = TextureColorMode::Direct16Bit;
if (color_mode == new_color_mode)
return;
color_mode = new_color_mode;
page_changed = true;
}
void GPU::TextureConfig::SetFromPolygonTexcoord(u32 texcoord0, u32 texcoord1) void GPU::TextureConfig::SetFromPolygonTexcoord(u32 texcoord0, u32 texcoord1)
{ {
SetFromPaletteAttribute(Truncate16(texcoord0 >> 16)); SetFromPaletteAttribute(Truncate16(texcoord0 >> 16));
@ -778,11 +765,16 @@ void GPU::TextureConfig::SetFromPageAttribute(u16 value)
if (page_attribute == value) if (page_attribute == value)
return; return;
base_x = static_cast<s32>(ZeroExtend32(value & UINT16_C(0x0F)) * UINT32_C(64));
base_y = static_cast<s32>(ZeroExtend32((value >> 11) & UINT16_C(1)) * UINT32_C(512));
SetColorMode(static_cast<TextureColorMode>((value >> 7) & UINT16_C(0x03)));
page_attribute = value; page_attribute = value;
page_changed = true; page_changed = true;
base_x = static_cast<s32>(ZeroExtend32(value & UINT16_C(0x0F)) * UINT32_C(64));
base_y = static_cast<s32>(ZeroExtend32((value >> 11) & UINT16_C(1)) * UINT32_C(512));
color_mode = (static_cast<TextureColorMode>((value >> 7) & UINT16_C(0x03)));
if (color_mode == TextureColorMode::Reserved_Direct16Bit)
color_mode = TextureColorMode::Direct16Bit;
transparency_mode = (static_cast<TransparencyMode>((value >> 5) & UINT16_C(0x03)));
} }
void GPU::TextureConfig::SetFromPaletteAttribute(u16 value) void GPU::TextureConfig::SetFromPaletteAttribute(u16 value)

View file

@ -110,6 +110,14 @@ protected:
Reserved_Direct16Bit = 3 Reserved_Direct16Bit = 3
}; };
enum class TransparencyMode : u8
{
HalfBackgroundPlusHalfForeground = 0,
BackgroundPlusForeground = 1,
BackgroundMinusForeground = 2,
BackgroundPlusQuarterForeground = 3
};
union RenderCommand union RenderCommand
{ {
u32 bits; u32 bits;
@ -127,6 +135,7 @@ protected:
// Helper functions. // Helper functions.
bool IsTextureEnabled() const { return (primitive != Primitive::Line && texture_enable); } bool IsTextureEnabled() const { return (primitive != Primitive::Line && texture_enable); }
bool IsTextureBlendingEnabled() const { return (IsTextureEnabled() && !texture_blend_disable); } bool IsTextureBlendingEnabled() const { return (IsTextureEnabled() && !texture_blend_disable); }
bool IsTransparencyEnabled() const { return transparency_enable; }
}; };
// TODO: Use BitField to do sign extending instead // TODO: Use BitField to do sign extending instead
@ -181,7 +190,7 @@ protected:
u32 bits; u32 bits;
BitField<u32, u8, 0, 4> texture_page_x_base; BitField<u32, u8, 0, 4> texture_page_x_base;
BitField<u32, u8, 4, 1> texture_page_y_base; BitField<u32, u8, 4, 1> texture_page_y_base;
BitField<u32, u8, 5, 2> semi_transparency; BitField<u32, TransparencyMode, 5, 2> semi_transparency_mode;
BitField<u32, TextureColorMode, 7, 2> texture_color_mode; BitField<u32, TextureColorMode, 7, 2> texture_color_mode;
BitField<u32, bool, 9, 1> dither_enable; BitField<u32, bool, 9, 1> dither_enable;
BitField<u32, bool, 10, 1> draw_to_display_area; BitField<u32, bool, 10, 1> draw_to_display_area;
@ -221,14 +230,13 @@ protected:
u16 page_attribute; // from register in rectangle modes/vertex in polygon modes u16 page_attribute; // from register in rectangle modes/vertex in polygon modes
u16 palette_attribute; // from vertex u16 palette_attribute; // from vertex
TextureColorMode color_mode; // from register/vertex in polygon modes TextureColorMode color_mode; // from register/vertex in polygon modes
TransparencyMode transparency_mode;
bool page_changed = false; bool page_changed = false;
bool IsPageChanged() const { return page_changed; } bool IsPageChanged() const { return page_changed; }
void ClearPageChangedFlag() { page_changed = false; } void ClearPageChangedFlag() { page_changed = false; }
void SetColorMode(TextureColorMode new_color_mode);
void SetFromPolygonTexcoord(u32 texcoord0, u32 texcoord1); void SetFromPolygonTexcoord(u32 texcoord0, u32 texcoord1);
void SetFromRectangleTexcoord(u32 texcoord); void SetFromRectangleTexcoord(u32 texcoord);

View file

@ -191,6 +191,36 @@ void GPU_HW_OpenGL::SetScissor()
glScissor(x, y, width, height); glScissor(x, y, width, height);
} }
void GPU_HW_OpenGL::SetBlendState()
{
struct BlendVars
{
GLenum src_factor;
GLenum func;
GLenum dst_factor;
float color;
};
static const std::array<BlendVars, 4> blend_vars = {{
{GL_CONSTANT_COLOR, GL_FUNC_ADD, GL_CONSTANT_COLOR, 0.5f}, // B/2 + F/2
{GL_ONE, GL_FUNC_ADD, GL_ONE, -1.0f}, // B + F
{GL_ONE, GL_FUNC_REVERSE_SUBTRACT, GL_ONE, -1.0f}, // B - F
{GL_CONSTANT_COLOR, GL_FUNC_ADD, GL_ONE, 0.25f} // B + F/4
}};
if (!m_batch_command.IsTransparencyEnabled())
{
glDisable(GL_BLEND);
return;
}
const BlendVars& vars = blend_vars[static_cast<u8>(m_texture_config.transparency_mode)];
glEnable(GL_BLEND);
glBlendFuncSeparate(vars.src_factor, vars.dst_factor, GL_ONE, GL_ZERO);
glBlendEquationSeparate(vars.func, GL_FUNC_ADD);
if (vars.color >= 0.0f)
glBlendColor(vars.color, vars.color, vars.color, 1.0f);
}
void GPU_HW_OpenGL::UpdateDisplay() void GPU_HW_OpenGL::UpdateDisplay()
{ {
GPU_HW::UpdateDisplay(); GPU_HW::UpdateDisplay();
@ -322,6 +352,7 @@ void GPU_HW_OpenGL::FlushRender()
SetProgram(m_batch_command.IsTextureEnabled(), m_batch_command.IsTextureBlendingEnabled()); SetProgram(m_batch_command.IsTextureEnabled(), m_batch_command.IsTextureBlendingEnabled());
SetViewport(); SetViewport();
SetScissor(); SetScissor();
SetBlendState();
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_fbo_id); glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_fbo_id);
glBindVertexArray(m_vao_id); glBindVertexArray(m_vao_id);

View file

@ -40,6 +40,7 @@ private:
void SetProgram(bool textured, bool blending); void SetProgram(bool textured, bool blending);
void SetViewport(); void SetViewport();
void SetScissor(); void SetScissor();
void SetBlendState();
std::unique_ptr<GL::Texture> m_framebuffer_texture; std::unique_ptr<GL::Texture> m_framebuffer_texture;
GLuint m_framebuffer_fbo_id = 0; GLuint m_framebuffer_fbo_id = 0;