Dynamically manage PPGe images so 50+ are okay.

Otherwise, we try to allocate all at once and could run out of ram.

Should fix #2242.
This commit is contained in:
Unknown W. Brackets committed 2013-12-08 11:06:18 -08:00
1 parent 18bcf63ee9
commit 2d3f0758c1
5 files changed
+220 -71

No files matched your search

+17 -15
View File
@@ -272,8 +272,9 @@ void PSPSaveDialog::DisplaySaveList(bool canMove)
for (int i = 0; i < param.GetFilenameCount(); i++)
{
int textureColor = 0xFFFFFFFF;
auto fileInfo = param.GetFileInfo(i);
if (param.GetFileInfo(i).size == 0 && param.GetFileInfo(i).textureData == 0)
if (fileInfo.size == 0 && fileInfo.texture != NULL)
textureColor = 0xFF777777;
// Calc save image position on screen
@@ -300,13 +301,12 @@ void PSPSaveDialog::DisplaySaveList(bool canMove)
int tw = 256;
int th = 256;
if (param.GetFileInfo(i).textureData != 0) {
tw = param.GetFileInfo(i).textureWidth;
th = param.GetFileInfo(i).textureHeight;
PPGeSetTexture(param.GetFileInfo(i).textureData, param.GetFileInfo(i).textureWidth, param.GetFileInfo(i).textureHeight);
if (fileInfo.texture != NULL) {
fileInfo.texture->SetTexture();
tw = fileInfo.texture->Width();
th = fileInfo.texture->Height();
PPGeDrawImage(x, y, w, h, 0, 0, 1, 1, tw, th, textureColor);
} else
PPGeDisableTexture();
}
PPGeSetDefaultTexture();
displayCount++;
}
@@ -322,8 +322,9 @@ void PSPSaveDialog::DisplaySaveList(bool canMove)
void PSPSaveDialog::DisplaySaveIcon()
{
int textureColor = CalcFadedColor(0xFFFFFFFF);
auto curSave = param.GetFileInfo(currentSelectedSave);
if (param.GetFileInfo(currentSelectedSave).size == 0)
if (curSave.size == 0)
textureColor = CalcFadedColor(0xFF777777);
// Calc save image position on screen
@@ -334,14 +335,15 @@ void PSPSaveDialog::DisplaySaveIcon()
int tw = 256;
int th = 256;
if (param.GetFileInfo(currentSelectedSave).textureData != 0) {
tw = param.GetFileInfo(currentSelectedSave).textureWidth;
th = param.GetFileInfo(currentSelectedSave).textureHeight;
PPGeSetTexture(param.GetFileInfo(currentSelectedSave).textureData, param.GetFileInfo(currentSelectedSave).textureWidth, param.GetFileInfo(currentSelectedSave).textureHeight);
} else
if (curSave.texture != NULL) {
curSave.texture->SetTexture();
tw = curSave.texture->Width();
th = curSave.texture->Height();
} else {
PPGeDisableTexture();
PPGeDrawImage(x, y, w, h, 0, 0 ,1 ,1 ,tw, th, textureColor);
if (param.GetFileInfo(currentSelectedSave).textureData != 0)
}
PPGeDrawImage(x, y, w, h, 0, 0, 1, 1, tw, th, textureColor);
if (curSave.texture != NULL)
PPGeSetDefaultTexture();
}
+22 -46
View File
@@ -1094,20 +1094,20 @@ void SavedataParam::Clear()
{
for (int i = 0; i < saveNameListDataCount; i++)
{
if (saveDataList[i].textureData != 0 && saveDataList[i].size != 0)
kernelMemory.Free(saveDataList[i].textureData);
saveDataList[i].textureData = 0;
if (saveDataList[i].texture != NULL)
delete saveDataList[i].texture;
saveDataList[i].texture = NULL;
}
delete[] saveDataList;
delete [] saveDataList;
saveDataList = 0;
saveDataListCount = 0;
}
if (noSaveIcon)
{
if(noSaveIcon->textureData != 0)
kernelMemory.Free(noSaveIcon->textureData);
noSaveIcon->textureData = 0;
if (noSaveIcon->texture != NULL)
delete noSaveIcon->texture;
noSaveIcon->texture = NULL;
delete noSaveIcon;
noSaveIcon = 0;
}
@@ -1242,33 +1242,6 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param)
return 0;
}
bool SavedataParam::CreatePNGIcon(u8* pngData, int pngSize, SaveFileInfo& info)
{
unsigned char *textureData;
int w,h;
int success = pngLoadPtr(pngData, (int)pngSize, &w, &h, &textureData, false);
u32 texSize = w*h*4;
u32 atlasPtr;
if (success)
atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon");
if (success && atlasPtr != (u32)-1)
{
info.textureData = atlasPtr;
Memory::Memcpy(atlasPtr, textureData, texSize);
free(textureData);
info.textureWidth = w;
info.textureHeight = h;
}
else
{
WARN_LOG(SCEUTILITY, "Unable to load PNG data for savedata.");
return false;
}
return true;
}
void SavedataParam::SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::string saveName)
{
saveInfo.size = info.size;
@@ -1277,7 +1250,12 @@ void SavedataParam::SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::
saveInfo.modif_time = info.mtime;
// Start with a blank slate.
saveInfo.textureData = 0;
if (saveInfo.texture != NULL) {
if (!noSaveIcon || saveInfo.texture != noSaveIcon->texture) {
delete saveInfo.texture;
}
saveInfo.texture = NULL;
}
saveInfo.title[0] = 0;
saveInfo.saveTitle[0] = 0;
saveInfo.saveDetail[0] = 0;
@@ -1287,12 +1265,7 @@ void SavedataParam::SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::
std::string fileDataPath2 = savePath + GetGameName(pspParam) + saveName + "/" + ICON0_FILENAME;
PSPFileInfo info2 = pspFileSystem.GetFileInfo(fileDataPath2);
if (info2.exists)
{
u8 *textureDataPNG = new u8[(size_t)info2.size];
ReadPSPFile(fileDataPath2, &textureDataPNG, info2.size, NULL);
CreatePNGIcon(textureDataPNG, (int)info2.size, saveInfo);
delete[] textureDataPNG;
}
saveInfo.texture = new PPGeImage(fileDataPath2);
// Load info in PARAM.SFO
fileDataPath2 = savePath + GetGameName(pspParam) + saveName + "/" + SFO_FILENAME;
@@ -1323,7 +1296,12 @@ void SavedataParam::ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName)
saveInfo.size = 0;
saveInfo.saveName = saveName;
saveInfo.idx = 0;
saveInfo.textureData = 0;
if (saveInfo.texture != NULL) {
if (!noSaveIcon || saveInfo.texture != noSaveIcon->texture) {
delete saveInfo.texture;
}
saveInfo.texture = NULL;
}
if (GetPspParam()->newData.IsValid() && GetPspParam()->newData->buf.IsValid())
{
@@ -1332,11 +1310,9 @@ void SavedataParam::ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName)
{
noSaveIcon = new SaveFileInfo();
PspUtilitySavedataFileData *newData = GetPspParam()->newData;
CreatePNGIcon(newData->buf, (int)newData->size, *noSaveIcon);
noSaveIcon->texture = new PPGeImage(newData->buf.ptr, (SceSize)newData->size);
}
saveInfo.textureData = noSaveIcon->textureData;
saveInfo.textureWidth = noSaveIcon->textureWidth;
saveInfo.textureHeight = noSaveIcon->textureHeight;
saveInfo.texture = noSaveIcon->texture;
}
}
+28 -10
View File
@@ -21,6 +21,7 @@
#include "Core/HLE/sceRtc.h"
#include "Core/System.h"
#include "Core/Dialog/PSPDialog.h"
#include "Core/Util/PPGeDraw.h"
#include "Common/CommonTypes.h"
#undef st_ctime
@@ -250,12 +251,9 @@ struct SaveFileInfo
tm modif_time;
u32 textureData;
int textureWidth;
int textureHeight;
PPGeImage *texture;
SaveFileInfo() : size(0), saveName(""), idx(0),
textureData(0), textureWidth(0), textureHeight(0)
SaveFileInfo() : size(0), saveName(""), idx(0), texture(NULL)
{
memset(title, 0, 128);
memset(saveTitle, 0, 128);
@@ -265,7 +263,7 @@ struct SaveFileInfo
void DoState(PointerWrap &p)
{
auto s = p.Section("SaveFileInfo", 1);
auto s = p.Section("SaveFileInfo", 1, 2);
if (!s)
return;
@@ -278,9 +276,30 @@ struct SaveFileInfo
p.DoArray(saveDetail, sizeof(saveDetail));
p.Do(modif_time);
p.Do(textureData);
p.Do(textureWidth);
p.Do(textureHeight);
if (s <= 1) {
u32 textureData;
int textureWidth;
int textureHeight;
p.Do(textureData);
p.Do(textureWidth);
p.Do(textureHeight);
if (textureData != 0) {
// Must be MODE_READ.
texture = new PPGeImage("");
texture->CompatLoad(textureData, textureWidth, textureHeight);
}
} else {
bool hasTexture = texture != NULL;
p.Do(hasTexture);
if (hasTexture) {
if (p.mode == p.MODE_READ) {
texture = new PPGeImage("");
}
texture->DoState(p);
}
}
}
};
@@ -337,7 +356,6 @@ public:
private:
void Clear();
bool CreatePNGIcon(u8* pngData, int pngSize, SaveFileInfo& info);
void SetFileInfo(int idx, PSPFileInfo &info, std::string saveName);
void SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::string saveName);
void ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName);
+111
View File
@@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <algorithm>
#include "Core/Util/PPGeDraw.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
@@ -24,6 +25,7 @@
#include "Core/HLE/sceGe.h"
#include "Core/MemMap.h"
#include "image/zim_load.h"
#include "image/png_load.h"
#include "util/text/utf8.h"
#include "Core/System.h"
@@ -802,3 +804,112 @@ void PPGeDisableTexture()
WriteCmd(GE_CMD_TEXTUREMAPENABLE, 0);
}
std::vector<PPGeImage *> PPGeImage::loadedTextures_;
PPGeImage::PPGeImage(const std::string &pspFilename)
: filename_(pspFilename), texture_(0) {
}
PPGeImage::PPGeImage(u32 pngPointer, size_t pngSize)
: filename_(""), png_(pngPointer), size_(pngSize) {
}
PPGeImage::~PPGeImage() {
Free();
}
bool PPGeImage::Load() {
Free();
// In case it fails to load.
width_ = 0;
height_ = 0;
unsigned char *textureData;
int success;
if (filename_.empty()) {
success = pngLoadPtr(Memory::GetPointer(png_), size_, &width_, &height_, &textureData, false);
} else {
std::string pngData;
if (pspFileSystem.ReadEntireFile(filename_, pngData) < 0) {
WARN_LOG(SCEGE, "Bad PPGeImage - cannot load file");
return false;
}
success = pngLoadPtr((const unsigned char *)&pngData[0], pngData.size(), &width_, &height_, &textureData, false);
}
if (!success) {
WARN_LOG(SCEGE, "Bad PPGeImage - not a valid png");
return false;
}
u32 texSize = width_ * height_ * 4;
texture_ = __PPGeDoAlloc(texSize, true, "Savedata Icon");
if (texture_ == 0) {
WARN_LOG(SCEGE, "Bad PPGeImage - unable to allocate space for texture");
return false;
}
Memory::Memcpy(texture_, textureData, texSize);
free(textureData);
lastFrame_ = gpuStats.numFlips;
loadedTextures_.push_back(this);
return true;
}
void PPGeImage::Free() {
if (texture_ != 0) {
kernelMemory.Free(texture_);
texture_ = 0;
loadedTextures_.erase(std::remove(loadedTextures_.begin(), loadedTextures_.end(), this), loadedTextures_.end());
}
}
void PPGeImage::DoState(PointerWrap &p) {
auto s = p.Section("PPGeImage", 1);
if (!s)
return;
p.Do(filename_);
p.Do(png_);
p.Do(size_);
p.Do(texture_);
p.Do(width_);
p.Do(height_);
p.Do(lastFrame_);
}
void PPGeImage::CompatLoad(u32 texture, int width, int height) {
// Won't be reloadable, so don't add to loadedTextures_.
texture_ = texture;
width_ = width;
height_ = height;
}
void PPGeImage::Decimate() {
static const int TOO_OLD_AGE = 30;
int tooOldFrame = gpuStats.numFlips - TOO_OLD_AGE;
for (size_t i = 0; i < loadedTextures_.size(); ++i) {
if (loadedTextures_[i]->lastFrame_ < tooOldFrame) {
loadedTextures_[i]->Free();
// That altered loadedTextures_.
--i;
}
}
}
void PPGeImage::SetTexture() {
if (texture_ == 0) {
Decimate();
Load();
}
if (texture_ != 0) {
lastFrame_ = gpuStats.numFlips;
PPGeSetTexture(texture_, width_, height_);
} else {
PPGeDisableTexture();
}
}
+42
View File
@@ -103,6 +103,48 @@ void PPGeDrawImage(int atlasImage, float x, float y, int align, u32 color = 0xFF
void PPGeDrawImage(int atlasImage, float x, float y, float w, float h, int align, u32 color = 0xFFFFFFFF);
void PPGeDrawImage(float x, float y, float w, float h, float u1, float v1, float u2, float v2, int tw, int th, u32 color);
class PPGeImage {
public:
PPGeImage(const std::string &pspFilename);
PPGeImage(u32 pngPointer, size_t pngSize);
~PPGeImage();
void SetTexture();
// Does not normally need to be called (except to force preloading.)
bool Load();
void Free();
void DoState(PointerWrap &p);
// Do not use, only for savestate upgrading.
void CompatLoad(u32 texture, int width, int height);
int Width() {
return width_;
}
int Height() {
return height_;
}
private:
static void Decimate();
static std::vector<PPGeImage *> loadedTextures_;
std::string filename_;
// Only valid if filename_.empty().
u32 png_;
size_t size_;
u32 texture_;
int width_;
int height_;
int lastFrame_;
};
void PPGeDrawRect(float x1, float y1, float x2, float y2, u32 color);
void PPGeSetDefaultTexture();