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
+38
-8
@@ -1643,14 +1643,14 @@ ScreenRenderFlags EmuScreen::PreRender(ScreenRenderMode mode) {
|
||||
|
||||
using namespace Draw;
|
||||
skipBufferEffects_ = g_Config.bSkipBufferEffects;
|
||||
UpdateGameOutput();
|
||||
if (!skipBufferEffects_ && PSP_IsInited()) {
|
||||
if (ShouldRunEmulation(mode)) {
|
||||
// We need to run emulation here, and perform all the normal render passes.
|
||||
return RunEmulation(false);
|
||||
} else if (gpu && GPUIsBuffered()) {
|
||||
// Need to check for gpu here, we might be in reset.
|
||||
const DeviceOrientation orientation = GetDeviceOrientation();
|
||||
const DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(orientation);
|
||||
const DisplayLayoutConfig &displayLayoutConfig = GameLayoutConfig();
|
||||
// We run just the post shaders.
|
||||
gpu->PrepareCopyDisplayToOutput(displayLayoutConfig);
|
||||
// Screens on top like reporting might want to take screenshots of existing framebuffers.
|
||||
@@ -1660,6 +1660,38 @@ ScreenRenderFlags EmuScreen::PreRender(ScreenRenderMode mode) {
|
||||
return ScreenRenderFlags::NONE;
|
||||
}
|
||||
|
||||
// Sends the game to a Game output, if there is one. Not in non-buffered mode, which draws straight
|
||||
// into the backbuffer during emulation.
|
||||
void EmuScreen::UpdateGameOutput() {
|
||||
const OutputDisplay *output = screenManager()->FindOutput(OutputRole::Game);
|
||||
gameOnOutput_ = output && gpu && !skipBufferEffects_ && GPUIsBuffered();
|
||||
if (!gpu) {
|
||||
return;
|
||||
}
|
||||
if (!gameOnOutput_) {
|
||||
gpu->SetPresentationOutput(nullptr);
|
||||
return;
|
||||
}
|
||||
OutputParams params;
|
||||
params.pixelWidth = output->swapchain->Width();
|
||||
params.pixelHeight = output->swapchain->Height();
|
||||
params.orientation = params.pixelHeight > params.pixelWidth * 1.1f ? DeviceOrientation::Portrait : DeviceOrientation::Landscape;
|
||||
gameOutputOrientation_ = params.orientation;
|
||||
gpu->SetPresentationOutput(¶ms);
|
||||
}
|
||||
|
||||
const DisplayLayoutConfig &EmuScreen::GameLayoutConfig() const {
|
||||
return g_Config.GetDisplayLayoutConfig(gameOnOutput_ ? gameOutputOrientation_ : GetDeviceOrientation());
|
||||
}
|
||||
|
||||
bool EmuScreen::renderOutput(const OutputDisplay &output) {
|
||||
if (output.role != OutputRole::Game || !gameOnOutput_ || !PSP_IsInited()) {
|
||||
return false;
|
||||
}
|
||||
gpu->CopyDisplayToOutput(GameLayoutConfig());
|
||||
return true;
|
||||
}
|
||||
|
||||
ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
|
||||
// Moved from update, because we want it to be possible for booting to happen even when the screen
|
||||
// is in the background, like when choosing Reset from the pause menu.
|
||||
@@ -1677,13 +1709,12 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
|
||||
System_Notify(SystemNotification::KEEP_SCREEN_AWAKE);
|
||||
}
|
||||
|
||||
const DeviceOrientation orientation = GetDeviceOrientation();
|
||||
const DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(orientation);
|
||||
const DisplayLayoutConfig &displayLayoutConfig = GameLayoutConfig();
|
||||
// We might have a bad viewport after RunEmulation, reset.
|
||||
Viewport viewport{0.0f, 0.0f, (float)g_display.pixel_xres, (float)g_display.pixel_yres, 0.0f, 1.0f};
|
||||
|
||||
if (!skipBufferEffects_ && !ShouldRunEmulation(mode)) {
|
||||
if (gpu) {
|
||||
if (gpu && !gameOnOutput_) {
|
||||
gpu->CopyDisplayToOutput(displayLayoutConfig);
|
||||
}
|
||||
draw->SetViewport(viewport);
|
||||
@@ -1716,7 +1747,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
|
||||
const bool skipBufferEffects = skipBufferEffects_;
|
||||
|
||||
// Gotta copy the output at some point. Also this is where we take the screenshot if needed.
|
||||
if (gpu) {
|
||||
if (gpu && !gameOnOutput_) {
|
||||
gpu->CopyDisplayToOutput(displayLayoutConfig);
|
||||
}
|
||||
|
||||
@@ -1771,8 +1802,7 @@ ScreenRenderFlags EmuScreen::RunEmulation(bool skipBufferEffects) {
|
||||
|
||||
g_OSD.NudgeIngameNotifications();
|
||||
|
||||
const DeviceOrientation orientation = GetDeviceOrientation();
|
||||
const DisplayLayoutConfig &displayLayoutConfig = g_Config.GetDisplayLayoutConfig(orientation);
|
||||
const DisplayLayoutConfig &displayLayoutConfig = GameLayoutConfig();
|
||||
__DisplaySetDisplayLayoutConfig(displayLayoutConfig);
|
||||
|
||||
DrawContext *draw = screenManager()->getDrawContext();
|
||||
|
||||
Reference in new issue
Block a user