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) if (surf == nullptr)
__android_log_print(ANDROID_LOG_ERROR, DOLPHIN_TAG, "Error: Surface is null."); __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 if (g_renderer)
// surface has changed g_renderer->ChangeSurface(surf);
if (GLInterface)
{
GLInterface->UpdateHandle(surf);
Renderer::s_ChangedSurface.Reset();
Renderer::s_SurfaceNeedsChanged.Set();
Renderer::s_ChangedSurface.Wait();
}
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestroyed(JNIEnv* env, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestroyed(JNIEnv* env,
jobject obj) jobject obj)
{ {
if (g_renderer)
g_renderer->ChangeSurface(nullptr);
if (surf) if (surf)
{ {
ANativeWindow_release(surf); ANativeWindow_release(surf);
surf = nullptr; 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, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_RefreshWiimotes(JNIEnv* env,
jobject obj) jobject obj)

View File

@ -77,6 +77,7 @@
#include "InputCommon/ControllerInterface/ControllerInterface.h" #include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h" #include "VideoCommon/VideoConfig.h"
@ -907,6 +908,12 @@ void CFrame::OnRenderParentResize(wxSizeEvent& event)
} }
m_LogWindow->Refresh(); m_LogWindow->Refresh();
m_LogWindow->Update(); 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(); 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::DoCallbacks(OSD::CallbackType::OnFrame);
OSD::DrawMessages(); OSD::DrawMessages();
if (s_SurfaceNeedsChanged.IsSet()) #ifdef ANDROID
if (s_surface_needs_change.IsSet())
{ {
GLInterface->UpdateHandle(s_new_surface_handle);
GLInterface->UpdateSurface(); GLInterface->UpdateSurface();
s_SurfaceNeedsChanged.Clear(); s_new_surface_handle = nullptr;
s_ChangedSurface.Set(); s_surface_needs_change.Clear();
s_surface_changed.Set();
} }
#endif
// Copy the rendered frame to the real window // Copy the rendered frame to the real window
GLInterface->Swap(); GLInterface->Swap();
@ -1814,4 +1818,16 @@ int Renderer::GetMaxTextureSize()
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s_max_texture_size); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s_max_texture_size);
return 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; int GetMaxTextureSize() override;
void ChangeSurface(void* new_surface_handle) override;
private: private:
void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc,
const TargetRectangle& targetPixelRc, const void* data); const TargetRectangle& targetPixelRc, const void* data);

View File

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

View File

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