mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-09-19 21:40:22 +00:00
Add dmabuf tests that can run in ci
This is a test balloon tests that use /dev/udmabuf to produce dmabufs that we can use in ci, even if we don't have a GPU. Currently, the tests we can do are somewhat limited, since mesas software renderers don't support dmabufs yet.
This commit is contained in:
parent
5369b07eb0
commit
acad180cee
67
testsuite/gdk/dmabuf-support.c
Normal file
67
testsuite/gdk/dmabuf-support.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "gdk/gdkdmabuffourccprivate.h"
|
||||
#include "udmabuf.h"
|
||||
|
||||
static void
|
||||
test_dmabuf_no_gpu (void)
|
||||
{
|
||||
guchar buffer[4];
|
||||
GdkTexture *texture;
|
||||
GError *error = NULL;
|
||||
GdkTextureDownloader *downloader;
|
||||
gsize stride;
|
||||
GBytes *bytes;
|
||||
const guchar *data;
|
||||
|
||||
if (!udmabuf_initialize (&error))
|
||||
{
|
||||
g_test_fail_printf ("%s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer[0] = 255;
|
||||
buffer[1] = 0;
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 255;
|
||||
|
||||
bytes = g_bytes_new_static (buffer, 4);
|
||||
|
||||
texture = udmabuf_texture_new (1, 1,
|
||||
DRM_FORMAT_RGBA8888,
|
||||
gdk_color_state_get_srgb (),
|
||||
FALSE,
|
||||
bytes,
|
||||
4,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
downloader = gdk_texture_downloader_new (texture);
|
||||
gdk_texture_downloader_set_format (downloader, gdk_texture_get_format (texture));
|
||||
gdk_texture_downloader_set_color_state (downloader, gdk_texture_get_color_state (texture));
|
||||
|
||||
bytes = gdk_texture_downloader_download_bytes (downloader, &stride);
|
||||
|
||||
gdk_texture_downloader_free (downloader);
|
||||
|
||||
data = g_bytes_get_data (bytes, NULL);
|
||||
g_assert_true (memcmp (data, buffer, 4) == 0);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
gtk_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/dmabuf/no-gpu", test_dmabuf_no_gpu);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
@ -33,10 +33,18 @@ if x11_enabled
|
||||
]
|
||||
endif
|
||||
|
||||
if os_linux
|
||||
tests += [
|
||||
{ 'name': 'dmabuf-support',
|
||||
'sources': [ 'udmabuf.c' ],
|
||||
},
|
||||
]
|
||||
endif
|
||||
|
||||
foreach t : tests
|
||||
test_name = t.get('name')
|
||||
test_exe = executable(test_name,
|
||||
sources: '@0@.c'.format(test_name),
|
||||
sources: [ '@0@.c'.format(test_name) ] + t.get('sources', []),
|
||||
c_args: common_cflags,
|
||||
dependencies: libgtk_dep,
|
||||
install: false,
|
||||
|
297
testsuite/gdk/udmabuf.c
Normal file
297
testsuite/gdk/udmabuf.c
Normal file
@ -0,0 +1,297 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "udmabuf.h"
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/udmabuf.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <errno.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gio/gio.h>
|
||||
#include "gdk/gdkdmabuffourccprivate.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int mem_fd;
|
||||
int dmabuf_fd;
|
||||
size_t size;
|
||||
gpointer data;
|
||||
} UDmabuf;
|
||||
|
||||
static int udmabuf_fd;
|
||||
|
||||
gboolean
|
||||
udmabuf_initialize (GError **error)
|
||||
{
|
||||
if (udmabuf_fd == 0)
|
||||
{
|
||||
udmabuf_fd = open ("/dev/udmabuf", O_RDWR);
|
||||
if (udmabuf_fd == -1)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Failed to open /dev/udmabuf: %s",
|
||||
g_strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
return udmabuf_fd != -1;
|
||||
}
|
||||
|
||||
static void
|
||||
udmabuf_free (gpointer data)
|
||||
{
|
||||
UDmabuf *udmabuf = data;
|
||||
|
||||
munmap (udmabuf->data, udmabuf->size);
|
||||
close (udmabuf->mem_fd);
|
||||
close (udmabuf->dmabuf_fd);
|
||||
|
||||
g_free (udmabuf);
|
||||
}
|
||||
|
||||
#define align(x,y) (((x) + (y) - 1) & ~((y) - 1))
|
||||
|
||||
static UDmabuf *
|
||||
udmabuf_allocate (size_t size,
|
||||
GError **error)
|
||||
{
|
||||
int mem_fd = -1;
|
||||
int dmabuf_fd = -1;
|
||||
uint64_t alignment;
|
||||
int res;
|
||||
gpointer data;
|
||||
UDmabuf *udmabuf;
|
||||
|
||||
if (udmabuf_fd == 0)
|
||||
{
|
||||
if (!udmabuf_initialize (error))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (udmabuf_fd == -1)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"udmabuf not available");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
alignment = sysconf (_SC_PAGE_SIZE);
|
||||
|
||||
size = align (size, alignment);
|
||||
|
||||
mem_fd = memfd_create ("gtk", MFD_ALLOW_SEALING);
|
||||
if (mem_fd == -1)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Failed to open /dev/udmabuf: %s",
|
||||
g_strerror (errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = ftruncate (mem_fd, size);
|
||||
if (res == -1)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"ftruncate failed: %s",
|
||||
g_strerror (errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fcntl (mem_fd, F_ADD_SEALS, F_SEAL_SHRINK) < 0)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"ftruncate failed: %s",
|
||||
g_strerror (errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dmabuf_fd = ioctl (udmabuf_fd,
|
||||
UDMABUF_CREATE,
|
||||
&(struct udmabuf_create) {
|
||||
.memfd = mem_fd,
|
||||
.flags = UDMABUF_FLAGS_CLOEXEC,
|
||||
.offset = 0,
|
||||
.size = size
|
||||
});
|
||||
|
||||
if (dmabuf_fd < 0)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"UDMABUF_CREATE ioctl failed: %s",
|
||||
g_strerror (errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
data = mmap (NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, mem_fd, 0);
|
||||
|
||||
if (data == NULL || data == MAP_FAILED)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"mmap failed: %s",
|
||||
g_strerror (errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
udmabuf = g_new0 (UDmabuf, 1);
|
||||
|
||||
udmabuf->mem_fd = mem_fd;
|
||||
udmabuf->dmabuf_fd = dmabuf_fd;
|
||||
udmabuf->size = size;
|
||||
udmabuf->data = data;
|
||||
|
||||
return udmabuf;
|
||||
|
||||
fail:
|
||||
if (mem_fd != -1)
|
||||
close (mem_fd);
|
||||
if (dmabuf_fd != -1)
|
||||
close (dmabuf_fd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
GdkTexture *
|
||||
udmabuf_texture_new (gsize width,
|
||||
gsize height,
|
||||
guint fourcc,
|
||||
GdkColorState *color_state,
|
||||
gboolean premultiplied,
|
||||
GBytes *bytes,
|
||||
gsize stride,
|
||||
GError **error)
|
||||
{
|
||||
GdkDmabufTextureBuilder *builder;
|
||||
GdkTexture *texture;
|
||||
UDmabuf *udmabuf;
|
||||
gconstpointer data;
|
||||
gsize size;
|
||||
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
|
||||
udmabuf = udmabuf_allocate (size, error);
|
||||
if (udmabuf == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (udmabuf->data, data, size);
|
||||
|
||||
builder = gdk_dmabuf_texture_builder_new ();
|
||||
|
||||
gdk_dmabuf_texture_builder_set_display (builder, gdk_display_get_default ());
|
||||
gdk_dmabuf_texture_builder_set_width (builder, width);
|
||||
gdk_dmabuf_texture_builder_set_height (builder, height);
|
||||
gdk_dmabuf_texture_builder_set_fourcc (builder, fourcc);
|
||||
gdk_dmabuf_texture_builder_set_modifier (builder, 0);
|
||||
gdk_dmabuf_texture_builder_set_color_state (builder, color_state);
|
||||
gdk_dmabuf_texture_builder_set_premultiplied (builder, premultiplied);
|
||||
gdk_dmabuf_texture_builder_set_n_planes (builder, 1);
|
||||
gdk_dmabuf_texture_builder_set_fd (builder, 0, udmabuf->dmabuf_fd);
|
||||
gdk_dmabuf_texture_builder_set_stride (builder, 0, stride);
|
||||
gdk_dmabuf_texture_builder_set_offset (builder, 0, 0);
|
||||
|
||||
texture = gdk_dmabuf_texture_builder_build (builder, udmabuf_free, udmabuf, error);
|
||||
|
||||
g_object_unref (builder);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
GdkTexture *
|
||||
udmabuf_texture_new (gsize width,
|
||||
gsize height,
|
||||
guint fourcc,
|
||||
GdkColorState *color_state,
|
||||
gboolean premultiplied,
|
||||
GBytes *bytes,
|
||||
gsize stride,
|
||||
GError **error)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
"Dmabufs are not supported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
GdkTexture *
|
||||
udmabuf_texture_from_texture (GdkTexture *texture,
|
||||
GError **error)
|
||||
{
|
||||
guint fourcc;
|
||||
gboolean premultiplied;
|
||||
guchar *data;
|
||||
gsize width, height, stride;
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture2;
|
||||
|
||||
switch ((int) gdk_texture_get_format (texture))
|
||||
{
|
||||
#ifdef HAVE_DMABUF
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
fourcc = DRM_FORMAT_ARGB8888;
|
||||
premultiplied = TRUE;
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
fourcc = DRM_FORMAT_BGRA8888;
|
||||
premultiplied = TRUE;
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
fourcc = DRM_FORMAT_ABGR8888;
|
||||
premultiplied = TRUE;
|
||||
break;
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
fourcc = DRM_FORMAT_RGBA8888;
|
||||
premultiplied = TRUE;
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
fourcc = DRM_FORMAT_ARGB8888;
|
||||
premultiplied = FALSE;
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
fourcc = DRM_FORMAT_BGRA8888;
|
||||
premultiplied = FALSE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Unsupported memory format %u", gdk_texture_get_format (texture));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
stride = (width * 4 + 255) & ~255;
|
||||
data = g_malloc (stride * height);
|
||||
|
||||
gdk_texture_download (texture, data, stride);
|
||||
bytes = g_bytes_new_take (data, stride * height);
|
||||
|
||||
texture2 = udmabuf_texture_new (width, height,
|
||||
fourcc,
|
||||
gdk_texture_get_color_state (texture),
|
||||
premultiplied,
|
||||
bytes, stride,
|
||||
error);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture2;
|
||||
}
|
||||
|
17
testsuite/gdk/udmabuf.h
Normal file
17
testsuite/gdk/udmabuf.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
gboolean udmabuf_initialize (GError **error);
|
||||
|
||||
GdkTexture * udmabuf_texture_new (gsize width,
|
||||
gsize height,
|
||||
guint fourcc,
|
||||
GdkColorState *color_state,
|
||||
gboolean premultiplied,
|
||||
GBytes *bytes,
|
||||
gsize stride,
|
||||
GError **error);
|
||||
|
||||
GdkTexture * udmabuf_texture_from_texture (GdkTexture *texture,
|
||||
GError **error);
|
Loading…
Reference in New Issue
Block a user