From da1a04be8da8410abcf58f1261e8bc99e7aff4a7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 14 Feb 2016 22:07:10 +0100 Subject: [PATCH] Make the workqueue slightly safer. Put g_gameInfoCache on the heap. Cherry-picked from #8592 --- UI/BackgroundAudio.cpp | 2 +- UI/EmuScreen.cpp | 4 ++-- UI/GameInfoCache.cpp | 11 ++++++++-- UI/GameInfoCache.h | 9 ++++---- UI/GameScreen.cpp | 24 +++++++++++----------- UI/GameSettingsScreen.cpp | 2 +- UI/MainScreen.cpp | 6 +++--- UI/MiscScreens.cpp | 2 +- UI/NativeApp.cpp | 12 +++++------ UI/PauseScreen.cpp | 6 +++--- UI/SavedataScreen.cpp | 14 ++++++------- Windows/main.cpp | 4 +--- android/jni/app-android.cpp | 5 ++++- ext/glslang | 2 +- ext/native/gfx/gl_lost_manager.cpp | 4 ++-- ext/native/thin3d/thin3d_gl.cpp | 14 ++++--------- ext/native/thread/prioritizedworkqueue.cpp | 9 +++++--- ext/native/thread/prioritizedworkqueue.h | 7 ++++++- 18 files changed, 73 insertions(+), 64 deletions(-) diff --git a/UI/BackgroundAudio.cpp b/UI/BackgroundAudio.cpp index 64421d8312..c0128d9b8d 100644 --- a/UI/BackgroundAudio.cpp +++ b/UI/BackgroundAudio.cpp @@ -206,7 +206,7 @@ int PlayBackgroundAudio() { // last changed... (to prevent crazy amount of reads when skipping through a list) if (!at3Reader && bgGamePath.size() && (time_now_d() - gameLastChanged > 0.5)) { // Grab some audio from the current game and play it. - GameInfo *gameInfo = g_gameInfoCache.GetInfo(NULL, bgGamePath, GAMEINFO_WANTSND); + GameInfo *gameInfo = g_gameInfoCache->GetInfo(NULL, bgGamePath, GAMEINFO_WANTSND); if (!gameInfo) return 0; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index d8fc228688..65d9297058 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -89,7 +89,7 @@ void EmuScreen::bootGame(const std::string &filename) { } //pre-emptive loading of game specific config if possible, to get all the settings - GameInfo *info = g_gameInfoCache.GetInfo(NULL, filename, 0); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, filename, 0); if (info && !info->id.empty()) { g_Config.loadGameConfig(info->id); } @@ -139,7 +139,7 @@ void EmuScreen::bootComplete() { host->BootDone(); host->UpdateDisassembly(); - g_gameInfoCache.FlushBGs(); + g_gameInfoCache->FlushBGs(); NOTICE_LOG(BOOT, "Loading %s...", PSP_CoreParameter().fileToStart.c_str()); autoLoad(); diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 3464566ad6..eb87a979fa 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -45,7 +45,7 @@ #define unique_ptr auto_ptr #endif -GameInfoCache g_gameInfoCache; +GameInfoCache *g_gameInfoCache; GameInfo::~GameInfo() { delete iconTexture; @@ -583,6 +583,7 @@ handleELF: } info_->pending = false; info_->DisposeFileLoader(); + // ILOG("Completed writing info for %s", info_->GetTitle().c_str()); } virtual float priority() { @@ -595,9 +596,13 @@ private: DISALLOW_COPY_AND_ASSIGN(GameInfoWorkItem); }; +GameInfoCache::GameInfoCache() : gameInfoWQ_(nullptr) { + Init(); +} GameInfoCache::~GameInfoCache() { Clear(); + Shutdown(); } void GameInfoCache::Init() { @@ -614,8 +619,10 @@ void GameInfoCache::Shutdown() { } void GameInfoCache::Clear() { - if (gameInfoWQ_) + if (gameInfoWQ_) { gameInfoWQ_->Flush(); + gameInfoWQ_->WaitUntilDone(); + } for (auto iter = info_.begin(); iter != info_.end(); iter++) { { lock_guard lock(iter->second->lock); diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 9fa3c36a39..1770702162 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -175,13 +175,12 @@ protected: class GameInfoCache { public: - GameInfoCache() : gameInfoWQ_(0) {} + GameInfoCache(); ~GameInfoCache(); // This creates a background worker thread! - void Init(); - void Shutdown(); void Clear(); + void ClearTextures(); void PurgeType(IdentifiedFileType fileType); // All data in GameInfo including iconTexture may be zero the first time you call this @@ -199,6 +198,8 @@ public: } private: + void Init(); + void Shutdown(); void SetupTexture(GameInfo *info, std::string &textureData, Thin3DContext *thin3d, Thin3DTexture *&tex, double &loadTime); // Maps ISO path to info. @@ -209,4 +210,4 @@ private: }; // This one can be global, no good reason not to. -extern GameInfoCache g_gameInfoCache; +extern GameInfoCache *g_gameInfoCache; diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index fc74f7498f..b8b3b9fb53 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -44,8 +44,8 @@ GameScreen::~GameScreen() { } void GameScreen::CreateViews() { - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); - g_gameInfoCache.WaitUntilDone(info); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); + g_gameInfoCache->WaitUntilDone(info); I18NCategory *di = GetI18NCategory("Dialog"); I18NCategory *ga = GetI18NCategory("Game"); @@ -117,7 +117,7 @@ void GameScreen::CreateViews() { UI::EventReturn GameScreen::OnCreateConfig(UI::EventParams &e) { - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_,0); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_,0); g_Config.createGameConfig(info->id); g_Config.saveGameConfig(info->id); info->hasConfig = true; @@ -130,7 +130,7 @@ void GameScreen::CallbackDeleteConfig(bool yes) { if (yes) { - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, 0); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0); g_Config.deleteGameConfig(info->id); info->hasConfig = false; screenManager()->RecreateAllViews(); @@ -155,7 +155,7 @@ void GameScreen::update(InputState &input) { Thin3DContext *thin3d = screenManager()->getThin3DContext(); - GameInfo *info = g_gameInfoCache.GetInfo(thin3d, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); + GameInfo *info = g_gameInfoCache->GetInfo(thin3d, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); if (tvTitle_) tvTitle_->SetText(info->GetTitle() + " (" + info->id + ")"); @@ -216,7 +216,7 @@ UI::EventReturn GameScreen::OnPlay(UI::EventParams &e) { } UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) { - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); if (info && info->paramSFOLoaded) { std::string discID = info->paramSFO.GetValueString("DISC_ID"); screenManager()->push(new GameSettingsScreen(gamePath_, discID, true)); @@ -227,7 +227,7 @@ UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) { UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) { I18NCategory *di = GetI18NCategory("Dialog"); I18NCategory *ga = GetI18NCategory("Game"); - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); if (info) { // Check that there's any savedata to delete std::vector saveDirs = info->GetSaveDataDirectories(); @@ -243,7 +243,7 @@ UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) { } void GameScreen::CallbackDeleteSaveData(bool yes) { - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, 0); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0); if (yes) { info->DeleteAllSaveData(); info->saveDataSize = 0; @@ -254,7 +254,7 @@ void GameScreen::CallbackDeleteSaveData(bool yes) { UI::EventReturn GameScreen::OnDeleteGame(UI::EventParams &e) { I18NCategory *di = GetI18NCategory("Dialog"); I18NCategory *ga = GetI18NCategory("Game"); - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); if (info) { screenManager()->push( new PromptScreen(di->T("DeleteConfirmGame", "Do you really want to delete this game\nfrom your device? You can't undo this."), ga->T("ConfirmDelete"), di->T("Cancel"), @@ -265,16 +265,16 @@ UI::EventReturn GameScreen::OnDeleteGame(UI::EventParams &e) { } void GameScreen::CallbackDeleteGame(bool yes) { - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, 0); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0); if (yes) { info->Delete(); - g_gameInfoCache.Clear(); + g_gameInfoCache->Clear(); screenManager()->switchScreen(new MainScreen()); } } UI::EventReturn GameScreen::OnCreateShortcut(UI::EventParams &e) { - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, 0); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0); if (info) { host->CreateDesktopShortcut(gamePath_, info->GetTitle()); } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 6afb8510d9..be63de07a1 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -77,7 +77,7 @@ bool GameSettingsScreen::UseVerticalLayout() const { } void GameSettingsScreen::CreateViews() { - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); if (bEditThenRestore) { diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index bd98b3ccea..17b0973d61 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -173,7 +173,7 @@ private: }; void GameButton::Draw(UIContext &dc) { - GameInfo *ginfo = g_gameInfoCache.GetInfo(dc.GetThin3DContext(), gamePath_, 0); + GameInfo *ginfo = g_gameInfoCache->GetInfo(dc.GetThin3DContext(), gamePath_, 0); Thin3DTexture *texture = 0; u32 color = 0, shadowColor = 0; using namespace UI; @@ -976,7 +976,7 @@ bool MainScreen::DrawBackgroundFor(UIContext &dc, const std::string &gamePath, f GameInfo *ginfo = 0; if (!gamePath.empty()) { - ginfo = g_gameInfoCache.GetInfo(dc.GetThin3DContext(), gamePath, GAMEINFO_WANTBG); + ginfo = g_gameInfoCache->GetInfo(dc.GetThin3DContext(), gamePath, GAMEINFO_WANTBG); // Loading texture data may bind a texture. dc.RebindTexture(); @@ -1009,7 +1009,7 @@ UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) { std::string path = e.s; #endif GameInfo *ginfo = 0; - ginfo = g_gameInfoCache.GetInfo(nullptr, path, GAMEINFO_WANTBG); + ginfo = g_gameInfoCache->GetInfo(nullptr, path, GAMEINFO_WANTBG); if (ginfo && ginfo->fileType == FILETYPE_PSP_SAVEDATA_DIRECTORY) { return UI::EVENT_DONE; } diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 1faf067bd1..f9e616263e 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -105,7 +105,7 @@ void DrawBackground(UIContext &dc, float alpha = 1.0f) { } void DrawGameBackground(UIContext &dc, const std::string &gamePath) { - GameInfo *ginfo = g_gameInfoCache.GetInfo(dc.GetThin3DContext(), gamePath, GAMEINFO_WANTBG); + GameInfo *ginfo = g_gameInfoCache->GetInfo(dc.GetThin3DContext(), gamePath, GAMEINFO_WANTBG); dc.Flush(); if (ginfo) { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 6385dca2e8..ed8c845d23 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -486,8 +486,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch if (!boot_filename.empty() && stateToLoad != NULL) SaveState::Load(stateToLoad); - g_gameInfoCache.Init(); - screenManager = new ScreenManager(); if (skipLogo) { screenManager->switchScreen(new EmuScreen(boot_filename)); @@ -596,6 +594,8 @@ void NativeInitGraphics(GraphicsContext *graphicsContext) { winAudioBackend = CreateAudioBackend((AudioBackendType)g_Config.iAudioBackend); winAudioBackend->Init(MainWindow::GetHWND(), &Win32Mix, 44100); #endif + + g_gameInfoCache = new GameInfoCache(); } void NativeShutdownGraphics() { @@ -606,7 +606,8 @@ void NativeShutdownGraphics() { screenManager->deviceLost(); - g_gameInfoCache.Clear(); + delete g_gameInfoCache; + g_gameInfoCache = nullptr; uiTexture->Release(); @@ -764,13 +765,12 @@ void NativeUpdate(InputState &input) { } void NativeDeviceLost() { - g_gameInfoCache.Clear(); + // g_gameInfoCache.Clear(); screenManager->deviceLost(); if (GetGPUBackend() == GPUBackend::OPENGL) { gl_lost(); } - // Should dirty EVERYTHING } bool NativeIsAtTopLevel() { @@ -933,8 +933,6 @@ void NativeShutdown() { delete screenManager; screenManager = 0; - g_gameInfoCache.Shutdown(); - delete host; host = 0; g_Config.Save(); diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index a47aa0ecbc..ca43c32fd9 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -181,7 +181,7 @@ SaveSlotView::SaveSlotView(const std::string &gameFilename, int slot, UI::Layout using namespace UI; screenshotFilename_ = SaveState::GenerateSaveSlotFilename(gamePath_, slot, "jpg"); - PrioritizedWorkQueue *wq = g_gameInfoCache.WorkQueue(); + PrioritizedWorkQueue *wq = g_gameInfoCache->WorkQueue(); Add(new Spacer(5)); AsyncImageFileView *fv = Add(new AsyncImageFileView(screenshotFilename_, IS_DEFAULT, wq, new UI::LayoutParams(82 * 2, 47 * 2))); @@ -409,7 +409,7 @@ UI::EventReturn GamePauseScreen::OnSwitchUMD(UI::EventParams &e) { void GamePauseScreen::CallbackDeleteConfig(bool yes) { if (yes) { - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, 0); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0); g_Config.unloadGameConfig(); g_Config.deleteGameConfig(info->id); info->hasConfig = false; @@ -423,7 +423,7 @@ UI::EventReturn GamePauseScreen::OnCreateConfig(UI::EventParams &e) g_Config.createGameConfig(gameId); g_Config.changeGameSpecific(gameId); g_Config.saveGameConfig(gameId); - GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, 0); + GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0); if (info) { info->hasConfig = true; } diff --git a/UI/SavedataScreen.cpp b/UI/SavedataScreen.cpp index 73c6ca3bb5..3d8283c2e9 100644 --- a/UI/SavedataScreen.cpp +++ b/UI/SavedataScreen.cpp @@ -58,7 +58,7 @@ public: void CreatePopupContents(UI::ViewGroup *parent) override { using namespace UI; - GameInfo *ginfo = g_gameInfoCache.GetInfo(screenManager()->getThin3DContext(), savePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); + GameInfo *ginfo = g_gameInfoCache->GetInfo(screenManager()->getThin3DContext(), savePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); LinearLayout *root = new LinearLayout(ORIENT_VERTICAL); parent->Add(root); if (!ginfo) @@ -86,7 +86,7 @@ public: } else { std::string image_path = ReplaceAll(savePath_, ".ppst", ".jpg"); if (File::Exists(image_path)) { - PrioritizedWorkQueue *wq = g_gameInfoCache.WorkQueue(); + PrioritizedWorkQueue *wq = g_gameInfoCache->WorkQueue(); toprow->Add(new AsyncImageFileView(image_path, IS_DEFAULT, wq, new UI::LayoutParams(500, 500/16*9))); } else { toprow->Add(new TextView(sa->T("No screenshot"), new LinearLayoutParams(Margins(10, 5)))); @@ -128,7 +128,7 @@ private: }; UI::EventReturn SavedataPopupScreen::OnDeleteButtonClick(UI::EventParams &e) { - GameInfo *ginfo = g_gameInfoCache.GetInfo(nullptr, savePath_, GAMEINFO_WANTSIZE); + GameInfo *ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GAMEINFO_WANTSIZE); ginfo->Delete(); screenManager()->finishDialog(this, DR_NO); return UI::EVENT_DONE; @@ -142,7 +142,7 @@ static std::string CleanSaveString(std::string str) { } void SavedataButton::Draw(UIContext &dc) { - GameInfo *ginfo = g_gameInfoCache.GetInfo(dc.GetThin3DContext(), savePath_, GAMEINFO_WANTSIZE); + GameInfo *ginfo = g_gameInfoCache->GetInfo(dc.GetThin3DContext(), savePath_, GAMEINFO_WANTSIZE); Thin3DTexture *texture = 0; u32 color = 0, shadowColor = 0; using namespace UI; @@ -274,8 +274,8 @@ SavedataBrowser::SavedataBrowser(std::string path, UI::LayoutParams *layoutParam } SavedataBrowser::~SavedataBrowser() { - g_gameInfoCache.PurgeType(FILETYPE_PPSSPP_SAVESTATE); - g_gameInfoCache.PurgeType(FILETYPE_PSP_SAVEDATA_DIRECTORY); + g_gameInfoCache->PurgeType(FILETYPE_PPSSPP_SAVESTATE); + g_gameInfoCache->PurgeType(FILETYPE_PSP_SAVEDATA_DIRECTORY); } void SavedataBrowser::Refresh() { @@ -368,7 +368,7 @@ void SavedataScreen::CreateViews() { } UI::EventReturn SavedataScreen::OnSavedataButtonClick(UI::EventParams &e) { - GameInfo *ginfo = g_gameInfoCache.GetInfo(screenManager()->getThin3DContext(), e.s, 0); + GameInfo *ginfo = g_gameInfoCache->GetInfo(screenManager()->getThin3DContext(), e.s, 0); screenManager()->push(new SavedataPopupScreen(e.s, ginfo->GetTitle())); // the game path: e.s; return UI::EVENT_DONE; diff --git a/Windows/main.cpp b/Windows/main.cpp index b68b3377f0..7faef1bf22 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -552,7 +552,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin { //hack to enable/disable menu command accelerate keys MainWindow::UpdateCommands(); - + //hack to make it possible to get to main window from floating windows with Esc if (msg.hwnd != hwndMain && msg.wParam == VK_ESCAPE) BringWindowToTop(hwndMain); @@ -600,8 +600,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin delete host; g_Config.Save(); - g_gameInfoCache.Clear(); - g_gameInfoCache.Shutdown(); LogManager::Shutdown(); if (g_Config.bRestartRequired) { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index da584745b0..aaa541281f 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -31,6 +31,7 @@ #include "Common/GraphicsContext.h" #include "Common/GL/GLInterfaceBase.h" +#include "UI/GameInfoCache.h" #include "app-android.h" @@ -736,7 +737,9 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J ProcessFrameCommands(env); } - // Restore lost device objects. TODO: This feels like the wrong place for this. + ILOG("After render loop."); + g_gameInfoCache->WorkQueue()->Flush(); + NativeDeviceLost(); ILOG("NativeDeviceLost completed."); diff --git a/ext/glslang b/ext/glslang index c49d1ab8cd..7aaea5a33b 160000 --- a/ext/glslang +++ b/ext/glslang @@ -1 +1 @@ -Subproject commit c49d1ab8cdf04e90e307c516b8618ba9840b0231 +Subproject commit 7aaea5a33ba0c4165cdffb008e7cda2858d0c985 diff --git a/ext/native/gfx/gl_lost_manager.cpp b/ext/native/gfx/gl_lost_manager.cpp index 98cf37c52d..0462f2e890 100644 --- a/ext/native/gfx/gl_lost_manager.cpp +++ b/ext/native/gfx/gl_lost_manager.cpp @@ -49,10 +49,10 @@ void gl_lost() { // TODO: We should really do this when we get the context back, not during gl_lost... ILOG("gl_lost() restoring %i items:", (int)holders->size()); for (size_t i = 0; i < holders->size(); i++) { - ILOG("GLLost(%i / %i, %p)", (int)(i + 1), (int) holders->size(), (*holders)[i]); + ILOG("GLLost(%i / %i, %p, %08x)", (int)(i + 1), (int) holders->size(), (*holders)[i], *((uint32_t *)((*holders)[i]))); (*holders)[i]->GLLost(); } - ILOG("gl_lost() completed restoring %i items:", (int)holders->size()); + ILOG("gl_lost() completed on %i items:", (int)holders->size()); inLost = false; } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 9a706688ed..62101d27be 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -473,17 +473,11 @@ public: } void GLLost() override { + // We lost our GL context - zero out the tex_. + tex_ = 0; generatedMips_ = false; - if (!filename_.empty()) { - if (LoadFromFile(filename_.c_str())) { - ILOG("Reloaded lost texture %s", filename_.c_str()); - } else { - ELOG("Failed to reload lost texture %s", filename_.c_str()); - } - } else { - WLOG("Texture %p cannot be restored - has no filename", this); - tex_ = 0; - } + // Don't try to restore stuff, that's not what this is for. Lost just means + // that all our textures and buffers are invalid. } void Finalize(int zim_flags) override; diff --git a/ext/native/thread/prioritizedworkqueue.cpp b/ext/native/thread/prioritizedworkqueue.cpp index 9559ead072..421d08b92d 100644 --- a/ext/native/thread/prioritizedworkqueue.cpp +++ b/ext/native/thread/prioritizedworkqueue.cpp @@ -23,13 +23,14 @@ void PrioritizedWorkQueue::Stop() { } void PrioritizedWorkQueue::Flush() { - if (queue_.empty()) - return; lock_guard guard(mutex_); + int flush_count = 0; for (auto iter = queue_.begin(); iter != queue_.end(); ++iter) { delete *iter; + flush_count++; } queue_.clear(); + ILOG("Flushed %d un-executed tasks", flush_count); } void PrioritizedWorkQueue::WaitUntilDone() { @@ -40,7 +41,7 @@ void PrioritizedWorkQueue::WaitUntilDone() { bool empty; { lock_guard guard(mutex_); - empty = queue_.empty(); + empty = queue_.empty() && !working_; } if (empty) { break; @@ -53,6 +54,7 @@ void PrioritizedWorkQueue::WaitUntilDone() { // The worker should simply call this in a loop. Will block when appropriate. PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { lock_guard guard(mutex_); + working_ = false; // The thread only calls Pop if it's done. if (done_) { return 0; } @@ -77,6 +79,7 @@ PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { if (best != queue_.end()) { PrioritizedWorkQueueItem *poppedItem = *best; queue_.erase(best); + working_ = true; // This will be worked on. return poppedItem; } else { // Not really sure how this can happen, but let's be safe. diff --git a/ext/native/thread/prioritizedworkqueue.h b/ext/native/thread/prioritizedworkqueue.h index 7ed8165177..9ebfd21df0 100644 --- a/ext/native/thread/prioritizedworkqueue.h +++ b/ext/native/thread/prioritizedworkqueue.h @@ -23,7 +23,7 @@ private: class PrioritizedWorkQueue { public: - PrioritizedWorkQueue() : done_(false) {} + PrioritizedWorkQueue() : done_(false), working_(false) {} ~PrioritizedWorkQueue(); // Takes ownership. void Add(PrioritizedWorkQueueItem *item); @@ -36,8 +36,13 @@ public: void Stop(); void WaitUntilDone(); + bool IsWorking() { + return working_; + } + private: bool done_; + bool working_; recursive_mutex mutex_; condition_variable notEmpty_;