Compare commits
10 Commits
wip/matthi
...
dmabuf-tex
Author | SHA1 | Date | |
---|---|---|---|
|
79835c7e57 | ||
|
1740aeab40 | ||
|
589a662052 | ||
|
349e0156b3 | ||
|
a9fb224b8d | ||
|
e2162c13ee | ||
|
17103d765f | ||
|
c1bf9e3320 | ||
|
6f913eac15 | ||
|
f9b0b55361 |
@@ -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>
|
||||
|
106
gdk/gdkdisplay.c
106
gdk/gdkdisplay.c
@@ -37,6 +37,7 @@
|
||||
#include "gdkmonitorprivate.h"
|
||||
#include "gdkrectangle.h"
|
||||
#include "gdkvulkancontext.h"
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#include <epoxy/egl.h>
|
||||
@@ -404,6 +405,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 +1262,68 @@ gdk_display_create_vulkan_context (GdkDisplay *self,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* To support a drm format, we must be able to import it into GL
|
||||
* using the relevant EGL extensions, and download it into a memory
|
||||
* texture, possibly doing format conversion with shaders (in GSK).
|
||||
*/
|
||||
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;
|
||||
|
||||
if (!gdk_dmabuf_texture_may_support ((unsigned int)formats[i]))
|
||||
continue;
|
||||
|
||||
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, "Supported 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 +1365,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 +1893,43 @@ 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 on this display.
|
||||
*
|
||||
* Note that GTK uses EGL to convert some formats, so the list
|
||||
* of supported formats depends on the GL API that is used on
|
||||
* the 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)
|
||||
{
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
397
gdk/gdkdmabuftexture.c
Normal file
397
gdk/gdkdmabuftexture.c
Normal file
@@ -0,0 +1,397 @@
|
||||
/* 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 <gsk/gsk.h>
|
||||
#include <gsk/gl/gskglrenderer.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;
|
||||
|
||||
unsigned int n_planes;
|
||||
|
||||
/* Per-plane properties */
|
||||
int fds[4];
|
||||
unsigned int strides[4];
|
||||
unsigned int offsets[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);
|
||||
}
|
||||
|
||||
typedef struct _GdkDrmFormatInfo GdkDrmFormatInfo;
|
||||
struct _GdkDrmFormatInfo
|
||||
{
|
||||
unsigned int fourcc;
|
||||
GdkMemoryFormat memory_format;
|
||||
gboolean requires_gl;
|
||||
};
|
||||
|
||||
static GdkDrmFormatInfo supported_formats[] = {
|
||||
{ DRM_FORMAT_RGB888, GDK_MEMORY_R8G8B8, FALSE },
|
||||
{ DRM_FORMAT_BGR888, GDK_MEMORY_B8G8R8, FALSE },
|
||||
{ DRM_FORMAT_ARGB8888, GDK_MEMORY_A8R8G8B8_PREMULTIPLIED, FALSE },
|
||||
{ DRM_FORMAT_RGBA8888, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, FALSE },
|
||||
{ DRM_FORMAT_BGRA8888, GDK_MEMORY_B8G8R8A8_PREMULTIPLIED, FALSE },
|
||||
{ DRM_FORMAT_ABGR16161616F, GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED, FALSE },
|
||||
{ DRM_FORMAT_YUYV, GDK_MEMORY_DEFAULT, TRUE },
|
||||
{ DRM_FORMAT_NV12, GDK_MEMORY_DEFAULT, TRUE },
|
||||
{ DRM_FORMAT_P010, GDK_MEMORY_R16G16B16A16_PREMULTIPLIED, TRUE },
|
||||
{ DRM_FORMAT_YUV420, GDK_MEMORY_DEFAULT, TRUE },
|
||||
};
|
||||
|
||||
static GdkDrmFormatInfo *
|
||||
get_drm_format_info (unsigned int fourcc)
|
||||
{
|
||||
for (int i = 0; i < G_N_ELEMENTS (supported_formats); i++)
|
||||
{
|
||||
if (supported_formats[i].fourcc == fourcc)
|
||||
return &supported_formats[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_dmabuf_texture_may_support (unsigned int fourcc)
|
||||
{
|
||||
return get_drm_format_info (fourcc) != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
do_indirect_download (GdkDmabufTexture *self,
|
||||
GdkMemoryFormat format,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GskRenderer *renderer;
|
||||
int width, height;
|
||||
GskRenderNode *node;
|
||||
GdkTexture *gl_texture;
|
||||
GdkTextureDownloader *downloader;
|
||||
GError *error = NULL;
|
||||
|
||||
GDK_DEBUG (MISC, "Using gsk_renderer_render_texture 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)));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
width = gdk_texture_get_width (GDK_TEXTURE (self));
|
||||
height = gdk_texture_get_height (GDK_TEXTURE (self));
|
||||
|
||||
node = gsk_texture_node_new (GDK_TEXTURE (self), &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
gl_texture = gsk_renderer_render_texture (renderer, node, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
gsk_render_node_unref (node);
|
||||
|
||||
gsk_renderer_unrealize (renderer);
|
||||
g_object_unref (renderer);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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->strides[0];
|
||||
size = self->strides[0] * height;
|
||||
|
||||
if (ioctl (self->fds[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->fds[0], self->offsets[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->fds[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 src_format = gdk_texture_get_format (texture);
|
||||
GdkDrmFormatInfo *info;
|
||||
|
||||
info = get_drm_format_info (self->fourcc);
|
||||
|
||||
if (info->requires_gl || self->n_planes > 1)
|
||||
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->strides[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->fds[0] = self->fds[1] = self->fds[2] = self->fds[3] = -1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
display_supports_format (GdkDisplay *display,
|
||||
unsigned int fourcc,
|
||||
guint64 modifier)
|
||||
{
|
||||
const GdkDmabufFormat *formats;
|
||||
gsize n_formats;
|
||||
|
||||
if (!display)
|
||||
return FALSE;
|
||||
|
||||
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)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data)
|
||||
{
|
||||
GdkDmabufTexture *self;
|
||||
GdkTexture *update_texture;
|
||||
GdkDisplay *display = gdk_dmabuf_texture_builder_get_display (builder);
|
||||
uint32_t fourcc = gdk_dmabuf_texture_builder_get_fourcc (builder);
|
||||
uint64_t modifier = gdk_dmabuf_texture_builder_get_modifier (builder);
|
||||
unsigned int n_planes = gdk_dmabuf_texture_builder_get_n_planes (builder);
|
||||
GdkDrmFormatInfo *info;
|
||||
|
||||
info = get_drm_format_info (fourcc);
|
||||
|
||||
if (!info ||
|
||||
((info->requires_gl || n_planes > 1) && !display_supports_format (display, fourcc, modifier)))
|
||||
{
|
||||
g_warning ("Unsupported dmabuf format %c%c%c%c:%#lx",
|
||||
fourcc & 0xff, (fourcc >> 8) & 0xff, (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff, modifier);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GDK_DEBUG (MISC, "Dmabuf texture in format %c%c%c%c:%#lx",
|
||||
fourcc & 0xff, (fourcc >> 8) & 0xff, (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff, modifier);
|
||||
|
||||
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 = info->memory_format;
|
||||
|
||||
g_set_object (&self->display, display);
|
||||
|
||||
self->fourcc = fourcc;
|
||||
self->modifier = modifier;
|
||||
self->n_planes = n_planes;
|
||||
|
||||
memcpy (self->fds, gdk_dmabuf_texture_builder_get_fds (builder), sizeof (int) * 4);
|
||||
memcpy (self->strides, gdk_dmabuf_texture_builder_get_strides (builder), sizeof (unsigned int) * 4);
|
||||
memcpy (self->offsets, gdk_dmabuf_texture_builder_get_offsets (builder), sizeof (unsigned int) * 4);
|
||||
|
||||
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_n_planes (GdkDmabufTexture *texture)
|
||||
{
|
||||
return texture->n_planes;
|
||||
}
|
||||
|
||||
int *
|
||||
gdk_dmabuf_texture_get_fds (GdkDmabufTexture *texture)
|
||||
{
|
||||
return texture->fds;
|
||||
}
|
||||
|
||||
unsigned int *
|
||||
gdk_dmabuf_texture_get_strides (GdkDmabufTexture *texture)
|
||||
{
|
||||
return texture->strides;
|
||||
}
|
||||
|
||||
unsigned int *
|
||||
gdk_dmabuf_texture_get_offsets (GdkDmabufTexture *texture)
|
||||
{
|
||||
return texture->offsets;
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
43
gdk/gdkdmabuftexture.h
Normal file
43
gdk/gdkdmabuftexture.h
Normal 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
|
1151
gdk/gdkdmabuftexturebuilder.c
Normal file
1151
gdk/gdkdmabuftexturebuilder.c
Normal file
File diff suppressed because it is too large
Load Diff
115
gdk/gdkdmabuftexturebuilder.h
Normal file
115
gdk/gdkdmabuftexturebuilder.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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
|
||||
unsigned int gdk_dmabuf_texture_builder_get_n_planes (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
void gdk_dmabuf_texture_builder_set_n_planes (GdkDmabufTextureBuilder *self,
|
||||
unsigned int n_planes);
|
||||
|
||||
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
|
||||
|
29
gdk/gdkdmabuftextureprivate.h
Normal file
29
gdk/gdkdmabuftextureprivate.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkdmabuftexture.h"
|
||||
|
||||
#include "gdkdmabuftexturebuilder.h"
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
int * gdk_dmabuf_texture_builder_get_fds (GdkDmabufTextureBuilder *builder);
|
||||
unsigned int * gdk_dmabuf_texture_builder_get_offsets (GdkDmabufTextureBuilder *builder);
|
||||
unsigned int * gdk_dmabuf_texture_builder_get_strides (GdkDmabufTextureBuilder *builder);
|
||||
|
||||
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);
|
||||
unsigned int gdk_dmabuf_texture_get_n_planes (GdkDmabufTexture *texture);
|
||||
int * gdk_dmabuf_texture_get_fds (GdkDmabufTexture *texture);
|
||||
unsigned int * gdk_dmabuf_texture_get_offsets (GdkDmabufTexture *texture);
|
||||
unsigned int * gdk_dmabuf_texture_get_strides (GdkDmabufTexture *texture);
|
||||
|
||||
gboolean gdk_dmabuf_texture_may_support (unsigned int fourcc);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -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',
|
||||
|
@@ -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,16 @@ gdk_registry_handle_global (void *data,
|
||||
wl_registry_bind (display_wayland->wl_registry, id, &wl_shm_interface, 1);
|
||||
wl_shm_add_listener (display_wayland->shm, &wl_shm_listener, display_wayland);
|
||||
}
|
||||
else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0 && version >= 4)
|
||||
{
|
||||
display_wayland->linux_dmabuf =
|
||||
wl_registry_bind (display_wayland->wl_registry, id, &zwp_linux_dmabuf_v1_interface, version);
|
||||
display_wayland->linux_dmabuf_feedback =
|
||||
zwp_linux_dmabuf_v1_get_default_feedback (display_wayland->linux_dmabuf);
|
||||
zwp_linux_dmabuf_feedback_v1_add_listener (display_wayland->linux_dmabuf_feedback,
|
||||
&linux_dmabuf_feedback_listener, display_wayland);
|
||||
_gdk_wayland_display_async_roundtrip (display_wayland);
|
||||
}
|
||||
else if (strcmp (interface, "xdg_wm_base") == 0)
|
||||
{
|
||||
display_wayland->xdg_wm_base_id = id;
|
||||
@@ -726,6 +825,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);
|
||||
|
@@ -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;
|
||||
|
@@ -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 = []
|
||||
|
@@ -42,9 +42,12 @@
|
||||
#include <gdk/gdkmemorytextureprivate.h>
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
|
||||
#include <gdk/gdkdmabuftextureprivate.h>
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
G_DEFINE_TYPE (GskGLDriver, gsk_gl_driver, G_TYPE_OBJECT)
|
||||
|
||||
static guint
|
||||
@@ -224,6 +227,8 @@ 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) \
|
||||
@@ -238,6 +243,7 @@ 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)
|
||||
{
|
||||
@@ -373,6 +379,11 @@ 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; \
|
||||
@@ -399,8 +410,8 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
|
||||
g_steal_pointer (&program); \
|
||||
} G_STMT_END;
|
||||
# include "gskglprograms.defs"
|
||||
#undef GSK_GL_DEFINE_PROGRAM_CLIP
|
||||
#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
|
||||
@@ -703,6 +714,306 @@ gsk_gl_driver_cache_texture (GskGLDriver *self,
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
import_dmabuf_planes (GskGLDriver *self,
|
||||
int width,
|
||||
int height,
|
||||
unsigned int fourcc,
|
||||
guint64 modifier,
|
||||
unsigned int n_planes,
|
||||
int *fds,
|
||||
unsigned int *strides,
|
||||
unsigned int *offsets)
|
||||
{
|
||||
GdkGLContext *context = self->command_queue->context;
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
EGLDisplay egl_display;
|
||||
EGLint attribs[64];
|
||||
EGLImage image;
|
||||
guint texture_id;
|
||||
int i;
|
||||
|
||||
g_assert (1 <= n_planes && n_planes <= 4);
|
||||
|
||||
GSK_DEBUG (OPENGL,
|
||||
"Importing dma-buf into GL via EGLImage. Format %c%c%c%c:%#lx",
|
||||
fourcc & 0xff, (fourcc >> 8) & 0xff, (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff, modifier);
|
||||
|
||||
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++] = width;
|
||||
attribs[i++] = EGL_HEIGHT;
|
||||
attribs[i++] = height;
|
||||
attribs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||
attribs[i++] = fourcc;
|
||||
|
||||
#define ADD_PLANE(plane) \
|
||||
{ \
|
||||
if (modifier != DRM_FORMAT_MOD_INVALID) \
|
||||
{ \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_MODIFIER_LO_EXT; \
|
||||
attribs[i++] = modifier & 0xFFFFFFFF; \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ## _MODIFIER_HI_EXT; \
|
||||
attribs[i++] = modifier >> 32; \
|
||||
} \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_FD_EXT; \
|
||||
attribs[i++] = fds[plane]; \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_PITCH_EXT; \
|
||||
attribs[i++] = strides[plane]; \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_OFFSET_EXT; \
|
||||
attribs[i++] = offsets[plane]; \
|
||||
}
|
||||
|
||||
ADD_PLANE (0);
|
||||
|
||||
if (n_planes > 1) ADD_PLANE (1);
|
||||
if (n_planes > 2) ADD_PLANE (2);
|
||||
if (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)
|
||||
{
|
||||
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_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
|
||||
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 } };
|
||||
}
|
||||
|
||||
typedef struct _TextureFormatInfo TextureFormatInfo;
|
||||
struct _TextureFormatInfo
|
||||
{
|
||||
int n_planes;
|
||||
unsigned int subformats[3];
|
||||
int plane_indices[3];
|
||||
int hsub[3];
|
||||
int vsub[3];
|
||||
int uniforms[3];
|
||||
};
|
||||
|
||||
static TextureFormatInfo texture_format_info[] = {
|
||||
{ .n_planes = 2,
|
||||
.subformats = { DRM_FORMAT_GR88, DRM_FORMAT_ARGB8888 },
|
||||
.plane_indices = { 0, 0 },
|
||||
.hsub = { 1, 2 },
|
||||
.vsub = { 1, 1 },
|
||||
.uniforms = { UNIFORM_SHARED_SOURCE, UNIFORM_YUYV_SOURCE2 },
|
||||
},
|
||||
{ .n_planes = 2,
|
||||
.subformats = { DRM_FORMAT_R8, DRM_FORMAT_GR88 },
|
||||
.plane_indices = { 0, 1 },
|
||||
.hsub = { 1, 2 },
|
||||
.vsub = { 1, 2 },
|
||||
.uniforms = { UNIFORM_SHARED_SOURCE, UNIFORM_NV12_SOURCE2 },
|
||||
},
|
||||
{ .n_planes = 2,
|
||||
.subformats = { DRM_FORMAT_R16, DRM_FORMAT_GR1616 },
|
||||
.plane_indices = { 0, 1 },
|
||||
.hsub = { 1, 2 },
|
||||
.vsub = { 1, 2 },
|
||||
.uniforms = { UNIFORM_SHARED_SOURCE, UNIFORM_NV12_SOURCE2 },
|
||||
},
|
||||
{ .n_planes = 3,
|
||||
.subformats = { DRM_FORMAT_R8, DRM_FORMAT_R8, DRM_FORMAT_R8 },
|
||||
.plane_indices = { 0, 1, 2 },
|
||||
.hsub = { 1, 2, 2 },
|
||||
.vsub = { 1, 2, 2 },
|
||||
.uniforms = { UNIFORM_SHARED_SOURCE, UNIFORM_YUV420_SOURCE2, UNIFORM_YUV420_SOURCE3 },
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static unsigned int release_render_target (GskGLDriver *self,
|
||||
GskGLRenderTarget *render_target,
|
||||
gboolean release_texture,
|
||||
gboolean cache_texture);
|
||||
|
||||
static unsigned int
|
||||
gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
|
||||
GdkDmabufTexture *texture)
|
||||
{
|
||||
int width, height;
|
||||
guint64 modifier;
|
||||
TextureFormatInfo *info;
|
||||
GskGLProgram *program;
|
||||
GskGLRenderTarget *render_target;
|
||||
guint prev_fbo;
|
||||
|
||||
width = gdk_texture_get_width (GDK_TEXTURE (texture));
|
||||
height = gdk_texture_get_height (GDK_TEXTURE (texture));
|
||||
modifier = gdk_dmabuf_texture_get_modifier (texture);
|
||||
|
||||
if (gdk_dmabuf_texture_get_fourcc (texture) == DRM_FORMAT_YUYV)
|
||||
{
|
||||
info = &texture_format_info[0];
|
||||
program = self->yuyv;
|
||||
}
|
||||
else if (gdk_dmabuf_texture_get_fourcc (texture) == DRM_FORMAT_NV12)
|
||||
{
|
||||
info = &texture_format_info[1];
|
||||
program = self->nv12;
|
||||
}
|
||||
else if (gdk_dmabuf_texture_get_fourcc (texture) == DRM_FORMAT_P010)
|
||||
{
|
||||
info = &texture_format_info[2];
|
||||
program = self->nv12;
|
||||
}
|
||||
else if (gdk_dmabuf_texture_get_fourcc (texture) == DRM_FORMAT_YUV420)
|
||||
{
|
||||
info = &texture_format_info[3];
|
||||
program = self->yuv420;
|
||||
}
|
||||
else
|
||||
{
|
||||
return import_dmabuf_planes (self,
|
||||
gdk_texture_get_width (GDK_TEXTURE (texture)),
|
||||
gdk_texture_get_height (GDK_TEXTURE (texture)),
|
||||
gdk_dmabuf_texture_get_fourcc (texture),
|
||||
gdk_dmabuf_texture_get_modifier (texture),
|
||||
gdk_dmabuf_texture_get_n_planes (texture),
|
||||
gdk_dmabuf_texture_get_fds (texture),
|
||||
gdk_dmabuf_texture_get_strides (texture),
|
||||
gdk_dmabuf_texture_get_offsets (texture));
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
for (int i = 0; i < info->n_planes; i++)
|
||||
{
|
||||
int plane = info->plane_indices[i];
|
||||
int texture_id = import_dmabuf_planes (self,
|
||||
width / info->hsub[i],
|
||||
height / info->vsub[i],
|
||||
info->subformats[i],
|
||||
modifier,
|
||||
1,
|
||||
gdk_dmabuf_texture_get_fds (texture) + plane,
|
||||
gdk_dmabuf_texture_get_strides (texture) + plane,
|
||||
gdk_dmabuf_texture_get_offsets (texture) + plane);
|
||||
|
||||
gsk_gl_program_set_uniform_texture (program,
|
||||
info->uniforms[i], 0,
|
||||
GL_TEXTURE_2D, GL_TEXTURE0 + i, texture_id);
|
||||
|
||||
gsk_gl_driver_autorelease_texture (self, 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_gl_driver_load_texture:
|
||||
* @self: a `GdkTexture`
|
||||
@@ -759,7 +1070,11 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
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))
|
||||
{
|
||||
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
|
||||
GdkGLContext *texture_context = gdk_gl_texture_get_context (gl_texture);
|
||||
@@ -788,9 +1103,8 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
t = gsk_gl_texture_new (texture_id,
|
||||
width, height,
|
||||
self->current_frame_id);
|
||||
t = gsk_gl_texture_new (texture_id, width, height, self->current_frame_id);
|
||||
|
||||
if (ensure_mipmap)
|
||||
{
|
||||
glBindTexture (GL_TEXTURE_2D, t->texture_id);
|
||||
@@ -962,6 +1276,47 @@ 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`
|
||||
@@ -987,36 +1342,7 @@ gsk_gl_driver_release_render_target (GskGLDriver *self,
|
||||
GskGLRenderTarget *render_target,
|
||||
gboolean release_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
|
||||
{
|
||||
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;
|
||||
return release_render_target (self, render_target, release_texture, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -69,7 +69,9 @@ 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
|
||||
@@ -116,10 +118,13 @@ 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;
|
||||
|
||||
|
@@ -87,3 +87,22 @@ 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 (yuyv,
|
||||
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("yuyv.glsl")),
|
||||
GSK_GL_ADD_UNIFORM (1, YUYV_SOURCE2, u_source2))
|
||||
|
||||
GSK_GL_DEFINE_PROGRAM_NO_CLIP (nv12,
|
||||
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("nv12.glsl")),
|
||||
GSK_GL_ADD_UNIFORM (1, NV12_SOURCE2, u_source2))
|
||||
|
||||
GSK_GL_DEFINE_PROGRAM_NO_CLIP (yuv420,
|
||||
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("yuv420.glsl")),
|
||||
GSK_GL_ADD_UNIFORM (1, YUV420_SOURCE2, u_source2)
|
||||
GSK_GL_ADD_UNIFORM (2, YUV420_SOURCE3, u_source2))
|
||||
|
@@ -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,15 @@
|
||||
#include "gskglprogramprivate.h"
|
||||
#include "gskglrenderjobprivate.h"
|
||||
#include "gskglshadowlibraryprivate.h"
|
||||
#include "gskdebugprivate.h"
|
||||
|
||||
#include "ninesliceprivate.h"
|
||||
#include "fp16private.h"
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
#define ORTHO_NEAR_PLANE -10000
|
||||
#define ORTHO_FAR_PLANE 10000
|
||||
#define MAX_GRADIENT_STOPS 6
|
||||
@@ -3568,16 +3575,11 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
|
||||
gboolean ensure_mipmap,
|
||||
GskGLRenderOffscreen *offscreen)
|
||||
{
|
||||
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) &&
|
||||
!gl_texture)
|
||||
!(GDK_IS_GL_TEXTURE (texture) || GDK_IS_DMABUF_TEXTURE (texture)))
|
||||
{
|
||||
const GskGLIconData *icon_data;
|
||||
|
||||
@@ -3591,16 +3593,18 @@ 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 (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);
|
||||
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));
|
||||
|
||||
offscreen->texture_id = gsk_gl_driver_load_texture (job->driver, texture, ensure_mipmap);
|
||||
init_full_texture_region (offscreen);
|
||||
offscreen->has_mipmap = ensure_mipmap;
|
||||
|
||||
if (gl_texture && offscreen->texture_id == gdk_gl_texture_get_id (gl_texture))
|
||||
offscreen->sync = gdk_gl_texture_get_sync (gl_texture);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
49
gsk/gl/resources/nv12.glsl
Normal file
49
gsk/gl/resources/nv12.glsl
Normal file
@@ -0,0 +1,49 @@
|
||||
// VERTEX_SHADER:
|
||||
// nv12.glsl
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
vUv = vec2(aUv.x, aUv.y);
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
// nv12.glsl
|
||||
|
||||
uniform sampler2D u_source2;
|
||||
|
||||
vec4 yuv_to_rgb(vec4 yuv)
|
||||
{
|
||||
vec4 res;
|
||||
|
||||
float Y = 1.16438356 * (yuv.x - 0.0625);
|
||||
float su = yuv.y - 0.5;
|
||||
float sv = yuv.z - 0.5;
|
||||
|
||||
res.r = Y + 1.59602678 * sv;
|
||||
res.g = Y - 0.39176229 * su - 0.81296764 * sv;
|
||||
res.b = Y + 2.01723214 * su;
|
||||
|
||||
res.rgb *= yuv.w;
|
||||
res.a = yuv.w;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* This shader converts 2-plane yuv (DRM_FORMAT_NV12 or DRM_FORMAT_P010)
|
||||
* into rgb. It assumes that the two planes have been imported separately,
|
||||
* the first one as R texture, the second one as RG.
|
||||
*/
|
||||
|
||||
void main() {
|
||||
vec4 y = GskTexture(u_source, vUv);
|
||||
vec4 uv = GskTexture(u_source2, vUv);
|
||||
|
||||
vec4 yuv;
|
||||
|
||||
yuv.x = y.x;
|
||||
yuv.yz = uv.xy;
|
||||
yuv.w = 1.0;
|
||||
|
||||
gskSetOutputColor(yuv_to_rgb(yuv));
|
||||
}
|
51
gsk/gl/resources/yuv420.glsl
Normal file
51
gsk/gl/resources/yuv420.glsl
Normal file
@@ -0,0 +1,51 @@
|
||||
// VERTEX_SHADER:
|
||||
// y_uv_to_rgba.glsl
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
vUv = vec2(aUv.x, aUv.y);
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
// y_uv_to_rgba.glsl
|
||||
|
||||
uniform sampler2D u_source2;
|
||||
uniform sampler2D u_source3;
|
||||
|
||||
vec4 yuv_to_rgb(vec4 yuv)
|
||||
{
|
||||
vec4 res;
|
||||
|
||||
float Y = 1.16438356 * (yuv.x - 0.0625);
|
||||
float su = yuv.y - 0.5;
|
||||
float sv = yuv.z - 0.5;
|
||||
|
||||
res.r = Y + 1.59602678 * sv;
|
||||
res.g = Y - 0.39176229 * su - 0.81296764 * sv;
|
||||
res.b = Y + 2.01723214 * su;
|
||||
|
||||
res.rgb *= yuv.w;
|
||||
res.a = yuv.w;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* This shader converts 3-plane yuv (DRM_FORMAT_YUY420) into rgb.
|
||||
*/
|
||||
|
||||
|
||||
void main() {
|
||||
vec4 y = GskTexture(u_source, vUv);
|
||||
vec4 u = GskTexture(u_source2, vUv);
|
||||
vec4 v = GskTexture(u_source3, vUv);
|
||||
|
||||
vec4 yuv;
|
||||
|
||||
yuv.x = y.x;
|
||||
yuv.y = u.x;
|
||||
yuv.z = v.x;
|
||||
yuv.w = 1.0;
|
||||
|
||||
gskSetOutputColor(yuv_to_rgb(yuv));
|
||||
}
|
49
gsk/gl/resources/yuyv.glsl
Normal file
49
gsk/gl/resources/yuyv.glsl
Normal file
@@ -0,0 +1,49 @@
|
||||
// VERTEX_SHADER:
|
||||
// y_xuxv_to_rgba.glsl
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
vUv = vec2(aUv.x, aUv.y);
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
// y_xuxv_to_rgba.glsl
|
||||
|
||||
uniform sampler2D u_source2;
|
||||
|
||||
vec4 yuv_to_rgb(vec4 yuv)
|
||||
{
|
||||
vec4 res;
|
||||
|
||||
float Y = 1.16438356 * (yuv.x - 0.0625);
|
||||
float su = yuv.y - 0.5;
|
||||
float sv = yuv.z - 0.5;
|
||||
|
||||
res.r = Y + 1.59602678 * sv;
|
||||
res.g = Y - 0.39176229 * su - 0.81296764 * sv;
|
||||
res.b = Y + 2.01723214 * su;
|
||||
|
||||
res.rgb *= yuv.w;
|
||||
res.a = yuv.w;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* This shader converts single-plane yuv (DRM_FORMAT_YUYV) into rgb.
|
||||
* It assumes that the buffer has been imported twice - once as RG
|
||||
* texture with full size, and once as RGBA textures with half the
|
||||
* width (to account for the subsampling).
|
||||
*/
|
||||
void main() {
|
||||
vec4 y = GskTexture(u_source, vUv);
|
||||
vec4 uv = GskTexture(u_source2, vUv);
|
||||
|
||||
vec4 yuv;
|
||||
|
||||
yuv.x = y.x;
|
||||
yuv.yz = uv.yw;
|
||||
yuv.w = 1.0;
|
||||
|
||||
gskSetOutputColor(yuv_to_rgb(yuv));
|
||||
}
|
@@ -20,6 +20,9 @@ gsk_private_gl_shaders = [
|
||||
'gl/resources/custom.glsl',
|
||||
'gl/resources/filled_border.glsl',
|
||||
'gl/resources/mask.glsl',
|
||||
'gl/resources/yuyv.glsl',
|
||||
'gl/resources/nv12.glsl',
|
||||
'gl/resources/yuv420.glsl',
|
||||
]
|
||||
|
||||
gsk_public_sources = files([
|
||||
|
Reference in New Issue
Block a user