forked from AuroraMiddleware/gtk
7872b41f16
That way we ensure that the GL context(s) get disposed, which they previously weren't due to them still being the current context. This also implicitly adds testing of gLContext destruction, which previously wasn't ever done by any test.
123 lines
3.5 KiB
C
123 lines
3.5 KiB
C
#include <gtk/gtk.h>
|
|
|
|
#include "gsk/gl/gskglrenderer.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;
|
|
|
|
g_test_message ("Checking texture access in thread %p...", g_thread_self());
|
|
/* 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);
|
|
|
|
g_test_message ("...done in thread %p", g_thread_self());
|
|
}
|
|
|
|
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)
|
|
{
|
|
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 ());
|
|
|
|
ensure_texture_access (GDK_TEXTURE (texture));
|
|
|
|
/* 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());
|
|
|
|
g_task_return_boolean (task, TRUE);
|
|
}
|
|
|
|
static void
|
|
texture_threads (void)
|
|
{
|
|
GskRenderer *gl_renderer;
|
|
GskRenderNode *node;
|
|
GMainLoop *loop;
|
|
GdkTexture *texture;
|
|
GTask *task;
|
|
GError *error = NULL;
|
|
|
|
/* 1. Get a GL renderer */
|
|
gl_renderer = gsk_gl_renderer_new ();
|
|
if (!gsk_renderer_realize (gl_renderer, NULL, &error))
|
|
{
|
|
g_test_skip (error->message);
|
|
|
|
g_clear_error (&error);
|
|
g_clear_object (&gl_renderer);
|
|
return;
|
|
}
|
|
|
|
/* 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. 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 */
|
|
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);
|
|
|
|
/* 6. Run the main loop waiting for the thread to return */
|
|
g_main_loop_run (loop);
|
|
|
|
/* 7. All good */
|
|
gsk_renderer_unrealize (gl_renderer);
|
|
g_clear_pointer (&loop, g_main_loop_unref);
|
|
g_clear_object (&gl_renderer);
|
|
g_main_context_release (NULL);
|
|
gdk_gl_context_clear_current ();
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
gtk_test_init (&argc, &argv, NULL);
|
|
|
|
g_test_add_func ("/texture-threads", texture_threads);
|
|
|
|
return g_test_run ();
|
|
}
|