Skip to content

Commit

Permalink
OpenGLDevice: Fix surfaceless context switch
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Dec 15, 2024
1 parent fbb411a commit 6e2223b
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 4 deletions.
6 changes: 6 additions & 0 deletions src/core/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 7 additions & 2 deletions src/util/gpu_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool> exclusive_fullscreen_control, Error* error)
Expand Down Expand Up @@ -723,8 +729,7 @@ void GPUDevice::RenderImGui(GPUSwapChain* swap_chain)
0.0f, 0.0f, static_cast<float>(swap_chain->GetWidth()), static_cast<float>(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));

Expand Down
1 change: 1 addition & 0 deletions src/util/gpu_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,7 @@ class GPUDevice
const ExclusiveFullscreenMode* exclusive_fullscreen_mode,
std::optional<bool> 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,
Expand Down
6 changes: 4 additions & 2 deletions src/util/opengl_context_egl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "common/error.h"
#include "common/log.h"

#include "glad/gl.h"

#include <atomic>
#include <cstring>
#include <optional>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}

Expand Down
6 changes: 6 additions & 0 deletions src/util/opengl_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,12 @@ std::unique_ptr<GPUSwapChain> OpenGLDevice::CreateSwapChain(const WindowInfo& wi
return std::make_unique<OpenGLSwapChain>(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<const char*>(glGetString(GL_VENDOR));
Expand Down
1 change: 1 addition & 0 deletions src/util/opengl_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class OpenGLDevice final : public GPUDevice
const ExclusiveFullscreenMode* exclusive_fullscreen_mode,
std::optional<bool> exclusive_fullscreen_control,
Error* error) override;
bool SwitchToSurfacelessRendering(Error* error) override;
std::unique_ptr<GPUTexture> 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,
Expand Down

0 comments on commit 6e2223b

Please sign in to comment.