From d6ad1b79b97974ad3e3bd2a1b2c7474f0dd797b0 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Mon, 2 May 2022 21:15:28 +0200 Subject: Fix crash when destroying OpenGL views that haven't been realized --- src/mac_gl.m | 3 +++ src/win_gl.c | 3 +++ src/x11_gl.c | 3 +++ test/meson.build | 3 ++- test/test_gl_free_unrealized.c | 61 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 test/test_gl_free_unrealized.c diff --git a/src/mac_gl.m b/src/mac_gl.m index dd94e54..25704c3 100644 --- a/src/mac_gl.m +++ b/src/mac_gl.m @@ -135,6 +135,9 @@ static PuglStatus puglMacGlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose)) { PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView; + if (!drawView) { + return PUGL_FAILURE; + } [[drawView openGLContext] makeCurrentContext]; return PUGL_SUCCESS; diff --git a/src/win_gl.c b/src/win_gl.c index 0a035a1..a755020 100644 --- a/src/win_gl.c +++ b/src/win_gl.c @@ -258,6 +258,9 @@ static PuglStatus puglWinGlEnter(PuglView* view, const PuglExposeEvent* expose) { PuglWinGlSurface* surface = (PuglWinGlSurface*)view->impl->surface; + if (!surface || !surface->hglrc) { + return PUGL_FAILURE; + } wglMakeCurrent(view->impl->hdc, surface->hglrc); diff --git a/src/x11_gl.c b/src/x11_gl.c index 1ebe829..41007cd 100644 --- a/src/x11_gl.c +++ b/src/x11_gl.c @@ -103,6 +103,9 @@ static PuglStatus puglX11GlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose)) { PuglX11GlSurface* surface = (PuglX11GlSurface*)view->impl->surface; + if (!surface || !surface->ctx) { + return PUGL_FAILURE; + } return glXMakeCurrent(view->impl->display, view->impl->win, surface->ctx) ? PUGL_SUCCESS diff --git a/test/meson.build b/test/meson.build index d8b27a9..e16e818 100644 --- a/test/meson.build +++ b/test/meson.build @@ -65,7 +65,8 @@ cairo_tests = [ gl_tests = [ 'gl', - 'gl_hints' + 'gl_free_unrealized', + 'gl_hints', ] vulkan_tests = [ diff --git a/test/test_gl_free_unrealized.c b/test/test_gl_free_unrealized.c new file mode 100644 index 0000000..c4d3fcd --- /dev/null +++ b/test/test_gl_free_unrealized.c @@ -0,0 +1,61 @@ +// Copyright 2022 David Robillard +// SPDX-License-Identifier: ISC + +/* + Tests that deleting an unrealized view works properly. + + This was a crash bug with OpenGL backends. +*/ + +#undef NDEBUG + +#include "test_utils.h" + +#include "pugl/gl.h" +#include "pugl/pugl.h" + +#include +#include +#include + +typedef struct { + PuglWorld* world; + PuglView* view; + PuglTestOptions opts; +} PuglTest; + +static PuglStatus +onEvent(PuglView* const view, const PuglEvent* const event) +{ + PuglTest* const test = (PuglTest*)puglGetHandle(view); + + if (test->opts.verbose) { + printEvent(event, "Event: ", true); + } + + return PUGL_SUCCESS; +} + +int +main(int argc, char** argv) +{ + PuglTest test = { + puglNewWorld(PUGL_PROGRAM, 0), NULL, puglParseTestOptions(&argc, &argv)}; + + // Set up view + test.view = puglNewView(test.world); + puglSetClassName(test.world, "Pugl Test"); + puglSetWindowTitle(test.view, "Pugl Free View Test"); + puglSetBackend(test.view, puglGlBackend()); + puglSetHandle(test.view, &test); + puglSetEventFunc(test.view, onEvent); + puglSetDefaultSize(test.view, 512, 512); + + assert(!puglGetVisible(test.view)); + + // Tear everything down without ever realizing the view + puglFreeView(test.view); + puglFreeWorld(test.world); + + return 0; +} -- cgit v1.2.1