Make things more consistent in the no-present case

This commit is contained in:
Henrik Rydgård
2026-02-08 10:04:47 +01:00
parent 37052cc1ae
commit aa17599f66
4 changed files with 51 additions and 29 deletions
+6 -6
View File
@@ -321,17 +321,17 @@ float GetTargetScore(const Point2D &originPos, int originIndex, const View *orig
distance = 0.001f;
}
float overlap = 0.0f;
float dirX = dx / distance;
float dirY = dy / distance;
const float dirX = dx / distance;
const float dirY = dy / distance;
bool wrongDirection = false;
bool vertical = false;
float horizOverlap = HorizontalOverlap(origin->GetBounds(), destination->GetBounds());
float vertOverlap = VerticalOverlap(origin->GetBounds(), destination->GetBounds());
const float horizOverlap = HorizontalOverlap(origin->GetBounds(), destination->GetBounds());
const float vertOverlap = VerticalOverlap(origin->GetBounds(), destination->GetBounds());
if (horizOverlap == 1.0f && vertOverlap == 1.0f) {
if (direction != FOCUS_PREV_PAGE && direction != FOCUS_NEXT_PAGE) {
INFO_LOG(Log::UI, "Contain overlap");
return 0.0;
INFO_LOG(Log::UI, "Contain overlap: %s, %s", origin->Tag().c_str(), destination->Tag().c_str());
return 0.0f;
}
}
float originSize = 0.0f;
+22 -23
View File
@@ -1588,11 +1588,13 @@ void FramebufferManagerCommon::CopyDisplayToOutput(const DisplayLayoutConfig &co
DEBUG_LOG(Log::FrameBuf, "Display disabled, displaying only black");
}
// No framebuffer to display! Clear to black.
if (useBufferedRendering_) {
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }, "CopyDisplayToOutput");
}
presentation_->SourceBlank();
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE);
presentation_->NotifyPresent();
if (useBufferedRendering_) {
presentation_->CopyToOutput(config);
} else {
presentation_->NotifyPresent();
}
return;
}
@@ -1651,27 +1653,22 @@ void FramebufferManagerCommon::CopyDisplayToOutput(const DisplayLayoutConfig &co
if (Memory::IsValidAddress(fbaddr)) {
// The game is displaying something directly from RAM. In GTA, it's decoded video.
// If successful, this effectively calls presentation_->NotifyPresent();
if (DrawFramebufferToOutput(config, Memory::GetPointerUnchecked(fbaddr), displayStride_, displayFormat_)) {
presentation_->CopyToOutput(config);
} else {
if (useBufferedRendering_) {
// Bind and clear the backbuffer. This should be the first time during the frame that it's bound.
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }, "CopyDisplayToOutput_DrawError");
}
presentation_->NotifyPresent();
if (!DrawFramebufferToOutput(config, Memory::GetPointerUnchecked(fbaddr), displayStride_, displayFormat_)) {
// No framebuffer to display! Clear to black.
presentation_->SourceBlank();
}
return;
} else {
DEBUG_LOG(Log::FrameBuf, "Found no FBO to display! displayFBPtr = %08x", fbaddr);
// No framebuffer to display! Clear to black.
if (useBufferedRendering_) {
// Bind and clear the backbuffer. This should be the first time during the frame that it's bound.
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }, "CopyDisplayToOutput_NoFBO");
} // For non-buffered rendering, every frame is cleared anyway.
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE);
presentation_->NotifyPresent();
return;
// No framebuffer to display! Clear to black.
presentation_->SourceBlank();
}
if (useBufferedRendering_) {
presentation_->CopyToOutput(config);
} else {
presentation_->NotifyPresent();
}
return;
}
vfb->usageFlags |= FB_USAGE_DISPLAYED_FRAMEBUFFER;
@@ -1733,12 +1730,14 @@ void FramebufferManagerCommon::CopyDisplayToOutput(const DisplayLayoutConfig &co
presentation_->SourceFramebuffer(vfb->fbo, actualWidth, actualHeight);
presentation_->RunPostshaderPasses(config, flags, uvRotation, u0, v0, u1, v1);
presentation_->CopyToOutput(config);
} else if (useBufferedRendering_) {
WARN_LOG(Log::FrameBuf, "Using buffered rendering, and current VFB lacks an FBO: %08x", vfb->fb_address);
} else {
// This is OK because here we're in "skip buffered" mode, so even if we haven't presented
// we will have a render target.
presentation_->NotifyPresent();
if (useBufferedRendering_) {
presentation_->CopyToOutput(config);
} else {
presentation_->NotifyPresent();
}
}
// This may get called mid-draw if the game uses an immediate flip.
+20
View File
@@ -599,6 +599,15 @@ Draw::ShaderModule *PresentationCommon::CompileShaderModule(ShaderStage stage, S
return draw_->CreateShaderModule(stage, lang_, (const uint8_t *)translated.c_str(), translated.size(), "postshader");
}
void PresentationCommon::SourceBlank() {
DoRelease(srcTexture_);
DoRelease(srcFramebuffer_);
srcWidth_ = 0;
srcHeight_ = 0;
}
// If texture == null, that means there's nothing to display, so we should show a black screen in CopyToOutput.
void PresentationCommon::SourceTexture(Draw::Texture *texture, int bufferWidth, int bufferHeight) {
// AddRef before release and assign in case it's the same.
texture->AddRef();
@@ -682,6 +691,11 @@ void PresentationCommon::RunPostshaderPasses(const DisplayLayoutConfig &config,
}
CalculateDisplayOutputRect(config, &rc_, 480.0f, 272.0f, frame, uvRotation);
if (!srcTexture_ && !srcFramebuffer_) {
// Presenting blank, no need to run post shaders. But we did compute the output rect.
return;
}
// To make buffer updates easier, we use one array of verts.
int postVertsOffset = (int)sizeof(Vertex) * 4;
@@ -887,6 +901,12 @@ void PresentationCommon::CopyToOutput(const DisplayLayoutConfig &config) {
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }, "FinalBlit");
draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_);
if (!srcFramebuffer_ && !srcTexture_) {
// Bound blank. We're done (although we could draw a black rectangle here).
presentedThisFrame_ = true;
return;
}
Draw::Pipeline *pipeline = (outputFlags_ & OutputFlags::RB_SWIZZLE) ? texColorRBSwizzle_ : texColor_;
if (useStereo) {
+3
View File
@@ -124,6 +124,9 @@ public:
void DeviceRestore(Draw::DrawContext *draw);
void UpdateUniforms(bool hasVideo);
// One of these must be called every frame.
void SourceBlank();
void SourceTexture(Draw::Texture *texture, int bufferWidth, int bufferHeight);
void SourceFramebuffer(Draw::Framebuffer *fb, int bufferWidth, int bufferHeight);