From 261d6998fb7461fcdf6cf66a57863b8ed505a67c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 12 Jan 2022 18:56:08 +0100 Subject: [PATCH] render/gles2: query glGetGraphicsResetStatusKHR Call glGetGraphicsResetStatusKHR in wlr_renderer_begin to figure out when a GPU reset occurs. Destroy the renderer when this happens (the OpenGL context is defunct). --- include/render/gles2.h | 1 + render/gles2/renderer.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/render/gles2.h b/include/render/gles2.h index 6631d34c..ff39206c 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -57,6 +57,7 @@ struct wlr_gles2_renderer { PFNGLPOPDEBUGGROUPKHRPROC glPopDebugGroupKHR; PFNGLPUSHDEBUGGROUPKHRPROC glPushDebugGroupKHR; PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES; + PFNGLGETGRAPHICSRESETSTATUSKHRPROC glGetGraphicsResetStatusKHR; } procs; struct { diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index ee4f60e8..47c58b19 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -198,6 +198,19 @@ static bool gles2_bind_buffer(struct wlr_renderer *wlr_renderer, return true; } +static const char *reset_status_str(GLenum status) { + switch (status) { + case GL_GUILTY_CONTEXT_RESET_KHR: + return "guilty"; + case GL_INNOCENT_CONTEXT_RESET_KHR: + return "innocent"; + case GL_UNKNOWN_CONTEXT_RESET_KHR: + return "unknown"; + default: + return ""; + } +} + static bool gles2_begin(struct wlr_renderer *wlr_renderer, uint32_t width, uint32_t height) { struct wlr_gles2_renderer *renderer = @@ -205,6 +218,15 @@ static bool gles2_begin(struct wlr_renderer *wlr_renderer, uint32_t width, push_gles2_debug(renderer); + if (renderer->procs.glGetGraphicsResetStatusKHR) { + GLenum status = renderer->procs.glGetGraphicsResetStatusKHR(); + if (status != GL_NO_ERROR) { + wlr_log(WLR_ERROR, "GPU reset (%s)", reset_status_str(status)); + wl_signal_emit_mutable(&wlr_renderer->events.lost, NULL); + return false; + } + } + glViewport(0, 0, width, height); renderer->viewport_width = width; renderer->viewport_height = height; @@ -771,6 +793,21 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { "glEGLImageTargetRenderbufferStorageOES"); } + if (check_gl_ext(exts_str, "GL_KHR_robustness")) { + GLint notif_strategy = 0; + glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_KHR, ¬if_strategy); + switch (notif_strategy) { + case GL_LOSE_CONTEXT_ON_RESET_KHR: + wlr_log(WLR_DEBUG, "GPU reset notifications are enabled"); + load_gl_proc(&renderer->procs.glGetGraphicsResetStatusKHR, + "glGetGraphicsResetStatusKHR"); + break; + case GL_NO_RESET_NOTIFICATION_KHR: + wlr_log(WLR_DEBUG, "GPU reset notifications are disabled"); + break; + } + } + if (renderer->exts.KHR_debug) { glEnable(GL_DEBUG_OUTPUT_KHR); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);