diff --git a/src/pse-sdl/sdl_interface.cpp b/src/pse-sdl/sdl_interface.cpp index 45a918861..c846b7f1d 100644 --- a/src/pse-sdl/sdl_interface.cpp +++ b/src/pse-sdl/sdl_interface.cpp @@ -304,6 +304,7 @@ void SDLInterface::RenderDisplay() return; glViewport(0, 0, m_window_width, m_window_height - 20); + glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); diff --git a/src/pse/gpu.cpp b/src/pse/gpu.cpp index 4d89e420e..313c352bc 100644 --- a/src/pse/gpu.cpp +++ b/src/pse/gpu.cpp @@ -388,7 +388,6 @@ void GPU::WriteGP0(u32 value) m_GPUSTAT.texture_disable = (param & (UINT32_C(1) << 11)) != 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.SetColorMode(m_GPUSTAT.texture_color_mode); Log_DebugPrintf("Set draw mode %08X", param); } break; @@ -749,18 +748,6 @@ void GPU::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) {} 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) { SetFromPaletteAttribute(Truncate16(texcoord0 >> 16)); @@ -778,11 +765,16 @@ void GPU::TextureConfig::SetFromPageAttribute(u16 value) if (page_attribute == value) return; - base_x = static_cast(ZeroExtend32(value & UINT16_C(0x0F)) * UINT32_C(64)); - base_y = static_cast(ZeroExtend32((value >> 11) & UINT16_C(1)) * UINT32_C(512)); - SetColorMode(static_cast((value >> 7) & UINT16_C(0x03))); page_attribute = value; page_changed = true; + + base_x = static_cast(ZeroExtend32(value & UINT16_C(0x0F)) * UINT32_C(64)); + base_y = static_cast(ZeroExtend32((value >> 11) & UINT16_C(1)) * UINT32_C(512)); + color_mode = (static_cast((value >> 7) & UINT16_C(0x03))); + if (color_mode == TextureColorMode::Reserved_Direct16Bit) + color_mode = TextureColorMode::Direct16Bit; + + transparency_mode = (static_cast((value >> 5) & UINT16_C(0x03))); } void GPU::TextureConfig::SetFromPaletteAttribute(u16 value) diff --git a/src/pse/gpu.h b/src/pse/gpu.h index 78335516f..d2fd020f2 100644 --- a/src/pse/gpu.h +++ b/src/pse/gpu.h @@ -110,6 +110,14 @@ protected: Reserved_Direct16Bit = 3 }; + enum class TransparencyMode : u8 + { + HalfBackgroundPlusHalfForeground = 0, + BackgroundPlusForeground = 1, + BackgroundMinusForeground = 2, + BackgroundPlusQuarterForeground = 3 + }; + union RenderCommand { u32 bits; @@ -127,6 +135,7 @@ protected: // Helper functions. bool IsTextureEnabled() const { return (primitive != Primitive::Line && texture_enable); } bool IsTextureBlendingEnabled() const { return (IsTextureEnabled() && !texture_blend_disable); } + bool IsTransparencyEnabled() const { return transparency_enable; } }; // TODO: Use BitField to do sign extending instead @@ -181,7 +190,7 @@ protected: u32 bits; BitField texture_page_x_base; BitField texture_page_y_base; - BitField semi_transparency; + BitField semi_transparency_mode; BitField texture_color_mode; BitField dither_enable; BitField draw_to_display_area; @@ -221,14 +230,13 @@ protected: u16 page_attribute; // from register in rectangle modes/vertex in polygon modes u16 palette_attribute; // from vertex TextureColorMode color_mode; // from register/vertex in polygon modes + TransparencyMode transparency_mode; bool page_changed = false; bool IsPageChanged() const { return page_changed; } void ClearPageChangedFlag() { page_changed = false; } - void SetColorMode(TextureColorMode new_color_mode); - void SetFromPolygonTexcoord(u32 texcoord0, u32 texcoord1); void SetFromRectangleTexcoord(u32 texcoord); diff --git a/src/pse/gpu_hw_opengl.cpp b/src/pse/gpu_hw_opengl.cpp index 3e11c8aa3..0d3b20887 100644 --- a/src/pse/gpu_hw_opengl.cpp +++ b/src/pse/gpu_hw_opengl.cpp @@ -191,6 +191,36 @@ void GPU_HW_OpenGL::SetScissor() 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 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(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() { GPU_HW::UpdateDisplay(); @@ -322,6 +352,7 @@ void GPU_HW_OpenGL::FlushRender() SetProgram(m_batch_command.IsTextureEnabled(), m_batch_command.IsTextureBlendingEnabled()); SetViewport(); SetScissor(); + SetBlendState(); glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_fbo_id); glBindVertexArray(m_vao_id); diff --git a/src/pse/gpu_hw_opengl.h b/src/pse/gpu_hw_opengl.h index fba9a28ae..503c068ba 100644 --- a/src/pse/gpu_hw_opengl.h +++ b/src/pse/gpu_hw_opengl.h @@ -40,6 +40,7 @@ private: void SetProgram(bool textured, bool blending); void SetViewport(); void SetScissor(); + void SetBlendState(); std::unique_ptr m_framebuffer_texture; GLuint m_framebuffer_fbo_id = 0;