mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-03 13:01:55 +01:00
Android: Show the game on a second display, with the controls on the phone
A presentation display (HDMI or USB-C video out, some wireless displays, or the simulated ones in Developer options) gets a Presentation with a SurfaceView, whose surface becomes a Game output, when the backend is Vulkan. Otherwise Android keeps mirroring. The surface mustn't be touched after surfaceDestroyed returns, so the output is removed with the new Native_RemoveOutputAndWait(), which returns once the render thread has let go of it (or right away if the graphics are down). The UI drawn on an output now leaves out the main swapchain's pre-rotation, as the game already did. "In menus on %1" gets the device name from Settings.Global.DEVICE_NAME. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
f6fa84329e
commit
5fbd134a7d
10 files changed
+265
-10
No files matched your search
@@ -34,6 +34,7 @@
|
||||
#include <clocale>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -204,14 +205,22 @@ struct OutputRequest {
|
||||
int height;
|
||||
};
|
||||
static std::mutex g_outputRequestLock;
|
||||
static std::condition_variable g_outputRequestsDoneCond;
|
||||
static std::vector<OutputRequest> g_outputRequests;
|
||||
// Counts requests queued and handled, for Native_RemoveOutputAndWait. Under g_outputRequestLock.
|
||||
static uint64_t g_outputRequestsQueued = 0;
|
||||
static uint64_t g_outputRequestsDone = 0;
|
||||
// Whether the outputs have swapchains, between NativeInitGraphics and NativeShutdownGraphics.
|
||||
static bool g_outputsLive = false;
|
||||
static std::atomic<int> g_nextOutputId{1};
|
||||
|
||||
static void ProcessOutputRequests() {
|
||||
std::vector<OutputRequest> requests;
|
||||
uint64_t queued;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_outputRequestLock);
|
||||
requests.swap(g_outputRequests);
|
||||
queued = g_outputRequestsQueued;
|
||||
}
|
||||
for (const OutputRequest &request : requests) {
|
||||
switch (request.type) {
|
||||
@@ -220,6 +229,15 @@ static void ProcessOutputRequests() {
|
||||
case OutputRequest::Type::REMOVE: g_screenManager->RemoveOutput(request.id); break;
|
||||
}
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(g_outputRequestLock);
|
||||
g_outputRequestsDone = queued;
|
||||
g_outputRequestsDoneCond.notify_all();
|
||||
}
|
||||
|
||||
static void SetOutputsLive(bool live) {
|
||||
std::lock_guard<std::mutex> guard(g_outputRequestLock);
|
||||
g_outputsLive = live;
|
||||
g_outputRequestsDoneCond.notify_all();
|
||||
}
|
||||
|
||||
static int renderCounter = 0;
|
||||
@@ -975,6 +993,7 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) {
|
||||
// An output removed while there was no device can't be recreated, its surface may be gone.
|
||||
ProcessOutputRequests();
|
||||
g_screenManager->deviceRestored(g_draw);
|
||||
SetOutputsLive(true);
|
||||
|
||||
g_audioBackend = System_CreateAudioBackend();
|
||||
if (g_audioBackend) {
|
||||
@@ -1092,6 +1111,7 @@ void NativeShutdownGraphics(GraphicsContext *graphicsContext) {
|
||||
if (g_screenManager) {
|
||||
g_screenManager->deviceLost();
|
||||
}
|
||||
SetOutputsLive(false);
|
||||
g_iconCache.ClearTextures();
|
||||
|
||||
if (gpu) {
|
||||
@@ -2044,6 +2064,7 @@ int Native_AddOutput(OutputRole role, const Draw::SwapchainDesc &desc) {
|
||||
request.desc = desc;
|
||||
std::lock_guard<std::mutex> guard(g_outputRequestLock);
|
||||
g_outputRequests.push_back(request);
|
||||
g_outputRequestsQueued++;
|
||||
return request.id;
|
||||
}
|
||||
|
||||
@@ -2055,6 +2076,7 @@ void Native_ResizeOutput(int id, int width, int height) {
|
||||
request.height = height;
|
||||
std::lock_guard<std::mutex> guard(g_outputRequestLock);
|
||||
g_outputRequests.push_back(request);
|
||||
g_outputRequestsQueued++;
|
||||
}
|
||||
|
||||
void Native_RemoveOutput(int id) {
|
||||
@@ -2063,6 +2085,21 @@ void Native_RemoveOutput(int id) {
|
||||
request.id = id;
|
||||
std::lock_guard<std::mutex> guard(g_outputRequestLock);
|
||||
g_outputRequests.push_back(request);
|
||||
g_outputRequestsQueued++;
|
||||
}
|
||||
|
||||
bool Native_RemoveOutputAndWait(int id) {
|
||||
Native_RemoveOutput(id);
|
||||
std::unique_lock<std::mutex> lock(g_outputRequestLock);
|
||||
const uint64_t queued = g_outputRequestsQueued;
|
||||
// Without a device, the outputs have no swapchains to let go of.
|
||||
const bool done = g_outputRequestsDoneCond.wait_for(lock, std::chrono::seconds(3), [=] {
|
||||
return !g_outputsLive || g_outputRequestsDone >= queued;
|
||||
});
|
||||
if (!done) {
|
||||
ERROR_LOG(Log::G3D, "Timed out waiting for output %d to be removed", id);
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
bool Native_UpdateScreenScale(int pixel_width, int pixel_height, float customScale) {
|
||||
|
||||
Reference in new issue
Block a user