mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
Renderer: Handle resize events on-demand instead of polling
We now differentiate between a resize event and surface change/destroyed event, reducing the overhead for resizes in the Vulkan backend. It is also now now safe to change the surface multiple times if the video thread is lagging behind.
This commit is contained in:
@ -845,12 +845,10 @@ std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTe
|
||||
|
||||
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
|
||||
{
|
||||
u32 backbuffer_width = std::max(GLInterface->GetBackBufferWidth(), 1u);
|
||||
u32 backbuffer_height = std::max(GLInterface->GetBackBufferHeight(), 1u);
|
||||
|
||||
s_raster_font->printMultilineText(text, left * 2.0f / static_cast<float>(backbuffer_width) - 1.0f,
|
||||
1.0f - top * 2.0f / static_cast<float>(backbuffer_height), 0,
|
||||
backbuffer_width, backbuffer_height, color);
|
||||
s_raster_font->printMultilineText(text,
|
||||
left * 2.0f / static_cast<float>(m_backbuffer_width) - 1.0f,
|
||||
1.0f - top * 2.0f / static_cast<float>(m_backbuffer_height), 0,
|
||||
m_backbuffer_width, m_backbuffer_height, color);
|
||||
}
|
||||
|
||||
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||
@ -1319,15 +1317,16 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
|
||||
ResetAPIState();
|
||||
|
||||
UpdateDrawRectangle();
|
||||
TargetRectangle flipped_trc = GetTargetRectangle();
|
||||
|
||||
// Flip top and bottom for some reason; TODO: Fix the code to suck less?
|
||||
std::swap(flipped_trc.top, flipped_trc.bottom);
|
||||
|
||||
// Do our OSD callbacks
|
||||
OSD::DoCallbacks(OSD::CallbackType::OnFrame);
|
||||
|
||||
// Check if we need to render to a new surface.
|
||||
CheckForSurfaceChange();
|
||||
CheckForSurfaceResize();
|
||||
UpdateDrawRectangle();
|
||||
TargetRectangle flipped_trc = GetTargetRectangle();
|
||||
std::swap(flipped_trc.top, flipped_trc.bottom);
|
||||
|
||||
// Skip screen rendering when running in headless mode.
|
||||
if (!IsHeadless())
|
||||
{
|
||||
@ -1357,32 +1356,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
glFlush();
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
// Handle surface changes on Android.
|
||||
if (m_surface_needs_change.IsSet())
|
||||
{
|
||||
GLInterface->UpdateHandle(m_new_surface_handle);
|
||||
GLInterface->UpdateSurface();
|
||||
m_surface_handle = m_new_surface_handle;
|
||||
m_new_surface_handle = nullptr;
|
||||
m_surface_needs_change.Clear();
|
||||
m_surface_changed.Set();
|
||||
}
|
||||
#endif
|
||||
|
||||
GLInterface->Update();
|
||||
|
||||
// Was the size changed since the last frame?
|
||||
bool window_resized = false;
|
||||
int window_width = static_cast<int>(std::max(GLInterface->GetBackBufferWidth(), 1u));
|
||||
int window_height = static_cast<int>(std::max(GLInterface->GetBackBufferHeight(), 1u));
|
||||
if (window_width != m_backbuffer_width || window_height != m_backbuffer_height)
|
||||
{
|
||||
window_resized = true;
|
||||
m_backbuffer_width = window_width;
|
||||
m_backbuffer_height = window_height;
|
||||
}
|
||||
|
||||
bool target_size_changed = CalculateTargetSize();
|
||||
bool stencil_buffer_enabled =
|
||||
static_cast<FramebufferManager*>(g_framebuffer_manager.get())->HasStencilBuffer();
|
||||
@ -1392,10 +1366,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
stencil_buffer_enabled != BoundingBox::NeedsStencilBuffer() ||
|
||||
s_last_stereo_mode != (g_ActiveConfig.stereo_mode != StereoMode::Off);
|
||||
|
||||
if (window_resized || fb_needs_update)
|
||||
{
|
||||
UpdateDrawRectangle();
|
||||
}
|
||||
if (fb_needs_update)
|
||||
{
|
||||
s_last_stereo_mode = g_ActiveConfig.stereo_mode != StereoMode::Off;
|
||||
@ -1415,6 +1385,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
g_framebuffer_manager = std::make_unique<FramebufferManager>(
|
||||
m_target_width, m_target_height, s_MSAASamples, BoundingBox::NeedsStencilBuffer());
|
||||
BoundingBox::SetTargetSizeChanged(m_target_width, m_target_height);
|
||||
UpdateDrawRectangle();
|
||||
}
|
||||
|
||||
if (s_vsync != g_ActiveConfig.IsVSync())
|
||||
@ -1455,6 +1426,30 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||
ClearEFBCache();
|
||||
}
|
||||
|
||||
void Renderer::CheckForSurfaceChange()
|
||||
{
|
||||
if (!m_surface_changed.TestAndClear())
|
||||
return;
|
||||
|
||||
m_surface_handle = m_new_surface_handle;
|
||||
m_new_surface_handle = nullptr;
|
||||
GLInterface->UpdateHandle(m_surface_handle);
|
||||
GLInterface->UpdateSurface();
|
||||
|
||||
// With a surface change, the window likely has new dimensions.
|
||||
m_backbuffer_width = GLInterface->GetBackBufferWidth();
|
||||
m_backbuffer_height = GLInterface->GetBackBufferHeight();
|
||||
}
|
||||
|
||||
void Renderer::CheckForSurfaceResize()
|
||||
{
|
||||
if (!m_surface_resized.TestAndClear())
|
||||
return;
|
||||
|
||||
m_backbuffer_width = m_new_backbuffer_width;
|
||||
m_backbuffer_height = m_new_backbuffer_height;
|
||||
}
|
||||
|
||||
void Renderer::DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc,
|
||||
const TargetRectangle& source_rc)
|
||||
{
|
||||
@ -1572,16 +1567,4 @@ void Renderer::SetInterlacingMode()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void Renderer::ChangeSurface(void* new_surface_handle)
|
||||
{
|
||||
// Win32 polls the window size when redrawing, X11 runs an event loop in another thread.
|
||||
// This is only necessary for Android at this point, although handling resizes here
|
||||
// would be more efficient than polling.
|
||||
#ifdef ANDROID
|
||||
m_new_surface_handle = new_surface_handle;
|
||||
m_surface_needs_change.Set();
|
||||
m_surface_changed.Wait();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user