Release resources if we error in the Bitmap constructor.

This commit is contained in:
Wayward Heart 2024-05-19 03:10:01 -05:00
parent 8fcd6dd605
commit 65aab17dba

View file

@ -509,6 +509,7 @@ Bitmap::Bitmap(const char *filename)
} }
BitmapOpenHandler handler; BitmapOpenHandler handler;
try {
shState->fileSystem().openRead(handler, filename); shState->fileSystem().openRead(handler, filename);
if (!handler.error.empty()) { if (!handler.error.empty()) {
@ -519,18 +520,25 @@ Bitmap::Bitmap(const char *filename)
throw Exception(Exception::SDLError, "Error loading image '%s': %s", throw Exception(Exception::SDLError, "Error loading image '%s': %s",
filename, SDL_GetError()); filename, SDL_GetError());
} }
} catch (const Exception &e) {
if (hiresBitmap)
delete hiresBitmap;
throw e;
}
if (handler.gif) { if (handler.gif) {
p = new BitmapPrivate(this);
p->selfHires = hiresBitmap;
if (handler.gif->width >= (uint32_t)glState.caps.maxTexSize || handler.gif->height > (uint32_t)glState.caps.maxTexSize) if (handler.gif->width >= (uint32_t)glState.caps.maxTexSize || handler.gif->height > (uint32_t)glState.caps.maxTexSize)
{ {
if (hiresBitmap)
delete hiresBitmap;
throw new Exception(Exception::MKXPError, "Animation too large (%ix%i, max %ix%i)", throw new Exception(Exception::MKXPError, "Animation too large (%ix%i, max %ix%i)",
handler.gif->width, handler.gif->height, glState.caps.maxTexSize, glState.caps.maxTexSize); handler.gif->width, handler.gif->height, glState.caps.maxTexSize, glState.caps.maxTexSize);
} }
p = new BitmapPrivate(this);
p->selfHires = hiresBitmap;
if (handler.gif->frame_count == 1) { if (handler.gif->frame_count == 1) {
TEXFBO texfbo; TEXFBO texfbo;
try { try {
@ -542,6 +550,10 @@ Bitmap::Bitmap(const char *filename)
delete handler.gif; delete handler.gif;
delete handler.gif_data; delete handler.gif_data;
delete p;
if (hiresBitmap)
delete hiresBitmap;
throw e; throw e;
} }
@ -579,8 +591,7 @@ Bitmap::Bitmap(const char *filename)
if (i > 0) { if (i > 0) {
int status = gif_decode_frame(handler.gif, i); int status = gif_decode_frame(handler.gif, i);
if (status != GIF_OK && status != GIF_WORKING) { if (status != GIF_OK && status != GIF_WORKING) {
for (TEXFBO &frame : p->animation.frames) releaseResources();
shState->texPool().release(frame);
gif_finalise(handler.gif); gif_finalise(handler.gif);
delete handler.gif; delete handler.gif;
@ -597,8 +608,7 @@ Bitmap::Bitmap(const char *filename)
} }
catch (const Exception &e) catch (const Exception &e)
{ {
for (TEXFBO &frame : p->animation.frames) releaseResources();
shState->texPool().release(frame);
gif_finalise(handler.gif); gif_finalise(handler.gif);
delete handler.gif; delete handler.gif;
@ -640,7 +650,14 @@ Bitmap::Bitmap(int width, int height, bool isHires)
hiresBitmap->setLores(this); hiresBitmap->setLores(this);
} }
TEXFBO tex = shState->texPool().request(width, height); TEXFBO tex;
try {
tex = shState->texPool().request(width, height);
} catch (const Exception &e) {
if (hiresBitmap)
delete hiresBitmap;
throw e;
}
p = new BitmapPrivate(this); p = new BitmapPrivate(this);
p->gl = tex; p->gl = tex;
@ -713,7 +730,12 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
// TODO: Clean me up // TODO: Clean me up
if (!other.isAnimated() || frame >= -1) { if (!other.isAnimated() || frame >= -1) {
try {
p->gl = shState->texPool().request(other.width(), other.height()); p->gl = shState->texPool().request(other.width(), other.height());
} catch (const Exception &e) {
delete p;
throw e;
}
GLMeta::blitBegin(p->gl); GLMeta::blitBegin(p->gl);
// Blit just the current frame of the other animated bitmap // Blit just the current frame of the other animated bitmap
@ -742,8 +764,7 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
try { try {
newframe = shState->texPool().request(p->animation.width, p->animation.height); newframe = shState->texPool().request(p->animation.width, p->animation.height);
} catch(const Exception &e) { } catch(const Exception &e) {
for (TEXFBO &f : p->animation.frames) releaseResources();
shState->texPool().release(f);
throw e; throw e;
} }
@ -770,10 +791,15 @@ Bitmap::Bitmap(TEXFBO &other)
} }
p = new BitmapPrivate(this); p = new BitmapPrivate(this);
p->gl = shState->texPool().request(other.width, other.height);
p->selfHires = hiresBitmap; p->selfHires = hiresBitmap;
try {
p->gl = shState->texPool().request(other.width, other.height);
} catch (const Exception &e) {
delete p;
throw e;
}
if (p->selfHires != nullptr) { if (p->selfHires != nullptr) {
p->gl.selfHires = &p->selfHires->getGLTypes(); p->gl.selfHires = &p->selfHires->getGLTypes();
} }
@ -831,6 +857,8 @@ void Bitmap::initFromSurface(SDL_Surface *imgSurf, Bitmap *hiresBitmap, bool for
} }
catch (const Exception &e) catch (const Exception &e)
{ {
if (hiresBitmap)
delete hiresBitmap;
SDL_FreeSurface(imgSurf); SDL_FreeSurface(imgSurf);
throw e; throw e;
} }