AGS: Engine: in SetMemoryBackBuffer() don't reset batch surfs during render

In ALSoftwareGraphicsDriver:
* Save index of a currently rendered sprite batch (or none, if not inside
a render pass).
* In SetMemoryBackBuffer() don't reset virtual screen subbitmaps
  unless we are outside render pass.
* In InitSpriteBatch() also test if batch's surface is subbitmap to the
  current virtual screen (in case one was replaced, but batch's surface
  stayed).

Partially from upstream 5dd078961020da6478347dac01dea729471333d1
This commit is contained in:
Walter Agazzi 2023-03-03 17:07:48 +01:00 committed by Thierry Crozat
parent e62a2c3504
commit 43723e170a
4 changed files with 28 additions and 3 deletions

View File

@ -289,8 +289,10 @@ void ScummVMRendererGraphicsDriver::InitSpriteBatch(size_t index, const SpriteBa
else if (desc.Transform.ScaleX == 1.f && desc.Transform.ScaleY == 1.f) {
// We need this subbitmap for plugins, which use _stageVirtualScreen and are unaware of possible multiple viewports;
// TODO: there could be ways to optimize this further, but best is to update plugin rendering hooks (and upgrade plugins)
if (!batch.Surface || !batch.IsVirtualScreen || batch.Surface->GetWidth() != src_w || batch.Surface->GetHeight() != src_h
|| batch.Surface->GetSubOffset() != desc.Viewport.GetLT()) {
if (!batch.Surface || !batch.IsVirtualScreen ||
(batch.Surface->GetWidth() != src_w) || (batch.Surface->GetHeight() != src_h) ||
(!batch.Surface->IsSameBitmap(virtualScreen)) ||
(batch.Surface->GetSubOffset() != desc.Viewport.GetLT())) {
Rect rc = RectWH(desc.Viewport.Left, desc.Viewport.Top, desc.Viewport.GetWidth(), desc.Viewport.GetHeight());
batch.Surface.reset(BitmapHelper::CreateSubBitmap(virtualScreen, rc));
}
@ -575,7 +577,11 @@ void ScummVMRendererGraphicsDriver::SetMemoryBackBuffer(Bitmap *backBuffer) {
}
_stageVirtualScreen = virtualScreen;
// Reset old virtual screen's subbitmaps
// Reset old virtual screen's subbitmaps;
// NOTE: this MUST NOT be called in the midst of the RenderSpriteBatches!
assert(_rendSpriteBatch == UINT32_MAX);
if (_rendSpriteBatch != UINT32_MAX)
return;
for (auto &batch : _spriteBatches) {
if (batch.IsVirtualScreen)
batch.Surface.reset();

View File

@ -194,6 +194,19 @@ bool is_linear_bitmap(BITMAP *bmp) {
return true;
}
bool is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2) {
if ((bmp1 == nullptr) || (bmp2 == nullptr))
return false;
if (bmp1 == bmp2)
return true;
// TODO: allegro also returns true if one bmp is a sub of the other,
// i.e. they share the same id
// This (if needed?) would require a different implementation
return false;
}
void bmp_select(BITMAP *bmp) {
// No implementation needed
}

View File

@ -207,6 +207,7 @@ extern void pivot_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, int cx
extern bool is_screen_bitmap(BITMAP *bmp);
extern bool is_video_bitmap(BITMAP *bmp);
extern bool is_linear_bitmap(BITMAP *bmp);
extern bool is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2);
extern bool is_planar_bitmap(BITMAP *bmp);
extern void bmp_select(BITMAP *bmp);
extern byte *bmp_write_line(BITMAP *bmp, int line);

View File

@ -101,6 +101,11 @@ public:
return _alBitmap->isSubBitmap();
}
// Do both bitmaps share same data (usually: subbitmaps, or parent/subbitmap)
inline bool IsSameBitmap(Bitmap *other) const {
return is_same_bitmap(_alBitmap, other->_alBitmap) != 0;
}
// Checks if bitmap cannot be used
inline bool IsNull() const {
return !_alBitmap;