mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-15 23:40:29 +02:00
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:
1 parent
18bcf63ee9
commit
2d3f0758c1
5 files changed
+220
-71
No files matched your search
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user