Compare commits

...

8 Commits

Author SHA1 Message Date
Matthias Clasen
451f7ba2e4 wip: Try using EXT_OES_EGL_image_external
This only has a chance of working with GLES,
but doesn't.
2023-10-06 12:40:43 -04:00
Matthias Clasen
636202aac0 debug spew 2023-10-06 12:40:19 -04:00
Matthias Clasen
66551f3032 wip 2023-10-06 11:43:23 -04:00
Matthias Clasen
b9a4d8b54d dmatexturebuilder: Support multiple planes
So far, this is just the API, the code that
creates textures doesn't use more than one
plane yet.
2023-10-05 17:54:25 -04:00
Matthias Clasen
e58570a4ee gsk: Import GdkDmabufTextures in GL
Import these by wrapping them in an EGLImage
and then importing it into GL.
2023-10-03 19:27:16 -04:00
Matthias Clasen
431597bc7a Add GdkDmabufTexture
Add a new GdkTexture subclass for supporting
dmabuf buffers on Linux. Also add a builder
called GdkDmabufTextureBuilder.
2023-10-03 19:27:16 -04:00
Matthias Clasen
7a11bc9442 display: Get supported dmabuf formats
These are the dmabuf formats that we can hope to
download by first importing them as an EGLImage and
then downloading them as a GL texture.
2023-10-03 19:27:16 -04:00
Matthias Clasen
0d27813b42 wayland: Get format info for dmabufs
For now, all we do with it is dump it if you
set GDK_DEBUG=misc. In the future, it will
be used to determine the dmabuf formats we
can support.
2023-10-03 19:27:16 -04:00
19 changed files with 2169 additions and 2 deletions

View File

@@ -42,6 +42,8 @@
#include <gdk/gdkdevicetool.h>
#include <gdk/gdkdisplay.h>
#include <gdk/gdkdisplaymanager.h>
#include <gdk/gdkdmabuftexture.h>
#include <gdk/gdkdmabuftexturebuilder.h>
#include <gdk/gdkdrag.h>
#include <gdk/gdkdragsurface.h>
#include <gdk/gdkdragsurfacesize.h>

View File

@@ -404,6 +404,8 @@ gdk_display_finalize (GObject *object)
g_list_free_full (display->seats, g_object_unref);
g_free (display->egl_dmabuf_formats);
G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
}
@@ -1259,6 +1261,61 @@ gdk_display_create_vulkan_context (GdkDisplay *self,
NULL);
}
static void
init_dmabuf_formats (GdkDisplay *self)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
if (priv->egl_display != EGL_NO_DISPLAY)
{
int num_formats;
int *formats;
GArray *array;
eglQueryDmaBufFormatsEXT (priv->egl_display, 0, NULL, &num_formats);
formats = g_new (int, num_formats);
eglQueryDmaBufFormatsEXT (priv->egl_display, num_formats, formats, &num_formats);
array = g_array_new (FALSE, FALSE, sizeof (GdkDmabufFormat));
for (int i = 0; i < num_formats; i++)
{
int num_modifiers;
uint64_t *modifiers;
unsigned int *external_only;
eglQueryDmaBufModifiersEXT (priv->egl_display, formats[i], 0, NULL, NULL, &num_modifiers);
modifiers = g_new (uint64_t, num_modifiers);
external_only = g_new (unsigned int, num_modifiers);
eglQueryDmaBufModifiersEXT (priv->egl_display, formats[i], num_modifiers, modifiers, external_only, &num_modifiers);
if (num_modifiers == 0)
g_array_append_val (array, ((GdkDmabufFormat){ formats[i], 0 }));
else
{
for (int j = 0; j < num_modifiers; j++)
g_array_append_val (array, ((GdkDmabufFormat){ formats[i], modifiers[j] }));
}
g_free (modifiers);
}
g_free (formats);
self->egl_dmabuf_n_formats = array->len;
self->egl_dmabuf_formats = (GdkDmabufFormat *) g_array_free (array, FALSE);
}
GDK_DEBUG (MISC, "EGL dmabuf formats: (%lu)", self->egl_dmabuf_n_formats);
for (gsize i = 0; i < self->egl_dmabuf_n_formats; i++)
{
uint32_t f = self->egl_dmabuf_formats[i].fourcc;
uint64_t m = self->egl_dmabuf_formats[i].modifier;
GDK_DEBUG (MISC, " %c%c%c%c:%#lx", f & 0xff, (f >> 8) & 0xff, (f >> 16) & 0xff, (f >> 24) & 0xff, m);
}
}
static void
gdk_display_init_gl (GdkDisplay *self)
{
@@ -1300,6 +1357,10 @@ gdk_display_init_gl (GdkDisplay *self)
gdk_gl_backend_use (GDK_GL_CONTEXT_GET_CLASS (context)->backend_type);
gdk_profiler_end_mark (before, "initialize OpenGL", NULL);
gdk_gl_context_make_current (context);
init_dmabuf_formats (self);
}
/**
@@ -1824,6 +1885,40 @@ gdk_display_get_egl_display (GdkDisplay *self)
#endif
}
/**
* GdkDmabufFormat:
* @fourcc: the format code
* @modifiers: the format modifier
*
* The `GdkDmabufFormat` struct represents a dma-buf format
* as defined in the `drm_fourcc.h` header.
*
* Since: 4.14
*/
/**
* gdk_display_get_dmabuf_formats:
* @display: a `GdkDisplay`
* @n_formats: return location for the number of formats
*
* Returns the dma-buf formats that are supported for
* this display.
*
* Returns: (transfer none): an array of `GdkDmabufFormat` structs.
* The length of the array is returned in @n_formats
*
* Since: 4.14
*/
const GdkDmabufFormat *
gdk_display_get_dmabuf_formats (GdkDisplay *display,
gsize *n_formats)
{
gdk_display_prepare_gl (display, NULL);
*n_formats = display->egl_dmabuf_n_formats;
return display->egl_dmabuf_formats;
}
GdkDebugFlags
gdk_display_get_debug_flags (GdkDisplay *display)
{

View File

@@ -134,6 +134,17 @@ gboolean gdk_display_get_setting (GdkDisplay *display,
const char *name,
GValue *value);
typedef struct
{
uint32_t fourcc;
uint64_t modifier;
} GdkDmabufFormat;
GDK_AVAILABLE_IN_4_14
const GdkDmabufFormat *
gdk_display_get_dmabuf_formats (GdkDisplay *display,
gsize *n_formats);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplay, g_object_unref)
G_END_DECLS

View File

@@ -113,6 +113,9 @@ struct _GdkDisplay
guint have_egl_buffer_age : 1;
guint have_egl_no_config_context : 1;
guint have_egl_pixel_format_float : 1;
GdkDmabufFormat *egl_dmabuf_formats;
gsize egl_dmabuf_n_formats;
};
struct _GdkDisplayClass

451
gdk/gdkdmabuftexture.c Normal file
View File

@@ -0,0 +1,451 @@
/* gdkdmabuftexture.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 "gdkdmabuftextureprivate.h"
#ifndef __linux__
GType
gdk_dmabuf_texture_get_type (void)
{
return G_TYPE_INVALID;
}
#else
#include "gdkdisplayprivate.h"
#include "gdkmemoryformatprivate.h"
#include "gdkmemorytextureprivate.h"
#include <gdk/gdkglcontext.h>
#include <gdk/gdkgltexturebuilder.h>
#include <gdk/gdktexturedownloader.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/dma-buf.h>
#include <drm/drm_fourcc.h>
#include <epoxy/egl.h>
/**
* GdkDmabufTexture:
*
* A `GdkTexture` representing a dma-buf object.
*
* To create a `GdkDmabufTexture`, use the auxiliary
* [class@Gdk.DmabufTextureBuilder] object.
*
* Dma-buf textures can only be created on Linux.
*/
struct _GdkDmabufTexture
{
GdkTexture parent_instance;
GdkDisplay *display;
unsigned int fourcc;
guint64 modifier;
/* Per-plane properties */
int fd[4];
unsigned int stride[4];
unsigned int offset[4];
GDestroyNotify destroy;
gpointer data;
};
struct _GdkDmabufTextureClass
{
GdkTextureClass parent_class;
};
G_DEFINE_TYPE (GdkDmabufTexture, gdk_dmabuf_texture, GDK_TYPE_TEXTURE)
static void
gdk_dmabuf_texture_dispose (GObject *object)
{
GdkDmabufTexture *self = GDK_DMABUF_TEXTURE (object);
if (self->destroy)
self->destroy (self->data);
G_OBJECT_CLASS (gdk_dmabuf_texture_parent_class)->dispose (object);
}
static struct {
unsigned int fourcc;
guint64 modifier;
GdkMemoryFormat memory;
int planes;
} supported_formats[] = {
{ DRM_FORMAT_RGB888, DRM_FORMAT_MOD_LINEAR, GDK_MEMORY_R8G8B8, 1 },
{ DRM_FORMAT_BGR888, DRM_FORMAT_MOD_LINEAR, GDK_MEMORY_B8G8R8, 1 },
{ DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR, GDK_MEMORY_A8R8G8B8, 1 },
{ DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_LINEAR, GDK_MEMORY_A8B8G8R8, 1 },
{ DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_LINEAR, GDK_MEMORY_R8G8B8A8, 1 },
{ DRM_FORMAT_BGRA8888, DRM_FORMAT_MOD_LINEAR, GDK_MEMORY_B8G8R8A8, 1 },
};
static gboolean
get_memory_format (GdkDisplay *display,
unsigned int fourcc,
guint64 modifier,
GdkMemoryFormat *format,
int *n_planes)
{
/* We can always support simple linear formats */
for (int i = 0; i < G_N_ELEMENTS (supported_formats); i++)
{
if (supported_formats[i].fourcc == fourcc &&
supported_formats[i].modifier == modifier)
{
*format = supported_formats[i].memory;
*n_planes = supported_formats[i].planes;
return TRUE;
}
}
if (display)
{
const GdkDmabufFormat *formats;
gsize n_formats;
/* For others, we rely on a detour though GL */
formats = gdk_display_get_dmabuf_formats (display, &n_formats);
for (gsize i = 0; i < n_formats; i++)
{
if (formats[i].fourcc == fourcc &&
formats[i].modifier == modifier)
{
*format = GDK_MEMORY_A8R8G8B8; // FIXME
*n_planes = 1; // FIXME
return TRUE;
}
}
}
return FALSE;
}
static int
import_dmabuf_into_gl (GdkDmabufTexture *self)
{
GdkGLContext *context;
EGLDisplay egl_display;
EGLint attribs[64];
EGLImage image;
guint texture_id;
int i;
egl_display = gdk_display_get_egl_display (self->display);
if (egl_display == EGL_NO_DISPLAY)
{
g_warning ("Can't import dmabufs when not using EGL");
return 0;
}
i = 0;
attribs[i++] = EGL_WIDTH;
attribs[i++] = gdk_texture_get_width (GDK_TEXTURE (self));
attribs[i++] = EGL_HEIGHT;
attribs[i++] = gdk_texture_get_height (GDK_TEXTURE (self));
attribs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[i++] = self->fourcc;
#define ADD_PLANE_ATTRIBUTES(plane) \
if (self->fd[plane] != -1 || self->offset[plane] != 0) \
{ \
attribs[i++] = EGL_DMA_BUF_PLANE ## plane ## _FD_EXT; \
attribs[i++] = self->fd[plane]; \
attribs[i++] = EGL_DMA_BUF_PLANE ## plane ## _MODIFIER_LO_EXT; \
attribs[i++] = self->modifier & 0xFFFFFFFF; \
attribs[i++] = EGL_DMA_BUF_PLANE ## plane ## _MODIFIER_HI_EXT; \
attribs[i++] = self->modifier >> 32; \
attribs[i++] = EGL_DMA_BUF_PLANE ## plane ## _PITCH_EXT; \
attribs[i++] = self->stride[plane]; \
attribs[i++] = EGL_DMA_BUF_PLANE ## plane ## _OFFSET_EXT; \
attribs[i++] = self->offset[plane]; \
}
ADD_PLANE_ATTRIBUTES (0)
ADD_PLANE_ATTRIBUTES (1)
ADD_PLANE_ATTRIBUTES (2)
ADD_PLANE_ATTRIBUTES (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)
{
g_warning ("Failed to create EGL image: %d", eglGetError ());
return 0;
}
context = gdk_display_get_gl_context (self->display);
gdk_gl_context_make_current (context);
glGenTextures (1, &texture_id);
glBindTexture (GL_TEXTURE_2D, texture_id);
glEGLImageTargetTexture2DOES (GL_TEXTURE_2D, image);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
eglDestroyImageKHR (egl_display, image);
return texture_id;
}
static void
do_indirect_download (GdkDmabufTexture *self,
GdkMemoryFormat format,
guchar *data,
gsize stride)
{
GdkGLTextureBuilder *builder;
int id;
GdkTexture *gl_texture;
GdkTextureDownloader *downloader;
GDK_DEBUG (MISC, "Using EGLImage and GL import for downloading a dmabuf");
g_assert (GDK_IS_DISPLAY (self->display));
g_assert (GDK_IS_GL_CONTEXT (gdk_display_get_gl_context (self->display)));
id = import_dmabuf_into_gl (self);
if (id == 0)
return;
builder = gdk_gl_texture_builder_new ();
gdk_gl_texture_builder_set_context (builder, gdk_display_get_gl_context (self->display));
gdk_gl_texture_builder_set_id (builder, id);
gdk_gl_texture_builder_set_width (builder, gdk_texture_get_width (GDK_TEXTURE (self)));
gdk_gl_texture_builder_set_height (builder, gdk_texture_get_height (GDK_TEXTURE (self)));
gdk_gl_texture_builder_set_format (builder, gdk_texture_get_format (GDK_TEXTURE (self)));
gl_texture = gdk_gl_texture_builder_build (builder, NULL, NULL);
downloader = gdk_texture_downloader_new (gl_texture);
gdk_texture_downloader_set_format (downloader, format);
gdk_texture_downloader_download_into (downloader, data, stride);
gdk_texture_downloader_free (downloader);
g_object_unref (gl_texture);
g_object_unref (builder);
}
static void
do_direct_download (GdkDmabufTexture *self,
guchar *data,
gsize stride)
{
gsize size;
unsigned int height;
gsize src_stride;
guchar *src_data;
int bpp;
GDK_DEBUG (MISC, "Using mmap() and memcpy() for downloading a dmabuf");
height = gdk_texture_get_height (GDK_TEXTURE (self));
bpp = gdk_memory_format_bytes_per_pixel (gdk_texture_get_format (GDK_TEXTURE (self)));
src_stride = self->stride[0];
size = self->stride[0] * height;
if (ioctl (self->fd[0], DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_START|DMA_BUF_SYNC_READ }) < 0)
g_warning ("Failed to sync dma-buf: %s", g_strerror (errno));
src_data = mmap (NULL, size, PROT_READ, MAP_SHARED, self->fd[0], self->offset[0]);
if (stride == src_stride)
memcpy (data, src_data, size);
else
{
for (unsigned int i = 0; i < height; i++)
memcpy (data + i * stride, src_data + i * src_stride, height * bpp);
}
if (ioctl (self->fd[0], DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_END|DMA_BUF_SYNC_READ }) < 0)
g_warning ("Failed to sync dma-buf: %s", g_strerror (errno));
munmap (src_data, size);
}
static void
gdk_dmabuf_texture_download (GdkTexture *texture,
GdkMemoryFormat format,
guchar *data,
gsize stride)
{
GdkDmabufTexture *self = GDK_DMABUF_TEXTURE (texture);
GdkMemoryFormat fmt;
int planes;
GdkMemoryFormat src_format = gdk_texture_get_format (texture);
if (!get_memory_format (NULL, self->fourcc, self->modifier, &fmt, &planes))
do_indirect_download (self, format, data, stride);
else if (format == src_format)
do_direct_download (self, data, stride);
else
{
unsigned int width, height;
guchar *src_data;
gsize src_stride;
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
src_stride = self->stride[0];
src_data = g_new (guchar, src_stride * height);
do_direct_download (self, src_data, src_stride);
gdk_memory_convert (data, stride, format,
src_data, src_stride, src_format,
width, height);
g_free (src_data);
}
}
static void
gdk_dmabuf_texture_class_init (GdkDmabufTextureClass *klass)
{
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
texture_class->download = gdk_dmabuf_texture_download;
gobject_class->dispose = gdk_dmabuf_texture_dispose;
}
static void
gdk_dmabuf_texture_init (GdkDmabufTexture *self)
{
self->fd[0] = self->fd[1] = self->fd[2] = self->fd[3] = -1;
}
GdkTexture *
gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
GDestroyNotify destroy,
gpointer data)
{
GdkDmabufTexture *self;
GdkTexture *update_texture;
GdkMemoryFormat format;
int n_planes;
uint32_t f = gdk_dmabuf_texture_builder_get_fourcc (builder);
uint64_t m = gdk_dmabuf_texture_builder_get_modifier(builder);
if (!get_memory_format (gdk_dmabuf_texture_builder_get_display (builder),
gdk_dmabuf_texture_builder_get_fourcc (builder),
gdk_dmabuf_texture_builder_get_modifier (builder),
&format, &n_planes))
{
g_warning ("Unsupported dmabuf format %c%c%c%c:%#lx", f & 0xff, (f >> 8) & 0xff, (f >> 16) & 0xff, (f >> 24) & 0xff, m);
return NULL;
}
GDK_DEBUG (MISC, "Dmabuf texture in format %c%c%c%c:%#lx", f & 0xff, (f >> 8) & 0xff, (f >> 16) & 0xff, (f >> 24) & 0xff, m);
self = g_object_new (GDK_TYPE_DMABUF_TEXTURE,
"width", gdk_dmabuf_texture_builder_get_width (builder),
"height", gdk_dmabuf_texture_builder_get_height (builder),
NULL);
GDK_TEXTURE (self)->format = format;
g_set_object (&self->display, gdk_dmabuf_texture_builder_get_display (builder));
self->fourcc = gdk_dmabuf_texture_builder_get_fourcc (builder);
self->modifier = gdk_dmabuf_texture_builder_get_modifier (builder);
for (int i = 0; i < 4; i++)
{
self->fd[i] = gdk_dmabuf_texture_builder_get_fd (builder, i);
self->stride[i] = gdk_dmabuf_texture_builder_get_stride (builder, i);
if (self->stride[i] == 0)
self->stride[i] = gdk_dmabuf_texture_builder_get_width (builder) *
gdk_memory_format_bytes_per_pixel (format);
self->offset[i] = gdk_dmabuf_texture_builder_get_offset (builder, i);
}
update_texture = gdk_dmabuf_texture_builder_get_update_texture (builder);
if (update_texture)
{
cairo_region_t *update_region = gdk_dmabuf_texture_builder_get_update_region (builder);
if (update_region)
{
update_region = cairo_region_copy (update_region);
cairo_region_intersect_rectangle (update_region,
&(cairo_rectangle_int_t) {
0, 0,
update_texture->width, update_texture->height
});
gdk_texture_set_diff (GDK_TEXTURE (self), update_texture, update_region);
}
}
return GDK_TEXTURE (self);
}
unsigned int
gdk_dmabuf_texture_get_fourcc (GdkDmabufTexture *texture)
{
return texture->fourcc;
}
guint64
gdk_dmabuf_texture_get_modifier (GdkDmabufTexture *texture)
{
return texture->modifier;
}
unsigned int
gdk_dmabuf_texture_get_offset (GdkDmabufTexture *texture,
int plane)
{
return texture->offset[plane];
}
unsigned int
gdk_dmabuf_texture_get_stride (GdkDmabufTexture *texture,
int plane)
{
return texture->stride[plane];
}
int
gdk_dmabuf_texture_get_fd (GdkDmabufTexture *texture,
int plane)
{
return texture->fd[plane];
}
#endif /* __linux__ */

43
gdk/gdkdmabuftexture.h Normal file
View File

@@ -0,0 +1,43 @@
/* gdkdmabuftexture.h
*
* 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/>.
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
#include <gdk/gdktexture.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_TEXTURE (gdk_dmabuf_texture_get_type ())
#define GDK_DMABUF_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_DMABUF_TEXTURE, GdkDmabufTexture))
#define GDK_IS_DMABUF_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_DMABUF_TEXTURE))
typedef struct _GdkDmabufTexture GdkDmabufTexture;
typedef struct _GdkDmabufTextureClass GdkDmabufTextureClass;
GDK_AVAILABLE_IN_4_14
GType gdk_dmabuf_texture_get_type (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDmabufTexture, g_object_unref)
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,109 @@
/*
* 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.1 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/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdktypes.h>
G_BEGIN_DECLS
#define GDK_TYPE_DMABUF_TEXTURE_BUILDER (gdk_dmabuf_texture_builder_get_type ())
GDK_AVAILABLE_IN_4_14
GDK_DECLARE_INTERNAL_TYPE (GdkDmabufTextureBuilder, gdk_dmabuf_texture_builder, GDK, DMABUF_TEXTURE_BUILDER, GObject)
GDK_AVAILABLE_IN_4_14
GdkDmabufTextureBuilder *gdk_dmabuf_texture_builder_new (void);
GDK_AVAILABLE_IN_4_14
GdkDisplay * gdk_dmabuf_texture_builder_get_display (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_display (GdkDmabufTextureBuilder *self,
GdkDisplay *display);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_width (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_width (GdkDmabufTextureBuilder *self,
unsigned int width);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_height (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_height (GdkDmabufTextureBuilder *self,
unsigned int height);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_fourcc (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_fourcc (GdkDmabufTextureBuilder *self,
unsigned int fourcc);
GDK_AVAILABLE_IN_4_14
guint64 gdk_dmabuf_texture_builder_get_modifier (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_modifier (GdkDmabufTextureBuilder *self,
guint64 modifier);
GDK_AVAILABLE_IN_4_14
int gdk_dmabuf_texture_builder_get_fd (GdkDmabufTextureBuilder *self,
int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_fd (GdkDmabufTextureBuilder *self,
int plane,
int fd);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_stride (GdkDmabufTextureBuilder *self,
int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_stride (GdkDmabufTextureBuilder *self,
int plane,
unsigned int stride);
GDK_AVAILABLE_IN_4_14
unsigned int gdk_dmabuf_texture_builder_get_offset (GdkDmabufTextureBuilder *self,
int plane) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_offset (GdkDmabufTextureBuilder *self,
int plane,
unsigned int offset);
GDK_AVAILABLE_IN_4_14
GdkTexture * gdk_dmabuf_texture_builder_get_update_texture (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_update_texture (GdkDmabufTextureBuilder *self,
GdkTexture *texture);
GDK_AVAILABLE_IN_4_14
cairo_region_t * gdk_dmabuf_texture_builder_get_update_region (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
void gdk_dmabuf_texture_builder_set_update_region (GdkDmabufTextureBuilder *self,
cairo_region_t *region);
GDK_AVAILABLE_IN_4_14
GdkTexture * gdk_dmabuf_texture_builder_build (GdkDmabufTextureBuilder *self,
GDestroyNotify destroy,
gpointer data);
G_END_DECLS

View File

@@ -0,0 +1,24 @@
#pragma once
#include "gdkdmabuftexture.h"
#include "gdkdmabuftexturebuilder.h"
#include "gdktextureprivate.h"
G_BEGIN_DECLS
GdkTexture * gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
GDestroyNotify destroy,
gpointer data);
unsigned int gdk_dmabuf_texture_get_fourcc (GdkDmabufTexture *texture);
guint64 gdk_dmabuf_texture_get_modifier (GdkDmabufTexture *texture);
int gdk_dmabuf_texture_get_fd (GdkDmabufTexture *texture,
int plane);
unsigned int gdk_dmabuf_texture_get_offset (GdkDmabufTexture *texture,
int plane);
unsigned int gdk_dmabuf_texture_get_stride (GdkDmabufTexture *texture,
int plane);
G_END_DECLS

View File

@@ -17,6 +17,8 @@ gdk_public_sources = files([
'gdkdevicetool.c',
'gdkdisplay.c',
'gdkdisplaymanager.c',
'gdkdmabuftexture.c',
'gdkdmabuftexturebuilder.c',
'gdkdrag.c',
'gdkdragsurface.c',
'gdkdragsurfacesize.c',
@@ -79,6 +81,8 @@ gdk_public_headers = files([
'gdkdisplay.h',
'gdkdisplaymanager.h',
'gdkdrag.h',
'gdkdmabuftexture.h',
'gdkdmabuftexturebuilder.h',
'gdkdragsurfacesize.h',
'gdkdrawcontext.h',
'gdkdrop.h',

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"
@@ -298,7 +300,7 @@ wl_shm_format (void *data,
char buf[10];
#endif
GDK_DEBUG (MISC, "supported pixel format %s (0x%X)",
GDK_DEBUG (MISC, "supported shm pixel format %s (0x%X)",
get_format_name (format, buf), (guint) format);
}
@@ -306,6 +308,93 @@ 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, " %c%c%c%c:%#lx", f & 0xff, (f >> 8) & 0xff, (f >> 16) & 0xff, (f >> 24) & 0xff, 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 +471,18 @@ 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)
{
display_wayland->linux_dmabuf =
wl_registry_bind (display_wayland->wl_registry, id,
&zwp_linux_dmabuf_v1_interface,
MIN (version, 4));
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 +827,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);

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;

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 = []

View File

@@ -1136,7 +1136,12 @@ gsk_gl_driver_lookup_shader (GskGLDriver *self,
return program;
}
#if 0
void
gsk_gl_driver_save_texture_to_png (GskGLDriver *driver,
int texture_id,
int width,
int height,
const char *filename);
void
gsk_gl_driver_save_texture_to_png (GskGLDriver *driver,
int texture_id,
@@ -1160,6 +1165,7 @@ gsk_gl_driver_save_texture_to_png (GskGLDriver *driver,
g_object_unref (builder);
}
#if 0
void
gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
const char *directory)

View File

@@ -42,6 +42,10 @@ GSK_GL_DEFINE_PROGRAM (cross_fade,
GSK_GL_ADD_UNIFORM (1, CROSS_FADE_PROGRESS, u_progress)
GSK_GL_ADD_UNIFORM (2, CROSS_FADE_SOURCE2, u_source2))
GSK_GL_DEFINE_PROGRAM (dmabuf,
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("dmabuf.glsl")),
GSK_GL_ADD_UNIFORM (1, DMABUF_SOURCE, u_source_dmabuf))
GSK_GL_DEFINE_PROGRAM (filled_border,
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("filled_border.glsl")),
GSK_GL_ADD_UNIFORM (1, FILLED_BORDER_WIDTHS, u_widths)

View File

@@ -30,6 +30,8 @@
#include <gsk/gskglshaderprivate.h>
#include <gdk/gdktextureprivate.h>
#include <gdk/gdkmemorytextureprivate.h>
#include <gdk/gdkdmabuftextureprivate.h>
#include <gdk/gdkdisplayprivate.h>
#include <gsk/gsktransformprivate.h>
#include <gsk/gskroundedrectprivate.h>
#include <gsk/gskrectprivate.h>
@@ -43,10 +45,13 @@
#include "gskglprogramprivate.h"
#include "gskglrenderjobprivate.h"
#include "gskglshadowlibraryprivate.h"
#include "gskdebugprivate.h"
#include "ninesliceprivate.h"
#include "fp16private.h"
#include <epoxy/egl.h>
#define ORTHO_NEAR_PLANE -10000
#define ORTHO_FAR_PLANE 10000
#define MAX_GRADIENT_STOPS 6
@@ -3562,6 +3567,164 @@ gsk_gl_render_job_visit_gl_shader_node (GskGLRenderJob *job,
}
}
static unsigned int
import_dmabuf_texture (GskGLRenderJob *job,
GdkTexture *texture)
{
GdkDmabufTexture *dmabuf_texture = GDK_DMABUF_TEXTURE (texture);
GdkGLContext *context = job->command_queue->context;
GdkDisplay *display = gdk_gl_context_get_display (context);
EGLDisplay egl_display;
EGLint attribs[64];
EGLImage image;
guint texture_id;
int i;
GSK_DEBUG (OPENGL, "Importing dma-buf into GL via EGLImage");
egl_display = gdk_display_get_egl_display (display);
if (egl_display == NULL)
{
g_warning ("Can't import dmabufs when not using EGL");
return 0;
}
i = 0;
attribs[i++] = EGL_WIDTH;
attribs[i++] = gdk_texture_get_width (texture);
attribs[i++] = EGL_HEIGHT;
attribs[i++] = gdk_texture_get_height (texture);
attribs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[i++] = gdk_dmabuf_texture_get_fourcc (dmabuf_texture);
#define ADD_PLANE_ATTRIBUTES(plane) \
if (gdk_dmabuf_texture_get_fd (dmabuf_texture, plane) != -1 || gdk_dmabuf_texture_get_offset (dmabuf_texture, plane) != 0) \
{ \
attribs[i++] = EGL_DMA_BUF_PLANE ## plane ## _FD_EXT; \
attribs[i++] = gdk_dmabuf_texture_get_fd (dmabuf_texture, plane); \
attribs[i++] = EGL_DMA_BUF_PLANE ## plane ## _MODIFIER_LO_EXT; \
attribs[i++] = gdk_dmabuf_texture_get_modifier (dmabuf_texture) & 0xFFFFFFFF; \
attribs[i++] = EGL_DMA_BUF_PLANE ## plane ## _MODIFIER_HI_EXT; \
attribs[i++] = gdk_dmabuf_texture_get_modifier (dmabuf_texture) >> 32; \
attribs[i++] = EGL_DMA_BUF_PLANE ## plane ## _PITCH_EXT; \
attribs[i++] = gdk_dmabuf_texture_get_stride (dmabuf_texture, plane); \
attribs[i++] = EGL_DMA_BUF_PLANE ## plane ## _OFFSET_EXT; \
attribs[i++] = gdk_dmabuf_texture_get_offset (dmabuf_texture, plane); \
}
ADD_PLANE_ATTRIBUTES (0)
ADD_PLANE_ATTRIBUTES (1)
ADD_PLANE_ATTRIBUTES (2)
ADD_PLANE_ATTRIBUTES (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)
{
g_warning ("Failed to create EGL image: %#x\n", eglGetError ());
return 0;
}
gdk_gl_context_make_current (context);
glGenTextures (1, &texture_id);
glBindTexture (GL_TEXTURE_EXTERNAL_OES, texture_id);
glEGLImageTargetTexture2DOES (GL_TEXTURE_EXTERNAL_OES, image);
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
eglDestroyImageKHR (egl_display, image);
return texture_id;
}
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 } };
}
extern void
gsk_gl_driver_save_texture_to_png (GskGLDriver *driver,
int texture_id,
int width,
int height,
const char *filename);
static void
gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
GdkTexture *texture,
@@ -3570,6 +3733,56 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
{
GdkGLTexture *gl_texture = NULL;
if (GDK_IS_DMABUF_TEXTURE (texture))
{
unsigned int texture_id;
GskGLRenderTarget *render_target;
int width, height;
int prev_fbo;
GskGLProgram *program;
g_print ("importing YUYV\n");
width = gdk_texture_get_width (GDK_TEXTURE (texture));
height = gdk_texture_get_height (GDK_TEXTURE (texture));
texture_id = import_dmabuf_texture (job, texture);
gsk_gl_driver_save_texture_to_png (job->driver, texture_id, width, height, "tex.png");
gsk_gl_driver_create_render_target (job->driver, width, height, GL_RGBA8, &render_target);
prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->driver->command_queue, render_target->framebuffer_id);
gsk_gl_command_queue_clear (job->driver->command_queue, 0, &GRAPHENE_RECT_INIT (0, 0, width, height));
program = job->driver->dmabuf_no_clip;
gsk_gl_command_queue_begin_draw (job->driver->command_queue,
program->program_info,
width, height);
set_projection_for_size (job->driver, program, width, height);
set_viewport_for_size (job->driver, program, width, height);
reset_modelview (job->driver, program);
gsk_gl_program_set_uniform_texture (program,
UNIFORM_DMABUF_SOURCE, 0,
GL_TEXTURE_2D, GL_TEXTURE0, texture_id);
draw_rect (job->driver->command_queue, 0, 0, width, height);
gsk_gl_command_queue_end_draw (job->driver->command_queue);
gsk_gl_command_queue_bind_framebuffer (job->driver->command_queue, prev_fbo);
offscreen->texture_id = gsk_gl_driver_release_render_target (job->driver, render_target, FALSE);
init_full_texture_region (offscreen);
offscreen->has_mipmap = FALSE;
glDeleteTextures (1, &texture_id);
return;
}
if (GDK_IS_GL_TEXTURE (texture))
gl_texture = GDK_GL_TEXTURE (texture);

View File

@@ -0,0 +1,19 @@
// VERTEX_SHADER:
// dmabuf.glsl
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// dmabuf.glsl
uniform samplerExternalOES u_source_dmabuf;
void main() {
vec4 rgb = texture2D(u_source_dmabuf, vUv);
gskSetOutputColor(rgb);
}

View File

@@ -1,3 +1,5 @@
#extension GL_OES_EGL_image_external : require
#ifndef GSK_LEGACY
precision highp float;
#endif

View File

@@ -20,6 +20,7 @@ gsk_private_gl_shaders = [
'gl/resources/custom.glsl',
'gl/resources/filled_border.glsl',
'gl/resources/mask.glsl',
'gl/resources/dmabuf.glsl',
]
gsk_public_sources = files([