2021-09-12 22:19:35 +00:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
2021-10-07 03:15:25 +00:00
|
|
|
#include "gsk/gl/gskglrenderer.h"
|
2021-09-12 22:19:35 +00:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
2021-09-16 19:49:50 +00:00
|
|
|
g_test_message ("Checking texture access in thread %p...", g_thread_self());
|
2021-09-12 22:19:35 +00:00
|
|
|
/* 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);
|
2021-09-16 19:49:50 +00:00
|
|
|
|
|
|
|
g_test_message ("...done in thread %p", g_thread_self());
|
2021-09-12 22:19:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2021-09-16 19:49:50 +00:00
|
|
|
g_test_message ("Starting thread %p.", g_thread_self());
|
|
|
|
/* not sure this can happen, but if it does, we
|
|
|
|
* should clear_current() here. */
|
|
|
|
g_assert_null (gdk_gl_context_get_current ());
|
|
|
|
|
2021-09-12 22:19:35 +00:00
|
|
|
ensure_texture_access (GDK_TEXTURE (texture));
|
|
|
|
|
2021-09-16 19:49:50 +00:00
|
|
|
/* Makes sure the GL context is still NULL, because all the
|
|
|
|
* GL stuff should have happened in the main thread. */
|
|
|
|
g_assert_null (gdk_gl_context_get_current ());
|
|
|
|
g_test_message ("Returning from thread %p.", g_thread_self());
|
|
|
|
|
2021-09-12 22:19:35 +00:00
|
|
|
g_task_return_boolean (task, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
texture_threads (void)
|
|
|
|
{
|
|
|
|
GskRenderer *gl_renderer;
|
|
|
|
GskRenderNode *node;
|
|
|
|
GMainLoop *loop;
|
|
|
|
GdkTexture *texture;
|
|
|
|
GTask *task;
|
2021-10-18 11:38:35 +00:00
|
|
|
GError *error = NULL;
|
2021-09-12 22:19:35 +00:00
|
|
|
|
|
|
|
/* 1. Get a GL renderer */
|
2021-10-07 03:15:25 +00:00
|
|
|
gl_renderer = gsk_gl_renderer_new ();
|
2021-10-20 18:33:57 +00:00
|
|
|
if (!gsk_renderer_realize (gl_renderer, NULL, &error))
|
2021-10-18 11:38:35 +00:00
|
|
|
{
|
|
|
|
g_test_skip (error->message);
|
|
|
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
g_clear_object (&gl_renderer);
|
|
|
|
return;
|
|
|
|
}
|
2021-09-12 22:19:35 +00:00
|
|
|
|
|
|
|
/* 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 ());
|
|
|
|
|
2021-09-16 21:56:41 +00:00
|
|
|
/* 4. Acquire the main loop, so the run_in_thread() doesn't
|
|
|
|
* try to acquire it if it manages to outrace this thread.
|
|
|
|
*/
|
|
|
|
g_assert_true (g_main_context_acquire (NULL));
|
|
|
|
|
|
|
|
/* 5. Run a thread trying to download the texture */
|
2021-09-12 22:19:35 +00:00
|
|
|
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);
|
|
|
|
|
2021-09-16 21:56:41 +00:00
|
|
|
/* 6. Run the main loop waiting for the thread to return */
|
2021-09-12 22:19:35 +00:00
|
|
|
g_main_loop_run (loop);
|
|
|
|
|
2021-09-16 21:56:41 +00:00
|
|
|
/* 7. All good */
|
2021-09-12 22:19:35 +00:00
|
|
|
gsk_renderer_unrealize (gl_renderer);
|
|
|
|
g_clear_pointer (&loop, g_main_loop_unref);
|
|
|
|
g_clear_object (&gl_renderer);
|
2021-09-16 21:56:41 +00:00
|
|
|
g_main_context_release (NULL);
|
2022-01-06 18:08:42 +00:00
|
|
|
gdk_gl_context_clear_current ();
|
2021-09-12 22:19:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main (int argc, char *argv[])
|
|
|
|
{
|
|
|
|
gtk_test_init (&argc, &argv, NULL);
|
|
|
|
|
|
|
|
g_test_add_func ("/texture-threads", texture_threads);
|
|
|
|
|
|
|
|
return g_test_run ();
|
|
|
|
}
|