diff --git a/src/core/host.cpp b/src/core/host.cpp index 6083c6ee1..cc5da139f 100644 --- a/src/core/host.cpp +++ b/src/core/host.cpp @@ -459,7 +459,13 @@ void Host::UpdateDisplayWindow(bool fullscreen) // if surfaceless, just leave it if (wi->IsSurfaceless()) + { + DEV_LOG("Switching to surfaceless device"); + if (!g_gpu_device->SwitchToSurfacelessRendering(&error)) + ERROR_LOG("Failed to switch to surfaceless, rendering commands may fail: {}", error.GetDescription()); + return; + } if (!g_gpu_device->RecreateMainSwapChain(wi.value(), vsync_mode, allow_present_throttle, fullscreen_mode.has_value() ? &fullscreen_mode.value() : nullptr, diff --git a/src/core/system.cpp b/src/core/system.cpp index 514063138..e2420d7a5 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -5762,7 +5762,7 @@ void System::DisplayWindowResized() void System::UpdateGTEAspectRatio() { - if (!IsValid()) + if (!IsValidOrInitializing()) return; DisplayAspectRatio gte_ar = g_settings.display_aspect_ratio; diff --git a/src/util/gpu_device.cpp b/src/util/gpu_device.cpp index 231283c2a..73ecaa862 100644 --- a/src/util/gpu_device.cpp +++ b/src/util/gpu_device.cpp @@ -472,6 +472,12 @@ void GPUDevice::Destroy() DestroyDevice(); } +bool GPUDevice::SwitchToSurfacelessRendering(Error* error) +{ + // noop on everything except GL because of it's context nonsense + return true; +} + bool GPUDevice::RecreateMainSwapChain(const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) @@ -723,8 +729,7 @@ void GPUDevice::RenderImGui(GPUSwapChain* swap_chain) 0.0f, 0.0f, static_cast(swap_chain->GetWidth()), static_cast(swap_chain->GetHeight()), 0.0f, 1.0f); if (swap_chain->GetPreRotation() != WindowInfo::PreRotation::Identity) { - mproj = - GSMatrix4x4::RotationZ(WindowInfo::GetZRotationForPreRotation(swap_chain->GetPreRotation())) * mproj; + mproj = GSMatrix4x4::RotationZ(WindowInfo::GetZRotationForPreRotation(swap_chain->GetPreRotation())) * mproj; } PushUniformBuffer(&mproj, sizeof(mproj)); diff --git a/src/util/gpu_device.h b/src/util/gpu_device.h index ffcd7fd10..14c46d344 100644 --- a/src/util/gpu_device.h +++ b/src/util/gpu_device.h @@ -720,6 +720,7 @@ public: const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) = 0; + virtual bool SwitchToSurfacelessRendering(Error* error); bool RecreateMainSwapChain(const WindowInfo& wi, GPUVSyncMode vsync_mode, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, diff --git a/src/util/input_manager.cpp b/src/util/input_manager.cpp index b8e8e22ae..6b9df1911 100644 --- a/src/util/input_manager.cpp +++ b/src/util/input_manager.cpp @@ -1358,9 +1358,12 @@ void InputManager::UpdateRelativeMouseMode() if (s_relative_mouse_mode == has_relative_mode_bindings && s_hide_host_mouse_cursor == hide_mouse_cursor) return; +#ifndef __ANDROID__ s_relative_mouse_mode = has_relative_mode_bindings; s_hide_host_mouse_cursor = hide_mouse_cursor; - UpdateRelativeMouseMode(); +#endif + + UpdateHostMouseMode(); } void InputManager::UpdateHostMouseMode() diff --git a/src/util/opengl_context.cpp b/src/util/opengl_context.cpp index b8222f29c..c5ae86b0b 100644 --- a/src/util/opengl_context.cpp +++ b/src/util/opengl_context.cpp @@ -96,6 +96,14 @@ static void DisableBrokenExtensions(const char* gl_vendor, const char* gl_render VERBOSE_LOG("Keeping GL_EXT_shader_framebuffer_fetch on Adreno version {}", major_version); } } + else if (std::strstr(gl_vendor, "Imagination Technologies") && std::strstr(gl_renderer, "PowerVR")) + { + // Framebuffer fetch is apparently also broken on older PowerVR drivers. + // No clue what the range is, so just disable all of them... + GLAD_GL_EXT_shader_framebuffer_fetch = 0; + GLAD_GL_ARM_shader_framebuffer_fetch = 0; + VERBOSE_LOG("Disabling GL_EXT_shader_framebuffer_fetch on PowerVR driver."); + } // If we're missing GLES 3.2, but have OES_draw_elements_base_vertex, redirect the function pointers. if (!glad_glDrawElementsBaseVertex && GLAD_GL_OES_draw_elements_base_vertex && !GLAD_GL_ES_VERSION_3_2) diff --git a/src/util/opengl_context_egl.cpp b/src/util/opengl_context_egl.cpp index a2ddc9061..2d7f9addb 100644 --- a/src/util/opengl_context_egl.cpp +++ b/src/util/opengl_context_egl.cpp @@ -8,6 +8,8 @@ #include "common/error.h" #include "common/log.h" +#include "glad/gl.h" + #include #include #include @@ -164,7 +166,7 @@ EGLSurface OpenGLContextEGL::CreatePlatformSurface(EGLConfig config, const Windo bool OpenGLContextEGL::SupportsSurfaceless() const { - return GLAD_EGL_KHR_surfaceless_context; + return (!IsGLES() || GLAD_GL_OES_surfaceless_context) && GLAD_EGL_KHR_surfaceless_context; } EGLDisplay OpenGLContextEGL::TryGetPlatformDisplay(void* display, EGLenum platform, const char* platform_ext) @@ -294,7 +296,7 @@ void OpenGLContextEGL::DestroySurface(SurfaceHandle handle) EGLSurface surface = (EGLSurface)handle; if (m_current_surface == surface) { - eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, SupportsSurfaceless() ? m_context : EGL_NO_CONTEXT); m_current_surface = EGL_NO_SURFACE; } diff --git a/src/util/opengl_device.cpp b/src/util/opengl_device.cpp index 19d20f74f..4b181ffbc 100644 --- a/src/util/opengl_device.cpp +++ b/src/util/opengl_device.cpp @@ -637,6 +637,12 @@ std::unique_ptr OpenGLDevice::CreateSwapChain(const WindowInfo& wi return std::make_unique(wi_copy, vsync_mode, allow_present_throttle, surface_handle); } +bool OpenGLDevice::SwitchToSurfacelessRendering(Error* error) +{ + // We need to switch to surfaceless if we're temporarily destroying, otherwise we can't issue GL commands. + return m_gl_context->MakeCurrent(nullptr, error); +} + std::string OpenGLDevice::GetDriverInfo() const { const char* gl_vendor = reinterpret_cast(glGetString(GL_VENDOR)); diff --git a/src/util/opengl_device.h b/src/util/opengl_device.h index 4cf1be950..5846b34b0 100644 --- a/src/util/opengl_device.h +++ b/src/util/opengl_device.h @@ -52,6 +52,7 @@ public: const ExclusiveFullscreenMode* exclusive_fullscreen_mode, std::optional exclusive_fullscreen_control, Error* error) override; + bool SwitchToSurfacelessRendering(Error* error) override; std::unique_ptr CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples, GPUTexture::Type type, GPUTexture::Format format, GPUTexture::Flags flags, const void* data = nullptr, u32 data_stride = 0,