diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index b5b394409f..36609edda5 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -49,9 +49,11 @@ GameInfo::GameInfo() : fileType(IdentifiedFileType::UNKNOWN) { } GameInfo::~GameInfo() { - delete icon.texture; - delete pic0.texture; - delete pic1.texture; + std::lock_guard guard(lock); + sndDataLoaded = false; + icon.Clear(); + pic0.Clear(); + pic1.Clear(); delete fileLoader; } @@ -646,20 +648,6 @@ void GameInfoCache::Clear() { gameInfoWQ_->Flush(); gameInfoWQ_->WaitUntilDone(); } - for (auto iter = info_.begin(); iter != info_.end(); iter++) { - { - std::lock_guard lock(iter->second->lock); - iter->second->pic0.Clear(); - iter->second->pic1.Clear(); - iter->second->icon.Clear(); - - if (!iter->second->sndFileData.empty()) { - iter->second->sndFileData.clear(); - iter->second->sndDataLoaded = false; - } - } - delete iter->second; - } info_.clear(); } @@ -668,7 +656,6 @@ void GameInfoCache::FlushBGs() { std::lock_guard lock(iter->second->lock); iter->second->pic0.Clear(); iter->second->pic1.Clear(); - if (!iter->second->sndFileData.empty()) { iter->second->sndFileData.clear(); iter->second->sndDataLoaded = false; @@ -708,7 +695,7 @@ GameInfo *GameInfoCache::GetInfo(Draw::DrawContext *draw, const std::string &gam auto iter = info_.find(gamePath); if (iter != info_.end()) { - info = iter->second; + info = iter->second.get(); } // If wantFlags don't match, we need to start over. We'll just queue the work item again. @@ -745,22 +732,22 @@ GameInfo *GameInfoCache::GetInfo(Draw::DrawContext *draw, const std::string &gam GameInfoWorkItem *item = new GameInfoWorkItem(gamePath, info); gameInfoWQ_->Add(item); - info_[gamePath] = info; + info_[gamePath] = std::unique_ptr(info); return info; } -void GameInfoCache::SetupTexture(GameInfo *info, Draw::DrawContext *thin3d, GameInfoTex &icon) { +void GameInfoCache::SetupTexture(GameInfo *info, Draw::DrawContext *thin3d, GameInfoTex &tex) { using namespace Draw; - if (icon.data.size()) { - if (!icon.texture) { - icon.texture = CreateTextureFromFileData(thin3d, (const uint8_t *)icon.data.data(), (int)icon.data.size(), ImageFileType::DETECT); - if (icon.texture) { - icon.timeLoaded = time_now_d(); + if (tex.data.size()) { + if (!tex.texture) { + tex.texture = CreateTextureFromFileData(thin3d, (const uint8_t *)tex.data.data(), (int)tex.data.size(), ImageFileType::DETECT); + if (tex.texture) { + tex.timeLoaded = time_now_d(); } } if ((info->wantFlags & GAMEINFO_WANTBGDATA) == 0) { - icon.data.clear(); - icon.dataLoaded = false; + tex.data.clear(); + tex.dataLoaded = false; } } } diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 9191345202..616bf8947b 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -60,6 +60,12 @@ class FileLoader; enum class IdentifiedFileType; struct GameInfoTex { + GameInfoTex() {} + ~GameInfoTex() { + if (texture) { + ELOG("LEAKED GameInfoTex"); + } + } std::string data; ManagedTexture *texture = nullptr; // The time at which the Icon and the BG were loaded. @@ -77,6 +83,8 @@ struct GameInfoTex { texture = nullptr; } } +private: + DISALLOW_COPY_AND_ASSIGN(GameInfoTex); }; class GameInfo { @@ -145,6 +153,9 @@ protected: FileLoader *fileLoader = nullptr; std::string filePath_; + +private: + DISALLOW_COPY_AND_ASSIGN(GameInfo); }; class GameInfoCache { @@ -170,10 +181,10 @@ public: private: void Init(); void Shutdown(); - void SetupTexture(GameInfo *info, Draw::DrawContext *draw, GameInfoTex &icon); + void SetupTexture(GameInfo *info, Draw::DrawContext *draw, GameInfoTex &tex); // Maps ISO path to info. - std::map info_; + std::map > info_; // Work queue and management PrioritizedWorkQueue *gameInfoWQ_; diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 7085fb4481..c1731ffc29 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -44,7 +44,7 @@ #include "UI/GameInfoCache.h" AsyncImageFileView::AsyncImageFileView(const std::string &filename, UI::ImageSizeMode sizeMode, PrioritizedWorkQueue *wq, UI::LayoutParams *layoutParams) - : UI::Clickable(layoutParams), canFocus_(true), filename_(filename), color_(0xFFFFFFFF), sizeMode_(sizeMode), texture_(nullptr), textureFailed_(false), fixedSizeW_(0.0f), fixedSizeH_(0.0f) {} + : UI::Clickable(layoutParams), canFocus_(true), filename_(filename), color_(0xFFFFFFFF), sizeMode_(sizeMode), textureFailed_(false), fixedSizeW_(0.0f), fixedSizeH_(0.0f) {} AsyncImageFileView::~AsyncImageFileView() { delete texture_; @@ -75,10 +75,8 @@ void AsyncImageFileView::SetFilename(std::string filename) { if (filename_ != filename) { textureFailed_ = false; filename_ = filename; - if (texture_) { - delete texture_; - texture_ = nullptr; - } + delete texture_; + texture_ = nullptr; } } diff --git a/UI/PauseScreen.h b/UI/PauseScreen.h index 7fe25338eb..af128b2197 100644 --- a/UI/PauseScreen.h +++ b/UI/PauseScreen.h @@ -91,7 +91,7 @@ private: uint32_t color_; UI::ImageSizeMode sizeMode_; - ManagedTexture *texture_; + ManagedTexture *texture_ = nullptr; bool textureFailed_; float fixedSizeW_; float fixedSizeH_; diff --git a/UI/TextureUtil.cpp b/UI/TextureUtil.cpp index d2b8395cf8..927836994b 100644 --- a/UI/TextureUtil.cpp +++ b/UI/TextureUtil.cpp @@ -156,6 +156,7 @@ bool ManagedTexture::LoadFromFile(const std::string &filename, ImageFileType typ ManagedTexture *CreateTextureFromFile(Draw::DrawContext *draw, const char *filename, ImageFileType type, bool generateMips) { if (!draw) return nullptr; + // TODO: Load the texture on a background thread. ManagedTexture *mtex = new ManagedTexture(draw); if (!mtex->LoadFromFile(filename, type, generateMips)) { delete mtex; diff --git a/ext/native/gfx/gl_lost_manager.cpp b/ext/native/gfx/gl_lost_manager.cpp index 3fb56f44b4..915842e645 100644 --- a/ext/native/gfx/gl_lost_manager.cpp +++ b/ext/native/gfx/gl_lost_manager.cpp @@ -36,10 +36,14 @@ void unregister_gl_resource_holder(GfxResourceHolder *holder) { return; } if (holders) { + bool erased = false; for (size_t i = 0; i < holders->size(); i++) { if ((*holders)[i].holder == holder) { + if (erased) { + ELOG("GL object double-registered!"); + } holders->erase(holders->begin() + i); - return; + erased = true; } } WLOG("unregister_gl_resource_holder: Resource not registered"); diff --git a/ext/native/gfx_es2/glsl_program.cpp b/ext/native/gfx_es2/glsl_program.cpp index fadffff7b5..a4e2088500 100644 --- a/ext/native/gfx_es2/glsl_program.cpp +++ b/ext/native/gfx_es2/glsl_program.cpp @@ -221,13 +221,9 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { } void GLSLProgram::GLLost() { - // Quoth http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html; + // Quoth http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html: // "Note that when the EGL context is lost, all OpenGL resources associated with that context will be automatically deleted. // You do not need to call the corresponding "glDelete" methods such as glDeleteTextures to manually delete these lost resources." - // Hence, we comment out: - // glDeleteShader(this->vsh_); - // glDeleteShader(this->fsh_); - // glDeleteProgram(this->program_); program_ = 0; vsh_ = 0; fsh_ = 0;