VideoCommon: avoid assuming global state exists for 'EndUtilityDrawing', use last stored viewport/scissor rect instead

This commit is contained in:
iwubcode 2025-11-13 21:44:29 -06:00
parent 2acb49544c
commit a4599a1add
3 changed files with 36 additions and 3 deletions

View File

@ -34,10 +34,15 @@ void AbstractGfx::BeginUtilityDrawing()
void AbstractGfx::EndUtilityDrawing()
{
// Reset framebuffer/scissor/viewport. Pipeline will be reset at next draw.
// Reset framebuffer. Pipeline will be reset at next draw.
g_framebuffer_manager->BindEFBFramebuffer();
BPFunctions::SetScissorAndViewport(g_framebuffer_manager.get(), bpmem.scissorTL, bpmem.scissorBR,
bpmem.scissorOffset, xfmem.viewport);
// Reset our viewport and scissor to the last stored value
SetViewport(m_viewport_and_scissor.viewport_x, m_viewport_and_scissor.viewport_y,
m_viewport_and_scissor.viewport_width, m_viewport_and_scissor.viewport_height,
m_viewport_and_scissor.viewport_near_depth,
m_viewport_and_scissor.viewport_far_depth);
SetScissorRect(m_viewport_and_scissor.scissor_rect);
}
void AbstractGfx::SetFramebuffer(AbstractFramebuffer* framebuffer)
@ -87,6 +92,11 @@ void AbstractGfx::ClearRegion(const MathUtil::Rectangle<int>& target_rc, bool co
EndUtilityDrawing();
}
void AbstractGfx::StoreViewportAndScissor(const ViewportAndScissor& viewport_and_scissor)
{
m_viewport_and_scissor = viewport_and_scissor;
}
void AbstractGfx::SetViewportAndScissor(const MathUtil::Rectangle<int>& rect, float min_depth,
float max_depth)
{

View File

@ -126,6 +126,20 @@ public:
AbstractFramebuffer* GetCurrentFramebuffer() const { return m_current_framebuffer; }
struct ViewportAndScissor
{
MathUtil::Rectangle<int> scissor_rect;
float viewport_x;
float viewport_y;
float viewport_width;
float viewport_height;
float viewport_near_depth;
float viewport_far_depth;
};
// Stores the last viewport and scissor, the stored data is restored in 'EndUtilityDrawing'
void StoreViewportAndScissor(const ViewportAndScissor& viewport_and_scissor);
// Sets viewport and scissor to the specified rectangle. rect is assumed to be in framebuffer
// coordinates, i.e. lower-left origin in OpenGL.
void SetViewportAndScissor(const MathUtil::Rectangle<int>& rect, float min_depth = 0.0f,
@ -177,6 +191,7 @@ protected:
private:
Common::EventHook m_config_changed;
ViewportAndScissor m_viewport_and_scissor;
};
extern std::unique_ptr<AbstractGfx> g_gfx;

View File

@ -265,6 +265,14 @@ void SetScissorAndViewport(FramebufferManager* frame_buffer_manager, ScissorPos
y = static_cast<float>(g_gfx->GetCurrentFramebuffer()->GetHeight()) - y - height;
g_gfx->SetViewport(x, y, width, height, near_depth, far_depth);
g_gfx->StoreViewportAndScissor(AbstractGfx::ViewportAndScissor{.scissor_rect = converted_rc,
.viewport_x = x,
.viewport_y = y,
.viewport_width = width,
.viewport_height = height,
.viewport_near_depth = near_depth,
.viewport_far_depth = far_depth});
}
void SetDepthMode()