Files
gtk/gdk/gdkdmabufformatsbuilder.c
Matthias Clasen 3674497163 dmabuf: Add Wayland information
Add device and scanout information for dmabuf formats.

While this is not a great API, there is no good alternative to
making this information available to applications that want to
negotiate dmabuf formats suitable for graphics offload.

The getters for Wayland-specific information are kept as
Wayland backend apis.

Tests included.
2024-04-27 19:48:18 -04:00

163 lines
5.0 KiB
C

/* gdkdmabufformats.c
*
* Copyright 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdkdmabufformatsprivate.h"
#define GDK_ARRAY_NAME gdk_dmabuf_formats_builder
#define GDK_ARRAY_TYPE_NAME GdkDmabufFormatsBuilder
#define GDK_ARRAY_ELEMENT_TYPE GdkDmabufFormat
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 1024
#define GDK_ARRAY_NO_MEMSET 1
#include "gdk/gdkarrayimpl.c"
/* NB: We keep duplicates in the list for ease of use. Only when creating the final
* GdkDmabufFormats do we actually remove duplicates.
*/
GdkDmabufFormatsBuilder *
gdk_dmabuf_formats_builder_new (void)
{
GdkDmabufFormatsBuilder *result = g_new (GdkDmabufFormatsBuilder, 1);
gdk_dmabuf_formats_builder_init (result);
return result;
}
static int
gdk_dmabuf_format_compare (gconstpointer data_a,
gconstpointer data_b)
{
const GdkDmabufFormat *a = data_a;
const GdkDmabufFormat *b = data_b;
if (a->next_priority != b->next_priority)
return (a->next_priority < b->next_priority) ? -1 : 1;
else if (a->fourcc == b->fourcc)
return (a->modifier - b->modifier) >> 8 * (sizeof (gint64) - sizeof (gint));
else
return a->fourcc - b->fourcc;
}
static gboolean
gdk_dmabuf_format_equal (gconstpointer data_a,
gconstpointer data_b)
{
const GdkDmabufFormat *a = data_a;
const GdkDmabufFormat *b = data_b;
return a->fourcc == b->fourcc &&
a->flags == b->flags &&
a->modifier == b->modifier &&
a->device == b->device;
}
static void
gdk_dmabuf_formats_builder_sort (GdkDmabufFormatsBuilder *self)
{
qsort (gdk_dmabuf_formats_builder_get_data (self),
gdk_dmabuf_formats_builder_get_size (self),
sizeof (GdkDmabufFormat),
gdk_dmabuf_format_compare);
}
GdkDmabufFormats *
gdk_dmabuf_formats_builder_free_to_formats_for_device (GdkDmabufFormatsBuilder *self,
guint64 device)
{
GdkDmabufFormats *formats;
gdk_dmabuf_formats_builder_next_priority (self);
gdk_dmabuf_formats_builder_sort (self);
formats = gdk_dmabuf_formats_new (gdk_dmabuf_formats_builder_get_data (self),
gdk_dmabuf_formats_builder_get_size (self),
device);
gdk_dmabuf_formats_builder_clear (self);
g_free (self);
return formats;
}
GdkDmabufFormats *
gdk_dmabuf_formats_builder_free_to_formats (GdkDmabufFormatsBuilder *self)
{
return gdk_dmabuf_formats_builder_free_to_formats_for_device (self, 0);
}
void
gdk_dmabuf_formats_builder_add_format_for_device (GdkDmabufFormatsBuilder *self,
guint32 fourcc,
guint32 flags,
guint64 modifier,
guint64 device)
{
GdkDmabufFormat format = { fourcc, flags, modifier, device, G_MAXSIZE };
for (gsize i = 0; i < gdk_dmabuf_formats_builder_get_size (self); i++)
{
if (gdk_dmabuf_format_equal (gdk_dmabuf_formats_builder_get (self, i), &format))
return;
}
gdk_dmabuf_formats_builder_append (self, &format);
}
void
gdk_dmabuf_formats_builder_add_format (GdkDmabufFormatsBuilder *self,
guint32 fourcc,
guint64 modifier)
{
gdk_dmabuf_formats_builder_add_format_for_device (self, fourcc, 0, modifier, 0);
}
void
gdk_dmabuf_formats_builder_next_priority (GdkDmabufFormatsBuilder *self)
{
for (gsize i = gdk_dmabuf_formats_builder_get_size (self); i > 0; i--)
{
GdkDmabufFormat *format = gdk_dmabuf_formats_builder_get (self, i - 1);
if (format->next_priority != G_MAXSIZE)
break;
format->next_priority = gdk_dmabuf_formats_builder_get_size (self);
}
}
void
gdk_dmabuf_formats_builder_add_formats (GdkDmabufFormatsBuilder *self,
GdkDmabufFormats *formats)
{
for (gsize i = 0; i < gdk_dmabuf_formats_get_n_formats (formats); i++)
{
guint32 fourcc;
guint64 modifier;
gdk_dmabuf_formats_get_format (formats, i, &fourcc, &modifier);
gdk_dmabuf_formats_builder_add_format (self, fourcc, modifier);
}
}