mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-15 23:40:29 +02:00
The core and the headless tools no longer use mutexes, condition variables, spinlocks, std::atomic, std::thread or volatile flags. Threads hand off through libretro-common's retro_atomic and rthreads plus a few small pieces on top of them in Common/Thread: Thread, MpscQueue, EventCounter, ParkingLot waits and ReaderGate. Every wait blocks until it's woken; nothing polls on a timer. State that only one thread touches just loses its lock. The PSP filesystem, sceIo and the savedata dialog now belong to the emulation thread: async reads and writes run when they're queued and complete later in emulated time, and the IO and savedata threads are gone. The friend finder only talks to the adhoc server and hands what it gets to the emulation thread. GPU init always runs on the thread that starts the game. The Vulkan render and compile queues, pipeline and render pass caches, delete list and SPIR-V cache, the GL render queue, the software renderer's jit caches, the file loader caches, the web debugger, UPnP, input, savestates, logging and the GE debugger all hand off through queues and atomics. The IR jit's spinning profiler thread goes. A CPU thread with nothing to run now sleeps until work is queued instead of spinning. Headless with --debugger waits for a client while stopped, and ends the run once every client that connected has left. Web server shutdown keeps servicing the CPU queue until the server has finished.
153 lines
5.4 KiB
C++
153 lines
5.4 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
#include <functional>
|
|
|
|
#include "Common/Common.h"
|
|
|
|
#include <queues/mpsc_stack.h>
|
|
|
|
// Shows a visible message to the user.
|
|
// The default implementation in NativeApp.cpp uses our "osm" system (on screen messaging).
|
|
enum class OSDType {
|
|
MESSAGE_INFO,
|
|
MESSAGE_SUCCESS,
|
|
MESSAGE_WARNING,
|
|
MESSAGE_ERROR,
|
|
MESSAGE_ERROR_DUMP, // displays lots of text (after the first line), small size
|
|
MESSAGE_FILE_LINK,
|
|
MESSAGE_CENTERED_WARNING,
|
|
MESSAGE_CENTERED_ERROR,
|
|
|
|
ACHIEVEMENT_UNLOCKED,
|
|
|
|
// Side entries
|
|
ACHIEVEMENT_PROGRESS, // Achievement icon + "measured_progress" text, auto-hide after 2s
|
|
ACHIEVEMENT_CHALLENGE_INDICATOR, // Achievement icon ONLY, no auto-hide
|
|
|
|
LEADERBOARD_TRACKER,
|
|
LEADERBOARD_STARTED_FAILED,
|
|
LEADERBOARD_SUBMITTED,
|
|
|
|
PROGRESS_BAR,
|
|
|
|
STATUS_ICON, // Use icons from the atlas
|
|
|
|
VALUE_COUNT,
|
|
};
|
|
|
|
#undef None // X11, sigh.
|
|
|
|
enum class OSDMessageFlags {
|
|
None = 0,
|
|
SpinLeft = 1,
|
|
SpinRight = 2,
|
|
Transparent = 4,
|
|
};
|
|
ENUM_CLASS_BITOPS(OSDMessageFlags);
|
|
|
|
// Data holder for on-screen messages.
|
|
// Show/Set/Cancel may be called from any thread: they queue a command. Update(),
|
|
// Entries(), IsEmpty(), ClickEntry() and the ingame nudge belong to the one thread
|
|
// that drives the display, which applies the queued commands in Update().
|
|
class OnScreenDisplay {
|
|
public:
|
|
OnScreenDisplay();
|
|
~OnScreenDisplay();
|
|
|
|
// If you specify 0.0f as duration, a duration will be chosen automatically depending on type.
|
|
void Show(OSDType type, std::string_view text, float duration_s = 0.0f, const char *id = nullptr) {
|
|
Show(type, text, "", duration_s, id);
|
|
}
|
|
void Show(OSDType type, std::string_view text, std::string_view text2, float duration_s = 0.0f, const char *id = nullptr) {
|
|
Show(type, text, text2, "", duration_s, id);
|
|
}
|
|
void Show(OSDType type, std::string_view text, std::string_view text2, std::string_view icon, float duration_s = 0.0f, const char *id = nullptr);
|
|
|
|
void ShowOnOff(std::string_view message, bool on, float duration_s = 0.0f);
|
|
void CancelById(std::string_view id);
|
|
|
|
bool IsEmpty() const { return entries_.empty(); } // Shortcut to skip rendering.
|
|
|
|
// Call this every frame, cleans up old entries.
|
|
void Update();
|
|
|
|
// Specialized achievement-related types. These go to the side notifications, not the top-middle.
|
|
void ShowAchievementUnlocked(int achievementID);
|
|
void ShowAchievementProgress(int achievementID, bool show); // call with show=false to hide. There can only be one of these. When hiding it's ok to not pass a valid achievementID.
|
|
void ShowChallengeIndicator(int achievementID, bool show); // call with show=false to hide.
|
|
void ShowLeaderboardTracker(int leaderboardTrackerID, std::string_view trackerText, bool show); // show=true is used both for create and update.
|
|
void ShowLeaderboardStartEnd(std::string_view title, std::string_view description, bool started); // started = true for started, false for ended.
|
|
void ShowLeaderboardSubmitted(std::string_view title, std::string_view value);
|
|
|
|
// Progress bar controls
|
|
// Set is both create and update. If you set maxValue <= minValue, you'll create an "indeterminate" progress
|
|
// bar that doesn't show a specific amount of progress.
|
|
void SetProgressBar(std::string_view id, std::string_view message, float minValue, float maxValue, float progress, float delay_s);
|
|
void RemoveProgressBar(std::string_view id, bool success, float delay_s);
|
|
|
|
// Call every frame to keep the sidebar visible. Otherwise it'll fade out.
|
|
void NudgeIngameNotifications();
|
|
float IngameAlpha() const;
|
|
|
|
// Fades out everything related to achievements. Should be used on game shutdown.
|
|
void ClearAchievementStuff();
|
|
|
|
// Can't add an infinite number of "Show" functions, so starting to offer post-modification.
|
|
void SetFlags(std::string_view id, OSDMessageFlags flag);
|
|
void SetClickCallback(std::string_view id, std::function<void()> callback);
|
|
|
|
struct Entry {
|
|
OSDType type;
|
|
std::string text;
|
|
std::string text2;
|
|
std::string iconName;
|
|
int numericID;
|
|
std::string id;
|
|
OSDMessageFlags flags;
|
|
|
|
std::function<void()> clickCallback;
|
|
|
|
int instanceID;
|
|
double startTime;
|
|
double endTime;
|
|
|
|
// Progress-bar-only data:
|
|
float minValue;
|
|
float maxValue;
|
|
float progress;
|
|
};
|
|
|
|
std::vector<Entry> Entries();
|
|
|
|
// TODO: Use something more stable than the index.
|
|
void ClickEntry(size_t index, double now);
|
|
|
|
static float FadeinTime() { return 0.1f; }
|
|
static float FadeoutTime() { return 0.25f; }
|
|
|
|
private:
|
|
void Post(std::function<void(OnScreenDisplay &)> fn);
|
|
|
|
void ShowNow(OSDType type, std::string_view text, std::string_view text2, std::string_view icon, float duration_s, const char *id);
|
|
void CancelByIdNow(std::string_view id);
|
|
void ShowAchievementUnlockedNow(int achievementID);
|
|
void ShowAchievementProgressNow(int achievementID, bool show);
|
|
void ShowChallengeIndicatorNow(int achievementID, bool show);
|
|
void ShowLeaderboardTrackerNow(int leaderboardTrackerID, std::string_view trackerText, bool show);
|
|
void SetProgressBarNow(std::string_view id, std::string_view message, float minValue, float maxValue, float progress, float delay_s);
|
|
void RemoveProgressBarNow(std::string_view id, bool success, float delay_s);
|
|
void ClearAchievementStuffNow();
|
|
void SetClickCallbackNow(std::string_view id, std::function<void()> callback);
|
|
void SetFlagsNow(std::string_view id, OSDMessageFlags flags);
|
|
|
|
std::vector<Entry> entries_; // display thread only
|
|
mpsc_stack_t pending_;
|
|
|
|
double sideBarShowTime_ = 0.0;
|
|
};
|
|
|
|
extern OnScreenDisplay g_OSD;
|