[gtk/wip/otte/texture-threads] testsuite: Add a test for downloading textures in a different thread
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/texture-threads] testsuite: Add a test for downloading textures in a different thread
- Date: Sun, 12 Sep 2021 22:22:52 +0000 (UTC)
commit ed8aba82b704b3dad52d286bfde0aff4e0f5adca
Author: Benjamin Otte <otte redhat com>
Date: Mon Sep 13 00:19:35 2021 +0200
testsuite: Add a test for downloading textures in a different thread
This happens in the real world when using the inspector to look at a
node recording of a GStreamer video while the video is still playing.
GStreamer will use the GL context in a different thread while we are
busy trying to download it.
testsuite/gdk/meson.build | 1 +
testsuite/gdk/texture-threads.c | 96 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+)
---
diff --git a/testsuite/gdk/meson.build b/testsuite/gdk/meson.build
index 5e62e98775..3eff25868d 100644
--- a/testsuite/gdk/meson.build
+++ b/testsuite/gdk/meson.build
@@ -26,6 +26,7 @@ tests = [
'rgba',
'seat',
'texture',
+ 'texture-threads',
]
foreach t : tests
diff --git a/testsuite/gdk/texture-threads.c b/testsuite/gdk/texture-threads.c
new file mode 100644
index 0000000000..00828e6dbb
--- /dev/null
+++ b/testsuite/gdk/texture-threads.c
@@ -0,0 +1,96 @@
+#include <gtk/gtk.h>
+
+#include "gsk/ngl/gsknglrenderer.h"
+
+/* This function will be called from a thread and/or the main loop.
+ * Textures are threadsafe after all. */
+static void
+ensure_texture_access (GdkTexture *texture)
+{
+ /* Make sure to initialize the pixel to anything but red */
+ guint32 pixel = 0;
+
+ /* Just to be sure */
+ g_assert_cmpint (gdk_texture_get_width (texture), ==, 1);
+ g_assert_cmpint (gdk_texture_get_height (texture), ==, 1);
+
+ /* download the pixel */
+ gdk_texture_download (texture, (guchar *) &pixel, 4);
+
+ /* check the pixel is now red */
+ g_assert_cmphex (pixel, ==, 0xFFFF0000);
+}
+
+static void
+texture_download_done (GObject *texture,
+ GAsyncResult *res,
+ gpointer loop)
+{
+ ensure_texture_access (GDK_TEXTURE (texture));
+
+ g_main_loop_quit (loop);
+}
+
+static void
+texture_download_thread (GTask *task,
+ gpointer texture,
+ gpointer unused,
+ GCancellable *cancellable)
+{
+ ensure_texture_access (GDK_TEXTURE (texture));
+
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+texture_threads (void)
+{
+ GdkSurface *surface;
+ GskRenderer *gl_renderer;
+ GskRenderNode *node;
+ GMainLoop *loop;
+ GdkTexture *texture;
+ GTask *task;
+
+ /* 1. Get a GL renderer */
+ surface = gdk_surface_new_toplevel (gdk_display_get_default());
+ gl_renderer = gsk_ngl_renderer_new ();
+ g_assert_true (gsk_renderer_realize (gl_renderer, surface, NULL));
+
+ /* 2. Get a GL texture */
+ node = gsk_color_node_new (&(GdkRGBA) { 1, 0, 0, 1 }, &GRAPHENE_RECT_INIT(0, 0, 1, 1));
+ texture = gsk_renderer_render_texture (gl_renderer, node, &GRAPHENE_RECT_INIT(0, 0, 1, 1));
+ gsk_render_node_unref (node);
+
+ /* 3. This is a bit fishy, but we want to make sure that
+ * the texture's GL context is current in the main thread.
+ *
+ * If we had access to the context, we'd make_current() here.
+ */
+ ensure_texture_access (texture);
+ g_assert_nonnull (gdk_gl_context_get_current ());
+
+ /* 4. Run a thread trying to download the texture */
+ loop = g_main_loop_new (NULL, TRUE);
+ task = g_task_new (texture, NULL, texture_download_done, loop);
+ g_task_run_in_thread (task, texture_download_thread);
+ g_clear_object (&task);
+
+ /* 5. Run the main loop waiting for the thread to return */
+ g_main_loop_run (loop);
+
+ /* 6. All good */
+ g_clear_pointer (&loop, g_main_loop_unref);
+ g_clear_object (&gl_renderer);
+ g_clear_object (&surface);
+}
+
+int
+main (int argc, char *argv[])
+{
+ gtk_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/texture-threads", texture_threads);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]