From 7f917c8ba55050c63be1541ee11b360b88ab8feb Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 22 Jun 2020 19:13:11 +0300 Subject: [PATCH] rsx: Fix ABGR decoding for colormask and clear color - The bytes in these values are based on the format according to hw tests - G8B8 is unaffected as the first two bytes are already G8B8 for A8R8G8B8 standard layout (BGRA) - A8B8G8R8 and its derivatives have words 0 and 2 exchanged. --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 25 +++++++++++++++++-------- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 32 ++++++++++++++++++++++---------- rpcs3/Emu/RSX/rsx_utils.h | 28 ++++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index a7f4ac1b2d..79e0f349bd 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -568,6 +568,11 @@ void GLGSRender::clear_surface(u32 arg) if (auto colormask = (arg & 0xf0)) { + u8 clear_a = rsx::method_registers.clear_color_a(); + u8 clear_r = rsx::method_registers.clear_color_r(); + u8 clear_g = rsx::method_registers.clear_color_g(); + u8 clear_b = rsx::method_registers.clear_color_b(); + switch (rsx::method_registers.surface_color()) { case rsx::surface_color_format::x32: @@ -579,16 +584,22 @@ void GLGSRender::clear_surface(u32 arg) } case rsx::surface_color_format::g8b8: { + rsx::get_g8b8_clear_color(clear_r, clear_g, clear_b, clear_a); colormask = rsx::get_g8b8_r8g8_colormask(colormask); - [[fallthrough]]; + break; } - default: + case rsx::surface_color_format::a8b8g8r8: + case rsx::surface_color_format::x8b8g8r8_o8b8g8r8: + case rsx::surface_color_format::x8b8g8r8_z8b8g8r8: { - u8 clear_a = rsx::method_registers.clear_color_a(); - u8 clear_r = rsx::method_registers.clear_color_r(); - u8 clear_g = rsx::method_registers.clear_color_g(); - u8 clear_b = rsx::method_registers.clear_color_b(); + rsx::get_abgr8_clear_color(clear_r, clear_g, clear_b, clear_a); + colormask = rsx::get_abgr8_colormask(colormask); + break; + } + } + if (colormask) + { gl_state.clear_color(clear_r, clear_g, clear_b, clear_a); mask |= GLenum(gl::buffers::color); @@ -601,8 +612,6 @@ void GLGSRender::clear_surface(u32 arg) } update_color = true; - break; - } } } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index ca4e84fc7c..f78ece4875 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1130,33 +1130,45 @@ void VKGSRender::clear_surface(u32 mask) if (!m_draw_buffers.empty()) { bool use_fast_clear = false; - bool ignore_clear = false; + u8 clear_a = rsx::method_registers.clear_color_a(); + u8 clear_r = rsx::method_registers.clear_color_r(); + u8 clear_g = rsx::method_registers.clear_color_g(); + u8 clear_b = rsx::method_registers.clear_color_b(); + switch (rsx::method_registers.surface_color()) { case rsx::surface_color_format::x32: case rsx::surface_color_format::w16z16y16x16: case rsx::surface_color_format::w32z32y32x32: + { //NOP - ignore_clear = true; + colormask = 0; break; + } case rsx::surface_color_format::g8b8: + { + rsx::get_g8b8_clear_color(clear_r, clear_g, clear_b, clear_a); colormask = rsx::get_g8b8_r8g8_colormask(colormask); use_fast_clear = (colormask == (0x10 | 0x20)); - ignore_clear = (colormask == 0); - colormask |= (0x40 | 0x80); break; + } + case rsx::surface_color_format::a8b8g8r8: + case rsx::surface_color_format::x8b8g8r8_o8b8g8r8: + case rsx::surface_color_format::x8b8g8r8_z8b8g8r8: + { + rsx::get_abgr8_clear_color(clear_r, clear_g, clear_b, clear_a); + colormask = rsx::get_abgr8_colormask(colormask); + break; + } default: + { use_fast_clear = (colormask == (0x10 | 0x20 | 0x40 | 0x80)); break; } + } - if (!ignore_clear) + if (colormask) { - u8 clear_a = rsx::method_registers.clear_color_a(); - u8 clear_r = rsx::method_registers.clear_color_r(); - u8 clear_g = rsx::method_registers.clear_color_g(); - u8 clear_b = rsx::method_registers.clear_color_b(); - color_clear_values.color.float32[0] = static_cast(clear_r) / 255; color_clear_values.color.float32[1] = static_cast(clear_g) / 255; color_clear_values.color.float32[2] = static_cast(clear_b) / 255; diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index c3c8bea18f..6ee52250c0 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -737,14 +737,38 @@ namespace rsx return result; } - static inline void get_g8b8_r8g8_colormask(bool &red, bool &green, bool &blue, bool &alpha) + static inline void get_g8b8_r8g8_colormask(bool &red, bool &/*green*/, bool &blue, bool &alpha) { red = blue; - green = green; blue = false; alpha = false; } + static inline void get_g8b8_clear_color(u8& red, u8& /*green*/, u8& blue, u8& /*alpha*/) + { + red = blue; + } + + static inline u32 get_abgr8_colormask(u32 mask) + { + u32 result = 0; + if (mask & 0x10) result |= 0x40; + if (mask & 0x20) result |= 0x20; + if (mask & 0x40) result |= 0x10; + if (mask & 0x80) result |= 0x80; + return result; + } + + static inline void get_abgr8_colormask(bool& red, bool& /*green*/, bool& blue, bool& /*alpha*/) + { + std::swap(red, blue); + } + + static inline void get_abgr8_clear_color(u8& red, u8& /*green*/, u8& blue, u8& /*alpha*/) + { + std::swap(red, blue); + } + static inline color4f decode_border_color(u32 colorref) { color4f result;