Compare commits

..

1 Commits

Author SHA1 Message Date
Matthias Clasen b6f479375e dmabuf: Some debugging infrastructure
Add some helpers to print dmabuf formats.
2023-10-21 20:29:47 -04:00
32 changed files with 191 additions and 1464 deletions
+1 -26
View File
@@ -1,31 +1,6 @@
Overview of Changes in 4.13.2, 22-10-2023
Overview of Changes in 4.13.2, xx-xx-xxxx
=========================================
* GtkPrintdialog:
- New async-style api to replace GtkPrintOperation
* GtkEmojiChooser:
- Add more languages: Bengali, Hindi, Japanese, Finnish,
Thai and Norwegian bokmål
* Accessibility:
- Fix some utf8 handling issues
* GDK:
- Add support for dmabuf textures, with GdkDmabufTextureBuilder
- Add a few more supported memory formats for textures
* GSK:
- Add a fast-path for masking color
- Add support for importing dmabuf textures
- Handle GLES better by using some extensions
* Translation updates:
Catalan
Russian
Turkish
Overview of Changes in 4.13.1, 28-09-2023
=========================================
+4 -17
View File
@@ -391,9 +391,6 @@ gdk_display_dispose (GObject *object)
g_queue_clear (&display->queued_events);
g_clear_object (&display->egl_gsk_renderer);
g_clear_pointer (&display->egl_external_formats, gdk_dmabuf_formats_unref);
g_clear_object (&priv->gl_context);
#ifdef HAVE_EGL
g_clear_pointer (&priv->egl_display, eglTerminate);
@@ -1773,10 +1770,6 @@ gdk_display_init_egl (GdkDisplay *self,
epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_no_config_context");
self->have_egl_pixel_format_float =
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_pixel_format_float");
self->have_egl_dma_buf_import =
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_image_dma_buf_import_modifiers");
self->have_egl_dma_buf_export =
epoxy_has_egl_extension (priv->egl_display, "EGL_MESA_image_dma_buf_export");
if (self->have_egl_no_config_context)
priv->egl_config_high_depth = gdk_display_create_egl_config (self,
@@ -1846,7 +1839,7 @@ gdk_display_get_egl_display (GdkDisplay *self)
#endif
}
#ifdef HAVE_DMABUF
#ifdef HAVE_LINUX_DMA_BUF_H
static void
gdk_display_add_dmabuf_downloader (GdkDisplay *display,
const GdkDmabufDownloader *downloader,
@@ -1854,8 +1847,7 @@ gdk_display_add_dmabuf_downloader (GdkDisplay *display,
{
gsize i;
if (!downloader->add_formats (downloader, display, builder))
return;
downloader->add_formats (downloader, display, builder);
/* dmabuf_downloaders is NULL-terminated */
for (i = 0; i < G_N_ELEMENTS (display->dmabuf_downloaders) - 1; i++)
@@ -1884,22 +1876,17 @@ gdk_display_init_dmabuf (GdkDisplay *self)
builder = gdk_dmabuf_formats_builder_new ();
#ifdef HAVE_DMABUF
#ifdef HAVE_LINUX_DMA_BUF_H
if (!GDK_DEBUG_CHECK (DMABUF_DISABLE))
{
gdk_display_prepare_gl (self, NULL);
gdk_display_add_dmabuf_downloader (self, gdk_dmabuf_get_direct_downloader (), builder);
#ifdef HAVE_EGL
if (gdk_display_prepare_gl (self, NULL))
gdk_display_add_dmabuf_downloader (self, gdk_dmabuf_get_egl_downloader (), builder);
#endif
}
#endif
self->dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (builder);
}
}
/**
* gdk_display_get_dmabuf_formats:
-6
View File
@@ -114,15 +114,9 @@ struct _GdkDisplay
guint have_egl_buffer_age : 1;
guint have_egl_no_config_context : 1;
guint have_egl_pixel_format_float : 1;
guint have_egl_dma_buf_import : 1;
guint have_egl_dma_buf_export : 1;
GdkDmabufFormats *dmabuf_formats;
const GdkDmabufDownloader *dmabuf_downloaders[4];
/* Cached data the EGL dmabuf downloader */
gpointer egl_gsk_renderer;
GdkDmabufFormats *egl_external_formats;
};
struct _GdkDisplayClass
+90 -41
View File
@@ -24,11 +24,11 @@
#include "gdkdmabuftextureprivate.h"
#include "gdkmemoryformatprivate.h"
#ifdef HAVE_DMABUF
#ifdef HAVE_LINUX_DMA_BUF_H
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include <drm_fourcc.h>
#include <drm/drm_fourcc.h>
#include <epoxy/egl.h>
typedef struct _GdkDrmFormatInfo GdkDrmFormatInfo;
@@ -264,7 +264,7 @@ get_drm_format_info (guint32 fourcc)
return NULL;
}
static gboolean
static void
gdk_dmabuf_direct_downloader_add_formats (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
GdkDmabufFormatsBuilder *builder)
@@ -277,8 +277,6 @@ gdk_dmabuf_direct_downloader_add_formats (const GdkDmabufDownloader *downloader,
supported_formats[i].fourcc,
DRM_FORMAT_MOD_LINEAR);
}
return TRUE;
}
static gboolean
@@ -290,6 +288,7 @@ gdk_dmabuf_direct_downloader_supports (const GdkDmabufDownloader *downloader,
GError **error)
{
const GdkDrmFormatInfo *info;
char buf[36];
info = get_drm_format_info (dmabuf->fourcc);
@@ -297,8 +296,8 @@ gdk_dmabuf_direct_downloader_supports (const GdkDmabufDownloader *downloader,
{
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"Unsupported dmabuf format %.4s",
(char *) &dmabuf->fourcc);
"Unsupported dmabuf format %s",
gdk_dmabuf_fourcc_print (buf, sizeof (buf), dmabuf->fourcc));
return FALSE;
}
@@ -306,8 +305,8 @@ gdk_dmabuf_direct_downloader_supports (const GdkDmabufDownloader *downloader,
{
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"Unsupported dmabuf modifier %#lx (only linear buffers are supported)",
dmabuf->modifier);
"Unsupported dmabuf modifier %s (only linear buffers are supported)",
gdk_dmabuf_modifier_print (buf, sizeof (buf), dmabuf->modifier));
return FALSE;
}
@@ -328,13 +327,14 @@ gdk_dmabuf_direct_downloader_do_download (GdkTexture *texture,
gsize sizes[GDK_DMABUF_MAX_PLANES];
gsize needs_unmap[GDK_DMABUF_MAX_PLANES] = { FALSE, };
gsize i, j;
gchar buf[64];
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
info = get_drm_format_info (dmabuf->fourcc);
GDK_DEBUG (DMABUF,
"Using mmap() and memcpy() for downloading a dmabuf (format %.4s:%#lx)",
(char *)&dmabuf->fourcc, dmabuf->modifier);
"Using mmap() and memcpy() for downloading a dmabuf (format %s)",
gdk_dmabuf_format_print (buf, sizeof (buf), dmabuf->fourcc, dmabuf->modifier));
for (i = 0; i < dmabuf->n_planes; i++)
{
@@ -484,14 +484,6 @@ gdk_dmabuf_sanitize (GdkDmabuf *dest,
return FALSE;
}
if (src->modifier == DRM_FORMAT_MOD_INVALID)
{
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"GTK does not support the INVALID modifier.");
return FALSE;
}
info = get_drm_format_info (src->fourcc);
if (info == NULL)
@@ -505,7 +497,7 @@ gdk_dmabuf_sanitize (GdkDmabuf *dest,
*dest = *src;
if (src->modifier)
if (src->modifier && src->modifier != DRM_FORMAT_MOD_INVALID)
return TRUE;
switch (dest->fourcc)
@@ -527,27 +519,84 @@ gdk_dmabuf_sanitize (GdkDmabuf *dest,
return TRUE;
}
/*
* gdk_dmabuf_is_disjoint:
* @dmabuf: a sanitized GdkDmabuf
*
* A dmabuf is considered disjoint if it uses more than
* 1 file descriptor.
*
* Returns: %TRUE if the dmabuf is disjoint
**/
gboolean
gdk_dmabuf_is_disjoint (const GdkDmabuf *dmabuf)
const char *
gdk_dmabuf_fourcc_print (char *buf,
gsize size,
guint32 fourcc)
{
unsigned i;
for (i = 1; i < dmabuf->n_planes; i++)
{
if (dmabuf->planes[0].fd != dmabuf->planes[i].fd)
return TRUE;
}
return FALSE;
snprintf (buf, size, "%.4s", (char *)&fourcc);
return buf;
}
#endif /* HAVE_DMABUF */
static const char *
get_modifier_name (char *buf,
gsize size,
guint64 modifier)
{
static struct {
guchar id;
const char *name;
} vendors[] = {
{ DRM_FORMAT_MOD_VENDOR_NONE, "NONE" },
{ DRM_FORMAT_MOD_VENDOR_INTEL, "Intel" },
{ DRM_FORMAT_MOD_VENDOR_AMD, "AMD" },
{ DRM_FORMAT_MOD_VENDOR_NVIDIA, "NVidia" },
{ DRM_FORMAT_MOD_VENDOR_SAMSUNG, "Samsung" },
{ DRM_FORMAT_MOD_VENDOR_QCOM, "Qualcomm" },
{ DRM_FORMAT_MOD_VENDOR_VIVANTE, "Vivante" },
{ DRM_FORMAT_MOD_VENDOR_BROADCOM, "Broadcom" },
{ DRM_FORMAT_MOD_VENDOR_ARM, "Arm" },
{ DRM_FORMAT_MOD_VENDOR_ALLWINNER, "Allwinner" },
{ DRM_FORMAT_MOD_VENDOR_AMLOGIC, "Amlogic" },
};
if (modifier == DRM_FORMAT_MOD_INVALID)
return "INVALID";
else if (modifier == DRM_FORMAT_MOD_LINEAR)
return "LINEAR";
for (int i = 0; i < G_N_ELEMENTS (vendors); i++)
{
if (vendors[i].id == fourcc_mod_get_vendor (modifier))
{
snprintf (buf, size, "%s,%" G_GINT64_MODIFIER "u", vendors[i].name, modifier & 0x00ffffffffffffffUL);
return buf;
}
}
snprintf (buf, size, "%#" G_GINT64_MODIFIER "x", modifier);
return buf;
}
const char *
gdk_dmabuf_modifier_print (char *buf,
gsize size,
guint64 modifier)
{
char buf2[64];
snprintf (buf, size, "%s", get_modifier_name (buf2, sizeof (buf2), modifier));
return buf;
}
const char *
gdk_dmabuf_format_print (char *buf,
gsize size,
guint32 fourcc,
guint64 modifier)
{
gsize len;
char buf2[64];
gdk_dmabuf_fourcc_print (buf, size, fourcc);
len = strlen (buf);
snprintf (buf + len, size - len, ":%s", get_modifier_name (buf2, sizeof (buf2), modifier));
return buf;
}
#endif /* HAVE_LINUX_DMA_BUF_H */
-408
View File
@@ -1,408 +0,0 @@
/* gdkdmabufegl.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"
#if defined(HAVE_DMABUF) && defined (HAVE_EGL)
#include "gdkdmabufprivate.h"
#include "gdkdmabufformatsbuilderprivate.h"
#include "gdkdebugprivate.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkmemoryformatprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkglcontextprivate.h"
#include "gdktexturedownloader.h"
#include <graphene.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include <drm/drm_fourcc.h>
#include <epoxy/egl.h>
/* A dmabuf downloader implementation that downloads buffers via
* gsk_renderer_render_texture + GL texture download.
*/
static gboolean
gdk_dmabuf_egl_downloader_add_formats (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
GdkDmabufFormatsBuilder *builder)
{
GdkGLContext *context = gdk_display_get_gl_context (display);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
GdkDmabufFormatsBuilder *external;
gboolean retval = FALSE;
g_assert (display->egl_external_formats == NULL);
external = gdk_dmabuf_formats_builder_new ();
gdk_gl_context_make_current (context);
if (egl_display != EGL_NO_DISPLAY &&
display->have_egl_dma_buf_import &&
gdk_gl_context_has_image_storage (context))
{
int num_fourccs;
int *fourccs;
guint64 *modifiers;
unsigned int *external_only;
int n_mods;
eglQueryDmaBufFormatsEXT (egl_display, 0, NULL, &num_fourccs);
fourccs = g_new (int, num_fourccs);
eglQueryDmaBufFormatsEXT (egl_display, num_fourccs, fourccs, &num_fourccs);
n_mods = 80;
modifiers = g_new (guint64, n_mods);
external_only = g_new (unsigned int, n_mods);
for (int i = 0; i < num_fourccs; i++)
{
int num_modifiers;
eglQueryDmaBufModifiersEXT (egl_display,
fourccs[i],
0,
NULL,
NULL,
&num_modifiers);
if (num_modifiers > n_mods)
{
n_mods = num_modifiers;
modifiers = g_renew (guint64, modifiers, n_mods);
external_only = g_renew (unsigned int, external_only, n_mods);
}
eglQueryDmaBufModifiersEXT (egl_display,
fourccs[i],
num_modifiers,
modifiers,
external_only,
&num_modifiers);
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]);
if (external_only[j])
gdk_dmabuf_formats_builder_add_format (external, fourccs[i], modifiers[j]);
}
}
g_free (modifiers);
g_free (external_only);
g_free (fourccs);
retval = TRUE;
}
display->egl_external_formats = gdk_dmabuf_formats_builder_free_to_formats (external);
return retval;
}
static GdkMemoryFormat
get_memory_format (guint32 fourcc,
gboolean premultiplied)
{
switch (fourcc)
{
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_XRGB8888_A8:
case DRM_FORMAT_XBGR8888_A8:
return premultiplied ? GDK_MEMORY_A8R8G8B8_PREMULTIPLIED : GDK_MEMORY_A8R8G8B8;
case DRM_FORMAT_RGBA8888:
case DRM_FORMAT_RGBX8888_A8:
return premultiplied ? GDK_MEMORY_R8G8B8A8_PREMULTIPLIED : GDK_MEMORY_R8G8B8A8;
case DRM_FORMAT_BGRA8888:
return premultiplied ? GDK_MEMORY_B8G8R8A8_PREMULTIPLIED : GDK_MEMORY_B8G8R8A8;
case DRM_FORMAT_RGB888:
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_RGBX8888:
case DRM_FORMAT_BGRX8888:
return GDK_MEMORY_R8G8B8;
case DRM_FORMAT_BGR888:
return GDK_MEMORY_B8G8R8;
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_RGBX1010102:
case DRM_FORMAT_BGRX1010102:
case DRM_FORMAT_XRGB16161616:
case DRM_FORMAT_XBGR16161616:
return GDK_MEMORY_R16G16B16;
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_ABGR2101010:
case DRM_FORMAT_RGBA1010102:
case DRM_FORMAT_BGRA1010102:
case DRM_FORMAT_ARGB16161616:
case DRM_FORMAT_ABGR16161616:
return premultiplied ? GDK_MEMORY_R16G16B16A16_PREMULTIPLIED : GDK_MEMORY_R16G16B16A16;
case DRM_FORMAT_ARGB16161616F:
case DRM_FORMAT_ABGR16161616F:
return premultiplied ? GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED : GDK_MEMORY_R16G16B16A16_FLOAT;
case DRM_FORMAT_XRGB16161616F:
case DRM_FORMAT_XBGR16161616F:
return GDK_MEMORY_R16G16B16_FLOAT;
case DRM_FORMAT_YUYV:
case DRM_FORMAT_YVYU:
case DRM_FORMAT_UYVY:
case DRM_FORMAT_VYUY:
case DRM_FORMAT_XYUV8888:
case DRM_FORMAT_XVUY8888:
case DRM_FORMAT_VUY888:
return GDK_MEMORY_R8G8B8;
/* Add more formats here */
default:
return premultiplied ? GDK_MEMORY_A8R8G8B8_PREMULTIPLIED : GDK_MEMORY_A8R8G8B8;
}
}
static gboolean
gdk_dmabuf_egl_downloader_supports (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
const GdkDmabuf *dmabuf,
gboolean premultiplied,
GdkMemoryFormat *out_format,
GError **error)
{
EGLDisplay egl_display;
GdkGLContext *context;
int num_modifiers;
guint64 *modifiers;
unsigned int *external_only;
egl_display = gdk_display_get_egl_display (display);
if (egl_display == EGL_NO_DISPLAY)
{
g_set_error_literal (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"EGL not available");
return FALSE;
}
context = gdk_display_get_gl_context (display);
gdk_gl_context_make_current (context);
eglQueryDmaBufModifiersEXT (egl_display,
dmabuf->fourcc,
0,
NULL,
NULL,
&num_modifiers);
modifiers = g_newa (uint64_t, num_modifiers);
external_only = g_newa (unsigned int, num_modifiers);
eglQueryDmaBufModifiersEXT (egl_display,
dmabuf->fourcc,
num_modifiers,
modifiers,
external_only,
&num_modifiers);
for (int i = 0; i < num_modifiers; i++)
{
if (modifiers[i] == dmabuf->modifier)
{
*out_format = get_memory_format (dmabuf->fourcc, premultiplied);
return TRUE;
}
}
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"Unsupported dmabuf format: %.4s:%#" G_GINT64_MODIFIER "x",
(char *) &dmabuf->fourcc, dmabuf->modifier);
return FALSE;
}
/* Hack. We don't include gsk/gsk.h here to avoid a build order problem
* with the generated header gskenumtypes.h, so we need to hack around
* a bit to access the gsk api we need.
*/
typedef gpointer GskRenderer;
extern GskRenderer * gsk_gl_renderer_new (void);
extern gboolean gsk_renderer_realize (GskRenderer *renderer,
GdkSurface *surface,
GError **error);
extern GdkTexture * gsk_renderer_convert_texture (GskRenderer *renderer,
GdkTexture *texture);
typedef void (* InvokeFunc) (gpointer data);
typedef struct _InvokeData
{
volatile int spinlock;
InvokeFunc func;
gpointer data;
} InvokeData;
static gboolean
gdk_dmabuf_egl_downloader_invoke_callback (gpointer data)
{
InvokeData *invoke = data;
GdkGLContext *previous;
previous = gdk_gl_context_get_current ();
invoke->func (invoke->data);
if (previous)
gdk_gl_context_make_current (previous);
else
gdk_gl_context_clear_current ();
g_atomic_int_set (&invoke->spinlock, 1);
return FALSE;
}
/* Run func in the main thread, taking care not to disturb
* the current GL context of the caller.
*/
static void
gdk_dmabuf_egl_downloader_run (InvokeFunc func,
gpointer data)
{
InvokeData invoke = { 0, func, data };
g_main_context_invoke (NULL, gdk_dmabuf_egl_downloader_invoke_callback, &invoke);
while (g_atomic_int_get (&invoke.spinlock) == 0) ;
}
typedef struct _Download Download;
struct _Download
{
GdkDmabufTexture *texture;
GdkMemoryFormat format;
guchar *data;
gsize stride;
};
static GskRenderer *
get_gsk_renderer (GdkDisplay *display)
{
if (!display->egl_gsk_renderer)
{
GskRenderer *renderer;
GError *error = NULL;
renderer = gsk_gl_renderer_new ();
if (!gsk_renderer_realize (renderer, NULL, &error))
{
g_warning ("Failed to realize GL renderer: %s", error->message);
g_error_free (error);
g_object_unref (renderer);
return NULL;
}
display->egl_gsk_renderer = renderer;
}
return display->egl_gsk_renderer;
}
static void
gdk_dmabuf_egl_downloader_do_download (gpointer data)
{
Download *download = data;
GdkDisplay *display;
GskRenderer *renderer;
GdkTexture *native;
GdkTextureDownloader *downloader;
display = gdk_dmabuf_texture_get_display (download->texture);
renderer = get_gsk_renderer (display);
native = gsk_renderer_convert_texture (renderer, GDK_TEXTURE (download->texture));
downloader = gdk_texture_downloader_new (native);
gdk_texture_downloader_set_format (downloader, download->format);
gdk_texture_downloader_download_into (downloader, download->data, download->stride);
gdk_texture_downloader_free (downloader);
g_object_unref (native);
}
static void
gdk_dmabuf_egl_downloader_download (const GdkDmabufDownloader *downloader,
GdkTexture *texture,
GdkMemoryFormat format,
guchar *data,
gsize stride)
{
Download download;
GDK_DEBUG (DMABUF, "Using %s for downloading a dmabuf", downloader->name);
download.texture = GDK_DMABUF_TEXTURE (texture);
download.format = format;
download.data = data;
download.stride = stride;
gdk_dmabuf_egl_downloader_run (gdk_dmabuf_egl_downloader_do_download, &download);
}
const GdkDmabufDownloader *
gdk_dmabuf_get_egl_downloader (void)
{
static const GdkDmabufDownloader downloader = {
"egl",
gdk_dmabuf_egl_downloader_add_formats,
gdk_dmabuf_egl_downloader_supports,
gdk_dmabuf_egl_downloader_download,
};
return &downloader;
}
#endif /* HAVE_DMABUF && HAVE_EGL */
-10
View File
@@ -22,10 +22,6 @@
#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
@@ -121,12 +117,6 @@ 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 });
}
+16 -7
View File
@@ -22,9 +22,10 @@ struct _GdkDmabuf
struct _GdkDmabufDownloader
{
const char *name;
gboolean (* add_formats) (const GdkDmabufDownloader *downloader,
void (* add_formats) (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
GdkDmabufFormatsBuilder *builder);
gboolean (* supports) (const GdkDmabufDownloader *downloader,
GdkDisplay *display,
const GdkDmabuf *dmabuf,
@@ -38,17 +39,25 @@ struct _GdkDmabufDownloader
gsize stride);
};
#ifdef HAVE_DMABUF
#ifdef HAVE_LINUX_DMA_BUF_H
const GdkDmabufDownloader *
gdk_dmabuf_get_direct_downloader (void) G_GNUC_CONST;
const GdkDmabufDownloader * gdk_dmabuf_get_direct_downloader (void) G_GNUC_CONST;
const GdkDmabufDownloader * gdk_dmabuf_get_egl_downloader (void) G_GNUC_CONST;
gboolean gdk_dmabuf_sanitize (GdkDmabuf *dest,
gboolean gdk_dmabuf_sanitize (GdkDmabuf *dest,
gsize width,
gsize height,
const GdkDmabuf *src,
GError **error);
gboolean gdk_dmabuf_is_disjoint (const GdkDmabuf *dmabuf);
const char * gdk_dmabuf_fourcc_print (char *str,
gsize size,
guint32 fourcc);
const char * gdk_dmabuf_modifier_print (char *str,
gsize size,
guint64 modifier);
const char * gdk_dmabuf_format_print (char *str,
gsize size,
guint32 fourcc,
guint64 modifier);
#endif
+4 -4
View File
@@ -28,11 +28,11 @@
#include <gdk/gdkgltexturebuilder.h>
#include <gdk/gdktexturedownloader.h>
#ifdef HAVE_DMABUF
#ifdef HAVE_LINUX_DMA_BUF_H
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include <drm_fourcc.h>
#include <drm/drm_fourcc.h>
#include <epoxy/egl.h>
#endif
@@ -129,7 +129,7 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
gpointer data,
GError **error)
{
#ifdef HAVE_DMABUF
#ifdef HAVE_LINUX_DMA_BUF_H
GdkDmabufTexture *self;
GdkTexture *update_texture;
GdkDisplay *display;
@@ -210,7 +210,7 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
return GDK_TEXTURE (self);
#else /* !HAVE_DMABUF */
#else /* !HAVE_LINUX_DMA_BUF_H */
g_set_error_literal (error, GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_NOT_AVAILABLE,
"dmabuf support disabled at compile-time.");
return NULL;
+1 -13
View File
@@ -27,11 +27,6 @@
#include "gdkdmabuftextureprivate.h"
#include <cairo-gobject.h>
#ifdef HAVE_DMABUF
#include <drm_fourcc.h>
#else
#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
#endif
struct _GdkDmabufTextureBuilder
@@ -86,7 +81,7 @@ struct _GdkDmabufTextureBuilderClass
*
* The format of the data (for graphics data, essentially its colorspace) is described
* by a 32-bit integer. These format identifiers are defined in the header file
* [drm_fourcc.h](https://github.com/torvalds/linux/blob/master/include/uapi/drm_fourcc.h)
* [drm/drm_fourcc.h](https://github.com/torvalds/linux/blob/master/include/uapi/drm/drm_fourcc.h)
* and commonly referred to as **_fourcc_** values, since they are identified by 4 ASCII
* characters. Additionally, each DMA buffer has a **_modifier_**, which is a 64-bit integer
* that describes driver-specific details of the memory layout, such as tiling or compression.
@@ -603,13 +598,6 @@ gdk_dmabuf_texture_builder_set_modifier (GdkDmabufTextureBuilder *self,
guint64 modifier)
{
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
if (modifier == DRM_FORMAT_MOD_INVALID)
{
g_critical ("GTK does not support the INVALID modifier. "
"If you use code that produces it, it should include "
"instructions how to transform it into a regular modifier.");
return;
}
if (self->dmabuf.modifier == modifier)
return;
-214
View File
@@ -83,7 +83,6 @@
#include "gdkmemorytextureprivate.h"
#include "gdkprofilerprivate.h"
#include "gdkglversionprivate.h"
#include "gdkdmabufformatsprivate.h"
#include "gdkprivate.h"
@@ -96,10 +95,6 @@
#include <epoxy/egl.h>
#endif
#ifdef HAVE_DMABUF
#include <drm/drm_fourcc.h>
#endif
#include <math.h>
#define DEFAULT_ALLOWED_APIS GDK_GL_API_GL | GDK_GL_API_GLES
@@ -115,7 +110,6 @@ typedef struct {
guint has_unpack_subimage : 1;
guint has_debug_output : 1;
guint has_bgra : 1;
guint has_image_storage : 1;
guint extensions_checked : 1;
guint debug_enabled : 1;
guint forward_compatible : 1;
@@ -1564,8 +1558,6 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
epoxy_has_gl_extension ("GL_ARB_sync") ||
epoxy_has_gl_extension ("GL_APPLE_sync");
priv->has_image_storage = epoxy_has_gl_extension ("GL_EXT_EGL_image_storage");
#ifdef G_ENABLE_DEBUG
{
int max_texture_size;
@@ -1905,14 +1897,6 @@ gdk_gl_context_has_vertex_arrays (GdkGLContext *self)
}
}
gboolean
gdk_gl_context_has_image_storage (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_image_storage;
}
/* This is currently private! */
/* When using GL/ES, don't flip the 'R' and 'B' bits on Windows/ANGLE for glReadPixels() */
gboolean
@@ -1993,201 +1977,3 @@ gdk_gl_backend_use (GdkGLBackend backend_type)
g_assert (the_gl_backend_type == backend_type);
}
guint
gdk_gl_context_import_dmabuf (GdkGLContext *self,
int width,
int height,
const GdkDmabuf *dmabuf,
int target)
{
#if defined(HAVE_EGL) && defined(HAVE_DMABUF)
GdkDisplay *display = gdk_gl_context_get_display (self);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
EGLint attribs[64];
int i;
EGLImage image;
guint texture_id;
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), 0);
g_return_val_if_fail (width > 0, 0);
g_return_val_if_fail (height > 0, 0);
g_return_val_if_fail (1 <= dmabuf->n_planes && dmabuf->n_planes <= 4, 0);
g_return_val_if_fail (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES, 0);
if (egl_display == EGL_NO_DISPLAY || !display->have_egl_dma_buf_import)
return 0;
GDK_DEBUG (DMABUF,
"Importing dmabuf (format: %.4s:%#" G_GINT64_MODIFIER "x, planes: %u) into GL",
(char *) &dmabuf->fourcc, dmabuf->modifier, dmabuf->n_planes);
i = 0;
attribs[i++] = EGL_IMAGE_PRESERVED_KHR;
attribs[i++] = EGL_TRUE;
attribs[i++] = EGL_WIDTH;
attribs[i++] = width;
attribs[i++] = EGL_HEIGHT;
attribs[i++] = height;
attribs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[i++] = dmabuf->fourcc;
#define ADD_PLANE(plane) \
{ \
if (dmabuf->modifier != DRM_FORMAT_MOD_INVALID) \
{ \
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_MODIFIER_LO_EXT; \
attribs[i++] = dmabuf->modifier & 0xFFFFFFFF; \
attribs[i++] = EGL_DMA_BUF_PLANE## plane ## _MODIFIER_HI_EXT; \
attribs[i++] = dmabuf->modifier >> 32; \
} \
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_FD_EXT; \
attribs[i++] = dmabuf->planes[plane].fd; \
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_PITCH_EXT; \
attribs[i++] = dmabuf->planes[plane].stride; \
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_OFFSET_EXT; \
attribs[i++] = dmabuf->planes[plane].offset; \
}
ADD_PLANE (0);
if (dmabuf->n_planes > 1) ADD_PLANE (1);
if (dmabuf->n_planes > 2) ADD_PLANE (2);
if (dmabuf->n_planes > 3) ADD_PLANE (3);
attribs[i++] = EGL_NONE;
image = eglCreateImageKHR (egl_display,
EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT,
(EGLClientBuffer)NULL,
attribs);
if (image == EGL_NO_IMAGE)
{
GDK_DEBUG (DMABUF, "Creating EGLImage for dmabuf failed: %#x", eglGetError ());
return 0;
}
glGenTextures (1, &texture_id);
glBindTexture (target, texture_id);
glEGLImageTargetTexture2DOES (target, image);
glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
eglDestroyImageKHR (egl_display, image);
return texture_id;
#else
return 0;
#endif
}
gboolean
gdk_gl_context_export_dmabuf (GdkGLContext *self,
unsigned int texture_id,
GdkDmabuf *dmabuf)
{
#if defined(HAVE_EGL) && defined(HAVE_DMABUF)
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
GdkDisplay *display = gdk_gl_context_get_display (self);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
EGLContext egl_context = priv->egl_context;
EGLint attribs[10];
EGLImage image;
gboolean result = FALSE;
int i;
int fourcc;
int n_planes;
guint64 modifier;
int fds[GDK_DMABUF_MAX_PLANES];
int strides[GDK_DMABUF_MAX_PLANES];
int offsets[GDK_DMABUF_MAX_PLANES];
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), FALSE);
g_return_val_if_fail (texture_id > 0, FALSE);
g_return_val_if_fail (dmabuf != NULL, FALSE);
if (egl_display == EGL_NO_DISPLAY || !display->have_egl_dma_buf_export)
return 0;
GDK_DEBUG (DMABUF, "Exporting GL texture to dmabuf");
i = 0;
attribs[i++] = EGL_IMAGE_PRESERVED_KHR;
attribs[i++] = EGL_TRUE;
attribs[i++] = EGL_NONE;
image = eglCreateImageKHR (egl_display,
egl_context,
EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer)GUINT_TO_POINTER (texture_id),
attribs);
if (image == EGL_NO_IMAGE)
{
GDK_DEBUG (DMABUF, "Creating EGLImage for dmabuf failed: %#x", eglGetError ());
return FALSE;
}
if (!eglExportDMABUFImageQueryMESA (egl_display,
image,
&fourcc,
&n_planes,
&modifier))
{
GDK_DEBUG (DMABUF, "eglExportDMABUFImageQueryMESA failed: %#x", eglGetError ());
goto out;
}
if (n_planes < 1 || n_planes > GDK_DMABUF_MAX_PLANES)
{
GDK_DEBUG (DMABUF, "dmabufs with %d planes are not supported", n_planes);
goto out;
}
if (!eglExportDMABUFImageMESA (egl_display,
image,
fds,
strides,
offsets))
{
g_warning ("eglExportDMABUFImage failed: %#x", eglGetError ());
goto out;
}
for (i = 0; i < n_planes; i++)
{
if (fds[i] == -1)
{
g_warning ("dmabuf plane %d has no file descriptor", i);
goto out;
}
}
dmabuf->fourcc = (guint32)fourcc;
dmabuf->modifier = modifier;
dmabuf->n_planes = n_planes;
for (i = 0; i < n_planes; i++)
{
dmabuf->planes[i].fd = fds[i];
dmabuf->planes[i].stride = (int) strides[i];
dmabuf->planes[i].offset = (int) offsets[i];
}
GDK_DEBUG (DMABUF,
"Exported GL texture to dmabuf (format: %.4s:%#" G_GINT64_MODIFIER "x, planes: %d)",
(char *)&fourcc, modifier, n_planes);
result = TRUE;
out:
eglDestroyImageKHR (egl_display, image);
return result;
#else
return FALSE;
#endif
}
+1 -13
View File
@@ -23,7 +23,6 @@
#include "gdkglcontext.h"
#include "gdkdrawcontextprivate.h"
#include "gdkglversionprivate.h"
#include "gdkdmabufprivate.h"
G_BEGIN_DECLS
@@ -162,18 +161,7 @@ gboolean gdk_gl_context_has_bgra (GdkGLContext
gboolean gdk_gl_context_has_vertex_arrays (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_has_image_storage (GdkGLContext *self) G_GNUC_PURE;
double gdk_gl_context_get_scale (GdkGLContext *self);
guint gdk_gl_context_import_dmabuf (GdkGLContext *self,
int width,
int height,
const GdkDmabuf *dmabuf,
int target);
gboolean gdk_gl_context_export_dmabuf (GdkGLContext *self,
unsigned int texture_id,
GdkDmabuf *dmabuf);
G_END_DECLS
-2
View File
@@ -18,7 +18,6 @@ gdk_public_sources = files([
'gdkdisplay.c',
'gdkdisplaymanager.c',
'gdkdmabuf.c',
'gdkdmabufegl.c',
'gdkdmabufformats.c',
'gdkdmabufformatsbuilder.c',
'gdkdmabuftexture.c',
@@ -217,7 +216,6 @@ gdk_deps = [
platform_gio_dep,
pangocairo_dep,
vulkan_dep,
dmabuf_dep,
png_dep,
tiff_dep,
jpeg_dep,
+1 -2
View File
@@ -76,8 +76,7 @@ gsk_gl_attachment_state_bind_texture (GskGLAttachmentState *self,
g_assert (self != NULL);
g_assert (target == GL_TEXTURE_1D ||
target == GL_TEXTURE_2D ||
target == GL_TEXTURE_3D ||
target == GL_TEXTURE_EXTERNAL_OES);
target == GL_TEXTURE_3D);
g_assert (texture >= GL_TEXTURE0 && texture <= GL_TEXTURE16);
g_assert (texture - GL_TEXTURE0 < G_N_ELEMENTS (self->textures));
-3
View File
@@ -29,9 +29,6 @@ typedef struct _GskGLBindFramebuffer GskGLBindFramebuffer;
typedef struct _GskGLBindTexture GskGLBindTexture;
#define GSK_GL_N_FILTERS 3
#define SAMPLER_EXTERNAL 9
G_STATIC_ASSERT (SAMPLER_EXTERNAL >= GSK_GL_N_FILTERS * GSK_GL_N_FILTERS);
static inline guint
filter_index (GLint filter)
+10 -33
View File
@@ -282,10 +282,7 @@ snapshot_attachments (const GskGLAttachmentState *state,
{
bind[count].id = state->textures[i].id;
bind[count].texture = state->textures[i].texture;
if (state->textures[i].target == GL_TEXTURE_EXTERNAL_OES)
bind[count].sampler = SAMPLER_EXTERNAL;
else
bind[count].sampler = state->textures[i].sampler;
bind[count].sampler = state->textures[i].sampler;
count++;
}
}
@@ -1193,23 +1190,12 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
s->sync = NULL;
}
if (bind->sampler == SAMPLER_EXTERNAL)
glBindTexture (GL_TEXTURE_EXTERNAL_OES, bind->id);
else
glBindTexture (GL_TEXTURE_2D, bind->id);
glBindTexture (GL_TEXTURE_2D, bind->id);
textures[bind->texture] = bind->id;
if (!self->has_samplers)
{
if (bind->sampler == SAMPLER_EXTERNAL)
{
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
}
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
}
}
@@ -1219,16 +1205,8 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
glBindSampler (bind->texture, self->samplers[bind->sampler]);
else
{
if (bind->sampler == SAMPLER_EXTERNAL)
{
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
}
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
}
samplers[bind->texture] = bind->sampler;
}
@@ -1346,7 +1324,7 @@ gsk_gl_command_queue_end_frame (GskGLCommandQueue *self)
if (self->attachments->textures[i].id != 0)
{
glActiveTexture (GL_TEXTURE0 + i);
glBindTexture (self->attachments->textures[i].target, 0);
glBindTexture (GL_TEXTURE_2D, 0);
self->attachments->textures[i].id = 0;
self->attachments->textures[i].changed = FALSE;
@@ -1423,7 +1401,7 @@ gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, texture_id);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -1451,9 +1429,8 @@ gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
}
/* Restore the previous texture if it was set */
if (self->attachments->textures[0].id != 0 &&
self->attachments->textures[0].target == GL_TEXTURE_2D)
glBindTexture (self->attachments->textures[0].target, self->attachments->textures[0].id);
if (self->attachments->textures[0].id != 0)
glBindTexture (GL_TEXTURE_2D, self->attachments->textures[0].id);
return (int)texture_id;
}
-6
View File
@@ -54,7 +54,6 @@ typedef struct _GskGLCommandBind
*/
guint texture : 4;
/* the sampler to use. We set sampler to 15 to indicate external textures */
guint sampler : 4;
/* The identifier for the texture created with glGenTextures(). */
@@ -235,13 +234,8 @@ struct _GskGLCommandQueue
/* Array of samplers that we use for mag/min filter handling. It is indexed
* by the sampler_index() function.
*
* Note that when samplers are not supported (hello GLES), we fall back to
* setting the texture filter, but that needs to be done for every texture.
*
* Also note that we don't use all of these samplers since some combinations
* are invalid. An index of SAMPLER_EXTERNAL is used to indicate an external
* texture, which needs special sampler treatment.
*/
GLuint samplers[GSK_GL_N_FILTERS * GSK_GL_N_FILTERS];
+7 -15
View File
@@ -54,7 +54,6 @@ struct _GskGLCompiler
guint gl3 : 1;
guint gles : 1;
guint gles3 : 1;
guint legacy : 1;
guint debug_shaders : 1;
};
@@ -135,10 +134,7 @@ gsk_gl_compiler_new (GskGLDriver *driver,
gdk_gl_context_get_version (context, &maj, &min);
if (maj >= 3)
{
self->glsl_version = SHADER_VERSION_GLES3;
self->gles3 = TRUE;
}
self->glsl_version = SHADER_VERSION_GLES3;
else
{
self->glsl_version = SHADER_VERSION_GLES;
@@ -547,7 +543,6 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
const char *legacy = "";
const char *gl3 = "";
const char *gles = "";
const char *gles3 = "";
int program_id;
int vertex_id;
int fragment_id;
@@ -574,17 +569,15 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
if (self->gles)
gles = "#define GSK_GLES 1\n";
if (self->gles3)
gles3 = "#define GSK_GLES3 1\n";
if (self->gl3)
gl3 = "#define GSK_GL3 1\n";
vertex_id = glCreateShader (GL_VERTEX_SHADER);
glShaderSource (vertex_id,
11,
10,
(const char *[]) {
version, debug, legacy, gl3, gles, gles3, clip,
version, debug, legacy, gl3, gles,
clip,
get_shader_string (self->all_preamble),
get_shader_string (self->vertex_preamble),
get_shader_string (self->vertex_source),
@@ -596,7 +589,6 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
strlen (legacy),
strlen (gl3),
strlen (gles),
strlen (gles3),
strlen (clip),
g_bytes_get_size (self->all_preamble),
g_bytes_get_size (self->vertex_preamble),
@@ -615,9 +607,10 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
fragment_id = glCreateShader (GL_FRAGMENT_SHADER);
glShaderSource (fragment_id,
11,
10,
(const char *[]) {
version, debug, legacy, gl3, gles, gles3, clip,
version, debug, legacy, gl3, gles,
clip,
get_shader_string (self->all_preamble),
get_shader_string (self->fragment_preamble),
get_shader_string (self->fragment_source),
@@ -629,7 +622,6 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
strlen (legacy),
strlen (gl3),
strlen (gles),
strlen (gles3),
strlen (clip),
g_bytes_get_size (self->all_preamble),
g_bytes_get_size (self->fragment_preamble),
+31 -230
View File
@@ -44,8 +44,6 @@
#include <gdk/gdktextureprivate.h>
#include <gdk/gdkmemoryformatprivate.h>
#include <gdk/gdkdmabuftextureprivate.h>
G_DEFINE_TYPE (GskGLDriver, gsk_gl_driver, G_TYPE_OBJECT)
@@ -226,8 +224,6 @@ gsk_gl_driver_dispose (GObject *object)
GSK_GL_DELETE_PROGRAM(name); \
GSK_GL_DELETE_PROGRAM(name ## _no_clip); \
GSK_GL_DELETE_PROGRAM(name ## _rect_clip);
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, resource, uniforms) \
GSK_GL_DELETE_PROGRAM(name);
#define GSK_GL_DELETE_PROGRAM(name) \
G_STMT_START { \
if (self->name) \
@@ -242,7 +238,6 @@ gsk_gl_driver_dispose (GObject *object)
#undef GSK_GL_SHADER_JOINED
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_DEFINE_PROGRAM
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
if (self->shader_cache != NULL)
{
@@ -378,11 +373,6 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
GSK_GL_COMPILE_PROGRAM(name ## _no_clip, uniforms, "#define NO_CLIP 1\n"); \
GSK_GL_COMPILE_PROGRAM(name ## _rect_clip, uniforms, "#define RECT_CLIP 1\n"); \
GSK_GL_COMPILE_PROGRAM(name, uniforms, "");
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, sources, uniforms) \
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_VERTEX, NULL); \
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_FRAGMENT, NULL); \
sources \
GSK_GL_COMPILE_PROGRAM(name, uniforms, "#define NO_CLIP 1\n");
#define GSK_GL_COMPILE_PROGRAM(name, uniforms, clip) \
G_STMT_START { \
GskGLProgram *program; \
@@ -410,7 +400,6 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
} G_STMT_END;
# include "gskglprograms.defs"
#undef GSK_GL_DEFINE_PROGRAM
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_SHADER_SINGLE
#undef GSK_GL_SHADER_JOINED
@@ -713,178 +702,6 @@ gsk_gl_driver_cache_texture (GskGLDriver *self,
}
}
#if defined(HAVE_DMABUF) && defined (HAVE_EGL)
static void
set_viewport_for_size (GskGLDriver *self,
GskGLProgram *program,
float width,
float height)
{
float viewport[4] = { 0, 0, width, height };
gsk_gl_uniform_state_set4fv (program->uniforms,
program->program_info,
UNIFORM_SHARED_VIEWPORT, 0,
1,
(const float *)&viewport);
self->stamps[UNIFORM_SHARED_VIEWPORT]++;
}
#define ORTHO_NEAR_PLANE -10000
#define ORTHO_FAR_PLANE 10000
static void
set_projection_for_size (GskGLDriver *self,
GskGLProgram *program,
float width,
float height)
{
graphene_matrix_t projection;
graphene_matrix_init_ortho (&projection, 0, width, 0, height, ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE);
graphene_matrix_scale (&projection, 1, -1, 1);
gsk_gl_uniform_state_set_matrix (program->uniforms,
program->program_info,
UNIFORM_SHARED_PROJECTION, 0,
&projection);
self->stamps[UNIFORM_SHARED_PROJECTION]++;
}
static void
reset_modelview (GskGLDriver *self,
GskGLProgram *program)
{
graphene_matrix_t modelview;
graphene_matrix_init_identity (&modelview);
gsk_gl_uniform_state_set_matrix (program->uniforms,
program->program_info,
UNIFORM_SHARED_MODELVIEW, 0,
&modelview);
self->stamps[UNIFORM_SHARED_MODELVIEW]++;
}
static void
draw_rect (GskGLCommandQueue *command_queue,
float min_x,
float min_y,
float max_x,
float max_y)
{
GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (command_queue);
float min_u = 0;
float max_u = 1;
float min_v = 1;
float max_v = 0;
guint16 c = FP16_ZERO;
vertices[0] = (GskGLDrawVertex) { .position = { min_x, min_y }, .uv = { min_u, min_v }, .color = { c, c, c, c } };
vertices[1] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { min_u, max_v }, .color = { c, c, c, c } };
vertices[2] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { max_u, min_v }, .color = { c, c, c, c } };
vertices[3] = (GskGLDrawVertex) { .position = { max_x, max_y }, .uv = { max_u, max_v }, .color = { c, c, c, c } };
vertices[4] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { min_u, max_v }, .color = { c, c, c, c } };
vertices[5] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { max_u, min_v }, .color = { c, c, c, c } };
}
static unsigned int release_render_target (GskGLDriver *self,
GskGLRenderTarget *render_target,
gboolean release_texture,
gboolean cache_texture);
static guint
gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
GdkDmabufTexture *texture)
{
GdkGLContext *context = self->command_queue->context;
GdkDisplay *display = gdk_gl_context_get_display (context);
int max_texture_size = self->command_queue->max_texture_size;
const GdkDmabuf *dmabuf;
guint texture_id;
int width, height;
GskGLProgram *program;
GskGLRenderTarget *render_target;
guint prev_fbo;
gdk_gl_context_make_current (context);
width = gdk_texture_get_width (GDK_TEXTURE (texture));
height = gdk_texture_get_height (GDK_TEXTURE (texture));
if (width > max_texture_size || height > max_texture_size)
{
GDK_DEBUG (DMABUF, "Can't import dmabuf bigger than MAX_TEXTURE_SIZE (%d)", max_texture_size);
return 0;
}
dmabuf = gdk_dmabuf_texture_get_dmabuf (texture);
GDK_DEBUG (DMABUF, "DMA-buf Format %.4s:%#lx", (char *) &dmabuf->fourcc, dmabuf->modifier);
if (!gdk_dmabuf_formats_contains (display->egl_external_formats, dmabuf->fourcc, dmabuf->modifier))
{
GDK_DEBUG (DMABUF, "Import dmabuf as GL_TEXTURE_2D texture");
return gdk_gl_context_import_dmabuf (context, width, height,
dmabuf,
GL_TEXTURE_2D);
}
if (!gdk_gl_context_get_use_es (context))
{
GDK_DEBUG (DMABUF, "Can't import external_only dmabuf outside of GLES");
return 0;
}
GDK_DEBUG (DMABUF, "Import dmabuf as GL_TEXTURE_EXTERNAL_OES texture");
texture_id = gdk_gl_context_import_dmabuf (context, width, height,
dmabuf,
GL_TEXTURE_EXTERNAL_OES);
if (texture_id == 0)
return 0;
gsk_gl_driver_autorelease_texture (self, texture_id);
program = self->external;
gsk_gl_driver_create_render_target (self, width, height, GL_RGBA8, &render_target);
prev_fbo = gsk_gl_command_queue_bind_framebuffer (self->command_queue, render_target->framebuffer_id);
gsk_gl_command_queue_clear (self->command_queue, 0, &GRAPHENE_RECT_INIT (0, 0, width, height));
if (gsk_gl_command_queue_begin_draw (self->command_queue, program->program_info, width, height))
{
set_projection_for_size (self, program, width, height);
set_viewport_for_size (self, program, width, height);
reset_modelview (self, program);
gsk_gl_program_set_uniform_texture (program,
UNIFORM_EXTERNAL_SOURCE, 0,
GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE0, texture_id);
draw_rect (self->command_queue, 0, 0, width, height);
gsk_gl_command_queue_end_draw (self->command_queue);
}
gsk_gl_command_queue_bind_framebuffer (self->command_queue, prev_fbo);
return release_render_target (self, render_target, FALSE, FALSE);
}
#else
static guint
gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
GdkDmabufTexture *texture)
{
return 0;
}
#endif /* HAVE_DMABUF && HAVE_EGL */
/**
* gsk_gl_driver_load_texture:
* @self: a `GdkTexture`
@@ -941,11 +758,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
return t->texture_id;
}
if (GDK_IS_DMABUF_TEXTURE (texture))
{
texture_id = gsk_gl_driver_import_dmabuf_texture (self, GDK_DMABUF_TEXTURE (texture));
}
else if (GDK_IS_GL_TEXTURE (texture))
if (GDK_IS_GL_TEXTURE (texture))
{
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
GdkGLContext *texture_context = gdk_gl_texture_get_context (gl_texture);
@@ -1148,47 +961,6 @@ gsk_gl_driver_create_render_target (GskGLDriver *self,
return FALSE;
}
static unsigned int
release_render_target (GskGLDriver *self,
GskGLRenderTarget *render_target,
gboolean release_texture,
gboolean cache_texture)
{
guint texture_id;
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), 0);
g_return_val_if_fail (render_target != NULL, 0);
if (release_texture)
{
texture_id = 0;
g_ptr_array_add (self->render_targets, render_target);
}
else
{
texture_id = render_target->texture_id;
if (cache_texture)
{
GskGLTexture *texture;
texture = gsk_gl_texture_new (render_target->texture_id,
render_target->width,
render_target->height,
self->current_frame_id);
g_hash_table_insert (self->textures,
GUINT_TO_POINTER (texture_id),
g_steal_pointer (&texture));
}
gsk_gl_driver_autorelease_framebuffer (self, render_target->framebuffer_id);
g_free (render_target);
}
return texture_id;
}
/**
* gsk_gl_driver_release_render_target:
* @self: a `GskGLDriver`
@@ -1214,7 +986,36 @@ gsk_gl_driver_release_render_target (GskGLDriver *self,
GskGLRenderTarget *render_target,
gboolean release_texture)
{
return release_render_target (self, render_target, release_texture, TRUE);
guint texture_id;
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), 0);
g_return_val_if_fail (render_target != NULL, 0);
if (release_texture)
{
texture_id = 0;
g_ptr_array_add (self->render_targets, render_target);
}
else
{
GskGLTexture *texture;
texture_id = render_target->texture_id;
texture = gsk_gl_texture_new (render_target->texture_id,
render_target->width,
render_target->height,
self->current_frame_id);
g_hash_table_insert (self->textures,
GUINT_TO_POINTER (texture_id),
g_steal_pointer (&texture));
gsk_gl_driver_autorelease_framebuffer (self, render_target->framebuffer_id);
g_free (render_target);
}
return texture_id;
}
/**
-5
View File
@@ -69,9 +69,7 @@ typedef struct {
#define CONCAT_EXPANDED2(a,b) a##b
#define GSK_GL_ADD_UNIFORM(pos, KEY, name) UNIFORM_##KEY = UNIFORM_SHARED_LAST + pos,
#define GSK_GL_DEFINE_PROGRAM(name, resource, uniforms) enum { uniforms };
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, resource, uniforms) enum { uniforms };
# include "gskglprograms.defs"
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
#undef GSK_GL_DEFINE_PROGRAM
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_NO_UNIFORMS
@@ -118,13 +116,10 @@ struct _GskGLDriver
GskGLProgram *name ## _no_clip; \
GskGLProgram *name ## _rect_clip; \
GskGLProgram *name;
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, resource, uniforms) \
GskGLProgram *name;
# include "gskglprograms.defs"
#undef GSK_GL_NO_UNIFORMS
#undef GSK_GL_ADD_UNIFORM
#undef GSK_GL_DEFINE_PROGRAM
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
gint64 current_frame_id;
+1 -5
View File
@@ -119,11 +119,7 @@ gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
memset (pixel_data, 255, sizeof pixel_data);
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ())
#if G_BYTE_ORDER == G_BIG_ENDIAN
|| gdk_gl_context_get_use_es (gdk_gl_context_get_current ())
#endif
)
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ()))
{
gl_format = GL_RGBA;
gl_type = GL_UNSIGNED_BYTE;
+1 -5
View File
@@ -111,11 +111,7 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
"Uploading texture");
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ())
#if G_BYTE_ORDER == G_BIG_ENDIAN
|| gdk_gl_context_get_use_es (gdk_gl_context_get_current ())
#endif
)
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ()))
{
pixel_data = free_data = g_malloc (width * height * 4);
gdk_memory_convert (pixel_data, width * 4,
-10
View File
@@ -87,13 +87,3 @@ GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
GSK_GL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
GSK_GL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
GSK_GL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
/* Texture conversion shaders.
*
* Note: If you add new formats here, they need to be added
* to the list of supported formats in gdk/gdkdmabuftexture.c.
*/
GSK_GL_DEFINE_PROGRAM_NO_CLIP (external,
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("external.glsl")),
GSK_GL_ADD_UNIFORM (1, EXTERNAL_SOURCE, u_external_source))
+11 -11
View File
@@ -30,7 +30,6 @@
#include <gsk/gskglshaderprivate.h>
#include <gdk/gdktextureprivate.h>
#include <gdk/gdkmemorytextureprivate.h>
#include <gdk/gdkdmabuftexture.h>
#include <gsk/gsktransformprivate.h>
#include <gsk/gskroundedrectprivate.h>
#include <gsk/gskrectprivate.h>
@@ -48,7 +47,6 @@
#include "ninesliceprivate.h"
#include "fp16private.h"
#define ORTHO_NEAR_PLANE -10000
#define ORTHO_FAR_PLANE 10000
#define MAX_GRADIENT_STOPS 6
@@ -3632,12 +3630,16 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
gboolean ensure_mipmap,
GskGLRenderOffscreen *offscreen)
{
/* Don't put GL or dmabuf textures into icon caches, they are already on the GPU side */
GdkGLTexture *gl_texture = NULL;
if (GDK_IS_GL_TEXTURE (texture))
gl_texture = GDK_GL_TEXTURE (texture);
if (!ensure_mipmap &&
gsk_gl_texture_library_can_cache ((GskGLTextureLibrary *)job->driver->icons_library,
texture->width,
texture->height) &&
!(GDK_IS_GL_TEXTURE (texture) || GDK_IS_DMABUF_TEXTURE (texture)))
!gl_texture)
{
const GskGLIconData *icon_data;
@@ -3651,18 +3653,16 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
/* Only generate a mipmap if it does not make use reupload
* a GL texture which we could otherwise use directly.
*/
if (GDK_IS_GL_TEXTURE (texture) &&
gdk_gl_context_is_shared (gdk_gl_texture_get_context (GDK_GL_TEXTURE (texture)),
job->command_queue->context))
ensure_mipmap = gdk_gl_texture_has_mipmap (GDK_GL_TEXTURE (texture));
if (gl_texture &&
gdk_gl_context_is_shared (gdk_gl_texture_get_context (gl_texture), job->command_queue->context))
ensure_mipmap = gdk_gl_texture_has_mipmap (gl_texture);
offscreen->texture_id = gsk_gl_driver_load_texture (job->driver, texture, ensure_mipmap);
init_full_texture_region (offscreen);
offscreen->has_mipmap = ensure_mipmap;
if (GDK_IS_GL_TEXTURE (texture) &&
offscreen->texture_id == gdk_gl_texture_get_id (GDK_GL_TEXTURE (texture)))
offscreen->sync = gdk_gl_texture_get_sync (GDK_GL_TEXTURE (texture));
if (gl_texture && offscreen->texture_id == gdk_gl_texture_get_id (gl_texture))
offscreen->sync = gdk_gl_texture_get_sync (gl_texture);
}
}
-28
View File
@@ -1,28 +0,0 @@
// VERTEX_SHADER:
// external.glsl
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// external.glsl
#if defined(GSK_GLES) || defined(GSK_GLES3)
uniform samplerExternalOES u_external_source;
#else
/* Just to make this compile, we won't use it without GLES */
uniform sampler2D u_external_source;
#endif
void main() {
/* Open-code this here, since GskTexture() expects a sampler2D */
#if defined(GSK_GLES) || defined(GSK_LEGACY)
vec4 color = texture2D(u_external_source, vUv);
#else
vec4 color = texture(u_external_source, vUv);
#endif
gskSetOutputColor(color);
}
-6
View File
@@ -1,9 +1,3 @@
#if defined(GSK_GLES3)
#extension GL_OES_EGL_image_external_essl3 : require
#elif defined (GSK_GLES)
#extension GL_OES_EGL_image_external : require
#endif
#ifndef GSK_LEGACY
precision highp float;
#endif
-19
View File
@@ -684,22 +684,3 @@ gsk_renderer_set_debug_flags (GskRenderer *renderer,
priv->debug_flags = flags;
}
/* Feed a texture through a renderer and return the resulting 'native' texture. */
GdkTexture *
gsk_renderer_convert_texture (GskRenderer *self,
GdkTexture *texture)
{
int width, height;
GskRenderNode *node;
GdkTexture *result;
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
node = gsk_texture_node_new (texture, &GRAPHENE_RECT_INIT (0, 0, width, height));
result = gsk_renderer_render_texture (self, node, &GRAPHENE_RECT_INIT (0, 0, width, height));
gsk_render_node_unref (node);
return result;
}
-3
View File
@@ -56,8 +56,5 @@ GskDebugFlags gsk_renderer_get_debug_flags (GskRenderer
void gsk_renderer_set_debug_flags (GskRenderer *renderer,
GskDebugFlags flags);
GdkTexture * gsk_renderer_convert_texture (GskRenderer *renderer,
GdkTexture *texture);
G_END_DECLS
-1
View File
@@ -20,7 +20,6 @@ gsk_private_gl_shaders = [
'gl/resources/custom.glsl',
'gl/resources/filled_border.glsl',
'gl/resources/mask.glsl',
'gl/resources/external.glsl',
]
gsk_public_sources = files([
+5 -14
View File
@@ -162,6 +162,7 @@ check_headers = [
'inttypes.h',
'linux/input.h',
'linux/memfd.h',
'linux/dma-buf.h',
'locale.h',
'memory.h',
'stdint.h',
@@ -185,6 +186,10 @@ foreach h : check_headers
endif
endforeach
if os_linux and not cc.has_header('linux/dma-buf.h')
error('OS is Linux, but linux/dma-buf.h not found.')
endif
# Maths functions might be implemented in libm
libm = cc.find_library('m', required: false)
@@ -618,20 +623,6 @@ else
vulkan_pkg_found = false
endif
if cc.has_header('linux/dma-buf.h')
dmabuf_dep = dependency('libdrm',
required: os_linux)
else
if os_linux
error('OS is Linux, but linux/dma-buf.h not found.')
endif
dmabuf_dep = dependency('', required: false)
endif
cdata.set('HAVE_DMABUF', dmabuf_dep.found())
# We only care about drm_fourcc.h for all the fourccs,
# but not about linking to libdrm
dmabuf_dep = dmabuf_dep.partial_dependency(includes: true, compile_args: true)
cloudproviders_dep = dependency('cloudproviders',
required: get_option('cloudproviders'),
version: cloudproviders_req,
+1 -1
View File
@@ -3,7 +3,7 @@
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-heap.h>
#include <drm_fourcc.h>
#include <drm/drm_fourcc.h>
/* For this to work, you may need to give /dev/dma_heap/system
* lax permissions.
-295
View File
@@ -1,295 +0,0 @@
#include "config.h"
#include <gtk/gtk.h>
#include <gdk/gdkdisplayprivate.h>
#include <gdk/gdkglcontextprivate.h>
#include <gdk/gdkdmabuftextureprivate.h>
#ifdef HAVE_DMABUF
#include <drm/drm_fourcc.h>
#endif
static void
test_dmabuf_formats (void)
{
GdkDisplay *display;
GdkDmabufFormats *formats;
display = gdk_display_get_default ();
formats = gdk_display_get_dmabuf_formats (display);
#ifdef HAVE_DMABUF
/* We always have basic linear formats */
g_assert_true (gdk_dmabuf_formats_get_n_formats (formats) >= 6);
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_BGRA8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_ABGR16161616F, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_RGB888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_BGR888, DRM_FORMAT_MOD_LINEAR));
#else
g_assert_true (gdk_dmabuf_formats_get_n_formats (formats) == 0);
#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;
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, GL_TEXTURE_2D);
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/formats", test_dmabuf_formats);
g_test_add_func ("/dmabuf/export", test_dmabuf_export);
g_test_add_func ("/dmabuf/import", test_dmabuf_import);
return g_test_run ();
}
+6 -11
View File
@@ -52,24 +52,19 @@ foreach t : tests
endforeach
internal_tests = [
{ 'name': 'image' },
{ 'name': 'texture' },
{ 'name': 'gltexture' },
{ 'name': 'dmabuftexture', 'suites': 'failing' },
'image',
'texture',
'gltexture',
]
foreach t : internal_tests
test_name = t.get('name')
test_exe = executable(test_name,
sources: '@0@.c'.format(test_name),
test_exe = executable(t, '@0@.c'.format(t),
c_args: common_cflags + ['-DGTK_COMPILATION'],
dependencies: libgtk_static_dep,
install: false,
)
suites = ['gdk'] + t.get('suites', [])
test(test_name, test_exe,
test(t, test_exe,
args: [ '--tap', '-k' ],
protocol: 'tap',
env: [
@@ -77,6 +72,6 @@ foreach t : internal_tests
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
'DBUS_SESSION_BUS_ADDRESS=',
],
suite: suites,
suite: 'gdk',
)
endforeach