mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-04-22 06:02:04 +02:00
Merge pull request #145 from WaywardHeart/deletedBitmaps
Guard against deleted bitmaps
This commit is contained in:
commit
1b3d1d96c4
8 changed files with 160 additions and 32 deletions
|
@ -2592,24 +2592,6 @@ int Bitmap::maxSize(){
|
||||||
return glState.caps.maxTexSize;
|
return glState.caps.maxTexSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This might look ridiculous, but apparently, it is possible
|
|
||||||
// to encounter seemingly empty bitmaps during Graphics::update,
|
|
||||||
// or specifically, during a Sprite's prepare function.
|
|
||||||
|
|
||||||
// I have no idea why it happens, but it seems like just skipping
|
|
||||||
// them makes it okay, so... that's what this function is for, at
|
|
||||||
// least unless the actual source of the problem gets found, at
|
|
||||||
// which point I'd get rid of it.
|
|
||||||
|
|
||||||
// I get it to happen by trying to beat the first rival fight in
|
|
||||||
// Pokemon Flux, on macOS. I don't think I've seen anyone bring up
|
|
||||||
// something like this happening anywhere else, so... I dunno.
|
|
||||||
// If a game suddenly explodes during Graphics.update, maybe try
|
|
||||||
// breakpointing this?
|
|
||||||
bool Bitmap::invalid() const {
|
|
||||||
return p == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bitmap::assumeRubyGC()
|
void Bitmap::assumeRubyGC()
|
||||||
{
|
{
|
||||||
p->assumingRubyGC = true;
|
p->assumingRubyGC = true;
|
||||||
|
|
|
@ -167,8 +167,6 @@ public:
|
||||||
|
|
||||||
static int maxSize();
|
static int maxSize();
|
||||||
|
|
||||||
bool invalid() const;
|
|
||||||
|
|
||||||
void assumeRubyGC();
|
void assumeRubyGC();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -46,6 +46,8 @@ struct PlanePrivate
|
||||||
{
|
{
|
||||||
Bitmap *bitmap;
|
Bitmap *bitmap;
|
||||||
|
|
||||||
|
sigslot::connection bitmapDispCon;
|
||||||
|
|
||||||
NormValue opacity;
|
NormValue opacity;
|
||||||
BlendType blendType;
|
BlendType blendType;
|
||||||
Color *color;
|
Color *color;
|
||||||
|
@ -83,6 +85,14 @@ struct PlanePrivate
|
||||||
~PlanePrivate()
|
~PlanePrivate()
|
||||||
{
|
{
|
||||||
prepareCon.disconnect();
|
prepareCon.disconnect();
|
||||||
|
|
||||||
|
bitmapDisposal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitmapDisposal()
|
||||||
|
{
|
||||||
|
bitmap = 0;
|
||||||
|
bitmapDispCon.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateQuadSource()
|
void updateQuadSource()
|
||||||
|
@ -138,6 +148,9 @@ struct PlanePrivate
|
||||||
|
|
||||||
void prepare()
|
void prepare()
|
||||||
{
|
{
|
||||||
|
if (nullOrDisposed(bitmap))
|
||||||
|
return;
|
||||||
|
|
||||||
if (quadSourceDirty)
|
if (quadSourceDirty)
|
||||||
{
|
{
|
||||||
updateQuadSource();
|
updateQuadSource();
|
||||||
|
@ -176,8 +189,15 @@ void Plane::setBitmap(Bitmap *value)
|
||||||
|
|
||||||
p->bitmap = value;
|
p->bitmap = value;
|
||||||
|
|
||||||
if (!value)
|
p->bitmapDispCon.disconnect();
|
||||||
|
|
||||||
|
if (nullOrDisposed(value))
|
||||||
|
{
|
||||||
|
p->bitmap = 0;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->bitmapDispCon = value->wasDisposed.connect(&PlanePrivate::bitmapDisposal, p);
|
||||||
|
|
||||||
value->ensureNonMega();
|
value->ensureNonMega();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ struct SpritePrivate
|
||||||
{
|
{
|
||||||
Bitmap *bitmap;
|
Bitmap *bitmap;
|
||||||
|
|
||||||
|
sigslot::connection bitmapDispCon;
|
||||||
|
|
||||||
Quad quad;
|
Quad quad;
|
||||||
Transform trans;
|
Transform trans;
|
||||||
|
|
||||||
|
@ -137,6 +139,14 @@ struct SpritePrivate
|
||||||
{
|
{
|
||||||
srcRectCon.disconnect();
|
srcRectCon.disconnect();
|
||||||
prepareCon.disconnect();
|
prepareCon.disconnect();
|
||||||
|
|
||||||
|
bitmapDisposal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitmapDisposal()
|
||||||
|
{
|
||||||
|
bitmap = 0;
|
||||||
|
bitmapDispCon.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void recomputeBushDepth()
|
void recomputeBushDepth()
|
||||||
|
@ -189,9 +199,6 @@ struct SpritePrivate
|
||||||
if (nullOrDisposed(bitmap))
|
if (nullOrDisposed(bitmap))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (bitmap->invalid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!opacity)
|
if (!opacity)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -372,8 +379,15 @@ void Sprite::setBitmap(Bitmap *bitmap)
|
||||||
|
|
||||||
p->bitmap = bitmap;
|
p->bitmap = bitmap;
|
||||||
|
|
||||||
|
p->bitmapDispCon.disconnect();
|
||||||
|
|
||||||
if (nullOrDisposed(bitmap))
|
if (nullOrDisposed(bitmap))
|
||||||
|
{
|
||||||
|
p->bitmap = 0;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->bitmapDispCon = bitmap->wasDisposed.connect(&SpritePrivate::bitmapDisposal, p);
|
||||||
|
|
||||||
bitmap->ensureNonMega();
|
bitmap->ensureNonMega();
|
||||||
|
|
||||||
|
|
|
@ -331,6 +331,8 @@ struct TilemapPrivate
|
||||||
/* Dispose watches */
|
/* Dispose watches */
|
||||||
sigslot::connection autotilesDispCon[autotileCount];
|
sigslot::connection autotilesDispCon[autotileCount];
|
||||||
|
|
||||||
|
sigslot::connection tilesetDispCon;
|
||||||
|
|
||||||
/* Draw prepare call */
|
/* Draw prepare call */
|
||||||
sigslot::connection prepareCon;
|
sigslot::connection prepareCon;
|
||||||
|
|
||||||
|
@ -403,6 +405,7 @@ struct TilemapPrivate
|
||||||
|
|
||||||
/* Disconnect signal handlers */
|
/* Disconnect signal handlers */
|
||||||
tilesetCon.disconnect();
|
tilesetCon.disconnect();
|
||||||
|
tilesetDispCon.disconnect();
|
||||||
for (int i = 0; i < autotileCount; ++i)
|
for (int i = 0; i < autotileCount; ++i)
|
||||||
{
|
{
|
||||||
autotilesCon[i].disconnect();
|
autotilesCon[i].disconnect();
|
||||||
|
@ -490,6 +493,20 @@ struct TilemapPrivate
|
||||||
atlasDirty = true;
|
atlasDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void atlasContentsDisposal(int i)
|
||||||
|
{
|
||||||
|
// Guard against deleted bitmaps
|
||||||
|
autotiles[i] = 0;
|
||||||
|
|
||||||
|
invalidateAtlasContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tilesetDisposal()
|
||||||
|
{
|
||||||
|
tileset = 0;
|
||||||
|
tilesetDispCon.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
void invalidateBuffers()
|
void invalidateBuffers()
|
||||||
{
|
{
|
||||||
buffersDirty = true;
|
buffersDirty = true;
|
||||||
|
@ -1189,12 +1206,18 @@ void Tilemap::Autotiles::set(int i, Bitmap *bitmap)
|
||||||
p->invalidateAtlasContents();
|
p->invalidateAtlasContents();
|
||||||
|
|
||||||
p->autotilesCon[i].disconnect();
|
p->autotilesCon[i].disconnect();
|
||||||
|
p->autotilesDispCon[i].disconnect();
|
||||||
|
|
||||||
|
if (nullOrDisposed(bitmap))
|
||||||
|
{
|
||||||
|
p->autotiles[i] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
p->autotilesCon[i] = bitmap->modified.connect
|
p->autotilesCon[i] = bitmap->modified.connect
|
||||||
(&TilemapPrivate::invalidateAtlasContents, p);
|
(&TilemapPrivate::invalidateAtlasContents, p);
|
||||||
|
|
||||||
p->autotilesDispCon[i].disconnect();
|
p->autotilesDispCon[i] = bitmap->wasDisposed.connect( [i, this] { p->atlasContentsDisposal(i); } );
|
||||||
p->autotilesDispCon[i] = bitmap->wasDisposed.connect
|
|
||||||
(&TilemapPrivate::invalidateAtlasContents, p);
|
|
||||||
|
|
||||||
p->updateAutotileInfo();
|
p->updateAutotileInfo();
|
||||||
}
|
}
|
||||||
|
@ -1269,14 +1292,23 @@ void Tilemap::setTileset(Bitmap *value)
|
||||||
|
|
||||||
p->tileset = value;
|
p->tileset = value;
|
||||||
|
|
||||||
if (!value)
|
p->tilesetDispCon.disconnect();
|
||||||
|
p->tilesetCon.disconnect();
|
||||||
|
|
||||||
|
if (nullOrDisposed(value))
|
||||||
|
{
|
||||||
|
p->tileset = 0;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
p->invalidateAtlasSize();
|
p->invalidateAtlasSize();
|
||||||
p->tilesetCon.disconnect();
|
|
||||||
p->tilesetCon = value->modified.connect
|
p->tilesetCon = value->modified.connect
|
||||||
(&TilemapPrivate::invalidateAtlasSize, p);
|
(&TilemapPrivate::invalidateAtlasSize, p);
|
||||||
|
|
||||||
|
p->tilesetDispCon = value->wasDisposed.connect
|
||||||
|
(&TilemapPrivate::tilesetDisposal, p);
|
||||||
|
|
||||||
p->updateAtlasInfo();
|
p->updateAtlasInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,14 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
|
||||||
atlasDirty = true;
|
atlasDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void atlasDisposal(int i)
|
||||||
|
{
|
||||||
|
// Guard against deleted bitmaps
|
||||||
|
bitmaps[i] = 0;
|
||||||
|
|
||||||
|
invalidateAtlas();
|
||||||
|
}
|
||||||
|
|
||||||
void invalidateBuffers()
|
void invalidateBuffers()
|
||||||
{
|
{
|
||||||
buffersDirty = true;
|
buffersDirty = true;
|
||||||
|
@ -415,12 +423,18 @@ void TilemapVX::BitmapArray::set(int i, Bitmap *bitmap)
|
||||||
p->atlasDirty = true;
|
p->atlasDirty = true;
|
||||||
|
|
||||||
p->bmChangedCons[i].disconnect();
|
p->bmChangedCons[i].disconnect();
|
||||||
|
p->bmDisposedCons[i].disconnect();
|
||||||
|
|
||||||
|
if (nullOrDisposed(bitmap))
|
||||||
|
{
|
||||||
|
p->bitmaps[i] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
p->bmChangedCons[i] = bitmap->modified.connect
|
p->bmChangedCons[i] = bitmap->modified.connect
|
||||||
(&TilemapVXPrivate::invalidateAtlas, p);
|
(&TilemapVXPrivate::invalidateAtlas, p);
|
||||||
|
|
||||||
p->bmDisposedCons[i].disconnect();
|
p->bmDisposedCons[i] = bitmap->wasDisposed.connect( [i, this] { p->atlasDisposal(i); } );
|
||||||
p->bmDisposedCons[i] = bitmap->wasDisposed.connect
|
|
||||||
(&TilemapVXPrivate::invalidateAtlas, p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap *TilemapVX::BitmapArray::get(int i) const
|
Bitmap *TilemapVX::BitmapArray::get(int i) const
|
||||||
|
|
|
@ -172,6 +172,9 @@ struct WindowPrivate
|
||||||
|
|
||||||
Bitmap *contents;
|
Bitmap *contents;
|
||||||
|
|
||||||
|
sigslot::connection windowskinDispCon;
|
||||||
|
sigslot::connection contentsDispCon;
|
||||||
|
|
||||||
bool bgStretch;
|
bool bgStretch;
|
||||||
Rect *cursorRect;
|
Rect *cursorRect;
|
||||||
bool active;
|
bool active;
|
||||||
|
@ -282,6 +285,21 @@ struct WindowPrivate
|
||||||
shState->texPool().release(baseTex);
|
shState->texPool().release(baseTex);
|
||||||
cursorRectCon.disconnect();
|
cursorRectCon.disconnect();
|
||||||
prepareCon.disconnect();
|
prepareCon.disconnect();
|
||||||
|
|
||||||
|
windowskinDisposal();
|
||||||
|
contentsDisposal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void windowskinDisposal()
|
||||||
|
{
|
||||||
|
windowskin = 0;
|
||||||
|
windowskinDispCon.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void contentsDisposal()
|
||||||
|
{
|
||||||
|
contents = 0;
|
||||||
|
contentsDispCon.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void markControlVertDirty()
|
void markControlVertDirty()
|
||||||
|
@ -720,10 +738,17 @@ void Window::setWindowskin(Bitmap *value)
|
||||||
|
|
||||||
p->windowskin = value;
|
p->windowskin = value;
|
||||||
|
|
||||||
|
p->windowskinDispCon.disconnect();
|
||||||
|
|
||||||
if (nullOrDisposed(value))
|
if (nullOrDisposed(value))
|
||||||
|
{
|
||||||
|
p->windowskin = 0;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
value->ensureNonMega();
|
value->ensureNonMega();
|
||||||
|
|
||||||
|
p->windowskinDispCon = value->wasDisposed.connect(&WindowPrivate::windowskinDisposal, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setContents(Bitmap *value)
|
void Window::setContents(Bitmap *value)
|
||||||
|
@ -736,10 +761,18 @@ void Window::setContents(Bitmap *value)
|
||||||
p->contents = value;
|
p->contents = value;
|
||||||
p->controlsVertDirty = true;
|
p->controlsVertDirty = true;
|
||||||
|
|
||||||
|
p->contentsDispCon.disconnect();
|
||||||
|
|
||||||
if (nullOrDisposed(value))
|
if (nullOrDisposed(value))
|
||||||
|
{
|
||||||
|
p->contents = 0;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->contentsDispCon = value->wasDisposed.connect(&WindowPrivate::contentsDisposal, p);
|
||||||
|
|
||||||
value->ensureNonMega();
|
value->ensureNonMega();
|
||||||
|
|
||||||
p->contentsQuad.setTexPosRect(value->rect(), value->rect());
|
p->contentsQuad.setTexPosRect(value->rect(), value->rect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,9 @@ struct WindowVXPrivate
|
||||||
|
|
||||||
Bitmap *contents;
|
Bitmap *contents;
|
||||||
|
|
||||||
|
sigslot::connection windowskinDispCon;
|
||||||
|
sigslot::connection contentsDispCon;
|
||||||
|
|
||||||
Rect *cursorRect;
|
Rect *cursorRect;
|
||||||
bool active;
|
bool active;
|
||||||
bool arrowsVisible;
|
bool arrowsVisible;
|
||||||
|
@ -278,6 +281,21 @@ struct WindowVXPrivate
|
||||||
cursorRectCon.disconnect();
|
cursorRectCon.disconnect();
|
||||||
toneCon.disconnect();
|
toneCon.disconnect();
|
||||||
prepareCon.disconnect();
|
prepareCon.disconnect();
|
||||||
|
|
||||||
|
windowskinDisposal();
|
||||||
|
contentsDisposal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void windowskinDisposal()
|
||||||
|
{
|
||||||
|
windowskin = 0;
|
||||||
|
windowskinDispCon.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void contentsDisposal()
|
||||||
|
{
|
||||||
|
contents = 0;
|
||||||
|
contentsDispCon.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void invalidateCursorVert()
|
void invalidateCursorVert()
|
||||||
|
@ -908,6 +926,16 @@ void WindowVX::setWindowskin(Bitmap *value)
|
||||||
|
|
||||||
p->windowskin = value;
|
p->windowskin = value;
|
||||||
p->base.texDirty = true;
|
p->base.texDirty = true;
|
||||||
|
|
||||||
|
p->windowskinDispCon.disconnect();
|
||||||
|
|
||||||
|
if (nullOrDisposed(value))
|
||||||
|
{
|
||||||
|
p->windowskin = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->windowskinDispCon = value->wasDisposed.connect(&WindowVXPrivate::windowskinDisposal, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowVX::setContents(Bitmap *value)
|
void WindowVX::setContents(Bitmap *value)
|
||||||
|
@ -919,8 +947,15 @@ void WindowVX::setContents(Bitmap *value)
|
||||||
|
|
||||||
p->contents = value;
|
p->contents = value;
|
||||||
|
|
||||||
|
p->contentsDispCon.disconnect();
|
||||||
|
|
||||||
if (nullOrDisposed(value))
|
if (nullOrDisposed(value))
|
||||||
|
{
|
||||||
|
p->contents = 0;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->contentsDispCon = value->wasDisposed.connect(&WindowVXPrivate::contentsDisposal, p);
|
||||||
|
|
||||||
FloatRect rect = p->contents->rect();
|
FloatRect rect = p->contents->rect();
|
||||||
p->contentsQuad.setTexPosRect(rect, rect);
|
p->contentsQuad.setTexPosRect(rect, rect);
|
||||||
|
|
Loading…
Add table
Reference in a new issue