rsx: Use a proper struct to wrap around channel remap operations

This commit is contained in:
kd-11 2024-10-03 02:59:42 +03:00 committed by kd-11
parent b1b0ac4433
commit 826f805902
30 changed files with 317 additions and 308 deletions

View file

@ -216,36 +216,6 @@ namespace rsx
bool swizzled;
};
static const std::pair<std::array<u8, 4>, std::array<u8, 4>> default_remap_vector =
{
{ CELL_GCM_TEXTURE_REMAP_FROM_A, CELL_GCM_TEXTURE_REMAP_FROM_R, CELL_GCM_TEXTURE_REMAP_FROM_G, CELL_GCM_TEXTURE_REMAP_FROM_B },
{ CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP, CELL_GCM_TEXTURE_REMAP_REMAP }
};
static inline std::pair<std::array<u8, 4>, std::array<u8, 4>> decode_remap_encoding(u32 remap_ctl)
{
// Remapping tables; format is A-R-G-B
// Remap input table. Contains channel index to read color from
const std::array<u8, 4> remap_inputs =
{
static_cast<u8>(remap_ctl & 0x3),
static_cast<u8>((remap_ctl >> 2) & 0x3),
static_cast<u8>((remap_ctl >> 4) & 0x3),
static_cast<u8>((remap_ctl >> 6) & 0x3),
};
// Remap control table. Controls whether the remap value is used, or force either 0 or 1
const std::array<u8, 4> remap_lookup =
{
static_cast<u8>((remap_ctl >> 8) & 0x3),
static_cast<u8>((remap_ctl >> 10) & 0x3),
static_cast<u8>((remap_ctl >> 12) & 0x3),
static_cast<u8>((remap_ctl >> 14) & 0x3),
};
return std::make_pair(remap_inputs, remap_lookup);
}
template <typename T>
void pad_texture(void* input_pixels, void* output_pixels, u16 input_width, u16 input_height, u16 output_width, u16 /*output_height*/)
{
@ -774,142 +744,6 @@ namespace rsx
return (index + index_base) & 0x000FFFFF;
}
// Convert color write mask for G8B8 to R8G8
static inline u32 get_g8b8_r8g8_clearmask(u32 mask)
{
u32 result = 0;
if (mask & RSX_GCM_CLEAR_GREEN_BIT) result |= RSX_GCM_CLEAR_GREEN_BIT;
if (mask & RSX_GCM_CLEAR_BLUE_BIT) result |= RSX_GCM_CLEAR_RED_BIT;
return result;
}
static inline void get_g8b8_r8g8_colormask(bool &red, bool &/*green*/, bool &blue, bool &alpha)
{
red = blue;
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_clearmask(u32 mask)
{
u32 result = 0;
if (mask & RSX_GCM_CLEAR_RED_BIT) result |= RSX_GCM_CLEAR_BLUE_BIT;
if (mask & RSX_GCM_CLEAR_GREEN_BIT) result |= RSX_GCM_CLEAR_GREEN_BIT;
if (mask & RSX_GCM_CLEAR_BLUE_BIT) result |= RSX_GCM_CLEAR_RED_BIT;
if (mask & RSX_GCM_CLEAR_ALPHA_BIT) result |= RSX_GCM_CLEAR_ALPHA_BIT;
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);
}
template <typename T, typename U>
requires std::is_integral_v<T> && std::is_integral_v<U>
u8 renormalize_color8(T input, U base)
{
// Base will be some POT-1 value
const int value = static_cast<u8>(input & base);
return static_cast<u8>((value * 255) / base);
}
static inline void get_rgb565_clear_color(u8& red, u8& green, u8& blue, u8& /*alpha*/)
{
// RSX clear color is just a memcpy, so in this case the input is ARGB8 so only BG have the 16-bit input
const u16 raw_value = static_cast<u16>(green) << 8 | blue;
blue = renormalize_color8(raw_value, 0x1f);
green = renormalize_color8(raw_value >> 5, 0x3f);
red = renormalize_color8(raw_value >> 11, 0x1f);
}
static inline void get_a1rgb555_clear_color(u8& red, u8& green, u8& blue, u8& alpha, u8 alpha_override)
{
// RSX clear color is just a memcpy, so in this case the input is ARGB8 so only BG have the 16-bit input
const u16 raw_value = static_cast<u16>(green) << 8 | blue;
blue = renormalize_color8(raw_value, 0x1f);
green = renormalize_color8(raw_value >> 5, 0x1f);
red = renormalize_color8(raw_value >> 10, 0x1f);
// Alpha can technically be encoded into the clear but the format normally just injects constants.
// Will require hardware tests when possible to determine which approach makes more sense.
// alpha = static_cast<u8>((raw_value & (1 << 15)) ? 255 : 0);
alpha = alpha_override;
}
static inline u32 get_b8_clearmask(u32 mask)
{
u32 result = 0;
if (mask & RSX_GCM_CLEAR_BLUE_BIT) result |= RSX_GCM_CLEAR_RED_BIT;
return result;
}
static inline void get_b8_colormask(bool& red, bool& green, bool& blue, bool& alpha)
{
red = blue;
green = false;
blue = false;
alpha = false;
}
static inline void get_b8_clear_color(u8& red, u8& /*green*/, u8& blue, u8& /*alpha*/)
{
std::swap(red, blue);
}
static inline color4f decode_border_color(u32 colorref)
{
color4f result;
result.b = (colorref & 0xFF) / 255.f;
result.g = ((colorref >> 8) & 0xFF) / 255.f;
result.r = ((colorref >> 16) & 0xFF) / 255.f;
result.a = ((colorref >> 24) & 0xFF) / 255.f;
return result;
}
static inline const std::array<bool, 4> get_write_output_mask(rsx::surface_color_format format)
{
constexpr std::array<bool, 4> rgba = { true, true, true, true };
constexpr std::array<bool, 4> rgb = { true, true, true, false };
constexpr std::array<bool, 4> rg = { true, true, false, false };
constexpr std::array<bool, 4> r = { true, false, false, false };
switch (format)
{
case rsx::surface_color_format::a8r8g8b8:
case rsx::surface_color_format::a8b8g8r8:
case rsx::surface_color_format::w16z16y16x16:
case rsx::surface_color_format::w32z32y32x32:
return rgba;
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
case rsx::surface_color_format::r5g6b5:
case rsx::surface_color_format::x8r8g8b8_z8r8g8b8:
case rsx::surface_color_format::x8r8g8b8_o8r8g8b8:
case rsx::surface_color_format::x8b8g8r8_z8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_o8b8g8r8:
return rgb;
case rsx::surface_color_format::g8b8:
return rg;
case rsx::surface_color_format::b8:
case rsx::surface_color_format::x32:
return r;
default:
fmt::throw_exception("Unknown surface format 0x%x", static_cast<int>(format));
}
}
template <uint integer, uint frac, bool sign = true, typename To = f32>
static inline To decode_fxp(u32 bits)
{