VideoCommon: Call Renderer::SurfaceChanged on render parent resize

This is needed because for some reason the WSI for NV Vulkan drivers
doesn't return VK_ERROR_OUT_OF_DATE_KHR, so there is no other way to know
that a resize has occured apart from polling, which is a poor solution for
X11 (since it is blocking).
This commit is contained in:
Stenzek 2016-08-13 22:08:53 +10:00
parent 5346078791
commit 6a99cbd9fc
6 changed files with 44 additions and 29 deletions

View File

@ -747,35 +747,21 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceChang
if (surf == nullptr)
__android_log_print(ANDROID_LOG_ERROR, DOLPHIN_TAG, "Error: Surface is null.");
// If GLInterface isn't a thing yet then we don't need to let it know that the
// surface has changed
if (GLInterface)
{
GLInterface->UpdateHandle(surf);
Renderer::s_ChangedSurface.Reset();
Renderer::s_SurfaceNeedsChanged.Set();
Renderer::s_ChangedSurface.Wait();
}
if (g_renderer)
g_renderer->ChangeSurface(surf);
}
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestroyed(JNIEnv* env,
jobject obj)
{
if (g_renderer)
g_renderer->ChangeSurface(nullptr);
if (surf)
{
ANativeWindow_release(surf);
surf = nullptr;
}
// If GLInterface isn't a thing yet then we don't need to let it know that the
// surface has changed
if (GLInterface)
{
GLInterface->UpdateHandle(nullptr);
Renderer::s_ChangedSurface.Reset();
Renderer::s_SurfaceNeedsChanged.Set();
Renderer::s_ChangedSurface.Wait();
}
}
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_RefreshWiimotes(JNIEnv* env,
jobject obj)

View File

@ -77,6 +77,7 @@
#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
@ -907,6 +908,12 @@ void CFrame::OnRenderParentResize(wxSizeEvent& event)
}
m_LogWindow->Refresh();
m_LogWindow->Update();
// We call Renderer::ChangeSurface here to indicate the size has changed,
// but pass the same window handle. This is needed for the Vulkan backend,
// otherwise it cannot tell that the window has been resized on some drivers.
if (g_renderer)
g_renderer->ChangeSurface(GetRenderHandle());
}
event.Skip();
}

View File

@ -1620,12 +1620,16 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
OSD::DoCallbacks(OSD::CallbackType::OnFrame);
OSD::DrawMessages();
if (s_SurfaceNeedsChanged.IsSet())
#ifdef ANDROID
if (s_surface_needs_change.IsSet())
{
GLInterface->UpdateHandle(s_new_surface_handle);
GLInterface->UpdateSurface();
s_SurfaceNeedsChanged.Clear();
s_ChangedSurface.Set();
s_new_surface_handle = nullptr;
s_surface_needs_change.Clear();
s_surface_changed.Set();
}
#endif
// Copy the rendered frame to the real window
GLInterface->Swap();
@ -1814,4 +1818,16 @@ int Renderer::GetMaxTextureSize()
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s_max_texture_size);
return s_max_texture_size;
}
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
s_new_surface_handle = new_surface_handle;
s_surface_needs_change.Set();
s_surface_changed.Wait();
#endif
}
}

View File

@ -105,6 +105,8 @@ public:
int GetMaxTextureSize() override;
void ChangeSurface(void* new_surface_handle) override;
private:
void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc,
const TargetRectangle& targetPixelRc, const void* data);

View File

@ -60,10 +60,6 @@ Common::Event Renderer::s_screenshotCompleted;
volatile bool Renderer::s_bScreenshot;
// Final surface changing
Common::Flag Renderer::s_SurfaceNeedsChanged;
Common::Event Renderer::s_ChangedSurface;
// The framebuffer size
int Renderer::s_target_width;
int Renderer::s_target_height;
@ -74,6 +70,11 @@ int Renderer::s_backbuffer_height;
std::unique_ptr<PostProcessingShaderImplementation> Renderer::m_post_processor;
// Final surface changing
Common::Flag Renderer::s_surface_needs_change;
Common::Event Renderer::s_surface_changed;
void* Renderer::s_new_surface_handle;
TargetRectangle Renderer::target_rc;
int Renderer::s_last_efb_scale;

View File

@ -138,9 +138,8 @@ public:
static Common::Event s_screenshotCompleted;
// Final surface changing
static Common::Flag s_SurfaceNeedsChanged;
static Common::Event s_ChangedSurface;
// This is called when the surface is resized (WX) or the window changes (Android).
virtual void ChangeSurface(void* new_surface_handle) {}
protected:
static void CalculateTargetScale(int x, int y, int* scaledX, int* scaledY);
bool CalculateTargetSize(unsigned int framebuffer_width, unsigned int framebuffer_height);
@ -178,6 +177,10 @@ protected:
static const float GX_MAX_DEPTH;
static Common::Flag s_surface_needs_change;
static Common::Event s_surface_changed;
static void* s_new_surface_handle;
private:
static PEControl::PixelFormat prev_efb_format;
static unsigned int efb_scale_numeratorX;