GPU: Fix VRAM palette changes not being detected in hw renderer

Fixes wall texture animation in Mega Man Legends.
This commit is contained in:
Connor McLaughlin 2020-11-22 13:22:20 +10:00
parent b49067d165
commit e06f85a328
3 changed files with 38 additions and 39 deletions

View file

@ -358,30 +358,30 @@ protected:
BitField<u32, DMADirection, 29, 2> dma_direction;
BitField<u32, bool, 31, 1> display_line_lsb;
bool IsMaskingEnabled() const
ALWAYS_INLINE bool IsMaskingEnabled() const
{
static constexpr u32 MASK = ((1 << 11) | (1 << 12));
return ((bits & MASK) != 0);
}
bool SkipDrawingToActiveField() const
ALWAYS_INLINE bool SkipDrawingToActiveField() const
{
static constexpr u32 MASK = (1 << 19) | (1 << 22) | (1 << 10);
static constexpr u32 ACTIVE = (1 << 19) | (1 << 22);
return ((bits & MASK) == ACTIVE);
}
bool InInterleaved480iMode() const
ALWAYS_INLINE bool InInterleaved480iMode() const
{
static constexpr u32 ACTIVE = (1 << 19) | (1 << 22);
return ((bits & ACTIVE) == ACTIVE);
}
// During transfer/render operations, if ((dst_pixel & mask_and) == 0) { pixel = src_pixel | mask_or }
u16 GetMaskAND() const
ALWAYS_INLINE u16 GetMaskAND() const
{
// return check_mask_before_draw ? 0x8000 : 0x0000;
return Truncate16((bits << 3) & 0x8000);
}
u16 GetMaskOR() const
ALWAYS_INLINE u16 GetMaskOR() const
{
// return set_mask_while_drawing ? 0x8000 : 0x0000;
return Truncate16((bits << 4) & 0x8000);
@ -409,13 +409,21 @@ protected:
bool texture_page_changed;
bool texture_window_changed;
bool IsTexturePageChanged() const { return texture_page_changed; }
void SetTexturePageChanged() { texture_page_changed = true; }
void ClearTexturePageChangedFlag() { texture_page_changed = false; }
/// Returns a rectangle comprising the texture palette area.
ALWAYS_INLINE_RELEASE Common::Rectangle<u32> GetTexturePaletteRectangle() const
{
static constexpr std::array<u32, 4> palette_widths = {{16, 256, 0, 0}};
return Common::Rectangle<u32>::FromExtents(texture_palette_x, texture_palette_y,
palette_widths[static_cast<u8>(mode_reg.texture_mode.GetValue())], 1);
}
bool IsTextureWindowChanged() const { return texture_window_changed; }
void SetTextureWindowChanged() { texture_window_changed = true; }
void ClearTextureWindowChangedFlag() { texture_window_changed = false; }
ALWAYS_INLINE bool IsTexturePageChanged() const { return texture_page_changed; }
ALWAYS_INLINE void SetTexturePageChanged() { texture_page_changed = true; }
ALWAYS_INLINE void ClearTexturePageChangedFlag() { texture_page_changed = false; }
ALWAYS_INLINE bool IsTextureWindowChanged() const { return texture_window_changed; }
ALWAYS_INLINE void SetTextureWindowChanged() { texture_window_changed = true; }
ALWAYS_INLINE void ClearTextureWindowChangedFlag() { texture_window_changed = false; }
} m_draw_mode = {};
Common::Rectangle<u32> m_drawing_area{0, 0, VRAM_WIDTH, VRAM_HEIGHT};

View file

@ -829,7 +829,7 @@ void GPU_HW::IncludeVRAMDityRectangle(const Common::Rectangle<u32>& rect)
// shadow texture is updated
if (!m_draw_mode.IsTexturePageChanged() &&
(m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(rect) ||
(m_draw_mode.mode_reg.IsUsingPalette() && m_draw_mode.mode_reg.GetTexturePaletteRectangle().Intersects(rect))))
(m_draw_mode.mode_reg.IsUsingPalette() && m_draw_mode.GetTexturePaletteRectangle().Intersects(rect))))
{
m_draw_mode.SetTexturePageChanged();
}
@ -932,10 +932,9 @@ void GPU_HW::DispatchRenderCommand()
if (m_draw_mode.IsTexturePageChanged())
{
m_draw_mode.ClearTexturePageChangedFlag();
if (m_vram_dirty_rect.Valid() &&
(m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) ||
if (m_vram_dirty_rect.Valid() && (m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) ||
(m_draw_mode.mode_reg.IsUsingPalette() &&
m_draw_mode.mode_reg.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect))))
m_draw_mode.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect))))
{
// Log_DevPrintf("Invalidating VRAM read cache due to drawing area overlap");
if (!IsFlushed())

View file

@ -175,25 +175,17 @@ union GPUDrawModeReg
ALWAYS_INLINE u16 GetTexturePageBaseY() const { return ZeroExtend16(texture_page_y_base.GetValue()) * 256; }
/// Returns true if the texture mode requires a palette.
bool IsUsingPalette() const { return (bits & (2 << 7)) == 0; }
ALWAYS_INLINE bool IsUsingPalette() const { return (bits & (2 << 7)) == 0; }
/// Returns a rectangle comprising the texture page area.
Common::Rectangle<u32> GetTexturePageRectangle() const
ALWAYS_INLINE_RELEASE Common::Rectangle<u32> GetTexturePageRectangle() const
{
static constexpr std::array<u32, 4> texture_page_widths = {
{TEXTURE_PAGE_WIDTH / 4, TEXTURE_PAGE_WIDTH / 2, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_WIDTH} };
{TEXTURE_PAGE_WIDTH / 4, TEXTURE_PAGE_WIDTH / 2, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_WIDTH}};
return Common::Rectangle<u32>::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(),
texture_page_widths[static_cast<u8>(texture_mode.GetValue())],
TEXTURE_PAGE_HEIGHT);
}
/// Returns a rectangle comprising the texture palette area.
Common::Rectangle<u32> GetTexturePaletteRectangle() const
{
static constexpr std::array<u32, 4> palette_widths = { {16, 256, 0, 0} };
return Common::Rectangle<u32>::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(),
palette_widths[static_cast<u8>(texture_mode.GetValue())], 1);
}
};
union GPUTexturePaletteReg
@ -218,14 +210,14 @@ struct GPUTextureWindow
};
// 4x4 dither matrix.
static constexpr s32 DITHER_MATRIX[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE] = { {-4, +0, -3, +1}, // row 0
static constexpr s32 DITHER_MATRIX[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE] = {{-4, +0, -3, +1}, // row 0
{+2, -2, +3, -1}, // row 1
{-3, +1, -4, +0}, // row 2
{+4, -1, +2, -2} }; // row 3
{+4, -1, +2, -2}}; // row 3
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4200) // warning C4200: nonstandard extension used: zero-sized array in struct/union
#pragma warning(disable : 4200) // warning C4200: nonstandard extension used: zero-sized array in struct/union
#endif
enum class GPUBackendCommandType : u8