Compare commits

..

30 Commits

Author SHA1 Message Date
Matthias Clasen a77fde155d testsubsurface: Add dmabuf support 2023-10-28 22:22:45 -04:00
Matthias Clasen 004c2b8cc2 wayland: Add dmabuf support for subsurfaces
Allow attaching dmabuf textures without downloading.

Currently, this is using create_immed, so failure to import a
dmabuf will be deadly.
2023-10-28 22:22:44 -04:00
Matthias Clasen 0605888ac6 Add testsubsurface
A very simple test that just checks that re(attaching) textures
to subsurfaces and changing stacking order works.
2023-10-28 22:20:45 -04:00
Matthias Clasen ef5b1ba044 wayland: Implement subsurface api
So far, this just allows attaching shm wl_buffers,
so textures will be downloaded and copied.
2023-10-28 22:20:43 -04:00
Matthias Clasen 5fa7457171 gdk: Add private subsurface api
Add api to allow creating subsurfaces, and attaching textures
to them. This is just the api, there is no implementation yet.
2023-10-28 20:57:07 -04:00
Matthias Clasen f50edb6910 wayland: Get format info for dmabufs
For now, all we do with it is dump the formats if you
set GDK_DEBUG=misc. In the future, this will be used
when attaching dmabufs to subsurfaces.
2023-10-25 23:22:55 -04:00
Benjamin Otte 2d874e601c Merge branch 'wip/otte/for-main' into 'main'
gl: Remove optimization that does the wrong thing

See merge request GNOME/gtk!6528
2023-10-24 02:51:02 +00:00
Benjamin Otte c9b83dfa1d testsuite: Add a test for texture-scale filters
Check that the right filter is chosen and that that filter is
implemented correctly.

The test is disabled for Cairo because Cairo (or rather Pixman)
doesn't follow the filtering specifications for GL/Vulkan and in
particular the nearest filter picks a different pixel.
2023-10-24 01:41:25 +02:00
Benjamin Otte dd7a38069f gl: Remove optimization that does the wrong thing
Drawing a texture-scale node like a texture node when the filter is set
to "linear" doesn't work, because the texture node switches to
trilinear when mipmaps are available.
2023-10-24 01:37:38 +02:00
Benjamin Otte 51a181af7a Merge branch 'wip/otte/for-main' into 'main'
dmabuf: Seek back to the start

See merge request GNOME/gtk!6526
2023-10-23 19:57:21 +00:00
Benjamin Otte 8fcd9bc0c4 gl: Make sure render_texture() sets the right format for high depth
Setting the format got lost when converting this coe to the texture
builder, because that codepaths avods the texture sniffing and always
uses RGBA8.
2023-10-23 21:22:17 +02:00
Benjamin Otte e2edf693f5 gdk: Make float32 report its true depth
I have no idea how this is the only value that is wrong.
2023-10-23 21:22:17 +02:00
Benjamin Otte 323300e92a dmabuf: Seek back to the start
https://docs.kernel.org/driver-api/dma-buf.html recommends doing that,
so we do that.
2023-10-23 17:57:57 +02:00
Benjamin Otte e688be1cff gdk: Add some debug messages around dmabuf initialization 2023-10-23 17:57:57 +02:00
Guillaume Bernard 611d5cf844 Update French translation
(cherry picked from commit 3b8c1189f4)
2023-10-23 15:22:29 +00:00
Matthias Clasen 51cb1aeb4e Merge branch 'matthiasc/for-main' into 'main'
Matthiasc/for main

See merge request GNOME/gtk!6519
2023-10-23 04:11:04 +00:00
Matthias Clasen 625eb508e8 dmabuftexturebuilder: Fix doc formatting 2023-10-22 23:24:46 -04:00
Matthias Clasen 2718e1715d display: Add details to the docs 2023-10-22 23:24:27 -04:00
Matthias Clasen 6ddcad6b33 dmabuf: Update a comment 2023-10-22 23:14:07 -04:00
Matthias Clasen 0c23997f70 Merge branch 'matthiasc/for-main' into 'main'
Cosmetics

See merge request GNOME/gtk!6518
2023-10-23 03:13:41 +00:00
Matthias Clasen 4d1ef63009 gsk: Ensure dmabuf formats are initialized
We just poking at display members here, there is no guarantee that
dmabuf formats have been initialized. So do it explicitly.

This prevents a crash in the inspector when viewing a recorded frame
containing a dmabuf texture, since the inspector uses a separate
display connection.
2023-10-22 22:48:18 -04:00
Matthias Clasen 30e14f73fa glcontext: Better debug spew
Print out all the extensions we checked.
2023-10-22 22:41:53 -04:00
Matthias Clasen 39e205aa78 dmabuf: Don't print unsupported formats
We were confusingly printing "supported format" for dmabuf formats
that we end up not adding to our list of supported formats. Don't
do that, it is confusing. At the same time, we shuold print out
the linear formats we support via mmap.
2023-10-22 22:29:44 -04:00
Matthias Clasen f0ec1660c1 Make testdmabuf fall back to memfd
If we can't open /dev/dma_heap/system, fall back to using memfd_create.
It does not let us make a 'proper' dmabuf, but it is good enough to
test our handling of linear buffers in various formats.
2023-10-22 22:18:30 -04:00
Matthias Clasen 79f98f3a13 Cosmetics
Typo fix.
2023-10-22 22:18:30 -04:00
Benjamin Otte 5f0557027d Merge branch 'wip/otte/for-main' into 'main'
dmabuf: Add NV16, NV61, NV24 and NV42

See merge request GNOME/gtk!6517
2023-10-23 01:49:30 +00:00
Benjamin Otte a579e3bc6d build: Fix up header includes
These weren't fixed in the merge request in
  https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6489
to the change from
  https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6514
2023-10-23 03:12:09 +02:00
Benjamin Otte 8f70f4b85e dmabuf: Add support for 3 plane YUV formats 2023-10-23 02:54:23 +02:00
Benjamin Otte 911198cddd dmabuf: Add NV16, NV61, NV24 and NV42
and sanitize them and NV21.
2023-10-23 02:54:23 +02:00
Matthias Clasen ca5247a995 Post-release version bump 2023-10-22 19:04:54 -04:00
29 changed files with 2121 additions and 853 deletions
+3
View File
@@ -1,3 +1,6 @@
Overview of Changes in 4.13.3, xx-xx-xxxx
=========================================
Overview of Changes in 4.13.2, 22-10-2023
=========================================
+10
View File
@@ -1882,6 +1882,9 @@ gdk_display_init_dmabuf (GdkDisplay *self)
if (self->dmabuf_formats != NULL)
return;
GDK_DISPLAY_DEBUG (self, DMABUF,
"Beginning initialization of dmabuf support");
builder = gdk_dmabuf_formats_builder_new ();
#ifdef HAVE_DMABUF
@@ -1899,6 +1902,10 @@ gdk_display_init_dmabuf (GdkDisplay *self)
#endif
self->dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (builder);
GDK_DISPLAY_DEBUG (self, DMABUF,
"Initialized support for %zu dmabuf formats",
gdk_dmabuf_formats_get_n_formats (self->dmabuf_formats));
}
/**
@@ -1910,6 +1917,9 @@ gdk_display_init_dmabuf (GdkDisplay *self)
* GTK may use OpenGL or Vulkan to support some formats.
* Calling this function will then initialize them if they aren't yet.
*
* The formats returned by this function can be used for negotiating
* buffer formats with producers such as v4l, pipewire or GStreamer.
*
* Returns: (transfer none): a `GdkDmabufFormats` object
*
* Since: 4.14
+221 -29
View File
@@ -133,15 +133,31 @@ download_nv12 (guchar *dst_data,
{
const guchar *y_data, *uv_data;
gsize x, y, y_stride, uv_stride;
gsize U, V;
gsize U, V, X_SUB, Y_SUB;
if (dmabuf->fourcc == DRM_FORMAT_NV21)
switch (dmabuf->fourcc)
{
U = 1; V = 0;
}
else
{
U = 0; V = 1;
case DRM_FORMAT_NV12:
U = 0; V = 1; X_SUB = 2; Y_SUB = 2;
break;
case DRM_FORMAT_NV21:
U = 1; V = 0; X_SUB = 2; Y_SUB = 2;
break;
case DRM_FORMAT_NV16:
U = 0; V = 1; X_SUB = 2; Y_SUB = 1;
break;
case DRM_FORMAT_NV61:
U = 1; V = 0; X_SUB = 2; Y_SUB = 1;
break;
case DRM_FORMAT_NV24:
U = 0; V = 1; X_SUB = 1; Y_SUB = 1;
break;
case DRM_FORMAT_NV42:
U = 1; V = 0; X_SUB = 1; Y_SUB = 1;
break;
default:
g_assert_not_reached ();
return;
}
y_stride = dmabuf->planes[0].stride;
@@ -149,35 +165,108 @@ download_nv12 (guchar *dst_data,
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + height * y_stride);
uv_stride = dmabuf->planes[1].stride;
uv_data = src_data[1] + dmabuf->planes[1].offset;
g_return_if_fail (sizes[1] >= dmabuf->planes[1].offset + (height + 1) / 2 * uv_stride);
g_return_if_fail (sizes[1] >= dmabuf->planes[1].offset + (height + Y_SUB - 1) / Y_SUB * uv_stride);
for (y = 0; y < height; y += 2)
for (y = 0; y < height; y += Y_SUB)
{
guchar *dst2_data = dst_data + dst_stride;
const guchar *y2_data = y_data + y_stride;
for (x = 0; x < width; x += 2)
for (x = 0; x < width; x += X_SUB)
{
int r, g, b;
gsize xs, ys;
get_uv_values (&itu601_wide, uv_data[x + U], uv_data[x + V], &r, &g, &b);
get_uv_values (&itu601_wide, uv_data[x / X_SUB * 2 + U], uv_data[x / X_SUB * 2 + V], &r, &g, &b);
set_rgb_values (&dst_data[3 * x], y_data[x], r, g, b);
if (x + 1 < width)
set_rgb_values (&dst_data[3 * (x + 1)], y_data[x], r, g, b);
if (y + 1 < height)
{
set_rgb_values (&dst2_data[3 * x], y2_data[x], r, g, b);
if (x + 1 < width)
set_rgb_values (&dst2_data[3 * (x + 1)], y2_data[x], r, g, b);
}
for (ys = 0; ys < Y_SUB && y + ys < height; ys++)
for (xs = 0; xs < X_SUB && x + xs < width; xs++)
set_rgb_values (&dst_data[3 * (x + xs) + dst_stride * ys], y_data[x + xs + y_stride * ys], r, g, b);
}
dst_data += 2 * dst_stride;
y_data += 2 * y_stride;
dst_data += Y_SUB * dst_stride;
y_data += Y_SUB * y_stride;
uv_data += uv_stride;
}
}
static void
download_yuv_3 (guchar *dst_data,
gsize dst_stride,
GdkMemoryFormat dst_format,
gsize width,
gsize height,
const GdkDmabuf *dmabuf,
const guchar *src_data[GDK_DMABUF_MAX_PLANES],
gsize sizes[GDK_DMABUF_MAX_PLANES])
{
const guchar *y_data, *u_data, *v_data;
gsize x, y, y_stride, u_stride, v_stride;
gsize U, V, X_SUB, Y_SUB;
switch (dmabuf->fourcc)
{
case DRM_FORMAT_YUV410:
U = 1; V = 2; X_SUB = 4; Y_SUB = 4;
break;
case DRM_FORMAT_YVU410:
U = 2; V = 1; X_SUB = 4; Y_SUB = 4;
break;
case DRM_FORMAT_YUV411:
U = 1; V = 2; X_SUB = 4; Y_SUB = 1;
break;
case DRM_FORMAT_YVU411:
U = 2; V = 1; X_SUB = 4; Y_SUB = 1;
break;
case DRM_FORMAT_YUV420:
U = 1; V = 2; X_SUB = 2; Y_SUB = 2;
break;
case DRM_FORMAT_YVU420:
U = 2; V = 1; X_SUB = 2; Y_SUB = 2;
break;
case DRM_FORMAT_YUV422:
U = 1; V = 2; X_SUB = 2; Y_SUB = 1;
break;
case DRM_FORMAT_YVU422:
U = 2; V = 1; X_SUB = 2; Y_SUB = 1;
break;
case DRM_FORMAT_YUV444:
U = 1; V = 2; X_SUB = 1; Y_SUB = 1;
break;
case DRM_FORMAT_YVU444:
U = 2; V = 1; X_SUB = 1; Y_SUB = 1;
break;
default:
g_assert_not_reached ();
return;
}
y_stride = dmabuf->planes[0].stride;
y_data = src_data[0] + dmabuf->planes[0].offset;
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + height * y_stride);
u_stride = dmabuf->planes[U].stride;
u_data = src_data[U] + dmabuf->planes[U].offset;
g_return_if_fail (sizes[U] >= dmabuf->planes[U].offset + (height + Y_SUB - 1) / Y_SUB * u_stride);
v_stride = dmabuf->planes[V].stride;
v_data = src_data[V] + dmabuf->planes[V].offset;
g_return_if_fail (sizes[V] >= dmabuf->planes[V].offset + (height + Y_SUB - 1) / Y_SUB * v_stride);
for (y = 0; y < height; y += Y_SUB)
{
for (x = 0; x < width; x += X_SUB)
{
int r, g, b;
gsize xs, ys;
get_uv_values (&itu601_wide, u_data[x / X_SUB], v_data[x / X_SUB], &r, &g, &b);
for (ys = 0; ys < Y_SUB && y + ys < height; ys++)
for (xs = 0; xs < X_SUB && x + xs < width; xs++)
set_rgb_values (&dst_data[3 * (x + xs) + dst_stride * ys], y_data[x + xs + y_stride * ys], r, g, b);
}
dst_data += Y_SUB * dst_stride;
y_data += Y_SUB * y_stride;
u_data += u_stride;
v_data += v_stride;
}
}
static void
download_yuyv (guchar *dst_data,
gsize dst_stride,
@@ -246,10 +335,24 @@ static const GdkDrmFormatInfo supported_formats[] = {
/* YUV formats */
{ DRM_FORMAT_NV12, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_NV21, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_NV16, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_NV61, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_NV24, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_NV42, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
{ DRM_FORMAT_YUYV, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
{ DRM_FORMAT_YVYU, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
{ DRM_FORMAT_VYUY, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
{ DRM_FORMAT_UYVY, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
{ DRM_FORMAT_YUV410, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YVU410, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YUV411, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YVU411, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YUV420, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YVU420, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YUV422, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YVU422, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YUV444, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
{ DRM_FORMAT_YVU444, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
};
static const GdkDrmFormatInfo *
@@ -273,6 +376,10 @@ gdk_dmabuf_direct_downloader_add_formats (const GdkDmabufDownloader *downloader,
for (i = 0; i < G_N_ELEMENTS (supported_formats); i++)
{
GDK_DEBUG (DMABUF, "%s dmabuf format %.4s:%#" G_GINT64_MODIFIER "x",
downloader->name,
(char *) &supported_formats[i].fourcc, (guint64) DRM_FORMAT_MOD_LINEAR);
gdk_dmabuf_formats_builder_add_format (builder,
supported_formats[i].fourcc,
DRM_FORMAT_MOD_LINEAR);
@@ -356,6 +463,8 @@ gdk_dmabuf_direct_downloader_do_download (GdkTexture *texture,
g_warning ("Failed to seek dmabuf: %s", g_strerror (errno));
goto out;
}
/* be a good citizen and seek back to the start, as the dos recommend */
lseek (dmabuf->planes[i].fd, 0, SEEK_SET);
if (ioctl (dmabuf->planes[i].fd, DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_START|DMA_BUF_SYNC_READ }) < 0)
g_warning ("Failed to sync dmabuf: %s", g_strerror (errno));
@@ -447,15 +556,14 @@ gdk_dmabuf_get_direct_downloader (void)
* controlled by the callers.
*
* Things we do here:
*
*
* 1. Disallow any dmabuf format that we do not know.
*
* 1. Treat the INVALID modifier the same as LINEAR.
* 1. Reject the INVALID modifier, accept the LINEAR one.
*
* 2. Ignore all other modifiers.
*
* 3. Try and fix various inconsistencies between V4L and Mesa,
* like NV12.
* 3. Try and fix various inconsistencies between V4L and Mesa, like NV12.
*
* *** WARNING ***
*
@@ -511,6 +619,9 @@ gdk_dmabuf_sanitize (GdkDmabuf *dest,
switch (dest->fourcc)
{
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV61:
if (dest->n_planes == 1)
{
dest->n_planes = 2;
@@ -520,6 +631,87 @@ gdk_dmabuf_sanitize (GdkDmabuf *dest,
}
break;
case DRM_FORMAT_NV24:
case DRM_FORMAT_NV42:
if (dest->n_planes == 1)
{
dest->n_planes = 2;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = dest->planes[0].stride * 2;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
}
break;
case DRM_FORMAT_YUV410:
case DRM_FORMAT_YVU410:
if (dest->n_planes == 1)
{
dest->n_planes = 3;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = (dest->planes[0].stride + 3) / 4;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
dest->planes[2].fd = dest->planes[1].fd;
dest->planes[2].stride = dest->planes[1].stride;
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * ((height + 3) / 4);
}
break;
case DRM_FORMAT_YUV411:
case DRM_FORMAT_YVU411:
if (dest->n_planes == 1)
{
dest->n_planes = 3;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = (dest->planes[0].stride + 3) / 4;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
dest->planes[2].fd = dest->planes[1].fd;
dest->planes[2].stride = dest->planes[1].stride;
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * height;
}
break;
case DRM_FORMAT_YUV420:
case DRM_FORMAT_YVU420:
if (dest->n_planes == 1)
{
dest->n_planes = 3;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = (dest->planes[0].stride + 1) / 2;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
dest->planes[2].fd = dest->planes[1].fd;
dest->planes[2].stride = dest->planes[1].stride;
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * ((height + 1) / 2);
}
break;
case DRM_FORMAT_YUV422:
case DRM_FORMAT_YVU422:
if (dest->n_planes == 1)
{
dest->n_planes = 3;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = (dest->planes[0].stride + 1) / 2;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
dest->planes[2].fd = dest->planes[1].fd;
dest->planes[2].stride = dest->planes[1].stride;
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * height;
}
break;
case DRM_FORMAT_YUV444:
case DRM_FORMAT_YVU444:
if (dest->n_planes == 1)
{
dest->n_planes = 3;
dest->planes[1].fd = dest->planes[0].fd;
dest->planes[1].stride = dest->planes[0].stride;
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
dest->planes[2].fd = dest->planes[1].fd;
dest->planes[2].stride = dest->planes[1].stride;
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * height;
}
break;
default:
break;
}
+12 -7
View File
@@ -33,7 +33,7 @@
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include <drm/drm_fourcc.h>
#include <drm_fourcc.h>
#include <epoxy/egl.h>
/* A dmabuf downloader implementation that downloads buffers via
@@ -101,17 +101,20 @@ gdk_dmabuf_egl_downloader_add_formats (const GdkDmabufDownloader *downloader,
for (int j = 0; j < num_modifiers; j++)
{
GDK_DEBUG (DMABUF, "supported %sEGL dmabuf format %.4s:%#" G_GINT64_MODIFIER "x",
external_only[j] ? "external " : "",
(char *) &fourccs[i],
modifiers[j]);
/* All linear formats we support are already added my the mmap downloader.
* We don't add external formats, unless we can use them (via GLES)
*/
if (modifiers[j] != DRM_FORMAT_MOD_LINEAR &&
(!external_only[j] || gdk_gl_context_get_use_es (context)))
gdk_dmabuf_formats_builder_add_format (builder, fourccs[i], modifiers[j]);
{
GDK_DEBUG (DMABUF, "%s%s dmabuf format %.4s:%#" G_GINT64_MODIFIER "x",
external_only[j] ? "external " : "",
downloader->name,
(char *) &fourccs[i],
modifiers[j]);
gdk_dmabuf_formats_builder_add_format (builder, fourccs[i], modifiers[j]);
}
if (external_only[j])
gdk_dmabuf_formats_builder_add_format (external, fourccs[i], modifiers[j]);
}
@@ -187,7 +190,9 @@ get_memory_format (guint32 fourcc,
case DRM_FORMAT_UYVY:
case DRM_FORMAT_VYUY:
case DRM_FORMAT_XYUV8888:
#ifdef DRM_FORMAT_XVUY8888
case DRM_FORMAT_XVUY8888:
#endif
case DRM_FORMAT_VUY888:
return GDK_MEMORY_R8G8B8;
+6 -3
View File
@@ -96,9 +96,12 @@ struct _GdkDmabufTextureBuilderClass
* to create the new texture.
*
* The required properties for a dma-buf texture are
* - The width and height in pixels
* - The `fourcc` code and `modifier` which identify the format and memory layout of the dma-buf
* - The file descriptor, offset and stride for each of the planes
*
* * The width and height in pixels
*
* * The `fourcc` code and `modifier` which identify the format and memory layout of the dma-buf
*
* * The file descriptor, offset and stride for each of the planes
*
* `GdkDmabufTextureBuilder` can be used for quick one-shot construction of
* textures as well as kept around and reused to construct multiple textures.
+7 -5
View File
@@ -97,7 +97,7 @@
#endif
#ifdef HAVE_DMABUF
#include <drm/drm_fourcc.h>
#include <drm_fourcc.h>
#endif
#include <math.h>
@@ -1577,9 +1577,10 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
"* Extensions checked:\n"
" - GL_KHR_debug: %s\n"
" - GL_EXT_unpack_subimage: %s\n"
" - GL_EXT_texture_format_BGRA8888: %s\n"
" - GL_EXT_EGL_image_storage: %s\n"
" - half float: %s\n"
" - sync: %s\n"
" - bgra: %s",
" - sync: %s",
gdk_gl_context_get_use_es (context) ? "OpenGL ES" : "OpenGL",
gdk_gl_version_get_major (&priv->gl_version), gdk_gl_version_get_minor (&priv->gl_version),
priv->is_legacy ? "legacy" : "core",
@@ -1587,9 +1588,10 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
max_texture_size,
priv->has_khr_debug ? "yes" : "no",
priv->has_unpack_subimage ? "yes" : "no",
priv->has_bgra ? "yes" : "no",
priv->has_image_storage ? "yes" : "no",
priv->has_half_float ? "yes" : "no",
priv->has_sync ? "yes" : "no",
priv->has_bgra ? "yes" : "no");
priv->has_sync ? "yes" : "no");
}
#endif
+1 -1
View File
@@ -569,7 +569,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
GDK_MEMORY_ALPHA_PREMULTIPLIED,
16,
G_ALIGNOF (float),
TRUE,
GDK_MEMORY_FLOAT32,
{ 0, 0, 3, 0 },
{ GL_RGBA32F, GL_RGBA, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
r32g32b32a32_float_to_float,
+44
View File
@@ -493,6 +493,12 @@ gdk_surface_real_get_scale (GdkSurface *surface)
return 1.0;
}
static GdkSubsurface *
gdk_surface_real_create_subsurface (GdkSurface *surface)
{
return NULL;
}
static void
gdk_surface_constructed (GObject *object)
{
@@ -515,6 +521,7 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
klass->beep = gdk_surface_real_beep;
klass->get_scale = gdk_surface_real_get_scale;
klass->create_subsurface = gdk_surface_real_create_subsurface;
/**
* GdkSurface:cursor: (attributes org.gtk.Property.get=gdk_surface_get_cursor org.gtk.Property.set=gdk_surface_set_cursor)
@@ -3054,3 +3061,40 @@ gdk_surface_leave_monitor (GdkSurface *surface,
{
g_signal_emit (surface, signals[LEAVE_MONITOR], 0, monitor);
}
GdkSubsurface *
gdk_surface_create_subsurface (GdkSurface *surface)
{
return GDK_SURFACE_GET_CLASS (surface)->create_subsurface (surface);
}
void
gdk_subsurface_destroy (GdkSubsurface *subsurface)
{
subsurface->class->destroy (subsurface);
}
void
gdk_subsurface_attach (GdkSubsurface *subsurface,
GdkTexture *texture,
const graphene_rect_t *bounds)
{
subsurface->class->attach (subsurface, texture, bounds);
}
/* If sibling is NULL, place the subsurface above its parent */
void
gdk_subsurface_place_above (GdkSubsurface *subsurface,
GdkSubsurface *sibling)
{
subsurface->class->place_above (subsurface, sibling);
}
/* If sibling is NULL, place the subsurface below its parent */
void
gdk_subsurface_place_below (GdkSubsurface *subsurface,
GdkSubsurface *sibling)
{
subsurface->class->place_below (subsurface, sibling);
}
+35
View File
@@ -23,9 +23,14 @@
#include "gdkenumtypes.h"
#include "gdksurface.h"
#include "gdktoplevel.h"
#include <graphene.h>
G_BEGIN_DECLS
typedef struct _GdkSubsurface GdkSubsurface;
typedef struct _GskRenderNode GskRenderNode;
struct _GdkSurface
{
GObject parent_instance;
@@ -146,6 +151,9 @@ struct _GdkSurfaceClass
cairo_region_t *region);
void (* request_layout) (GdkSurface *surface);
gboolean (* compute_size) (GdkSurface *surface);
GdkSubsurface *
(* create_subsurface) (GdkSurface *surface);
};
#define GDK_SURFACE_DESTROYED(d) (((GdkSurface *)(d))->destroyed)
@@ -334,7 +342,34 @@ void gdk_surface_request_motion (GdkSurface *surface);
gboolean gdk_surface_supports_edge_constraints (GdkSurface *surface);
GdkSubsurface * gdk_surface_create_subsurface (GdkSurface *surface);
typedef struct _GdkSubsurfaceClass GdkSubsurfaceClass;
struct _GdkSubsurfaceClass
{
void (* destroy) (GdkSubsurface *subsurface);
void (* attach) (GdkSubsurface *subsurface,
GdkTexture *texture,
const graphene_rect_t *bounds);
void (* place_above) (GdkSubsurface *subsurface,
GdkSubsurface *sibling);
void (* place_below) (GdkSubsurface *subsurface,
GdkSubsurface *sibling);
};
struct _GdkSubsurface
{
const GdkSubsurfaceClass *class;
};
void gdk_subsurface_destroy (GdkSubsurface *subsurface);
void gdk_subsurface_attach (GdkSubsurface *subsurface,
GdkTexture *texture,
const graphene_rect_t *bounds);
void gdk_subsurface_place_above (GdkSubsurface *subsurface,
GdkSubsurface *sibling);
void gdk_subsurface_place_below (GdkSubsurface *subsurface,
GdkSubsurface *sibling);
G_END_DECLS
+104 -28
View File
@@ -24,6 +24,7 @@
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/sysmacros.h>
#ifdef HAVE_LINUX_MEMFD_H
#include <linux/memfd.h>
@@ -56,6 +57,7 @@
#include <wayland/xdg-foreign-unstable-v1-client-protocol.h>
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
#include <wayland/server-decoration-client-protocol.h>
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "wm-button-layout-translation.h"
@@ -267,45 +269,105 @@ postpone_on_globals_closure (GdkWaylandDisplay *display_wayland,
g_list_append (display_wayland->on_has_globals_closures, closure);
}
#ifdef G_ENABLE_DEBUG
static const char *
get_format_name (uint32_t format,
char name[10])
{
if (format == 0)
g_strlcpy (name, "ARGB8888", 10);
else if (format == 1)
g_strlcpy (name, "XRGB8888", 10);
else
g_snprintf (name, 10, "4cc %c%c%c%c",
(char) (format & 0xff),
(char) ((format >> 8) & 0xff),
(char) ((format >> 16) & 0xff),
(char) ((format >> 24) & 0xff));
return name;
}
#endif
static void
wl_shm_format (void *data,
struct wl_shm *wl_shm,
uint32_t format)
{
#ifdef G_ENABLE_DEBUG
char buf[10];
#endif
GDK_DEBUG (MISC, "supported pixel format %s (0x%X)",
get_format_name (format, buf), (guint) format);
GDK_DEBUG (MISC, "supported shm pixel format %.4s (0x%X)", (char *) &format, format);
}
static const struct wl_shm_listener wl_shm_listener = {
wl_shm_format
};
static void
linux_dmabuf_done (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1)
{
GDK_DEBUG (MISC, "dmabuf feedback done");
}
static void
linux_dmabuf_format_table (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
int32_t fd,
uint32_t size)
{
GdkWaylandDisplay *display_wayland = data;
display_wayland->linux_dmabuf_n_formats = size / 16;
display_wayland->linux_dmabuf_formats = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
GDK_DEBUG (MISC, "got dmabuf format table (%lu entries)", display_wayland->linux_dmabuf_n_formats);
}
static void
linux_dmabuf_main_device (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
struct wl_array *device)
{
dev_t dev = *(dev_t *)device->data;
GDK_DEBUG (MISC, "got dmabuf main device: %u %u", major (dev), minor (dev));
}
static void
linux_dmabuf_tranche_done (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1)
{
GDK_DEBUG (MISC, "dmabuf feedback tranche done");
}
static void
linux_dmabuf_tranche_target_device (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
struct wl_array *device)
{
dev_t dev = *(dev_t *)device->data;
GDK_DEBUG (MISC, "got dmabuf tranche target device: %u %u", major (dev), minor (dev));
}
static void
linux_dmabuf_tranche_formats (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
struct wl_array *indices)
{
GdkWaylandDisplay *display_wayland = data;
GDK_DEBUG (MISC, "got dmabuf tranche formats (%lu entries):", indices->size / sizeof (guint16));
guint16 *pos;
wl_array_for_each (pos, indices)
{
LinuxDmabufFormat *fmt = &display_wayland->linux_dmabuf_formats[*pos];
uint32_t f = fmt->fourcc;
uint64_t m = fmt->modifier;
GDK_DEBUG (MISC, " %.4s:%#" G_GINT64_MODIFIER "x", (char *) &f, m);
}
}
static void
linux_dmabuf_tranche_flags (void *data,
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
uint32_t flags)
{
GDK_DEBUG (MISC,
"got dmabuf tranche flags: %s",
flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT ? "scanout" : "");
}
static const struct zwp_linux_dmabuf_feedback_v1_listener linux_dmabuf_feedback_listener = {
linux_dmabuf_done,
linux_dmabuf_format_table,
linux_dmabuf_main_device,
linux_dmabuf_tranche_done,
linux_dmabuf_tranche_target_device,
linux_dmabuf_tranche_formats,
linux_dmabuf_tranche_flags,
};
static void
server_decoration_manager_default_mode (void *data,
struct org_kde_kwin_server_decoration_manager *manager,
@@ -382,6 +444,16 @@ gdk_registry_handle_global (void *data,
wl_registry_bind (display_wayland->wl_registry, id, &wl_shm_interface, 1);
wl_shm_add_listener (display_wayland->shm, &wl_shm_listener, display_wayland);
}
else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0 && version >= 4)
{
display_wayland->linux_dmabuf =
wl_registry_bind (display_wayland->wl_registry, id, &zwp_linux_dmabuf_v1_interface, version);
display_wayland->linux_dmabuf_feedback =
zwp_linux_dmabuf_v1_get_default_feedback (display_wayland->linux_dmabuf);
zwp_linux_dmabuf_feedback_v1_add_listener (display_wayland->linux_dmabuf_feedback,
&linux_dmabuf_feedback_listener, display_wayland);
_gdk_wayland_display_async_roundtrip (display_wayland);
}
else if (strcmp (interface, "xdg_wm_base") == 0)
{
display_wayland->xdg_wm_base_id = id;
@@ -726,6 +798,10 @@ gdk_wayland_display_dispose (GObject *object)
g_clear_pointer (&display_wayland->xdg_activation, xdg_activation_v1_destroy);
g_clear_pointer (&display_wayland->fractional_scale, wp_fractional_scale_manager_v1_destroy);
g_clear_pointer (&display_wayland->viewporter, wp_viewporter_destroy);
g_clear_pointer (&display_wayland->linux_dmabuf, zwp_linux_dmabuf_v1_destroy);
g_clear_pointer (&display_wayland->linux_dmabuf_feedback, zwp_linux_dmabuf_feedback_v1_destroy);
if (display_wayland->linux_dmabuf_formats)
munmap (display_wayland->linux_dmabuf_formats, display_wayland->linux_dmabuf_n_formats * 16);
g_clear_pointer (&display_wayland->shm, wl_shm_destroy);
g_clear_pointer (&display_wayland->wl_registry, wl_registry_destroy);
+11
View File
@@ -71,6 +71,13 @@ typedef enum _GdkWaylandShellVariant
GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6
} GdkWaylandShellVariant;
typedef struct
{
uint32_t fourcc;
uint32_t padding;
uint64_t modifier;
} LinuxDmabufFormat;
struct _GdkWaylandDisplay
{
GdkDisplay parent_instance;
@@ -95,6 +102,10 @@ struct _GdkWaylandDisplay
struct wl_registry *wl_registry;
struct wl_compositor *compositor;
struct wl_shm *shm;
struct zwp_linux_dmabuf_v1 *linux_dmabuf;
struct zwp_linux_dmabuf_feedback_v1 *linux_dmabuf_feedback;
gsize linux_dmabuf_n_formats;
LinuxDmabufFormat *linux_dmabuf_formats;
struct xdg_wm_base *xdg_wm_base;
struct zxdg_shell_v6 *zxdg_shell_v6;
struct gtk_shell1 *gtk_shell;
+1 -1
View File
@@ -75,7 +75,7 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
WL_SURFACE_OFFSET_SINCE_VERSION)
wl_surface_offset (impl->display_server.wl_surface, dx, dy);
/* We should do ths when setting up the EGLSurface, but we don't make_current then */
/* We should do this when setting up the EGLSurface, but we don't make_current then */
eglSwapInterval (gdk_display_get_egl_display (gdk_draw_context_get_display (draw_context)), 0);
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->end_frame (draw_context, painted);
+1 -1
View File
@@ -35,6 +35,7 @@
#include <gdk/wayland/gdkdisplay-wayland.h>
#include <gdk/wayland/gdkseat-wayland.h>
#include <gsk/gsk.h>
#include <xkbcommon/xkbcommon.h>
@@ -222,4 +223,3 @@ void gdk_wayland_surface_update_scale (GdkSurface *surface);
GdkModifierType gdk_wayland_keymap_get_gdk_modifiers (GdkKeymap *keymap,
guint32 mods);
+2
View File
@@ -86,6 +86,8 @@ struct _GdkWaylandSurface
uint32_t last_configure_serial;
int state_freeze_count;
GPtrArray *subsurfaces;
};
typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
+256 -1
View File
@@ -33,9 +33,11 @@
#include "gdksurfaceprivate.h"
#include "gdktoplevelprivate.h"
#include "gdkdevice-wayland-private.h"
#include "gdkdmabuftextureprivate.h"
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include <stdlib.h>
#include <stdio.h>
@@ -48,6 +50,7 @@
#include "gdksurface-wayland-private.h"
#include "gdktoplevel-wayland-private.h"
/**
* GdkWaylandSurface:
*
@@ -152,13 +155,17 @@ wl_region_from_cairo_region (GdkWaylandDisplay *display,
}
/* }}} */
/* {{{ Surface implementation */
/* {{{ Surface implementation */
static void gdk_wayland_subsurface_destroy (GdkSubsurface *sub);
static void
gdk_wayland_surface_init (GdkWaylandSurface *impl)
{
impl->scale = GDK_FRACTIONAL_SCALE_INIT_INT (1);
impl->viewport_dirty = TRUE;
impl->subsurfaces = g_ptr_array_new ();
}
void
@@ -552,6 +559,7 @@ gdk_wayland_surface_finalize (GObject *object)
g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
g_clear_pointer (&impl->input_region, cairo_region_destroy);
g_clear_pointer (&impl->subsurfaces, g_ptr_array_unref);
G_OBJECT_CLASS (gdk_wayland_surface_parent_class)->finalize (object);
}
@@ -1135,6 +1143,17 @@ gdk_wayland_surface_set_input_region (GdkSurface *surface,
impl->input_region_dirty = TRUE;
}
static void
gdk_wayland_surface_destroy_subsurfaces (GdkWaylandSurface *impl)
{
for (gsize i = 0; i < impl->subsurfaces->len; i++)
{
GdkSubsurface *sub = g_ptr_array_index (impl->subsurfaces, i);
gdk_subsurface_destroy (sub);
}
g_ptr_array_set_size (impl->subsurfaces, 0);
}
static void
gdk_wayland_surface_destroy (GdkSurface *surface,
gboolean foreign_destroy)
@@ -1151,6 +1170,7 @@ gdk_wayland_surface_destroy (GdkSurface *surface,
if (GDK_IS_TOPLEVEL (surface))
gdk_wayland_toplevel_destroy (GDK_TOPLEVEL (surface));
gdk_wayland_surface_destroy_subsurfaces (GDK_WAYLAND_SURFACE (surface));
gdk_wayland_surface_destroy_wl_surface (GDK_WAYLAND_SURFACE (surface));
frame_clock = gdk_surface_get_frame_clock (surface);
@@ -1207,6 +1227,8 @@ gdk_wayland_surface_default_hide_surface (GdkWaylandSurface *surface)
{
}
static GdkSubsurface *gdk_wayland_surface_create_subsurface (GdkSurface *surface);
static void
gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
{
@@ -1230,6 +1252,7 @@ gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
surface_class->get_scale = gdk_wayland_surface_get_scale;
surface_class->set_opaque_region = gdk_wayland_surface_set_opaque_region;
surface_class->request_layout = gdk_wayland_surface_request_layout;
surface_class->create_subsurface = gdk_wayland_surface_create_subsurface;
klass->handle_configure = gdk_wayland_surface_default_handle_configure;
klass->handle_frame = gdk_wayland_surface_default_handle_frame;
@@ -1305,4 +1328,236 @@ gdk_wayland_surface_get_wl_surface (GdkSurface *surface)
}
/* }}}} */
/* {{{ Subsurface */
typedef struct {
GdkSubsurface subsurface;
GdkWaylandSurface *parent;
struct wl_surface *wl_surface;
struct wl_subsurface *wl_subsurface;
struct wp_viewport *wp_viewport;
} GdkWaylandSubsurface;
static void
dmabuf_buffer_release (void *data,
struct wl_buffer *wl_buffer)
{
GdkTexture *texture = data;
g_object_unref (texture);
wl_buffer_destroy (wl_buffer);
}
static const struct wl_buffer_listener dmabuf_buffer_listener = {
dmabuf_buffer_release,
};
static struct wl_buffer *
get_dmabuf_wl_buffer (GdkWaylandSubsurface *self,
GdkTexture *texture)
{
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self->parent)));
const GdkDmabuf *dmabuf;
struct zwp_linux_buffer_params_v1 *params;
struct wl_buffer *wl_buffer;
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
params = zwp_linux_dmabuf_v1_create_params (display->linux_dmabuf);
for (gsize i = 0; i < dmabuf->n_planes; i++)
zwp_linux_buffer_params_v1_add (params,
dmabuf->planes[i].fd,
i,
dmabuf->planes[i].offset,
dmabuf->planes[i].stride,
dmabuf->modifier >> 32,
dmabuf->modifier & 0xffffffff);
wl_buffer = zwp_linux_buffer_params_v1_create_immed (params,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture),
dmabuf->fourcc,
0);
wl_buffer_add_listener (wl_buffer, &dmabuf_buffer_listener, g_object_ref (texture));
return wl_buffer;
}
static void
shm_buffer_release (void *data,
struct wl_buffer *wl_buffer)
{
cairo_surface_t *surface = data;
/* Note: the wl_buffer is destroyed as cairo user data */
cairo_surface_destroy (surface);
}
static const struct wl_buffer_listener shm_buffer_listener = {
shm_buffer_release,
};
static struct wl_buffer *
get_shm_wl_buffer (GdkWaylandSubsurface *self,
GdkTexture *texture)
{
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self->parent)));
int width, height;
cairo_surface_t *surface;
GdkTextureDownloader *downloader;
struct wl_buffer *wl_buffer;
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
surface = gdk_wayland_display_create_shm_surface (display, width, height, &GDK_FRACTIONAL_SCALE_INIT_INT (1));
downloader = gdk_texture_downloader_new (texture);
gdk_texture_downloader_download_into (downloader,
cairo_image_surface_get_data (surface),
cairo_image_surface_get_stride (surface));
gdk_texture_downloader_free (downloader);
wl_buffer = _gdk_wayland_shm_surface_get_wl_buffer (surface);
wl_buffer_add_listener (wl_buffer, &shm_buffer_listener, surface);
return wl_buffer;
}
static struct wl_buffer *
get_wl_buffer (GdkWaylandSubsurface *self,
GdkTexture *texture)
{
if (GDK_IS_DMABUF_TEXTURE (texture))
return get_dmabuf_wl_buffer (self, texture);
else
return get_shm_wl_buffer (self, texture);
}
static void
gdk_wayland_subsurface_attach (GdkSubsurface *sub,
GdkTexture *texture,
const graphene_rect_t *rect)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
GDK_DEBUG (DMABUF,
"Attaching texture %p at %f %f %f %f",
texture,
rect->origin.x, rect->origin.y, rect->size.width, rect->size.height);
if (rect)
{
wl_subsurface_set_position (self->wl_subsurface,
floorf (rect->origin.x),
floorf (rect->origin.y));
wp_viewport_set_destination (self->wp_viewport,
ceilf (rect->origin.x + rect->size.width) - floorf (rect->origin.x),
ceilf (rect->origin.y + rect->size.height) - floorf (rect->origin.y));
}
if (texture)
{
wl_surface_attach (self->wl_surface, get_wl_buffer (self, texture), 0, 0);
wl_surface_damage_buffer (self->wl_surface,
0, 0,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture));
}
else
{
wl_surface_attach (self->wl_surface, NULL, 0, 0);
}
wl_surface_commit (self->wl_surface);
}
static void
gdk_wayland_subsurface_destroy (GdkSubsurface *sub)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
g_clear_pointer (&self->wp_viewport, wp_viewport_destroy);
g_clear_pointer (&self->wl_subsurface, wl_subsurface_destroy);
g_clear_pointer (&self->wl_surface, wl_surface_destroy);
g_ptr_array_remove (self->parent->subsurfaces, self);
g_free (self);
}
static void
gdk_wayland_subsurface_place_above (GdkSubsurface *sub,
GdkSubsurface *sibling)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
GdkWaylandSubsurface *sib = (GdkWaylandSubsurface *)sibling;
g_return_if_fail (sib == NULL || self->parent == sib->parent);
wl_subsurface_place_above (self->wl_subsurface,
sib ? sib->wl_surface : self->parent->display_server.wl_surface);
}
static void
gdk_wayland_subsurface_place_below (GdkSubsurface *sub,
GdkSubsurface *sibling)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
GdkWaylandSubsurface *sib = (GdkWaylandSubsurface *)sibling;
g_return_if_fail (sib == NULL || self->parent == sib->parent);
wl_subsurface_place_below (self->wl_subsurface,
sib ? sib->wl_surface : self->parent->display_server.wl_surface);
}
static const GdkSubsurfaceClass subsurface_class = {
gdk_wayland_subsurface_destroy,
gdk_wayland_subsurface_attach,
gdk_wayland_subsurface_place_above,
gdk_wayland_subsurface_place_below,
};
static GdkSubsurface *
gdk_wayland_surface_create_subsurface (GdkSurface *surface)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
GdkWaylandSubsurface *sub;
struct wl_region *wl_region;
if (display->viewporter == NULL)
{
GDK_DEBUG (DMABUF, "Can't use subsurfaces without viewporter");
return NULL;
}
sub = g_new0 (GdkWaylandSubsurface, 1);
sub->subsurface.class = &subsurface_class;
sub->parent = impl;
g_ptr_array_add (sub->parent->subsurfaces, sub);
sub->wl_surface = wl_compositor_create_surface (display->compositor);
wl_region = wl_compositor_create_region (display->compositor);
wl_surface_set_input_region (sub->wl_surface, wl_region);
wl_region_destroy (wl_region);
sub->wl_subsurface = wl_subcompositor_get_subsurface (display->subcompositor,
sub->wl_surface,
impl->display_server.wl_surface);
sub->wp_viewport = wp_viewporter_get_viewport (display->viewporter, sub->wl_surface);
GDK_DEBUG (DMABUF, "Subsurface created");
return (GdkSubsurface *) sub;
}
/* }}} */
/* vim:set foldmethod=marker expandtab: */
+1
View File
@@ -67,6 +67,7 @@ proto_sources = [
['idle-inhibit', 'unstable', 'v1', ],
['xdg-activation', 'staging', 'v1', ],
['fractional-scale', 'staging', 'v1', ],
['linux-dmabuf', 'unstable', 'v1', ],
]
gdk_wayland_gen_headers = []
+6 -2
View File
@@ -822,6 +822,8 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
GDK_DEBUG (DMABUF, "DMA-buf Format %.4s:%#lx", (char *) &dmabuf->fourcc, dmabuf->modifier);
gdk_display_init_dmabuf (display);
if (!gdk_dmabuf_formats_contains (display->egl_external_formats, dmabuf->fourcc, dmabuf->modifier))
{
GDK_DEBUG (DMABUF, "Import dmabuf as GL_TEXTURE_2D texture");
@@ -1799,8 +1801,9 @@ create_texture_from_texture_destroy (gpointer data)
}
GdkTexture *
gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
guint texture_id)
gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
guint texture_id,
GdkMemoryFormat format)
{
GskGLTextureState *state;
GdkGLTextureBuilder *builder;
@@ -1828,6 +1831,7 @@ gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
builder = gdk_gl_texture_builder_new ();
gdk_gl_texture_builder_set_context (builder, self->command_queue->context);
gdk_gl_texture_builder_set_id (builder, texture_id);
gdk_gl_texture_builder_set_format (builder, format);
gdk_gl_texture_builder_set_width (builder, texture->width);
gdk_gl_texture_builder_set_height (builder, texture->height);
gdk_gl_texture_builder_set_sync (builder, state->sync);
+2 -1
View File
@@ -154,7 +154,8 @@ void gsk_gl_driver_begin_frame (GskGLDriver *s
void gsk_gl_driver_end_frame (GskGLDriver *self);
void gsk_gl_driver_after_frame (GskGLDriver *self);
GdkTexture * gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
guint texture_id);
guint texture_id,
GdkMemoryFormat format);
void gsk_gl_driver_cache_texture (GskGLDriver *self,
const GskTextureKey *key,
guint texture_id);
+10 -3
View File
@@ -332,6 +332,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
GskGLRenderJob *job;
GdkTexture *texture;
guint texture_id;
GdkMemoryFormat gdk_format;
int width, height, max_size;
int format;
@@ -375,9 +376,15 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
if (gsk_render_node_get_preferred_depth (root) != GDK_MEMORY_U8 &&
gdk_gl_context_check_version (self->context, "3.0", "3.0"))
format = GL_RGBA32F;
{
gdk_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
format = GL_RGBA32F;
}
else
format = GL_RGBA8;
{
format = GL_RGBA8;
gdk_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
}
gdk_gl_context_make_current (self->context);
@@ -394,7 +401,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
#endif
gsk_gl_render_job_render_flipped (job, root);
texture_id = gsk_gl_driver_release_render_target (self->driver, render_target, FALSE);
texture = gsk_gl_driver_create_gdk_texture (self->driver, texture_id);
texture = gsk_gl_driver_create_gdk_texture (self->driver, texture_id, gdk_format);
gsk_gl_driver_end_frame (self->driver);
gsk_gl_render_job_free (job);
-6
View File
@@ -3784,12 +3784,6 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
GskTextureKey key;
guint texture_id;
if (filter == GSK_SCALING_FILTER_LINEAR)
{
gsk_gl_render_job_visit_texture (job, texture, bounds);
return;
}
gsk_gl_render_job_untransform_bounds (job, &job->current_clip->rect.bounds, &clip_rect);
if (!graphene_rect_intersection (bounds, &clip_rect, &clip_rect))
+1 -1
View File
@@ -1,5 +1,5 @@
project('gtk', 'c',
version: '4.13.2',
version: '4.13.3',
default_options: [
'buildtype=debugoptimized',
'warning_level=1',
+1042 -745
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -149,3 +149,11 @@ foreach t: gtk_tests
dependencies: [libgtk_dep, libm],
)
endforeach
executable('testsubsurface',
sources: '@0@.c'.format('testsubsurface'),
c_args: common_cflags + ['-DGTK_COMPILATION'],
dependencies: libgtk_static_dep,
install: false,
)
+48 -18
View File
@@ -2,6 +2,7 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/dma-heap.h>
#include <drm_fourcc.h>
@@ -9,36 +10,60 @@
* lax permissions.
*/
static int dma_heap_fd = -1;
static gboolean
initialize_dma_heap (void)
{
dma_heap_fd = open ("/dev/dma_heap/system", O_RDONLY | O_CLOEXEC);
return dma_heap_fd != -1;
}
static int
allocate_dma_buf (gsize size)
{
static int fd = -1;
struct dma_heap_allocation_data heap_data;
int ret;
if (fd == -1)
{
fd = open ("/dev/dma_heap/system", O_RDONLY | O_CLOEXEC);
if (fd == -1)
g_error ("Failed to open /dev/dma_heap/system");
}
heap_data.len = size;
heap_data.fd = 0;
heap_data.fd_flags = O_RDWR | O_CLOEXEC;
heap_data.heap_flags = 0;
ret = ioctl (fd, DMA_HEAP_IOCTL_ALLOC, &heap_data);
ret = ioctl (dma_heap_fd, DMA_HEAP_IOCTL_ALLOC, &heap_data);
if (ret)
g_error ("dma-buf allocation failed");
return heap_data.fd;
}
static int
allocate_memfd (gsize size)
{
int fd;
fd = memfd_create ("buffer", MFD_CLOEXEC);
if (fd == -1)
g_error ("memfd allocation failed");
ftruncate (fd, size);
return fd;
}
static int
allocate_buffer (gsize size)
{
if (dma_heap_fd != -1)
return allocate_dma_buf (size);
else
return allocate_memfd (size);
}
static void
populate_dma_buf (int fd,
const guchar *data,
gsize size)
populate_buffer (int fd,
const guchar *data,
gsize size)
{
guchar *buf;
@@ -253,8 +278,8 @@ texture_builder_set_planes (GdkDmabufTextureBuilder *builder,
for (i = 0; i < n_planes; i++)
{
int fd = allocate_dma_buf (sizes[i]);
populate_dma_buf (fd, buf + offset, sizes[i]);
int fd = allocate_buffer (sizes[i]);
populate_buffer (fd, buf + offset, sizes[i]);
gdk_dmabuf_texture_builder_set_fd (builder, i, fd);
gdk_dmabuf_texture_builder_set_stride (builder, i, strides[i]);
@@ -266,8 +291,8 @@ texture_builder_set_planes (GdkDmabufTextureBuilder *builder,
{
unsigned offset = 0;
unsigned i;
int fd = allocate_dma_buf (size);
populate_dma_buf (fd, buf, size);
int fd = allocate_buffer (size);
populate_buffer (fd, buf, size);
for (i = 0; i < n_planes; i++)
{
@@ -292,6 +317,11 @@ make_dmabuf_texture (const char *filename,
GdkDmabufTextureBuilder *builder;
GError *error = NULL;
if (initialize_dma_heap ())
g_print ("Using dma_heap\n");
else
g_print ("Using memfd\n");
texture = gdk_texture_new_from_filename (filename, NULL);
width = gdk_texture_get_width (texture);
@@ -318,8 +348,8 @@ make_dmabuf_texture (const char *filename,
{
gdk_dmabuf_texture_builder_set_n_planes (builder, 1);
fd = allocate_dma_buf (rgb_size);
populate_dma_buf (fd, rgb_data, rgb_size);
fd = allocate_buffer (rgb_size);
populate_buffer (fd, rgb_data, rgb_size);
gdk_dmabuf_texture_builder_set_fd (builder, 0, fd);
gdk_dmabuf_texture_builder_set_stride (builder, 0, rgb_stride);
+257
View File
@@ -0,0 +1,257 @@
#include <gtk/gtk.h>
#include "gtk/gtkwidgetprivate.h"
#include "gdk/gdksurfaceprivate.h"
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/dma-heap.h>
#include <drm_fourcc.h>
static int dma_heap_fd = -1;
static gboolean
initialize_dma_heap (void)
{
dma_heap_fd = open ("/dev/dma_heap/system", O_RDONLY | O_CLOEXEC);
return dma_heap_fd != -1;
}
static int
allocate_dma_buf (gsize size)
{
struct dma_heap_allocation_data heap_data;
int ret;
heap_data.len = size;
heap_data.fd = 0;
heap_data.fd_flags = O_RDWR | O_CLOEXEC;
heap_data.heap_flags = 0;
ret = ioctl (dma_heap_fd, DMA_HEAP_IOCTL_ALLOC, &heap_data);
if (ret)
g_error ("dma-buf allocation failed");
return heap_data.fd;
}
static void
free_dmabuf (gpointer data)
{
close (GPOINTER_TO_INT (data));
}
static GdkTexture *
make_dmabuf_color_texture (int width,
int height,
GdkRGBA *color)
{
int fd;
guchar *buf;
GdkDmabufTextureBuilder *builder;
GdkTexture *texture;
gsize stride, size;
GError *error = NULL;
stride = width * 4;
size = height * stride;
fd = allocate_dma_buf (size);
buf = mmap (NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
for (gsize i = 0; i < width * height * 4; i += 4)
{
buf[i] = 255 * color->blue;
buf[i + 1] = 255 * color->green;
buf[i + 2] = 255 * color->red;
buf[i + 3] = 255 * color->alpha;
}
munmap (buf, 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, DRM_FORMAT_ARGB8888);
gdk_dmabuf_texture_builder_set_modifier (builder, DRM_FORMAT_MOD_LINEAR);
gdk_dmabuf_texture_builder_set_n_planes (builder, 1);
gdk_dmabuf_texture_builder_set_fd (builder, 0, fd);
gdk_dmabuf_texture_builder_set_offset (builder, 0, 0);
gdk_dmabuf_texture_builder_set_stride (builder, 0, stride);
texture = gdk_dmabuf_texture_builder_build (builder, free_dmabuf, GINT_TO_POINTER (fd), &error);
if (texture == NULL)
g_error ("%s", error->message);
g_object_unref (builder);
return texture;
}
static GdkTexture *
make_shm_color_texture (int width,
int height,
GdkRGBA *color)
{
cairo_surface_t *surface;
cairo_t *cr;
guchar *data;
gsize stride;
GBytes *bytes;
GdkTexture *texture;
stride = 4 * width;
data = g_new (guchar, stride * height);
surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
width, height,
stride);
cr = cairo_create (surface);
gdk_cairo_set_source_rgba (cr, color);
cairo_paint (cr);
cairo_destroy (cr);
cairo_surface_destroy (surface);
bytes = g_bytes_new_take (data, stride * height);
texture = gdk_memory_texture_new (width, height, GDK_MEMORY_DEFAULT, bytes, stride);
g_bytes_unref (bytes);
return texture;
}
static GdkTexture *
make_color_texture (int width,
int height,
GdkRGBA *color)
{
if (dma_heap_fd != -1)
return make_dmabuf_color_texture (width, height, color);
else
return make_shm_color_texture (width, height, color);
}
static GdkSubsurface *
add_subsurface (GtkWidget *window,
GdkRGBA *color,
const graphene_rect_t *rect)
{
GdkSurface *surface;
GdkSubsurface *subsurface;
GdkTexture *texture;
surface = gtk_widget_get_surface (GTK_WIDGET (window));
subsurface = gdk_surface_create_subsurface (surface);
texture = make_color_texture (20, 20, color);
gdk_subsurface_attach (subsurface, texture, rect);
g_object_unref (texture);
return subsurface;
}
static GdkSubsurface *red, *blue;
static void red_above_blue (GtkButton *button) { gdk_subsurface_place_above (red, blue); }
static void red_below_blue (GtkButton *button) { gdk_subsurface_place_below (red, blue); }
static void blue_above_red (GtkButton *button) { gdk_subsurface_place_above (blue, red); }
static void blue_below_red (GtkButton *button) { gdk_subsurface_place_below (blue, red); }
static void red_above_main (GtkButton *button) { gdk_subsurface_place_above (red, NULL); }
static void red_below_main (GtkButton *button) { gdk_subsurface_place_below (red, NULL); }
static void blue_above_main (GtkButton *button) { gdk_subsurface_place_above (blue, NULL); }
static void blue_below_main (GtkButton *button) { gdk_subsurface_place_below (blue, NULL); }
static GtkWidget *
make_button (const char *name, gpointer cb)
{
GtkWidget *button;
button = gtk_button_new_with_label (name);
g_signal_connect (button, "clicked", G_CALLBACK (cb), NULL);
return button;
}
static void
change_colors (GtkButton *button)
{
GdkRGBA color;
GdkTexture *texture;
color.red = g_random_double_range (0.5, 1);
color.green = g_random_double_range (0, 0.5);
color.blue = g_random_double_range (0, 0.5);
color.alpha = 1;
texture = make_color_texture (20, 20, &color);
gdk_subsurface_attach (red, texture, &GRAPHENE_RECT_INIT (200, 100, 50, 50));
g_object_unref (texture);
color.red = g_random_double_range (0, 0.5);
color.green = g_random_double_range (0, 0.5);
color.blue = g_random_double_range (0.5, 1);
color.alpha = 1;
texture = make_color_texture (20, 20, &color);
gdk_subsurface_attach (blue, texture, &GRAPHENE_RECT_INIT (180, 120, 100, 20));
g_object_unref (texture);
}
static GtkWidget *
make_buttons (void)
{
GtkWidget *box;
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_box_append (GTK_BOX (box), make_button ("Red above blue", red_above_blue));
gtk_box_append (GTK_BOX (box), make_button ("Red below blue", red_below_blue));
gtk_box_append (GTK_BOX (box), make_button ("Red above main", red_above_main));
gtk_box_append (GTK_BOX (box), make_button ("Red below main", red_below_main));
gtk_box_append (GTK_BOX (box), make_button ("Blue above red", blue_above_red));
gtk_box_append (GTK_BOX (box), make_button ("Blue below red", blue_below_red));
gtk_box_append (GTK_BOX (box), make_button ("Blue above main", blue_above_main));
gtk_box_append (GTK_BOX (box), make_button ("Blue below main", blue_below_main));
gtk_box_append (GTK_BOX (box), make_button ("Change colors", change_colors));
return box;
}
int
main (int argc, char *argv[])
{
GtkWidget *window, *box;
gtk_init ();
window = gtk_window_new ();
gtk_window_set_default_size (GTK_WINDOW (window), 210, -1);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_widget_realize (window);
if (initialize_dma_heap ())
g_print ("Using dambufs\n");
else
g_print ("Failed to initialize dma-heap, using shm\n");
red = add_subsurface (window, &(GdkRGBA) { 1, 0, 0, 1 }, &GRAPHENE_RECT_INIT (200, 100, 50, 50));
blue = add_subsurface (window, &(GdkRGBA) { 0, 0, 1, 1 }, &GRAPHENE_RECT_INIT (180, 120, 100, 20));
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_window_set_child (GTK_WINDOW (window), box);
gtk_box_append (GTK_BOX (box), make_buttons ());
gtk_window_present (GTK_WINDOW (window));
while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
g_main_context_iteration (NULL, TRUE);
return 0;
}
+1 -1
View File
@@ -6,7 +6,7 @@
#include <gdk/gdkdmabuftextureprivate.h>
#ifdef HAVE_DMABUF
#include <drm/drm_fourcc.h>
#include <drm_fourcc.h>
#endif
static void
@@ -0,0 +1,30 @@
texture-scale {
bounds: 4 4 24 24;
filter: nearest;
texture: "texture1" url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJ0lEQVQYlWNkYPjwnwEPYMInSbqC\
AwwCDAcYBPCb4HAAlc9Ie0cCAB8uBo20gfbVAAAAAElFTkSuQmCC\
");
}
repeat {
bounds: 32 0 32 32;
child: texture-scale {
bounds: 0 0 1 1;
filter: nearest;
texture: "texture1";
}
}
repeat {
bounds: 0 32 32 32;
child: texture-scale {
bounds: 0 0 1 1;
texture: "texture1";
}
}
repeat {
bounds: 32 32 32 32;
child: texture-scale {
bounds: 0 0 1 1;
filter: trilinear;
texture: "texture1";
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

+1
View File
@@ -98,6 +98,7 @@ compare_render_tests = [
'shadow-opacity',
'shrink-rounded-border',
'stroke',
'texture-scale-filters-3d',
'texture-scale-magnify-10000x',
'texture-scale-magnify-rotate',
'texture-scale-stripes',