mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-01 03:57:17 +01:00
Secondary outputs, and --game-window on Mac to show the game in a second window
The ScreenManager keeps a list of secondary outputs, each with its own swapchain, recreated after a lost device. Platform code adds, resizes and removes them from any thread through Native_AddOutput() and friends, which take effect at the start of the next frame. Each frame, every output is drawn by the topmost screen that claims it (Screen::renderOutput). EmuScreen claims Game outputs: it presents the game there, laid out for that output, and leaves it out of the backbuffer, where the touch controls and the menus stay. Not in non-buffered mode, which draws straight into the backbuffer. --game-window opens such an output on Mac, with Metal. It's a smoke test for multiple swapchains, and a stand-in for an AirPlay display. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
56c76ace35
commit
d491fc90cf
17 files changed
+323
-8
No files matched your search
@@ -190,6 +190,38 @@ std::string config_filename;
|
||||
// that consumes it also sees those writes - with a plain bool it could see the flag first and keep stale bounds.
|
||||
static std::atomic<bool> resized{false};
|
||||
|
||||
struct OutputRequest {
|
||||
enum class Type {
|
||||
ADD,
|
||||
RESIZE,
|
||||
REMOVE,
|
||||
};
|
||||
Type type;
|
||||
int id;
|
||||
OutputRole role;
|
||||
Draw::SwapchainDesc desc;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
static std::mutex g_outputRequestLock;
|
||||
static std::vector<OutputRequest> g_outputRequests;
|
||||
static std::atomic<int> g_nextOutputId{1};
|
||||
|
||||
static void ProcessOutputRequests() {
|
||||
std::vector<OutputRequest> requests;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_outputRequestLock);
|
||||
requests.swap(g_outputRequests);
|
||||
}
|
||||
for (const OutputRequest &request : requests) {
|
||||
switch (request.type) {
|
||||
case OutputRequest::Type::ADD: g_screenManager->AddOutput(request.id, request.role, request.desc); break;
|
||||
case OutputRequest::Type::RESIZE: g_screenManager->ResizeOutput(request.id, request.width, request.height); break;
|
||||
case OutputRequest::Type::REMOVE: g_screenManager->RemoveOutput(request.id); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int renderCounter = 0;
|
||||
|
||||
struct PendingMessage {
|
||||
@@ -940,6 +972,8 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) {
|
||||
|
||||
g_screenManager->setUIContext(uiContext);
|
||||
g_screenManager->setPostRenderCallback(&CallbackPostRender, nullptr);
|
||||
// An output removed while there was no device can't be recreated, its surface may be gone.
|
||||
ProcessOutputRequests();
|
||||
g_screenManager->deviceRestored(g_draw);
|
||||
|
||||
g_audioBackend = System_CreateAudioBackend();
|
||||
@@ -1193,6 +1227,8 @@ void NativeFrame(GraphicsContext *graphicsContext) {
|
||||
#endif
|
||||
}
|
||||
|
||||
ProcessOutputRequests();
|
||||
|
||||
// NOTE: We must begin the frame before update, so we can do texture size queries and stuff in Measure etc.
|
||||
Draw::DebugFlags debugFlags = Draw::DebugFlags::NONE;
|
||||
if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::GPU_PROFILE)
|
||||
@@ -2000,6 +2036,35 @@ static bool IsWindowSmall(int pixelWidth, int pixelHeight) {
|
||||
return config.InternalRotationIsPortrait() ? (h < 480 + 80) : (w < 480 + 80);
|
||||
}
|
||||
|
||||
int Native_AddOutput(OutputRole role, const Draw::SwapchainDesc &desc) {
|
||||
OutputRequest request{};
|
||||
request.type = OutputRequest::Type::ADD;
|
||||
request.id = g_nextOutputId++;
|
||||
request.role = role;
|
||||
request.desc = desc;
|
||||
std::lock_guard<std::mutex> guard(g_outputRequestLock);
|
||||
g_outputRequests.push_back(request);
|
||||
return request.id;
|
||||
}
|
||||
|
||||
void Native_ResizeOutput(int id, int width, int height) {
|
||||
OutputRequest request{};
|
||||
request.type = OutputRequest::Type::RESIZE;
|
||||
request.id = id;
|
||||
request.width = width;
|
||||
request.height = height;
|
||||
std::lock_guard<std::mutex> guard(g_outputRequestLock);
|
||||
g_outputRequests.push_back(request);
|
||||
}
|
||||
|
||||
void Native_RemoveOutput(int id) {
|
||||
OutputRequest request{};
|
||||
request.type = OutputRequest::Type::REMOVE;
|
||||
request.id = id;
|
||||
std::lock_guard<std::mutex> guard(g_outputRequestLock);
|
||||
g_outputRequests.push_back(request);
|
||||
}
|
||||
|
||||
bool Native_UpdateScreenScale(int pixel_width, int pixel_height, float customScale) {
|
||||
INFO_LOG(Log::System, "Native_UpdateScreenScale: %dx%d, customScale=%f", pixel_width, pixel_height, customScale);
|
||||
|
||||
|
||||
Reference in new issue
Block a user