mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 10:50:10 +00:00
a61c7f7871
The dmabuf texture tests are failing, so we don't run them in ci, but the format tests are perfectly fine, so split them off. Add some tests for GdkDmabufFormatsBuilder and for the new gdk_dmabuf_formats_equal(), too.
273 lines
7.3 KiB
C
273 lines
7.3 KiB
C
#include "config.h"
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <gdk/gdkdisplayprivate.h>
|
|
#include <gdk/gdkglcontextprivate.h>
|
|
#include <gdk/gdkdmabuftextureprivate.h>
|
|
|
|
#ifdef HAVE_DMABUF
|
|
#include <drm_fourcc.h>
|
|
#endif
|
|
|
|
static cairo_surface_t *
|
|
make_surface (int width,
|
|
int height)
|
|
{
|
|
cairo_surface_t *surface;
|
|
cairo_t *cr;
|
|
guchar *data;
|
|
int stride;
|
|
|
|
stride = width * 4;
|
|
data = g_malloc (stride * height);
|
|
surface = cairo_image_surface_create_for_data (data,
|
|
CAIRO_FORMAT_ARGB32,
|
|
width, height, stride);
|
|
cr = cairo_create (surface);
|
|
cairo_set_source_rgb (cr, 1, 0, 0);
|
|
cairo_paint (cr);
|
|
cairo_destroy (cr);
|
|
|
|
return surface;
|
|
}
|
|
|
|
static unsigned int
|
|
upload_gl_texture (GdkGLContext *context,
|
|
cairo_surface_t *surface)
|
|
{
|
|
unsigned int id;
|
|
int width, height;
|
|
|
|
width = cairo_image_surface_get_width (surface);
|
|
height = cairo_image_surface_get_height (surface);
|
|
|
|
glGenTextures (1, &id);
|
|
glActiveTexture (GL_TEXTURE0);
|
|
glBindTexture (GL_TEXTURE_2D, id);
|
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE,
|
|
cairo_image_surface_get_data (surface));
|
|
|
|
g_assert_true (glGetError () == GL_NO_ERROR);
|
|
|
|
return id;
|
|
}
|
|
|
|
static void
|
|
export_dmabuf (GdkGLContext *context,
|
|
unsigned int texture_id,
|
|
GdkDmabuf *dmabuf)
|
|
{
|
|
gboolean ret;
|
|
|
|
ret = gdk_gl_context_export_dmabuf (context, texture_id, dmabuf);
|
|
|
|
g_assert_true (ret);
|
|
}
|
|
|
|
static void
|
|
free_dmabuf (gpointer data)
|
|
{
|
|
GdkDmabuf *dmabuf = data;
|
|
|
|
for (int i = 0; i < dmabuf->n_planes; i++)
|
|
close (dmabuf->planes[i].fd);
|
|
|
|
g_free (dmabuf);
|
|
}
|
|
|
|
static GdkTexture *
|
|
make_dmabuf_texture (GdkDisplay *display,
|
|
int width,
|
|
int height,
|
|
gboolean premultiplied,
|
|
GdkDmabuf *dmabuf)
|
|
{
|
|
GdkDmabufTextureBuilder *builder;
|
|
GdkTexture *texture;
|
|
GdkDmabuf *dmabuf2;
|
|
|
|
builder = gdk_dmabuf_texture_builder_new ();
|
|
|
|
gdk_dmabuf_texture_builder_set_display (builder, display);
|
|
gdk_dmabuf_texture_builder_set_width (builder, width);
|
|
gdk_dmabuf_texture_builder_set_premultiplied (builder, premultiplied);
|
|
gdk_dmabuf_texture_builder_set_height (builder, height);
|
|
gdk_dmabuf_texture_builder_set_fourcc (builder, dmabuf->fourcc);
|
|
gdk_dmabuf_texture_builder_set_modifier (builder, dmabuf->modifier);
|
|
gdk_dmabuf_texture_builder_set_n_planes (builder, dmabuf->n_planes);
|
|
for (int i = 0; i < dmabuf->n_planes; i++)
|
|
{
|
|
gdk_dmabuf_texture_builder_set_fd (builder, i, dmabuf->planes[i].fd);
|
|
gdk_dmabuf_texture_builder_set_stride (builder, i, dmabuf->planes[i].stride);
|
|
gdk_dmabuf_texture_builder_set_offset (builder, i, dmabuf->planes[i].offset);
|
|
}
|
|
|
|
dmabuf2 = g_new (GdkDmabuf, 1);
|
|
memcpy (dmabuf2, dmabuf, sizeof (GdkDmabuf));
|
|
|
|
texture = gdk_dmabuf_texture_builder_build (builder, free_dmabuf, dmabuf2, NULL);
|
|
|
|
g_assert_true (texture != NULL);
|
|
|
|
g_object_unref (builder);
|
|
|
|
return texture;
|
|
}
|
|
|
|
/* Make a dmabuftexture by exporting a GL texture,
|
|
* then download it and compare with the original
|
|
*/
|
|
static void
|
|
test_dmabuf_export (void)
|
|
{
|
|
GdkDisplay *display;
|
|
GdkGLContext *context;
|
|
GError *error = NULL;
|
|
cairo_surface_t *surface;
|
|
unsigned int texture_id;
|
|
GdkDmabuf dmabuf;
|
|
GdkTexture *texture;
|
|
guchar *data;
|
|
|
|
display = gdk_display_get_default ();
|
|
if (!gdk_display_prepare_gl (display, &error))
|
|
{
|
|
g_test_skip_printf ("no GL support: %s", error->message);
|
|
g_clear_error (&error);
|
|
return;
|
|
}
|
|
|
|
if (gdk_dmabuf_formats_get_n_formats (gdk_display_get_dmabuf_formats (display)) == 0)
|
|
{
|
|
g_test_skip_printf ("no dmabuf support");
|
|
return;
|
|
}
|
|
|
|
context = gdk_display_create_gl_context (display, &error);
|
|
g_assert_nonnull (context);
|
|
g_assert_no_error (error);
|
|
|
|
gdk_gl_context_realize (context, &error);
|
|
g_assert_no_error (error);
|
|
|
|
surface = make_surface (64, 64);
|
|
|
|
gdk_gl_context_make_current (context);
|
|
|
|
texture_id = upload_gl_texture (context, surface);
|
|
export_dmabuf (context, texture_id, &dmabuf);
|
|
texture = make_dmabuf_texture (display, 64, 64, TRUE, &dmabuf);
|
|
|
|
data = g_malloc (64 * 64 * 4);
|
|
gdk_texture_download (texture, data, 64 * 4);
|
|
|
|
g_assert_true (memcmp (cairo_image_surface_get_data (surface), data, 64 * 64 * 4) == 0);
|
|
|
|
g_free (data);
|
|
g_object_unref (texture);
|
|
cairo_surface_destroy (surface);
|
|
|
|
gdk_gl_context_make_current (context);
|
|
glDeleteTextures (1, &texture_id);
|
|
|
|
g_object_unref (context);
|
|
}
|
|
|
|
/* Make a dmabuftexture by exporting a GL texture,
|
|
* then import it into another GL context, download
|
|
* the resulting texture, and compare it to the original.
|
|
*/
|
|
static void
|
|
test_dmabuf_import (void)
|
|
{
|
|
GdkDisplay *display;
|
|
GdkGLContext *context;
|
|
GdkGLContext *context2;
|
|
GError *error = NULL;
|
|
cairo_surface_t *surface;
|
|
unsigned int texture_id;
|
|
unsigned int texture_id2;
|
|
GdkDmabuf dmabuf;
|
|
const GdkDmabuf *dmabuf2;
|
|
GdkTexture *texture;
|
|
GdkTexture *texture2;
|
|
GdkGLTextureBuilder *builder;
|
|
guchar *data;
|
|
gboolean external;
|
|
|
|
display = gdk_display_get_default ();
|
|
if (!gdk_display_prepare_gl (display, &error))
|
|
{
|
|
g_test_skip_printf ("no GL support: %s", error->message);
|
|
g_clear_error (&error);
|
|
return;
|
|
}
|
|
|
|
if (gdk_dmabuf_formats_get_n_formats (gdk_display_get_dmabuf_formats (display)) == 0)
|
|
{
|
|
g_test_skip_printf ("no dmabuf support");
|
|
return;
|
|
}
|
|
|
|
context = gdk_display_create_gl_context (display, &error);
|
|
g_assert_nonnull (context);
|
|
g_assert_no_error (error);
|
|
|
|
gdk_gl_context_realize (context, &error);
|
|
g_assert_no_error (error);
|
|
|
|
surface = make_surface (64, 64);
|
|
|
|
gdk_gl_context_make_current (context);
|
|
|
|
texture_id = upload_gl_texture (context, surface);
|
|
export_dmabuf (context, texture_id, &dmabuf);
|
|
texture = make_dmabuf_texture (display, 64, 64, TRUE, &dmabuf);
|
|
|
|
context2 = gdk_display_create_gl_context (display, &error);
|
|
g_assert_nonnull (context2);
|
|
g_assert_no_error (error);
|
|
|
|
gdk_gl_context_realize (context2, &error);
|
|
g_assert_no_error (error);
|
|
|
|
dmabuf2 = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
|
|
texture_id2 = gdk_gl_context_import_dmabuf (context2, 64, 64, dmabuf2, &external);
|
|
g_assert_cmpint (texture_id2, !=, 0);
|
|
g_assert_false (external);
|
|
|
|
builder = gdk_gl_texture_builder_new ();
|
|
gdk_gl_texture_builder_set_context (builder, context2);
|
|
gdk_gl_texture_builder_set_id (builder, texture_id2);
|
|
gdk_gl_texture_builder_set_width (builder, 64);
|
|
gdk_gl_texture_builder_set_height (builder, 64);
|
|
gdk_gl_texture_builder_set_format (builder, GDK_MEMORY_A8R8G8B8_PREMULTIPLIED);
|
|
texture2 = gdk_gl_texture_builder_build (builder, NULL, NULL);
|
|
|
|
data = g_malloc (64 * 64 * 4);
|
|
gdk_texture_download (texture2, data, 64 * 4);
|
|
|
|
g_assert_true (memcmp (cairo_image_surface_get_data (surface), data, 64 * 64 * 4) == 0);
|
|
|
|
g_free (data);
|
|
g_object_unref (texture);
|
|
g_object_unref (texture2);
|
|
|
|
gdk_gl_context_make_current (context);
|
|
glDeleteTextures (1, &texture_id);
|
|
|
|
g_object_unref (context);
|
|
g_object_unref (context2);
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
gtk_test_init (&argc, &argv, NULL);
|
|
|
|
g_test_add_func ("/dmabuf/export", test_dmabuf_export);
|
|
g_test_add_func ("/dmabuf/import", test_dmabuf_import);
|
|
|
|
return g_test_run ();
|
|
}
|