gtk/gdk/gdkdmabufformatsbuilder.c
Benjamin Otte e05764806a build: Change where we get drm_fourcc.h from
The canonical source for userspace is libdrm, not kernel headers.

Fixes compilation on Arch Linux.
2023-10-22 20:40:20 +02:00

144 lines
4.2 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"
#ifdef HAVE_DMABUF
#include <drm_fourcc.h>
#endif
#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->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->modifier == b->modifier;
}
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);
}
/* list must be sorted */
static void
gdk_dmabuf_formats_builder_remove_duplicates (GdkDmabufFormatsBuilder *self)
{
gsize i, j;
for (i = 1, j = 0; i < gdk_dmabuf_formats_builder_get_size (self); i++)
{
if (gdk_dmabuf_format_equal (gdk_dmabuf_formats_builder_get (self, i),
gdk_dmabuf_formats_builder_get (self, j)))
continue;
j++;
if (i != j)
*gdk_dmabuf_formats_builder_index (self, j) = *gdk_dmabuf_formats_builder_index (self, i);
}
}
GdkDmabufFormats *
gdk_dmabuf_formats_builder_free_to_formats (GdkDmabufFormatsBuilder *self)
{
GdkDmabufFormats *formats;
gdk_dmabuf_formats_builder_sort (self);
gdk_dmabuf_formats_builder_remove_duplicates (self);
formats = gdk_dmabuf_formats_new (gdk_dmabuf_formats_builder_get_data (self),
gdk_dmabuf_formats_builder_get_size (self));
gdk_dmabuf_formats_builder_clear (self);
g_free (self);
return formats;
}
void
gdk_dmabuf_formats_builder_add_format (GdkDmabufFormatsBuilder *self,
guint32 fourcc,
guint64 modifier)
{
#ifdef HAVE_DMABUF
g_return_if_fail (modifier != DRM_FORMAT_MOD_INVALID);
#else
g_return_if_reached ();
#endif
gdk_dmabuf_formats_builder_append (self, &(GdkDmabufFormat) { fourcc, modifier });
}
void
gdk_dmabuf_formats_builder_add_formats (GdkDmabufFormatsBuilder *self,
GdkDmabufFormats *formats)
{
gdk_dmabuf_formats_builder_splice (self,
gdk_dmabuf_formats_builder_get_size (self),
0,
FALSE,
gdk_dmabuf_formats_peek_formats (formats),
gdk_dmabuf_formats_get_n_formats (formats));
}