aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2022-01-12 18:56:08 +0100
committerSimon Zeni <simon@bl4ckb0ne.ca>2022-11-15 15:50:19 +0000
commit261d6998fb7461fcdf6cf66a57863b8ed505a67c (patch)
tree77bd847376c8e48abf1489fb3228747418fa804f
parent31ea61b390a3295248458ab7e8388848fb6810d0 (diff)
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).
-rw-r--r--include/render/gles2.h1
-rw-r--r--render/gles2/renderer.c37
2 files changed, 38 insertions, 0 deletions
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 "<invalid>";
+ }
+}
+
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, &notif_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);