WINTERMUTE: Delay Image-load until the data is needed.

This commit is contained in:
Einar Johan Trøan Sømåen 2012-07-09 05:27:50 +02:00
parent f147d0409d
commit acc2a95aca
7 changed files with 55 additions and 51 deletions

View File

@ -115,7 +115,6 @@ ERRORCODE CBFileManager::cleanup() {
#define MAX_FILE_SIZE 10000000
//////////////////////////////////////////////////////////////////////
byte *CBFileManager::readWholeFile(const Common::String &filename, uint32 *size, bool mustExist) {
byte *buffer = NULL;
Common::SeekableReadStream *file = openFile(filename);

View File

@ -253,8 +253,8 @@ ERRORCODE CBSubFrame::saveAsText(CBDynBuffer *buffer, int indent, bool complete)
if (complete)
buffer->putTextIndent(indent, "SUBFRAME {\n");
if (_surface && _surface->_filename != NULL)
buffer->putTextIndent(indent + 2, "IMAGE = \"%s\"\n", _surface->_filename);
if (_surface && _surface->getFileName() != "")
buffer->putTextIndent(indent + 2, "IMAGE = \"%s\"\n", _surface->getFileName());
if (_transparent != 0xFFFF00FF)
buffer->putTextIndent(indent + 2, "TRANSPARENT { %d,%d,%d }\n", RGBCOLGetR(_transparent), RGBCOLGetG(_transparent), RGBCOLGetB(_transparent));

View File

@ -38,12 +38,12 @@ CBSurface::CBSurface(CBGame *inGame): CBBase(inGame) {
_width = _height = 0;
_filename = NULL;
_filename = "";
_pixelOpReady = false;
_cKDefault = true;
_cKRed = _cKGreen = _cKBlue = 0;
_ckDefault = true;
_ckRed = _ckGreen = _ckBlue = 0;
_lifeTime = 0;
_keepLoaded = false;
@ -55,7 +55,6 @@ CBSurface::CBSurface(CBGame *inGame): CBBase(inGame) {
//////////////////////////////////////////////////////////////////////
CBSurface::~CBSurface() {
if (_pixelOpReady) endPixelOp();
if (_filename) delete [] _filename;
}
@ -139,21 +138,11 @@ ERRORCODE CBSurface::prepareToDraw() {
if (!_valid) {
//Game->LOG(0, "Reviving: %s", _filename);
return create(_filename, _cKDefault, _cKRed, _cKGreen, _cKBlue, _lifeTime, _keepLoaded);
return create(_filename.c_str(), _ckDefault, _ckRed, _ckGreen, _ckBlue, _lifeTime, _keepLoaded);
} else return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
void CBSurface::setFilename(const char *filename) {
delete[] _filename;
_filename = NULL;
if (!filename) return;
_filename = new char[strlen(filename) + 1];
if (_filename) strcpy(_filename, filename);
}
//////////////////////////////////////////////////////////////////////////
void CBSurface::setSize(int width, int height) {
_width = width;

View File

@ -38,10 +38,10 @@ class CBSurface: public CBBase {
public:
virtual ERRORCODE invalidate();
virtual ERRORCODE prepareToDraw();
bool _cKDefault;
byte _cKRed;
byte _cKGreen;
byte _cKBlue;
bool _ckDefault;
byte _ckRed;
byte _ckGreen;
byte _ckBlue;
uint32 _lastUsedTime;
bool _valid;
@ -72,11 +72,9 @@ public:
virtual ERRORCODE startPixelOp();
virtual ERRORCODE endPixelOp();
virtual bool isTransparentAtLite(int x, int y);
void setFilename(const char *filename);
void setSize(int width, int height);
int _referenceCount;
char *_filename;
virtual int getWidth() {
return _width;
@ -84,9 +82,11 @@ public:
virtual int getHeight() {
return _height;
}
const char* getFileName() { return _filename.c_str(); }
//void SetWidth(int Width){ _width = Width; }
//void SetHeight(int Height){ _height = Height; }
protected:
Common::String _filename;
int _height;
int _width;

View File

@ -52,6 +52,7 @@ CBSurfaceSDL::CBSurfaceSDL(CBGame *inGame) : CBSurface(inGame) {
_hasAlpha = true;
_lockPixels = NULL;
_lockPitch = 0;
_loaded = false;
}
//////////////////////////////////////////////////////////////////////////
@ -92,9 +93,7 @@ bool hasTransparency(Graphics::Surface *surf) {
//////////////////////////////////////////////////////////////////////////
ERRORCODE CBSurfaceSDL::create(const char *filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) {
/* CBRenderSDL *renderer = static_cast<CBRenderSDL *>(Game->_renderer); */
Common::String strFileName(filename);
CBImage *image = new CBImage(Game);
image->loadFile(strFileName);
_filename = filename;
// const Graphics::Surface *surface = image->getSurface();
if (defaultCK) {
@ -103,10 +102,28 @@ ERRORCODE CBSurfaceSDL::create(const char *filename, bool defaultCK, byte ckRed,
ckBlue = 255;
}
_ckDefault = defaultCK;
_ckRed = ckRed;
_ckGreen = ckGreen;
_ckBlue = ckBlue;
if (_lifeTime == 0 || lifeTime == -1 || lifeTime > _lifeTime)
_lifeTime = lifeTime;
_keepLoaded = keepLoaded;
if (_keepLoaded) _lifeTime = -1;
return STATUS_OK;
}
void CBSurfaceSDL::finishLoad() {
CBImage *image = new CBImage(Game);
image->loadFile(_filename);
_width = image->getSurface()->w;
_height = image->getSurface()->h;
bool isSaveGameGrayscale = scumm_strnicmp(filename, "savegame:", 9) == 0 && (filename[strFileName.size() - 1] == 'g' || filename[strFileName.size() - 1] == 'G');
bool isSaveGameGrayscale = scumm_strnicmp(_filename.c_str(), "savegame:", 9) == 0 && (_filename.c_str()[_filename.size() - 1] == 'g' || _filename.c_str()[_filename.size() - 1] == 'G');
if (isSaveGameGrayscale) {
warning("grayscaleConversion not yet implemented");
/* FIBITMAP *newImg = FreeImage_ConvertToGreyscale(img);
@ -145,14 +162,14 @@ ERRORCODE CBSurfaceSDL::create(const char *filename, bool defaultCK, byte ckRed,
// convert 32-bit BMPs to 24-bit or they appear totally transparent (does any app actually write alpha in BMP properly?)
// Well, actually, we don't convert via 24-bit as the color-key application overwrites the Alpha-channel anyhow.
delete _surface;
if (strFileName.hasSuffix(".bmp") && image->getSurface()->format.bytesPerPixel == 4) {
if (_filename.hasSuffix(".bmp") && image->getSurface()->format.bytesPerPixel == 4) {
_surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette());
TransparentSurface trans(*_surface);
trans.applyColorKey(ckRed, ckGreen, ckBlue);
trans.applyColorKey(_ckRed, _ckGreen, _ckBlue);
} else if (image->getSurface()->format.bytesPerPixel == 1 && image->getPalette()) {
_surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette());
TransparentSurface trans(*_surface);
trans.applyColorKey(ckRed, ckGreen, ckBlue, true);
trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, true);
} else if (image->getSurface()->format.bytesPerPixel == 4 && image->getSurface()->format != g_system->getScreenFormat()) {
_surface = image->getSurface()->convertTo(g_system->getScreenFormat());
} else {
@ -184,30 +201,15 @@ ERRORCODE CBSurfaceSDL::create(const char *filename, bool defaultCK, byte ckRed,
SDL_FreeSurface(surf);
delete imgDecoder; // TODO: Update this if ImageDecoder doesn't end up owning the surface.
_cKDefault = default_ck;
_cKRed = ck_red;
_cKGreen = ck_green;
_cKBlue = ck_blue;
#endif
if (!_filename || scumm_stricmp(_filename, filename) != 0) {
setFilename(filename);
}
if (_lifeTime == 0 || lifeTime == -1 || lifeTime > _lifeTime)
_lifeTime = lifeTime;
_keepLoaded = keepLoaded;
if (_keepLoaded) _lifeTime = -1;
_valid = true;
Game->addMem(_width * _height * 4);
delete image;
return STATUS_OK;
_loaded = true;
}
//////////////////////////////////////////////////////////////////////////
@ -459,7 +461,12 @@ ERRORCODE CBSurfaceSDL::displayTransform(int x, int y, int hotX, int hotY, Commo
ERRORCODE CBSurfaceSDL::drawSprite(int x, int y, Common::Rect *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) {
CBRenderSDL *renderer = static_cast<CBRenderSDL *>(Game->_renderer);
if (renderer->_forceAlphaColor != 0) alpha = renderer->_forceAlphaColor;
if (!_loaded) {
finishLoad();
}
if (renderer->_forceAlphaColor != 0)
alpha = renderer->_forceAlphaColor;
// This particular warning is rather messy, as this function is called a ton,
// thus we avoid printing it more than once.
@ -535,6 +542,7 @@ ERRORCODE CBSurfaceSDL::drawSprite(int x, int y, Common::Rect *rect, float zoomX
}
ERRORCODE CBSurfaceSDL::putSurface(const Graphics::Surface &surface, bool hasAlpha) {
_loaded = true;
_surface->copyFrom(surface);
_hasAlpha = hasAlpha;
CBRenderSDL *renderer = static_cast<CBRenderSDL *>(Game->_renderer);

View File

@ -35,6 +35,7 @@
namespace WinterMute {
struct TransparentSurface;
class CBImage;
class CBSurfaceSDL : public CBSurface {
public:
CBSurfaceSDL(CBGame *inGame);
@ -63,12 +64,18 @@ public:
static int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin);
static long DLL_CALLCONV TellProc(fi_handle handle);*/
virtual int getWidth() {
if (!_loaded) {
finishLoad();
}
if (_surface) {
return _surface->w;
}
return _width;
}
virtual int getHeight() {
if (!_loaded) {
finishLoad();
}
if (_surface) {
return _surface->h;
}
@ -77,7 +84,8 @@ public:
private:
Graphics::Surface *_surface;
bool _loaded;
void finishLoad();
ERRORCODE drawSprite(int x, int y, Common::Rect *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX = 0, int offsetY = 0);
void genAlphaMask(Graphics::Surface *surface);
uint32 getPixel(Graphics::Surface *surface, int x, int y);

View File

@ -53,7 +53,7 @@ CBSurfaceStorage::~CBSurfaceStorage() {
//////////////////////////////////////////////////////////////////////////
ERRORCODE CBSurfaceStorage::cleanup(bool warn) {
for (int i = 0; i < _surfaces.getSize(); i++) {
if (warn) Game->LOG(0, "CBSurfaceStorage warning: purging surface '%s', usage:%d", _surfaces[i]->_filename, _surfaces[i]->_referenceCount);
if (warn) Game->LOG(0, "CBSurfaceStorage warning: purging surface '%s', usage:%d", _surfaces[i]->getFileName(), _surfaces[i]->_referenceCount);
delete _surfaces[i];
}
_surfaces.removeAll();
@ -99,7 +99,7 @@ ERRORCODE CBSurfaceStorage::removeSurface(CBSurface *surface) {
//////////////////////////////////////////////////////////////////////
CBSurface *CBSurfaceStorage::addSurface(const char *filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) {
for (int i = 0; i < _surfaces.getSize(); i++) {
if (scumm_stricmp(_surfaces[i]->_filename, filename) == 0) {
if (scumm_stricmp(_surfaces[i]->getFileName(), filename) == 0) {
_surfaces[i]->_referenceCount++;
return _surfaces[i];
}