Compare commits
110 Commits
ebassi/fix
...
subsurface
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a77fde155d | ||
|
|
004c2b8cc2 | ||
|
|
0605888ac6 | ||
|
|
ef5b1ba044 | ||
|
|
5fa7457171 | ||
|
|
f50edb6910 | ||
|
|
2d874e601c | ||
|
|
c9b83dfa1d | ||
|
|
dd7a38069f | ||
|
|
51a181af7a | ||
|
|
8fcd9bc0c4 | ||
|
|
e2edf693f5 | ||
|
|
323300e92a | ||
|
|
e688be1cff | ||
|
|
611d5cf844 | ||
|
|
51cb1aeb4e | ||
|
|
625eb508e8 | ||
|
|
2718e1715d | ||
|
|
6ddcad6b33 | ||
|
|
0c23997f70 | ||
|
|
4d1ef63009 | ||
|
|
30e14f73fa | ||
|
|
39e205aa78 | ||
|
|
f0ec1660c1 | ||
|
|
79f98f3a13 | ||
|
|
5f0557027d | ||
|
|
a579e3bc6d | ||
|
|
8f70f4b85e | ||
|
|
911198cddd | ||
|
|
ca5247a995 | ||
|
|
004a881521 | ||
|
|
65993ed0e0 | ||
|
|
a4d0a5bda5 | ||
|
|
33bc276639 | ||
|
|
06822581f7 | ||
|
|
976143fbe9 | ||
|
|
9fd4feef0c | ||
|
|
5eed13bd07 | ||
|
|
d02d45dd8d | ||
|
|
13d0e311b7 | ||
|
|
52254f755f | ||
|
|
494154beb6 | ||
|
|
adde188eca | ||
|
|
8fb0ab2b43 | ||
|
|
b8b5835fc6 | ||
|
|
463307655c | ||
|
|
d17d8e04a6 | ||
|
|
d8d1dfd8f3 | ||
|
|
f581280811 | ||
|
|
3a9aea44df | ||
|
|
e05764806a | ||
|
|
5ca65f04fe | ||
|
|
32ba1e389c | ||
|
|
beb9e0c906 | ||
|
|
98f02f6221 | ||
|
|
13848969f4 | ||
|
|
0817dfe67f | ||
|
|
9e3f537a15 | ||
|
|
612e0e29f9 | ||
|
|
e1cbc96b8c | ||
|
|
410240fe7b | ||
|
|
73cf3a92f9 | ||
|
|
dd15122ccb | ||
|
|
5299f1384f | ||
|
|
58a0e4ffaa | ||
|
|
7ab9056c11 | ||
|
|
2d9fbb16bc | ||
|
|
cbfd8542c6 | ||
|
|
7679504134 | ||
|
|
446d461ad2 | ||
|
|
5b6fcfe8c9 | ||
|
|
59ce7ab222 | ||
|
|
0992837b08 | ||
|
|
aca02916ad | ||
|
|
98e883f9b4 | ||
|
|
2c66aa0c15 | ||
|
|
8843c0d504 | ||
|
|
8858f1c9ec | ||
|
|
a1c5c20e2c | ||
|
|
1da674423d | ||
|
|
10250a0a6a | ||
|
|
c0a2f9fbc3 | ||
|
|
bd974b08b3 | ||
|
|
d289c0d4f1 | ||
|
|
f4722289f7 | ||
|
|
389af3591c | ||
|
|
008d9e5327 | ||
|
|
09723d79c6 | ||
|
|
4586af5876 | ||
|
|
193d9cd31a | ||
|
|
f29303dea7 | ||
|
|
4e47d0d71e | ||
|
|
dd8c6e9f51 | ||
|
|
65676150c4 | ||
|
|
b0e26873f6 | ||
|
|
f4a67ebcbb | ||
|
|
000c876953 | ||
|
|
b8ffceaebb | ||
|
|
148b8e5cd8 | ||
|
|
583ad47b03 | ||
|
|
b95d8ebdd3 | ||
|
|
677a601d11 | ||
|
|
194db51fba | ||
|
|
d55fa0dfef | ||
|
|
612b5416af | ||
|
|
54637ae3b3 | ||
|
|
014adb841e | ||
|
|
a5c6a40b3c | ||
|
|
402a51b876 | ||
|
|
d1e091279c |
30
NEWS
30
NEWS
@@ -1,6 +1,34 @@
|
||||
Overview of Changes in 4.13.2, xx-xx-xxxx
|
||||
Overview of Changes in 4.13.3, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
Overview of Changes in 4.13.2, 22-10-2023
|
||||
=========================================
|
||||
|
||||
* GtkPrintdialog:
|
||||
- New async-style api to replace GtkPrintOperation
|
||||
|
||||
* GtkEmojiChooser:
|
||||
- Add more languages: Bengali, Hindi, Japanese, Finnish,
|
||||
Thai and Norwegian bokmål
|
||||
|
||||
* Accessibility:
|
||||
- Fix some utf8 handling issues
|
||||
|
||||
* GDK:
|
||||
- Add support for dmabuf textures, with GdkDmabufTextureBuilder
|
||||
- Add a few more supported memory formats for textures
|
||||
|
||||
* GSK:
|
||||
- Add a fast-path for masking color
|
||||
- Add support for importing dmabuf textures
|
||||
- Handle GLES better by using some extensions
|
||||
|
||||
* Translation updates:
|
||||
Catalan
|
||||
Russian
|
||||
Turkish
|
||||
|
||||
|
||||
Overview of Changes in 4.13.1, 28-09-2023
|
||||
=========================================
|
||||
|
||||
|
||||
@@ -391,6 +391,9 @@ gdk_display_dispose (GObject *object)
|
||||
|
||||
g_queue_clear (&display->queued_events);
|
||||
|
||||
g_clear_object (&display->egl_gsk_renderer);
|
||||
g_clear_pointer (&display->egl_external_formats, gdk_dmabuf_formats_unref);
|
||||
|
||||
g_clear_object (&priv->gl_context);
|
||||
#ifdef HAVE_EGL
|
||||
g_clear_pointer (&priv->egl_display, eglTerminate);
|
||||
@@ -1770,6 +1773,10 @@ gdk_display_init_egl (GdkDisplay *self,
|
||||
epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_no_config_context");
|
||||
self->have_egl_pixel_format_float =
|
||||
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_pixel_format_float");
|
||||
self->have_egl_dma_buf_import =
|
||||
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_image_dma_buf_import_modifiers");
|
||||
self->have_egl_dma_buf_export =
|
||||
epoxy_has_egl_extension (priv->egl_display, "EGL_MESA_image_dma_buf_export");
|
||||
|
||||
if (self->have_egl_no_config_context)
|
||||
priv->egl_config_high_depth = gdk_display_create_egl_config (self,
|
||||
@@ -1839,7 +1846,7 @@ gdk_display_get_egl_display (GdkDisplay *self)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_DMA_BUF_H
|
||||
#ifdef HAVE_DMABUF
|
||||
static void
|
||||
gdk_display_add_dmabuf_downloader (GdkDisplay *display,
|
||||
const GdkDmabufDownloader *downloader,
|
||||
@@ -1847,7 +1854,8 @@ gdk_display_add_dmabuf_downloader (GdkDisplay *display,
|
||||
{
|
||||
gsize i;
|
||||
|
||||
downloader->add_formats (downloader, display, builder);
|
||||
if (!downloader->add_formats (downloader, display, builder))
|
||||
return;
|
||||
|
||||
/* dmabuf_downloaders is NULL-terminated */
|
||||
for (i = 0; i < G_N_ELEMENTS (display->dmabuf_downloaders) - 1; i++)
|
||||
@@ -1866,27 +1874,39 @@ gdk_display_add_dmabuf_downloader (GdkDisplay *display,
|
||||
* 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 *display)
|
||||
void
|
||||
gdk_display_init_dmabuf (GdkDisplay *self)
|
||||
{
|
||||
GdkDmabufFormatsBuilder *builder;
|
||||
|
||||
if (display->dmabuf_formats != NULL)
|
||||
if (self->dmabuf_formats != NULL)
|
||||
return;
|
||||
|
||||
GDK_DISPLAY_DEBUG (self, DMABUF,
|
||||
"Beginning initialization of dmabuf support");
|
||||
|
||||
builder = gdk_dmabuf_formats_builder_new ();
|
||||
|
||||
#ifdef HAVE_LINUX_DMA_BUF_H
|
||||
#ifdef HAVE_DMABUF
|
||||
if (!GDK_DEBUG_CHECK (DMABUF_DISABLE))
|
||||
{
|
||||
gdk_display_prepare_gl (display, NULL);
|
||||
gdk_display_prepare_gl (self, NULL);
|
||||
|
||||
gdk_display_add_dmabuf_downloader (display, gdk_dmabuf_get_direct_downloader (), builder);
|
||||
gdk_display_add_dmabuf_downloader (self, gdk_dmabuf_get_direct_downloader (), builder);
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
if (gdk_display_prepare_gl (self, NULL))
|
||||
gdk_display_add_dmabuf_downloader (self, gdk_dmabuf_get_egl_downloader (), builder);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
display->dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (builder);
|
||||
}
|
||||
self->dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (builder);
|
||||
|
||||
GDK_DISPLAY_DEBUG (self, DMABUF,
|
||||
"Initialized support for %zu dmabuf formats",
|
||||
gdk_dmabuf_formats_get_n_formats (self->dmabuf_formats));
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_display_get_dmabuf_formats:
|
||||
@@ -1897,6 +1917,9 @@ init_dmabuf_formats (GdkDisplay *display)
|
||||
* GTK may use OpenGL or Vulkan to support some formats.
|
||||
* Calling this function will then initialize them if they aren't yet.
|
||||
*
|
||||
* The formats returned by this function can be used for negotiating
|
||||
* buffer formats with producers such as v4l, pipewire or GStreamer.
|
||||
*
|
||||
* Returns: (transfer none): a `GdkDmabufFormats` object
|
||||
*
|
||||
* Since: 4.14
|
||||
@@ -1904,7 +1927,7 @@ init_dmabuf_formats (GdkDisplay *display)
|
||||
GdkDmabufFormats *
|
||||
gdk_display_get_dmabuf_formats (GdkDisplay *display)
|
||||
{
|
||||
init_dmabuf_formats (display);
|
||||
gdk_display_init_dmabuf (display);
|
||||
|
||||
return display->dmabuf_formats;
|
||||
}
|
||||
|
||||
@@ -114,9 +114,15 @@ struct _GdkDisplay
|
||||
guint have_egl_buffer_age : 1;
|
||||
guint have_egl_no_config_context : 1;
|
||||
guint have_egl_pixel_format_float : 1;
|
||||
guint have_egl_dma_buf_import : 1;
|
||||
guint have_egl_dma_buf_export : 1;
|
||||
|
||||
GdkDmabufFormats *dmabuf_formats;
|
||||
const GdkDmabufDownloader *dmabuf_downloaders[4];
|
||||
|
||||
/* Cached data the EGL dmabuf downloader */
|
||||
gpointer egl_gsk_renderer;
|
||||
GdkDmabufFormats *egl_external_formats;
|
||||
};
|
||||
|
||||
struct _GdkDisplayClass
|
||||
@@ -211,6 +217,8 @@ gulong _gdk_display_get_next_serial (GdkDisplay *display
|
||||
void _gdk_display_pause_events (GdkDisplay *display);
|
||||
void _gdk_display_unpause_events (GdkDisplay *display);
|
||||
|
||||
void gdk_display_init_dmabuf (GdkDisplay *self);
|
||||
|
||||
GdkVulkanContext * gdk_display_create_vulkan_context (GdkDisplay *self,
|
||||
GError **error);
|
||||
|
||||
|
||||
632
gdk/gdkdmabuf.c
632
gdk/gdkdmabuf.c
@@ -24,31 +24,338 @@
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
|
||||
#ifdef HAVE_LINUX_DMA_BUF_H
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
typedef struct _GdkDrmFormatInfo GdkDrmFormatInfo;
|
||||
|
||||
struct _GdkDrmFormatInfo
|
||||
{
|
||||
guint32 fourcc;
|
||||
GdkMemoryFormat premultiplied_memory_format;
|
||||
GdkMemoryFormat unpremultiplied_memory_format;
|
||||
void (* download) (guchar *dst_data,
|
||||
gsize dst_stride,
|
||||
GdkMemoryFormat dst_format,
|
||||
gsize width,
|
||||
gsize height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
const guchar *src_datas[GDK_DMABUF_MAX_PLANES],
|
||||
gsize sizes[GDK_DMABUF_MAX_PLANES]);
|
||||
};
|
||||
|
||||
static GdkDrmFormatInfo supported_formats[] = {
|
||||
{ DRM_FORMAT_ARGB8888, GDK_MEMORY_A8R8G8B8_PREMULTIPLIED, GDK_MEMORY_A8R8G8B8 },
|
||||
{ DRM_FORMAT_RGBA8888, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, GDK_MEMORY_R8G8B8A8 },
|
||||
{ DRM_FORMAT_BGRA8888, GDK_MEMORY_B8G8R8A8_PREMULTIPLIED, GDK_MEMORY_B8G8R8A8 },
|
||||
{ DRM_FORMAT_ABGR16161616F, GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED, GDK_MEMORY_R16G16B16A16_FLOAT },
|
||||
{ DRM_FORMAT_RGB888, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8 },
|
||||
{ DRM_FORMAT_BGR888, GDK_MEMORY_B8G8R8, GDK_MEMORY_B8G8R8 },
|
||||
static void
|
||||
download_memcpy (guchar *dst_data,
|
||||
gsize dst_stride,
|
||||
GdkMemoryFormat dst_format,
|
||||
gsize width,
|
||||
gsize height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
const guchar *src_datas[GDK_DMABUF_MAX_PLANES],
|
||||
gsize sizes[GDK_DMABUF_MAX_PLANES])
|
||||
{
|
||||
const guchar *src_data;
|
||||
gsize src_stride;
|
||||
guint bpp;
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (dst_format);
|
||||
src_stride = dmabuf->planes[0].stride;
|
||||
src_data = src_datas[0] + dmabuf->planes[0].offset;
|
||||
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + (height - 1) * dst_stride + width * bpp);
|
||||
|
||||
if (dst_stride == src_stride)
|
||||
memcpy (dst_data, src_data, (height - 1) * dst_stride + width * bpp);
|
||||
else
|
||||
{
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
memcpy (dst_data + i * dst_stride, src_data + i * src_stride, width * bpp);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _YUVCoefficients YUVCoefficients;
|
||||
|
||||
struct _YUVCoefficients
|
||||
{
|
||||
int v_to_r;
|
||||
int u_to_g;
|
||||
int v_to_g;
|
||||
int u_to_b;
|
||||
};
|
||||
|
||||
static GdkDrmFormatInfo *
|
||||
/* multiplied by 65536 */
|
||||
//static const YUVCoefficients itu601_narrow = { 104597, -25675, -53279, 132201 };
|
||||
static const YUVCoefficients itu601_wide = { 74711, -25864, -38050, 133176 };
|
||||
|
||||
static inline void
|
||||
get_uv_values (const YUVCoefficients *coeffs,
|
||||
guint8 u,
|
||||
guint8 v,
|
||||
int *out_r,
|
||||
int *out_g,
|
||||
int *out_b)
|
||||
{
|
||||
int u2 = (int) u - 127;
|
||||
int v2 = (int) v - 127;
|
||||
*out_r = coeffs->v_to_r * v2;
|
||||
*out_g = coeffs->u_to_g * u2 + coeffs->v_to_g * v2;
|
||||
*out_b = coeffs->u_to_b * u2;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_rgb_values (guint8 rgb[3],
|
||||
guint8 y,
|
||||
int r,
|
||||
int g,
|
||||
int b)
|
||||
{
|
||||
int y2 = y * 65536;
|
||||
|
||||
rgb[0] = CLAMP ((y2 + r) >> 16, 0, 255);
|
||||
rgb[1] = CLAMP ((y2 + g) >> 16, 0, 255);
|
||||
rgb[2] = CLAMP ((y2 + b) >> 16, 0, 255);
|
||||
}
|
||||
|
||||
static void
|
||||
download_nv12 (guchar *dst_data,
|
||||
gsize dst_stride,
|
||||
GdkMemoryFormat dst_format,
|
||||
gsize width,
|
||||
gsize height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
const guchar *src_data[GDK_DMABUF_MAX_PLANES],
|
||||
gsize sizes[GDK_DMABUF_MAX_PLANES])
|
||||
{
|
||||
const guchar *y_data, *uv_data;
|
||||
gsize x, y, y_stride, uv_stride;
|
||||
gsize U, V, X_SUB, Y_SUB;
|
||||
|
||||
switch (dmabuf->fourcc)
|
||||
{
|
||||
case DRM_FORMAT_NV12:
|
||||
U = 0; V = 1; X_SUB = 2; Y_SUB = 2;
|
||||
break;
|
||||
case DRM_FORMAT_NV21:
|
||||
U = 1; V = 0; X_SUB = 2; Y_SUB = 2;
|
||||
break;
|
||||
case DRM_FORMAT_NV16:
|
||||
U = 0; V = 1; X_SUB = 2; Y_SUB = 1;
|
||||
break;
|
||||
case DRM_FORMAT_NV61:
|
||||
U = 1; V = 0; X_SUB = 2; Y_SUB = 1;
|
||||
break;
|
||||
case DRM_FORMAT_NV24:
|
||||
U = 0; V = 1; X_SUB = 1; Y_SUB = 1;
|
||||
break;
|
||||
case DRM_FORMAT_NV42:
|
||||
U = 1; V = 0; X_SUB = 1; Y_SUB = 1;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return;
|
||||
}
|
||||
|
||||
y_stride = dmabuf->planes[0].stride;
|
||||
y_data = src_data[0] + dmabuf->planes[0].offset;
|
||||
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + height * y_stride);
|
||||
uv_stride = dmabuf->planes[1].stride;
|
||||
uv_data = src_data[1] + dmabuf->planes[1].offset;
|
||||
g_return_if_fail (sizes[1] >= dmabuf->planes[1].offset + (height + Y_SUB - 1) / Y_SUB * uv_stride);
|
||||
|
||||
for (y = 0; y < height; y += Y_SUB)
|
||||
{
|
||||
for (x = 0; x < width; x += X_SUB)
|
||||
{
|
||||
int r, g, b;
|
||||
gsize xs, ys;
|
||||
|
||||
get_uv_values (&itu601_wide, uv_data[x / X_SUB * 2 + U], uv_data[x / X_SUB * 2 + V], &r, &g, &b);
|
||||
|
||||
for (ys = 0; ys < Y_SUB && y + ys < height; ys++)
|
||||
for (xs = 0; xs < X_SUB && x + xs < width; xs++)
|
||||
set_rgb_values (&dst_data[3 * (x + xs) + dst_stride * ys], y_data[x + xs + y_stride * ys], r, g, b);
|
||||
}
|
||||
dst_data += Y_SUB * dst_stride;
|
||||
y_data += Y_SUB * y_stride;
|
||||
uv_data += uv_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
download_yuv_3 (guchar *dst_data,
|
||||
gsize dst_stride,
|
||||
GdkMemoryFormat dst_format,
|
||||
gsize width,
|
||||
gsize height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
const guchar *src_data[GDK_DMABUF_MAX_PLANES],
|
||||
gsize sizes[GDK_DMABUF_MAX_PLANES])
|
||||
{
|
||||
const guchar *y_data, *u_data, *v_data;
|
||||
gsize x, y, y_stride, u_stride, v_stride;
|
||||
gsize U, V, X_SUB, Y_SUB;
|
||||
|
||||
switch (dmabuf->fourcc)
|
||||
{
|
||||
case DRM_FORMAT_YUV410:
|
||||
U = 1; V = 2; X_SUB = 4; Y_SUB = 4;
|
||||
break;
|
||||
case DRM_FORMAT_YVU410:
|
||||
U = 2; V = 1; X_SUB = 4; Y_SUB = 4;
|
||||
break;
|
||||
case DRM_FORMAT_YUV411:
|
||||
U = 1; V = 2; X_SUB = 4; Y_SUB = 1;
|
||||
break;
|
||||
case DRM_FORMAT_YVU411:
|
||||
U = 2; V = 1; X_SUB = 4; Y_SUB = 1;
|
||||
break;
|
||||
case DRM_FORMAT_YUV420:
|
||||
U = 1; V = 2; X_SUB = 2; Y_SUB = 2;
|
||||
break;
|
||||
case DRM_FORMAT_YVU420:
|
||||
U = 2; V = 1; X_SUB = 2; Y_SUB = 2;
|
||||
break;
|
||||
case DRM_FORMAT_YUV422:
|
||||
U = 1; V = 2; X_SUB = 2; Y_SUB = 1;
|
||||
break;
|
||||
case DRM_FORMAT_YVU422:
|
||||
U = 2; V = 1; X_SUB = 2; Y_SUB = 1;
|
||||
break;
|
||||
case DRM_FORMAT_YUV444:
|
||||
U = 1; V = 2; X_SUB = 1; Y_SUB = 1;
|
||||
break;
|
||||
case DRM_FORMAT_YVU444:
|
||||
U = 2; V = 1; X_SUB = 1; Y_SUB = 1;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return;
|
||||
}
|
||||
|
||||
y_stride = dmabuf->planes[0].stride;
|
||||
y_data = src_data[0] + dmabuf->planes[0].offset;
|
||||
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + height * y_stride);
|
||||
u_stride = dmabuf->planes[U].stride;
|
||||
u_data = src_data[U] + dmabuf->planes[U].offset;
|
||||
g_return_if_fail (sizes[U] >= dmabuf->planes[U].offset + (height + Y_SUB - 1) / Y_SUB * u_stride);
|
||||
v_stride = dmabuf->planes[V].stride;
|
||||
v_data = src_data[V] + dmabuf->planes[V].offset;
|
||||
g_return_if_fail (sizes[V] >= dmabuf->planes[V].offset + (height + Y_SUB - 1) / Y_SUB * v_stride);
|
||||
|
||||
for (y = 0; y < height; y += Y_SUB)
|
||||
{
|
||||
for (x = 0; x < width; x += X_SUB)
|
||||
{
|
||||
int r, g, b;
|
||||
gsize xs, ys;
|
||||
|
||||
get_uv_values (&itu601_wide, u_data[x / X_SUB], v_data[x / X_SUB], &r, &g, &b);
|
||||
|
||||
for (ys = 0; ys < Y_SUB && y + ys < height; ys++)
|
||||
for (xs = 0; xs < X_SUB && x + xs < width; xs++)
|
||||
set_rgb_values (&dst_data[3 * (x + xs) + dst_stride * ys], y_data[x + xs + y_stride * ys], r, g, b);
|
||||
}
|
||||
dst_data += Y_SUB * dst_stride;
|
||||
y_data += Y_SUB * y_stride;
|
||||
u_data += u_stride;
|
||||
v_data += v_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
download_yuyv (guchar *dst_data,
|
||||
gsize dst_stride,
|
||||
GdkMemoryFormat dst_format,
|
||||
gsize width,
|
||||
gsize height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
const guchar *src_datas[GDK_DMABUF_MAX_PLANES],
|
||||
gsize sizes[GDK_DMABUF_MAX_PLANES])
|
||||
{
|
||||
const guchar *src_data;
|
||||
gsize x, y, src_stride;
|
||||
gsize Y1, Y2, U, V;
|
||||
|
||||
switch (dmabuf->fourcc)
|
||||
{
|
||||
case DRM_FORMAT_YUYV:
|
||||
Y1 = 0; U = 1; Y2 = 2; V = 3;
|
||||
break;
|
||||
case DRM_FORMAT_YVYU:
|
||||
Y1 = 0; V = 1; Y2 = 2; U = 3;
|
||||
break;
|
||||
case DRM_FORMAT_UYVY:
|
||||
U = 0; Y1 = 1; V = 2; Y2 = 3;
|
||||
break;
|
||||
case DRM_FORMAT_VYUY:
|
||||
V = 0; Y1 = 1; U = 2; Y2 = 3;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return;
|
||||
}
|
||||
|
||||
src_stride = dmabuf->planes[0].stride;
|
||||
src_data = src_datas[0] + dmabuf->planes[0].offset;
|
||||
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + height * src_stride);
|
||||
|
||||
for (y = 0; y < height; y ++)
|
||||
{
|
||||
for (x = 0; x < width; x += 2)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
get_uv_values (&itu601_wide, src_data[2 * x + U], src_data[2 * x + V], &r, &g, &b);
|
||||
set_rgb_values (&dst_data[3 * x], src_data[2 * x + Y1], r, g, b);
|
||||
if (x + 1 < width)
|
||||
set_rgb_values (&dst_data[3 * (x + 1)], src_data[2 * x + Y2], r, g, b);
|
||||
}
|
||||
dst_data += dst_stride;
|
||||
src_data += src_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static const GdkDrmFormatInfo supported_formats[] = {
|
||||
{ DRM_FORMAT_BGRA8888, GDK_MEMORY_A8R8G8B8_PREMULTIPLIED, GDK_MEMORY_A8R8G8B8, download_memcpy },
|
||||
{ DRM_FORMAT_ABGR8888, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, GDK_MEMORY_R8G8B8A8, download_memcpy },
|
||||
{ DRM_FORMAT_ARGB8888, GDK_MEMORY_B8G8R8A8_PREMULTIPLIED, GDK_MEMORY_B8G8R8A8, download_memcpy },
|
||||
{ DRM_FORMAT_RGBA8888, GDK_MEMORY_A8B8G8R8_PREMULTIPLIED, GDK_MEMORY_A8B8G8R8, download_memcpy },
|
||||
{ DRM_FORMAT_BGRX8888, GDK_MEMORY_X8R8G8B8, GDK_MEMORY_X8R8G8B8, download_memcpy },
|
||||
{ DRM_FORMAT_XBGR8888, GDK_MEMORY_R8G8B8X8, GDK_MEMORY_R8G8B8X8, download_memcpy },
|
||||
{ DRM_FORMAT_XRGB8888, GDK_MEMORY_B8G8R8X8, GDK_MEMORY_B8G8R8X8, download_memcpy },
|
||||
{ DRM_FORMAT_RGBX8888, GDK_MEMORY_X8B8G8R8, GDK_MEMORY_X8B8G8R8, download_memcpy },
|
||||
{ DRM_FORMAT_ABGR16161616F, GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED, GDK_MEMORY_R16G16B16A16_FLOAT, download_memcpy },
|
||||
{ DRM_FORMAT_RGB888, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_memcpy },
|
||||
{ DRM_FORMAT_BGR888, GDK_MEMORY_B8G8R8, GDK_MEMORY_B8G8R8, download_memcpy },
|
||||
/* YUV formats */
|
||||
{ DRM_FORMAT_NV12, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
|
||||
{ DRM_FORMAT_NV21, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
|
||||
{ DRM_FORMAT_NV16, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
|
||||
{ DRM_FORMAT_NV61, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
|
||||
{ DRM_FORMAT_NV24, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
|
||||
{ DRM_FORMAT_NV42, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_nv12 },
|
||||
{ DRM_FORMAT_YUYV, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
|
||||
{ DRM_FORMAT_YVYU, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
|
||||
{ DRM_FORMAT_VYUY, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
|
||||
{ DRM_FORMAT_UYVY, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuyv },
|
||||
{ DRM_FORMAT_YUV410, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
|
||||
{ DRM_FORMAT_YVU410, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
|
||||
{ DRM_FORMAT_YUV411, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
|
||||
{ DRM_FORMAT_YVU411, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
|
||||
{ DRM_FORMAT_YUV420, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
|
||||
{ DRM_FORMAT_YVU420, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
|
||||
{ DRM_FORMAT_YUV422, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
|
||||
{ DRM_FORMAT_YVU422, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
|
||||
{ DRM_FORMAT_YUV444, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
|
||||
{ DRM_FORMAT_YVU444, GDK_MEMORY_R8G8B8, GDK_MEMORY_R8G8B8, download_yuv_3 },
|
||||
};
|
||||
|
||||
static const GdkDrmFormatInfo *
|
||||
get_drm_format_info (guint32 fourcc)
|
||||
{
|
||||
for (int i = 0; i < G_N_ELEMENTS (supported_formats); i++)
|
||||
@@ -60,7 +367,7 @@ get_drm_format_info (guint32 fourcc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
gdk_dmabuf_direct_downloader_add_formats (const GdkDmabufDownloader *downloader,
|
||||
GdkDisplay *display,
|
||||
GdkDmabufFormatsBuilder *builder)
|
||||
@@ -69,10 +376,16 @@ gdk_dmabuf_direct_downloader_add_formats (const GdkDmabufDownloader *downloader,
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (supported_formats); i++)
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "%s dmabuf format %.4s:%#" G_GINT64_MODIFIER "x",
|
||||
downloader->name,
|
||||
(char *) &supported_formats[i].fourcc, (guint64) DRM_FORMAT_MOD_LINEAR);
|
||||
|
||||
gdk_dmabuf_formats_builder_add_format (builder,
|
||||
supported_formats[i].fourcc,
|
||||
DRM_FORMAT_MOD_LINEAR);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -83,7 +396,7 @@ gdk_dmabuf_direct_downloader_supports (const GdkDmabufDownloader *downloader,
|
||||
GdkMemoryFormat *out_format,
|
||||
GError **error)
|
||||
{
|
||||
GdkDrmFormatInfo *info;
|
||||
const GdkDrmFormatInfo *info;
|
||||
|
||||
info = get_drm_format_info (dmabuf->fourcc);
|
||||
|
||||
@@ -105,14 +418,6 @@ gdk_dmabuf_direct_downloader_supports (const GdkDmabufDownloader *downloader,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dmabuf->n_planes > 1)
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_CREATION_FAILED,
|
||||
"Multiplanar dmabufs are not supported");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*out_format = premultiplied ? info->premultiplied_memory_format
|
||||
: info->unpremultiplied_memory_format;
|
||||
|
||||
@@ -124,39 +429,75 @@ gdk_dmabuf_direct_downloader_do_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
const GdkDrmFormatInfo *info;
|
||||
const GdkDmabuf *dmabuf;
|
||||
gsize size;
|
||||
unsigned int height;
|
||||
gsize src_stride;
|
||||
guchar *src_data;
|
||||
int bpp;
|
||||
|
||||
GDK_DEBUG (DMABUF, "Using mmap() and memcpy() for downloading a dmabuf");
|
||||
const guchar *src_data[GDK_DMABUF_MAX_PLANES];
|
||||
gsize sizes[GDK_DMABUF_MAX_PLANES];
|
||||
gsize needs_unmap[GDK_DMABUF_MAX_PLANES] = { FALSE, };
|
||||
gsize i, j;
|
||||
|
||||
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
|
||||
height = gdk_texture_get_height (texture);
|
||||
bpp = gdk_memory_format_bytes_per_pixel (gdk_texture_get_format (texture));
|
||||
info = get_drm_format_info (dmabuf->fourcc);
|
||||
|
||||
src_stride = dmabuf->planes[0].stride;
|
||||
size = dmabuf->planes[0].stride * height;
|
||||
GDK_DEBUG (DMABUF,
|
||||
"Using mmap() and memcpy() for downloading a dmabuf (format %.4s:%#lx)",
|
||||
(char *)&dmabuf->fourcc, dmabuf->modifier);
|
||||
|
||||
if (ioctl (dmabuf->planes[0].fd, 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, dmabuf->planes[0].fd, dmabuf->planes[0].offset);
|
||||
|
||||
if (stride == src_stride)
|
||||
memcpy (data, src_data, size);
|
||||
else
|
||||
for (i = 0; i < dmabuf->n_planes; i++)
|
||||
{
|
||||
for (unsigned int i = 0; i < height; i++)
|
||||
memcpy (data + i * stride, src_data + i * src_stride, height * bpp);
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
if (dmabuf->planes[i].fd == dmabuf->planes[j].fd)
|
||||
break;
|
||||
}
|
||||
if (j < i)
|
||||
{
|
||||
src_data[i] = src_data[j];
|
||||
sizes[i] = sizes[j];
|
||||
continue;
|
||||
}
|
||||
|
||||
sizes[i] = lseek (dmabuf->planes[i].fd, 0, SEEK_END);
|
||||
if (sizes[i] == (off_t) -1)
|
||||
{
|
||||
g_warning ("Failed to seek dmabuf: %s", g_strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
/* be a good citizen and seek back to the start, as the dos recommend */
|
||||
lseek (dmabuf->planes[i].fd, 0, SEEK_SET);
|
||||
|
||||
if (ioctl (dmabuf->planes[i].fd, DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_START|DMA_BUF_SYNC_READ }) < 0)
|
||||
g_warning ("Failed to sync dmabuf: %s", g_strerror (errno));
|
||||
|
||||
src_data[i] = mmap (NULL, sizes[i], PROT_READ, MAP_SHARED, dmabuf->planes[i].fd, dmabuf->planes[i].offset);
|
||||
if (src_data[i] == NULL)
|
||||
{
|
||||
g_warning ("Failed to mmap dmabuf: %s", g_strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
needs_unmap[i] = TRUE;
|
||||
}
|
||||
|
||||
munmap (src_data, size);
|
||||
info->download (data,
|
||||
stride,
|
||||
gdk_texture_get_format (texture),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture),
|
||||
dmabuf,
|
||||
src_data,
|
||||
sizes);
|
||||
|
||||
if (ioctl (dmabuf->planes[0].fd, 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));
|
||||
out:
|
||||
for (i = 0; i < dmabuf->n_planes; i++)
|
||||
{
|
||||
if (!needs_unmap[i])
|
||||
continue;
|
||||
|
||||
munmap ((void *)src_data[i], sizes[i]);
|
||||
|
||||
if (ioctl (dmabuf->planes[i].fd, DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_END|DMA_BUF_SYNC_READ }) < 0)
|
||||
g_warning ("Failed to sync dmabuf: %s", g_strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -172,16 +513,14 @@ gdk_dmabuf_direct_downloader_download (const GdkDmabufDownloader *downloader,
|
||||
gdk_dmabuf_direct_downloader_do_download (texture, data, stride);
|
||||
else
|
||||
{
|
||||
const GdkDmabuf *dmabuf;
|
||||
unsigned int width, height;
|
||||
guchar *src_data;
|
||||
gsize src_stride;
|
||||
|
||||
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
src_stride = dmabuf->planes[0].stride;
|
||||
src_stride = width * gdk_memory_format_bytes_per_pixel (src_format);
|
||||
src_data = g_new (guchar, src_stride * height);
|
||||
|
||||
gdk_dmabuf_direct_downloader_do_download (texture, src_data, src_stride);
|
||||
@@ -198,6 +537,7 @@ const GdkDmabufDownloader *
|
||||
gdk_dmabuf_get_direct_downloader (void)
|
||||
{
|
||||
static const GdkDmabufDownloader downloader = {
|
||||
"mmap",
|
||||
gdk_dmabuf_direct_downloader_add_formats,
|
||||
gdk_dmabuf_direct_downloader_supports,
|
||||
gdk_dmabuf_direct_downloader_download,
|
||||
@@ -206,4 +546,200 @@ gdk_dmabuf_get_direct_downloader (void)
|
||||
return &downloader;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LINUX_DMA_BUF_H */
|
||||
/*
|
||||
* Tries to sanitize the dmabuf to conform to the values expected
|
||||
* by Vulkan/EGL which should also be the values expected by
|
||||
* Wayland compositors
|
||||
*
|
||||
* We put these sanitized values into the GdkDmabufTexture, by
|
||||
* sanitizing the input from GdkDmabufTextureBuilder, which are
|
||||
* controlled by the callers.
|
||||
*
|
||||
* Things we do here:
|
||||
*
|
||||
* 1. Disallow any dmabuf format that we do not know.
|
||||
*
|
||||
* 1. Reject the INVALID modifier, accept the LINEAR one.
|
||||
*
|
||||
* 2. Ignore all other modifiers.
|
||||
*
|
||||
* 3. Try and fix various inconsistencies between V4L and Mesa, like NV12.
|
||||
*
|
||||
* *** WARNING ***
|
||||
*
|
||||
* This function is not absolutely perfect, you do not have a
|
||||
* perfect dmabuf afterwards.
|
||||
*
|
||||
* In particular, it doesn't check sizes.
|
||||
*
|
||||
* *** WARNING ***
|
||||
*/
|
||||
gboolean
|
||||
gdk_dmabuf_sanitize (GdkDmabuf *dest,
|
||||
gsize width,
|
||||
gsize height,
|
||||
const GdkDmabuf *src,
|
||||
GError **error)
|
||||
{
|
||||
const GdkDrmFormatInfo *info;
|
||||
|
||||
if (src->n_planes > GDK_DMABUF_MAX_PLANES)
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
|
||||
"GTK only support dmabufs with %u planes, not %u",
|
||||
GDK_DMABUF_MAX_PLANES, src->n_planes);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (src->modifier == DRM_FORMAT_MOD_INVALID)
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
|
||||
"GTK does not support the INVALID modifier.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
info = get_drm_format_info (src->fourcc);
|
||||
|
||||
if (info == NULL)
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
|
||||
"Unsupported dmabuf format %.4s",
|
||||
(char *) &src->fourcc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*dest = *src;
|
||||
|
||||
if (src->modifier)
|
||||
return TRUE;
|
||||
|
||||
switch (dest->fourcc)
|
||||
{
|
||||
case DRM_FORMAT_NV12:
|
||||
case DRM_FORMAT_NV21:
|
||||
case DRM_FORMAT_NV16:
|
||||
case DRM_FORMAT_NV61:
|
||||
if (dest->n_planes == 1)
|
||||
{
|
||||
dest->n_planes = 2;
|
||||
dest->planes[1].fd = dest->planes[0].fd;
|
||||
dest->planes[1].stride = dest->planes[0].stride;
|
||||
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
|
||||
}
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_NV24:
|
||||
case DRM_FORMAT_NV42:
|
||||
if (dest->n_planes == 1)
|
||||
{
|
||||
dest->n_planes = 2;
|
||||
dest->planes[1].fd = dest->planes[0].fd;
|
||||
dest->planes[1].stride = dest->planes[0].stride * 2;
|
||||
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
|
||||
}
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_YUV410:
|
||||
case DRM_FORMAT_YVU410:
|
||||
if (dest->n_planes == 1)
|
||||
{
|
||||
dest->n_planes = 3;
|
||||
dest->planes[1].fd = dest->planes[0].fd;
|
||||
dest->planes[1].stride = (dest->planes[0].stride + 3) / 4;
|
||||
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
|
||||
dest->planes[2].fd = dest->planes[1].fd;
|
||||
dest->planes[2].stride = dest->planes[1].stride;
|
||||
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * ((height + 3) / 4);
|
||||
}
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_YUV411:
|
||||
case DRM_FORMAT_YVU411:
|
||||
if (dest->n_planes == 1)
|
||||
{
|
||||
dest->n_planes = 3;
|
||||
dest->planes[1].fd = dest->planes[0].fd;
|
||||
dest->planes[1].stride = (dest->planes[0].stride + 3) / 4;
|
||||
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
|
||||
dest->planes[2].fd = dest->planes[1].fd;
|
||||
dest->planes[2].stride = dest->planes[1].stride;
|
||||
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * height;
|
||||
}
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_YUV420:
|
||||
case DRM_FORMAT_YVU420:
|
||||
if (dest->n_planes == 1)
|
||||
{
|
||||
dest->n_planes = 3;
|
||||
dest->planes[1].fd = dest->planes[0].fd;
|
||||
dest->planes[1].stride = (dest->planes[0].stride + 1) / 2;
|
||||
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
|
||||
dest->planes[2].fd = dest->planes[1].fd;
|
||||
dest->planes[2].stride = dest->planes[1].stride;
|
||||
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * ((height + 1) / 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_YUV422:
|
||||
case DRM_FORMAT_YVU422:
|
||||
if (dest->n_planes == 1)
|
||||
{
|
||||
dest->n_planes = 3;
|
||||
dest->planes[1].fd = dest->planes[0].fd;
|
||||
dest->planes[1].stride = (dest->planes[0].stride + 1) / 2;
|
||||
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
|
||||
dest->planes[2].fd = dest->planes[1].fd;
|
||||
dest->planes[2].stride = dest->planes[1].stride;
|
||||
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * height;
|
||||
}
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_YUV444:
|
||||
case DRM_FORMAT_YVU444:
|
||||
if (dest->n_planes == 1)
|
||||
{
|
||||
dest->n_planes = 3;
|
||||
dest->planes[1].fd = dest->planes[0].fd;
|
||||
dest->planes[1].stride = dest->planes[0].stride;
|
||||
dest->planes[1].offset = dest->planes[0].offset + dest->planes[0].stride * height;
|
||||
dest->planes[2].fd = dest->planes[1].fd;
|
||||
dest->planes[2].stride = dest->planes[1].stride;
|
||||
dest->planes[2].offset = dest->planes[1].offset + dest->planes[1].stride * height;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* gdk_dmabuf_is_disjoint:
|
||||
* @dmabuf: a sanitized GdkDmabuf
|
||||
*
|
||||
* A dmabuf is considered disjoint if it uses more than
|
||||
* 1 file descriptor.
|
||||
*
|
||||
* Returns: %TRUE if the dmabuf is disjoint
|
||||
**/
|
||||
gboolean
|
||||
gdk_dmabuf_is_disjoint (const GdkDmabuf *dmabuf)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 1; i < dmabuf->n_planes; i++)
|
||||
{
|
||||
if (dmabuf->planes[0].fd != dmabuf->planes[i].fd)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DMABUF */
|
||||
|
||||
413
gdk/gdkdmabufegl.c
Normal file
413
gdk/gdkdmabufegl.c
Normal file
@@ -0,0 +1,413 @@
|
||||
/* gdkdmabufegl.c
|
||||
*
|
||||
* Copyright 2023 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(HAVE_DMABUF) && defined (HAVE_EGL)
|
||||
#include "gdkdmabufprivate.h"
|
||||
|
||||
#include "gdkdmabufformatsbuilderprivate.h"
|
||||
#include "gdkdebugprivate.h"
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdktexturedownloader.h"
|
||||
|
||||
#include <graphene.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
/* A dmabuf downloader implementation that downloads buffers via
|
||||
* gsk_renderer_render_texture + GL texture download.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
gdk_dmabuf_egl_downloader_add_formats (const GdkDmabufDownloader *downloader,
|
||||
GdkDisplay *display,
|
||||
GdkDmabufFormatsBuilder *builder)
|
||||
{
|
||||
GdkGLContext *context = gdk_display_get_gl_context (display);
|
||||
EGLDisplay egl_display = gdk_display_get_egl_display (display);
|
||||
GdkDmabufFormatsBuilder *external;
|
||||
gboolean retval = FALSE;
|
||||
|
||||
g_assert (display->egl_external_formats == NULL);
|
||||
|
||||
external = gdk_dmabuf_formats_builder_new ();
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
if (egl_display != EGL_NO_DISPLAY &&
|
||||
display->have_egl_dma_buf_import &&
|
||||
gdk_gl_context_has_image_storage (context))
|
||||
{
|
||||
int num_fourccs;
|
||||
int *fourccs;
|
||||
guint64 *modifiers;
|
||||
unsigned int *external_only;
|
||||
int n_mods;
|
||||
|
||||
eglQueryDmaBufFormatsEXT (egl_display, 0, NULL, &num_fourccs);
|
||||
fourccs = g_new (int, num_fourccs);
|
||||
eglQueryDmaBufFormatsEXT (egl_display, num_fourccs, fourccs, &num_fourccs);
|
||||
|
||||
n_mods = 80;
|
||||
modifiers = g_new (guint64, n_mods);
|
||||
external_only = g_new (unsigned int, n_mods);
|
||||
|
||||
for (int i = 0; i < num_fourccs; i++)
|
||||
{
|
||||
int num_modifiers;
|
||||
|
||||
eglQueryDmaBufModifiersEXT (egl_display,
|
||||
fourccs[i],
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
&num_modifiers);
|
||||
|
||||
if (num_modifiers > n_mods)
|
||||
{
|
||||
n_mods = num_modifiers;
|
||||
modifiers = g_renew (guint64, modifiers, n_mods);
|
||||
external_only = g_renew (unsigned int, external_only, n_mods);
|
||||
}
|
||||
|
||||
eglQueryDmaBufModifiersEXT (egl_display,
|
||||
fourccs[i],
|
||||
num_modifiers,
|
||||
modifiers,
|
||||
external_only,
|
||||
&num_modifiers);
|
||||
|
||||
for (int j = 0; j < num_modifiers; j++)
|
||||
{
|
||||
/* All linear formats we support are already added my the mmap downloader.
|
||||
* We don't add external formats, unless we can use them (via GLES)
|
||||
*/
|
||||
if (modifiers[j] != DRM_FORMAT_MOD_LINEAR &&
|
||||
(!external_only[j] || gdk_gl_context_get_use_es (context)))
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "%s%s dmabuf format %.4s:%#" G_GINT64_MODIFIER "x",
|
||||
external_only[j] ? "external " : "",
|
||||
downloader->name,
|
||||
(char *) &fourccs[i],
|
||||
modifiers[j]);
|
||||
|
||||
gdk_dmabuf_formats_builder_add_format (builder, fourccs[i], modifiers[j]);
|
||||
}
|
||||
if (external_only[j])
|
||||
gdk_dmabuf_formats_builder_add_format (external, fourccs[i], modifiers[j]);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (modifiers);
|
||||
g_free (external_only);
|
||||
g_free (fourccs);
|
||||
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
display->egl_external_formats = gdk_dmabuf_formats_builder_free_to_formats (external);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static GdkMemoryFormat
|
||||
get_memory_format (guint32 fourcc,
|
||||
gboolean premultiplied)
|
||||
{
|
||||
switch (fourcc)
|
||||
{
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
case DRM_FORMAT_ABGR8888:
|
||||
case DRM_FORMAT_XRGB8888_A8:
|
||||
case DRM_FORMAT_XBGR8888_A8:
|
||||
return premultiplied ? GDK_MEMORY_A8R8G8B8_PREMULTIPLIED : GDK_MEMORY_A8R8G8B8;
|
||||
|
||||
case DRM_FORMAT_RGBA8888:
|
||||
case DRM_FORMAT_RGBX8888_A8:
|
||||
return premultiplied ? GDK_MEMORY_R8G8B8A8_PREMULTIPLIED : GDK_MEMORY_R8G8B8A8;
|
||||
|
||||
case DRM_FORMAT_BGRA8888:
|
||||
return premultiplied ? GDK_MEMORY_B8G8R8A8_PREMULTIPLIED : GDK_MEMORY_B8G8R8A8;
|
||||
|
||||
case DRM_FORMAT_RGB888:
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_XBGR8888:
|
||||
case DRM_FORMAT_RGBX8888:
|
||||
case DRM_FORMAT_BGRX8888:
|
||||
return GDK_MEMORY_R8G8B8;
|
||||
|
||||
case DRM_FORMAT_BGR888:
|
||||
return GDK_MEMORY_B8G8R8;
|
||||
|
||||
case DRM_FORMAT_XRGB2101010:
|
||||
case DRM_FORMAT_XBGR2101010:
|
||||
case DRM_FORMAT_RGBX1010102:
|
||||
case DRM_FORMAT_BGRX1010102:
|
||||
case DRM_FORMAT_XRGB16161616:
|
||||
case DRM_FORMAT_XBGR16161616:
|
||||
return GDK_MEMORY_R16G16B16;
|
||||
|
||||
case DRM_FORMAT_ARGB2101010:
|
||||
case DRM_FORMAT_ABGR2101010:
|
||||
case DRM_FORMAT_RGBA1010102:
|
||||
case DRM_FORMAT_BGRA1010102:
|
||||
case DRM_FORMAT_ARGB16161616:
|
||||
case DRM_FORMAT_ABGR16161616:
|
||||
return premultiplied ? GDK_MEMORY_R16G16B16A16_PREMULTIPLIED : GDK_MEMORY_R16G16B16A16;
|
||||
|
||||
case DRM_FORMAT_ARGB16161616F:
|
||||
case DRM_FORMAT_ABGR16161616F:
|
||||
return premultiplied ? GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED : GDK_MEMORY_R16G16B16A16_FLOAT;
|
||||
|
||||
case DRM_FORMAT_XRGB16161616F:
|
||||
case DRM_FORMAT_XBGR16161616F:
|
||||
return GDK_MEMORY_R16G16B16_FLOAT;
|
||||
|
||||
case DRM_FORMAT_YUYV:
|
||||
case DRM_FORMAT_YVYU:
|
||||
case DRM_FORMAT_UYVY:
|
||||
case DRM_FORMAT_VYUY:
|
||||
case DRM_FORMAT_XYUV8888:
|
||||
#ifdef DRM_FORMAT_XVUY8888
|
||||
case DRM_FORMAT_XVUY8888:
|
||||
#endif
|
||||
case DRM_FORMAT_VUY888:
|
||||
return GDK_MEMORY_R8G8B8;
|
||||
|
||||
/* Add more formats here */
|
||||
default:
|
||||
return premultiplied ? GDK_MEMORY_A8R8G8B8_PREMULTIPLIED : GDK_MEMORY_A8R8G8B8;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_dmabuf_egl_downloader_supports (const GdkDmabufDownloader *downloader,
|
||||
GdkDisplay *display,
|
||||
const GdkDmabuf *dmabuf,
|
||||
gboolean premultiplied,
|
||||
GdkMemoryFormat *out_format,
|
||||
GError **error)
|
||||
{
|
||||
EGLDisplay egl_display;
|
||||
GdkGLContext *context;
|
||||
int num_modifiers;
|
||||
guint64 *modifiers;
|
||||
unsigned int *external_only;
|
||||
|
||||
egl_display = gdk_display_get_egl_display (display);
|
||||
if (egl_display == EGL_NO_DISPLAY)
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
|
||||
"EGL not available");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
context = gdk_display_get_gl_context (display);
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
eglQueryDmaBufModifiersEXT (egl_display,
|
||||
dmabuf->fourcc,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
&num_modifiers);
|
||||
|
||||
modifiers = g_newa (uint64_t, num_modifiers);
|
||||
external_only = g_newa (unsigned int, num_modifiers);
|
||||
|
||||
eglQueryDmaBufModifiersEXT (egl_display,
|
||||
dmabuf->fourcc,
|
||||
num_modifiers,
|
||||
modifiers,
|
||||
external_only,
|
||||
&num_modifiers);
|
||||
|
||||
for (int i = 0; i < num_modifiers; i++)
|
||||
{
|
||||
if (modifiers[i] == dmabuf->modifier)
|
||||
{
|
||||
*out_format = get_memory_format (dmabuf->fourcc, premultiplied);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
g_set_error (error,
|
||||
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
|
||||
"Unsupported dmabuf format: %.4s:%#" G_GINT64_MODIFIER "x",
|
||||
(char *) &dmabuf->fourcc, dmabuf->modifier);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Hack. We don't include gsk/gsk.h here to avoid a build order problem
|
||||
* with the generated header gskenumtypes.h, so we need to hack around
|
||||
* a bit to access the gsk api we need.
|
||||
*/
|
||||
|
||||
typedef gpointer GskRenderer;
|
||||
|
||||
extern GskRenderer * gsk_gl_renderer_new (void);
|
||||
extern gboolean gsk_renderer_realize (GskRenderer *renderer,
|
||||
GdkSurface *surface,
|
||||
GError **error);
|
||||
extern GdkTexture * gsk_renderer_convert_texture (GskRenderer *renderer,
|
||||
GdkTexture *texture);
|
||||
|
||||
typedef void (* InvokeFunc) (gpointer data);
|
||||
|
||||
typedef struct _InvokeData
|
||||
{
|
||||
volatile int spinlock;
|
||||
InvokeFunc func;
|
||||
gpointer data;
|
||||
} InvokeData;
|
||||
|
||||
static gboolean
|
||||
gdk_dmabuf_egl_downloader_invoke_callback (gpointer data)
|
||||
{
|
||||
InvokeData *invoke = data;
|
||||
GdkGLContext *previous;
|
||||
|
||||
previous = gdk_gl_context_get_current ();
|
||||
|
||||
invoke->func (invoke->data);
|
||||
|
||||
if (previous)
|
||||
gdk_gl_context_make_current (previous);
|
||||
else
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
g_atomic_int_set (&invoke->spinlock, 1);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Run func in the main thread, taking care not to disturb
|
||||
* the current GL context of the caller.
|
||||
*/
|
||||
static void
|
||||
gdk_dmabuf_egl_downloader_run (InvokeFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
InvokeData invoke = { 0, func, data };
|
||||
|
||||
g_main_context_invoke (NULL, gdk_dmabuf_egl_downloader_invoke_callback, &invoke);
|
||||
|
||||
while (g_atomic_int_get (&invoke.spinlock) == 0) ;
|
||||
}
|
||||
|
||||
typedef struct _Download Download;
|
||||
|
||||
struct _Download
|
||||
{
|
||||
GdkDmabufTexture *texture;
|
||||
GdkMemoryFormat format;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
};
|
||||
|
||||
static GskRenderer *
|
||||
get_gsk_renderer (GdkDisplay *display)
|
||||
{
|
||||
if (!display->egl_gsk_renderer)
|
||||
{
|
||||
GskRenderer *renderer;
|
||||
GError *error = NULL;
|
||||
|
||||
renderer = gsk_gl_renderer_new ();
|
||||
|
||||
if (!gsk_renderer_realize (renderer, NULL, &error))
|
||||
{
|
||||
g_warning ("Failed to realize GL renderer: %s", error->message);
|
||||
g_error_free (error);
|
||||
g_object_unref (renderer);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
display->egl_gsk_renderer = renderer;
|
||||
}
|
||||
|
||||
return display->egl_gsk_renderer;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_dmabuf_egl_downloader_do_download (gpointer data)
|
||||
{
|
||||
Download *download = data;
|
||||
GdkDisplay *display;
|
||||
GskRenderer *renderer;
|
||||
GdkTexture *native;
|
||||
GdkTextureDownloader *downloader;
|
||||
|
||||
display = gdk_dmabuf_texture_get_display (download->texture);
|
||||
|
||||
renderer = get_gsk_renderer (display);
|
||||
|
||||
native = gsk_renderer_convert_texture (renderer, GDK_TEXTURE (download->texture));
|
||||
|
||||
downloader = gdk_texture_downloader_new (native);
|
||||
gdk_texture_downloader_set_format (downloader, download->format);
|
||||
gdk_texture_downloader_download_into (downloader, download->data, download->stride);
|
||||
gdk_texture_downloader_free (downloader);
|
||||
|
||||
g_object_unref (native);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_dmabuf_egl_downloader_download (const GdkDmabufDownloader *downloader,
|
||||
GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
Download download;
|
||||
|
||||
GDK_DEBUG (DMABUF, "Using %s for downloading a dmabuf", downloader->name);
|
||||
|
||||
download.texture = GDK_DMABUF_TEXTURE (texture);
|
||||
download.format = format;
|
||||
download.data = data;
|
||||
download.stride = stride;
|
||||
|
||||
gdk_dmabuf_egl_downloader_run (gdk_dmabuf_egl_downloader_do_download, &download);
|
||||
}
|
||||
|
||||
const GdkDmabufDownloader *
|
||||
gdk_dmabuf_get_egl_downloader (void)
|
||||
{
|
||||
static const GdkDmabufDownloader downloader = {
|
||||
"egl",
|
||||
gdk_dmabuf_egl_downloader_add_formats,
|
||||
gdk_dmabuf_egl_downloader_supports,
|
||||
gdk_dmabuf_egl_downloader_download,
|
||||
};
|
||||
|
||||
return &downloader;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DMABUF && HAVE_EGL */
|
||||
@@ -22,6 +22,10 @@
|
||||
|
||||
#include "gdkdmabufformatsprivate.h"
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
#define GDK_ARRAY_NAME gdk_dmabuf_formats_builder
|
||||
#define GDK_ARRAY_TYPE_NAME GdkDmabufFormatsBuilder
|
||||
#define GDK_ARRAY_ELEMENT_TYPE GdkDmabufFormat
|
||||
@@ -117,6 +121,12 @@ gdk_dmabuf_formats_builder_add_format (GdkDmabufFormatsBuilder *self,
|
||||
guint32 fourcc,
|
||||
guint64 modifier)
|
||||
{
|
||||
#ifdef HAVE_DMABUF
|
||||
g_return_if_fail (modifier != DRM_FORMAT_MOD_INVALID);
|
||||
#else
|
||||
g_return_if_reached ();
|
||||
#endif
|
||||
|
||||
gdk_dmabuf_formats_builder_append (self, &(GdkDmabufFormat) { fourcc, modifier });
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@ struct _GdkDmabuf
|
||||
|
||||
struct _GdkDmabufDownloader
|
||||
{
|
||||
void (* add_formats) (const GdkDmabufDownloader *downloader,
|
||||
const char *name;
|
||||
gboolean (* add_formats) (const GdkDmabufDownloader *downloader,
|
||||
GdkDisplay *display,
|
||||
GdkDmabufFormatsBuilder *builder);
|
||||
|
||||
gboolean (* supports) (const GdkDmabufDownloader *downloader,
|
||||
GdkDisplay *display,
|
||||
const GdkDmabuf *dmabuf,
|
||||
@@ -38,7 +38,17 @@ struct _GdkDmabufDownloader
|
||||
gsize stride);
|
||||
};
|
||||
|
||||
#ifdef HAVE_LINUX_DMA_BUF_H
|
||||
const GdkDmabufDownloader *
|
||||
gdk_dmabuf_get_direct_downloader (void) G_GNUC_CONST;
|
||||
#ifdef HAVE_DMABUF
|
||||
|
||||
const GdkDmabufDownloader * gdk_dmabuf_get_direct_downloader (void) G_GNUC_CONST;
|
||||
const GdkDmabufDownloader * gdk_dmabuf_get_egl_downloader (void) G_GNUC_CONST;
|
||||
|
||||
gboolean gdk_dmabuf_sanitize (GdkDmabuf *dest,
|
||||
gsize width,
|
||||
gsize height,
|
||||
const GdkDmabuf *src,
|
||||
GError **error);
|
||||
|
||||
gboolean gdk_dmabuf_is_disjoint (const GdkDmabuf *dmabuf);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,16 +22,17 @@
|
||||
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkdmabufformatsbuilderprivate.h"
|
||||
#include "gdkdmabufprivate.h"
|
||||
#include "gdktextureprivate.h"
|
||||
#include <gdk/gdkglcontext.h>
|
||||
#include <gdk/gdkgltexturebuilder.h>
|
||||
#include <gdk/gdktexturedownloader.h>
|
||||
|
||||
#ifdef HAVE_LINUX_DMA_BUF_H
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <epoxy/egl.h>
|
||||
#endif
|
||||
|
||||
@@ -128,17 +129,28 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef HAVE_LINUX_DMA_BUF_H
|
||||
#ifdef HAVE_DMABUF
|
||||
GdkDmabufTexture *self;
|
||||
GdkTexture *update_texture;
|
||||
GdkDisplay *display;
|
||||
const GdkDmabuf *dmabuf;
|
||||
GdkDmabuf dmabuf;
|
||||
GdkMemoryFormat format;
|
||||
GError *local_error = NULL;
|
||||
int width, height;
|
||||
gsize i;
|
||||
|
||||
display = gdk_dmabuf_texture_builder_get_display (builder);
|
||||
dmabuf = gdk_dmabuf_texture_builder_get_dmabuf (builder);
|
||||
width = gdk_dmabuf_texture_builder_get_width (builder);
|
||||
height = gdk_dmabuf_texture_builder_get_height (builder);
|
||||
|
||||
if (!gdk_dmabuf_sanitize (&dmabuf,
|
||||
width,
|
||||
height,
|
||||
gdk_dmabuf_texture_builder_get_dmabuf (builder),
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
gdk_display_init_dmabuf (display);
|
||||
|
||||
for (i = 0; display->dmabuf_downloaders[i] != NULL; i++)
|
||||
{
|
||||
@@ -147,7 +159,7 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
|
||||
|
||||
if (display->dmabuf_downloaders[i]->supports (display->dmabuf_downloaders[i],
|
||||
display,
|
||||
dmabuf,
|
||||
&dmabuf,
|
||||
gdk_dmabuf_texture_builder_get_premultiplied (builder),
|
||||
&format,
|
||||
local_error ? NULL : &local_error))
|
||||
@@ -160,15 +172,23 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GDK_DEBUG (DMABUF,
|
||||
"Dmabuf texture, format %.4s:%#lx, %s%u planes, memory format %u, downloader %s",
|
||||
(char *) &dmabuf.fourcc, dmabuf.modifier,
|
||||
gdk_dmabuf_texture_builder_get_premultiplied (builder) ? " premultiplied, " : "",
|
||||
dmabuf.n_planes,
|
||||
format,
|
||||
display->dmabuf_downloaders[i]->name);
|
||||
|
||||
self = g_object_new (GDK_TYPE_DMABUF_TEXTURE,
|
||||
"width", gdk_dmabuf_texture_builder_get_width (builder),
|
||||
"height", gdk_dmabuf_texture_builder_get_height (builder),
|
||||
"width", width,
|
||||
"height", height,
|
||||
NULL);
|
||||
|
||||
GDK_TEXTURE (self)->format = format;
|
||||
g_set_object (&self->display, display);
|
||||
self->downloader = display->dmabuf_downloaders[i];
|
||||
self->dmabuf = *dmabuf;
|
||||
self->dmabuf = dmabuf;
|
||||
self->destroy = destroy;
|
||||
self->data = data;
|
||||
|
||||
@@ -190,7 +210,7 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
|
||||
|
||||
return GDK_TEXTURE (self);
|
||||
|
||||
#else /* !HAVE_LINUX_DMA_BUF_H */
|
||||
#else /* !HAVE_DMABUF */
|
||||
g_set_error_literal (error, GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_NOT_AVAILABLE,
|
||||
"dmabuf support disabled at compile-time.");
|
||||
return NULL;
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <drm_fourcc.h>
|
||||
#else
|
||||
#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
|
||||
#endif
|
||||
|
||||
|
||||
struct _GdkDmabufTextureBuilder
|
||||
@@ -81,7 +86,7 @@ struct _GdkDmabufTextureBuilderClass
|
||||
*
|
||||
* The format of the data (for graphics data, essentially its colorspace) is described
|
||||
* by a 32-bit integer. These format identifiers are defined in the header file
|
||||
* [drm/drm_fourcc.h](https://github.com/torvalds/linux/blob/master/include/uapi/drm/drm_fourcc.h)
|
||||
* [drm_fourcc.h](https://github.com/torvalds/linux/blob/master/include/uapi/drm_fourcc.h)
|
||||
* and commonly referred to as **_fourcc_** values, since they are identified by 4 ASCII
|
||||
* characters. Additionally, each DMA buffer has a **_modifier_**, which is a 64-bit integer
|
||||
* that describes driver-specific details of the memory layout, such as tiling or compression.
|
||||
@@ -91,9 +96,12 @@ struct _GdkDmabufTextureBuilderClass
|
||||
* to create the new texture.
|
||||
*
|
||||
* The required properties for a dma-buf texture are
|
||||
* - The width and height in pixels
|
||||
* - The `fourcc` code and `modifier` which identify the format and memory layout of the dma-buf
|
||||
* - The file descriptor, offset and stride for each of the planes
|
||||
*
|
||||
* * The width and height in pixels
|
||||
*
|
||||
* * The `fourcc` code and `modifier` which identify the format and memory layout of the dma-buf
|
||||
*
|
||||
* * The file descriptor, offset and stride for each of the planes
|
||||
*
|
||||
* `GdkDmabufTextureBuilder` can be used for quick one-shot construction of
|
||||
* textures as well as kept around and reused to construct multiple textures.
|
||||
@@ -331,7 +339,7 @@ gdk_dmabuf_texture_builder_class_init (GdkDmabufTextureBuilderClass *klass)
|
||||
*/
|
||||
properties[PROP_N_PLANES] =
|
||||
g_param_spec_uint ("n-planes", NULL, NULL,
|
||||
0, 4, 0,
|
||||
1, GDK_DMABUF_MAX_PLANES, 1,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
@@ -365,6 +373,9 @@ static void
|
||||
gdk_dmabuf_texture_builder_init (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
self->premultiplied = TRUE;
|
||||
self->display = gdk_display_get_default ();
|
||||
self->dmabuf.n_planes = 1;
|
||||
|
||||
for (int i = 0; i < GDK_DMABUF_MAX_PLANES; i++)
|
||||
self->dmabuf.planes[i].fd = -1;
|
||||
}
|
||||
@@ -391,7 +402,7 @@ gdk_dmabuf_texture_builder_new (void)
|
||||
* Returns the display that this texture builder is
|
||||
* associated with.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the display
|
||||
* Returns: (transfer none): the display
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
@@ -421,6 +432,7 @@ gdk_dmabuf_texture_builder_set_display (GdkDmabufTextureBuilder *self,
|
||||
GdkDisplay *display)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (g_set_object (&self->display, display))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DISPLAY]);
|
||||
@@ -594,6 +606,13 @@ gdk_dmabuf_texture_builder_set_modifier (GdkDmabufTextureBuilder *self,
|
||||
guint64 modifier)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
if (modifier == DRM_FORMAT_MOD_INVALID)
|
||||
{
|
||||
g_critical ("GTK does not support the INVALID modifier. "
|
||||
"If you use code that produces it, it should include "
|
||||
"instructions how to transform it into a regular modifier.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->dmabuf.modifier == modifier)
|
||||
return;
|
||||
@@ -679,6 +698,7 @@ gdk_dmabuf_texture_builder_set_n_planes (GdkDmabufTextureBuilder *self,
|
||||
unsigned int n_planes)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (n_planes > 0 && n_planes <= GDK_DMABUF_MAX_PLANES);
|
||||
|
||||
if (self->dmabuf.n_planes == n_planes)
|
||||
return;
|
||||
@@ -959,16 +979,17 @@ gdk_dmabuf_texture_builder_build (GdkDmabufTextureBuilder *self,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
|
||||
g_return_val_if_fail (destroy == NULL || data != NULL, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
g_return_val_if_fail (self->width > 0, NULL);
|
||||
g_return_val_if_fail (self->height > 0, NULL);
|
||||
g_return_val_if_fail (self->dmabuf.fourcc != 0, NULL);
|
||||
g_return_val_if_fail (self->dmabuf.n_planes > 0, NULL);
|
||||
|
||||
for (int i = 0; i < self->dmabuf.n_planes; i++)
|
||||
g_return_val_if_fail (self->dmabuf.planes[i].fd != -1 || self->dmabuf.planes[i].offset != 0, NULL);
|
||||
for (i = 0; i < self->dmabuf.n_planes; i++)
|
||||
g_return_val_if_fail (self->dmabuf.planes[i].fd != -1, NULL);
|
||||
|
||||
if (GDK_DEBUG_CHECK (DMABUF_DISABLE))
|
||||
{
|
||||
|
||||
@@ -684,7 +684,7 @@ gdk_drop_read_async (GdkDrop *self,
|
||||
* gdk_drop_read_finish:
|
||||
* @self: a `GdkDrop`
|
||||
* @result: a `GAsyncResult`
|
||||
* @out_mime_type: (out) (type utf8): return location for the used mime type
|
||||
* @out_mime_type: (out) (type utf8) (transfer none): return location for the used mime type
|
||||
* @error: (nullable): location to store error information on failure
|
||||
*
|
||||
* Finishes an async drop read operation.
|
||||
|
||||
@@ -298,10 +298,16 @@ typedef enum
|
||||
* The color values are premultiplied with the alpha value.
|
||||
* @GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: 4 bytes; for red, green, blue, alpha
|
||||
* The color values are premultiplied with the alpha value.
|
||||
* @GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: 4 bytes; for alpha, blue, green, red,
|
||||
* The color values are premultiplied with the alpha value. Since 4.14
|
||||
* @GDK_MEMORY_B8G8R8A8: 4 bytes; for blue, green, red, alpha.
|
||||
* @GDK_MEMORY_A8R8G8B8: 4 bytes; for alpha, red, green, blue.
|
||||
* @GDK_MEMORY_R8G8B8A8: 4 bytes; for red, green, blue, alpha.
|
||||
* @GDK_MEMORY_A8B8G8R8: 4 bytes; for alpha, blue, green, red.
|
||||
* @GDK_MEMORY_B8G8R8X8: 4 bytes; for blue, green, red, unused. Since 4.14
|
||||
* @GDK_MEMORY_X8R8G8B8: 4 bytes; for unused, red, green, blue. Since 4.14
|
||||
* @GDK_MEMORY_R8G8B8X8: 4 bytes; for red, green, blue, unused. Since 4.14
|
||||
* @GDK_MEMORY_X8B8G8R8: 4 bytes; for unused, blue, green, red. Since 4.14
|
||||
* @GDK_MEMORY_R8G8B8: 3 bytes; for red, green, blue. The data is opaque.
|
||||
* @GDK_MEMORY_B8G8R8: 3 bytes; for blue, green, red. The data is opaque.
|
||||
* @GDK_MEMORY_R16G16B16: 3 guint16 values; for red, green, blue. Since: 4.6
|
||||
@@ -382,6 +388,11 @@ typedef enum {
|
||||
GDK_MEMORY_A16 GDK_AVAILABLE_ENUMERATOR_IN_4_12,
|
||||
GDK_MEMORY_A16_FLOAT GDK_AVAILABLE_ENUMERATOR_IN_4_12,
|
||||
GDK_MEMORY_A32_FLOAT GDK_AVAILABLE_ENUMERATOR_IN_4_12,
|
||||
GDK_MEMORY_A8B8G8R8_PREMULTIPLIED GDK_AVAILABLE_ENUMERATOR_IN_4_14,
|
||||
GDK_MEMORY_B8G8R8X8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
|
||||
GDK_MEMORY_X8R8G8B8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
|
||||
GDK_MEMORY_R8G8B8X8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
|
||||
GDK_MEMORY_X8B8G8R8 GDK_AVAILABLE_ENUMERATOR_IN_4_14,
|
||||
|
||||
GDK_MEMORY_N_FORMATS
|
||||
} GdkMemoryFormat;
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdkglversionprivate.h"
|
||||
#include "gdkdmabufformatsprivate.h"
|
||||
|
||||
#include "gdkprivate.h"
|
||||
|
||||
@@ -95,6 +96,10 @@
|
||||
#include <epoxy/egl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define DEFAULT_ALLOWED_APIS GDK_GL_API_GL | GDK_GL_API_GLES
|
||||
@@ -109,6 +114,8 @@ typedef struct {
|
||||
guint has_sync : 1;
|
||||
guint has_unpack_subimage : 1;
|
||||
guint has_debug_output : 1;
|
||||
guint has_bgra : 1;
|
||||
guint has_image_storage : 1;
|
||||
guint extensions_checked : 1;
|
||||
guint debug_enabled : 1;
|
||||
guint forward_compatible : 1;
|
||||
@@ -1531,11 +1538,13 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
|
||||
priv->has_unpack_subimage = gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)) ||
|
||||
epoxy_has_gl_extension ("GL_EXT_unpack_subimage");
|
||||
priv->has_khr_debug = epoxy_has_gl_extension ("GL_KHR_debug");
|
||||
priv->has_bgra = epoxy_has_gl_extension ("GL_EXT_texture_format_BGRA8888");
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->has_unpack_subimage = TRUE;
|
||||
priv->has_khr_debug = epoxy_has_gl_extension ("GL_KHR_debug");
|
||||
priv->has_bgra = TRUE;
|
||||
|
||||
/* We asked for a core profile, but we didn't get one, so we're in legacy mode */
|
||||
if (!gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
|
||||
@@ -1555,6 +1564,8 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
|
||||
epoxy_has_gl_extension ("GL_ARB_sync") ||
|
||||
epoxy_has_gl_extension ("GL_APPLE_sync");
|
||||
|
||||
priv->has_image_storage = epoxy_has_gl_extension ("GL_EXT_EGL_image_storage");
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
{
|
||||
int max_texture_size;
|
||||
@@ -1566,6 +1577,8 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
|
||||
"* Extensions checked:\n"
|
||||
" - GL_KHR_debug: %s\n"
|
||||
" - GL_EXT_unpack_subimage: %s\n"
|
||||
" - GL_EXT_texture_format_BGRA8888: %s\n"
|
||||
" - GL_EXT_EGL_image_storage: %s\n"
|
||||
" - half float: %s\n"
|
||||
" - sync: %s",
|
||||
gdk_gl_context_get_use_es (context) ? "OpenGL ES" : "OpenGL",
|
||||
@@ -1575,6 +1588,8 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
|
||||
max_texture_size,
|
||||
priv->has_khr_debug ? "yes" : "no",
|
||||
priv->has_unpack_subimage ? "yes" : "no",
|
||||
priv->has_bgra ? "yes" : "no",
|
||||
priv->has_image_storage ? "yes" : "no",
|
||||
priv->has_half_float ? "yes" : "no",
|
||||
priv->has_sync ? "yes" : "no");
|
||||
}
|
||||
@@ -1862,6 +1877,44 @@ gdk_gl_context_has_sync (GdkGLContext *self)
|
||||
return priv->has_sync;
|
||||
}
|
||||
|
||||
/* Return if GL_BGRA works with glTexImage2D */
|
||||
gboolean
|
||||
gdk_gl_context_has_bgra (GdkGLContext *self)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
|
||||
|
||||
return priv->has_bgra;
|
||||
}
|
||||
|
||||
/* Return if glGenVertexArrays, glBindVertexArray and glDeleteVertexArrays
|
||||
* can be used
|
||||
*/
|
||||
gboolean
|
||||
gdk_gl_context_has_vertex_arrays (GdkGLContext *self)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
|
||||
|
||||
switch (priv->api)
|
||||
{
|
||||
case GDK_GL_API_GL:
|
||||
return TRUE;
|
||||
|
||||
case GDK_GL_API_GLES:
|
||||
return gdk_gl_version_get_major (&priv->gl_version) >= 3;
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_gl_context_has_image_storage (GdkGLContext *self)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
|
||||
|
||||
return priv->has_image_storage;
|
||||
}
|
||||
|
||||
/* This is currently private! */
|
||||
/* When using GL/ES, don't flip the 'R' and 'B' bits on Windows/ANGLE for glReadPixels() */
|
||||
gboolean
|
||||
@@ -1942,3 +1995,201 @@ gdk_gl_backend_use (GdkGLBackend backend_type)
|
||||
|
||||
g_assert (the_gl_backend_type == backend_type);
|
||||
}
|
||||
|
||||
guint
|
||||
gdk_gl_context_import_dmabuf (GdkGLContext *self,
|
||||
int width,
|
||||
int height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
int target)
|
||||
{
|
||||
#if defined(HAVE_EGL) && defined(HAVE_DMABUF)
|
||||
GdkDisplay *display = gdk_gl_context_get_display (self);
|
||||
EGLDisplay egl_display = gdk_display_get_egl_display (display);
|
||||
EGLint attribs[64];
|
||||
int i;
|
||||
EGLImage image;
|
||||
guint texture_id;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), 0);
|
||||
g_return_val_if_fail (width > 0, 0);
|
||||
g_return_val_if_fail (height > 0, 0);
|
||||
g_return_val_if_fail (1 <= dmabuf->n_planes && dmabuf->n_planes <= 4, 0);
|
||||
g_return_val_if_fail (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES, 0);
|
||||
|
||||
if (egl_display == EGL_NO_DISPLAY || !display->have_egl_dma_buf_import)
|
||||
return 0;
|
||||
|
||||
GDK_DEBUG (DMABUF,
|
||||
"Importing dmabuf (format: %.4s:%#" G_GINT64_MODIFIER "x, planes: %u) into GL",
|
||||
(char *) &dmabuf->fourcc, dmabuf->modifier, dmabuf->n_planes);
|
||||
|
||||
i = 0;
|
||||
attribs[i++] = EGL_IMAGE_PRESERVED_KHR;
|
||||
attribs[i++] = EGL_TRUE;
|
||||
attribs[i++] = EGL_WIDTH;
|
||||
attribs[i++] = width;
|
||||
attribs[i++] = EGL_HEIGHT;
|
||||
attribs[i++] = height;
|
||||
attribs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||
attribs[i++] = dmabuf->fourcc;
|
||||
|
||||
#define ADD_PLANE(plane) \
|
||||
{ \
|
||||
if (dmabuf->modifier != DRM_FORMAT_MOD_INVALID) \
|
||||
{ \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_MODIFIER_LO_EXT; \
|
||||
attribs[i++] = dmabuf->modifier & 0xFFFFFFFF; \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ## _MODIFIER_HI_EXT; \
|
||||
attribs[i++] = dmabuf->modifier >> 32; \
|
||||
} \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_FD_EXT; \
|
||||
attribs[i++] = dmabuf->planes[plane].fd; \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_PITCH_EXT; \
|
||||
attribs[i++] = dmabuf->planes[plane].stride; \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_OFFSET_EXT; \
|
||||
attribs[i++] = dmabuf->planes[plane].offset; \
|
||||
}
|
||||
|
||||
ADD_PLANE (0);
|
||||
|
||||
if (dmabuf->n_planes > 1) ADD_PLANE (1);
|
||||
if (dmabuf->n_planes > 2) ADD_PLANE (2);
|
||||
if (dmabuf->n_planes > 3) ADD_PLANE (3);
|
||||
|
||||
attribs[i++] = EGL_NONE;
|
||||
|
||||
image = eglCreateImageKHR (egl_display,
|
||||
EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
(EGLClientBuffer)NULL,
|
||||
attribs);
|
||||
|
||||
if (image == EGL_NO_IMAGE)
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "Creating EGLImage for dmabuf failed: %#x", eglGetError ());
|
||||
return 0;
|
||||
}
|
||||
|
||||
glGenTextures (1, &texture_id);
|
||||
glBindTexture (target, texture_id);
|
||||
glEGLImageTargetTexture2DOES (target, image);
|
||||
glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
eglDestroyImageKHR (egl_display, image);
|
||||
|
||||
return texture_id;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_gl_context_export_dmabuf (GdkGLContext *self,
|
||||
unsigned int texture_id,
|
||||
GdkDmabuf *dmabuf)
|
||||
{
|
||||
#if defined(HAVE_EGL) && defined(HAVE_DMABUF)
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
|
||||
GdkDisplay *display = gdk_gl_context_get_display (self);
|
||||
EGLDisplay egl_display = gdk_display_get_egl_display (display);
|
||||
EGLContext egl_context = priv->egl_context;
|
||||
EGLint attribs[10];
|
||||
EGLImage image;
|
||||
gboolean result = FALSE;
|
||||
int i;
|
||||
int fourcc;
|
||||
int n_planes;
|
||||
guint64 modifier;
|
||||
int fds[GDK_DMABUF_MAX_PLANES];
|
||||
int strides[GDK_DMABUF_MAX_PLANES];
|
||||
int offsets[GDK_DMABUF_MAX_PLANES];
|
||||
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), FALSE);
|
||||
g_return_val_if_fail (texture_id > 0, FALSE);
|
||||
g_return_val_if_fail (dmabuf != NULL, FALSE);
|
||||
|
||||
if (egl_display == EGL_NO_DISPLAY || !display->have_egl_dma_buf_export)
|
||||
return 0;
|
||||
|
||||
GDK_DEBUG (DMABUF, "Exporting GL texture to dmabuf");
|
||||
|
||||
i = 0;
|
||||
attribs[i++] = EGL_IMAGE_PRESERVED_KHR;
|
||||
attribs[i++] = EGL_TRUE;
|
||||
|
||||
attribs[i++] = EGL_NONE;
|
||||
|
||||
image = eglCreateImageKHR (egl_display,
|
||||
egl_context,
|
||||
EGL_GL_TEXTURE_2D_KHR,
|
||||
(EGLClientBuffer)GUINT_TO_POINTER (texture_id),
|
||||
attribs);
|
||||
|
||||
if (image == EGL_NO_IMAGE)
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "Creating EGLImage for dmabuf failed: %#x", eglGetError ());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!eglExportDMABUFImageQueryMESA (egl_display,
|
||||
image,
|
||||
&fourcc,
|
||||
&n_planes,
|
||||
&modifier))
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "eglExportDMABUFImageQueryMESA failed: %#x", eglGetError ());
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (n_planes < 1 || n_planes > GDK_DMABUF_MAX_PLANES)
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "dmabufs with %d planes are not supported", n_planes);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!eglExportDMABUFImageMESA (egl_display,
|
||||
image,
|
||||
fds,
|
||||
strides,
|
||||
offsets))
|
||||
{
|
||||
g_warning ("eglExportDMABUFImage failed: %#x", eglGetError ());
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
if (fds[i] == -1)
|
||||
{
|
||||
g_warning ("dmabuf plane %d has no file descriptor", i);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
dmabuf->fourcc = (guint32)fourcc;
|
||||
dmabuf->modifier = modifier;
|
||||
dmabuf->n_planes = n_planes;
|
||||
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
dmabuf->planes[i].fd = fds[i];
|
||||
dmabuf->planes[i].stride = (int) strides[i];
|
||||
dmabuf->planes[i].offset = (int) offsets[i];
|
||||
}
|
||||
|
||||
GDK_DEBUG (DMABUF,
|
||||
"Exported GL texture to dmabuf (format: %.4s:%#" G_GINT64_MODIFIER "x, planes: %d)",
|
||||
(char *)&fourcc, modifier, n_planes);
|
||||
|
||||
result = TRUE;
|
||||
|
||||
out:
|
||||
eglDestroyImageKHR (egl_display, image);
|
||||
|
||||
return result;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "gdkglcontext.h"
|
||||
#include "gdkdrawcontextprivate.h"
|
||||
#include "gdkglversionprivate.h"
|
||||
#include "gdkdmabufprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -157,7 +158,22 @@ gboolean gdk_gl_context_has_vertex_half_float (GdkGLContext
|
||||
|
||||
gboolean gdk_gl_context_has_sync (GdkGLContext *self) G_GNUC_PURE;
|
||||
|
||||
gboolean gdk_gl_context_has_bgra (GdkGLContext *self) G_GNUC_PURE;
|
||||
|
||||
gboolean gdk_gl_context_has_vertex_arrays (GdkGLContext *self) G_GNUC_PURE;
|
||||
|
||||
gboolean gdk_gl_context_has_image_storage (GdkGLContext *self) G_GNUC_PURE;
|
||||
|
||||
double gdk_gl_context_get_scale (GdkGLContext *self);
|
||||
|
||||
G_END_DECLS
|
||||
guint gdk_gl_context_import_dmabuf (GdkGLContext *self,
|
||||
int width,
|
||||
int height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
int target);
|
||||
|
||||
gboolean gdk_gl_context_export_dmabuf (GdkGLContext *self,
|
||||
unsigned int texture_id,
|
||||
GdkDmabuf *dmabuf);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -141,9 +141,7 @@ struct _Download
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gdk_gl_texture_find_format (gboolean use_es,
|
||||
guint gl_major,
|
||||
guint gl_minor,
|
||||
gdk_gl_texture_find_format (GdkGLContext *context,
|
||||
GdkMemoryAlpha alpha,
|
||||
GLint gl_format,
|
||||
GLint gl_type,
|
||||
@@ -159,7 +157,7 @@ gdk_gl_texture_find_format (gboolean use_es,
|
||||
if (gdk_memory_format_alpha (format) != alpha)
|
||||
continue;
|
||||
|
||||
if (!gdk_memory_format_gl_format (format, use_es, gl_major, gl_minor, &q_internal_format, &q_format, &q_type, q_swizzle))
|
||||
if (!gdk_memory_format_gl_format (format, context, &q_internal_format, &q_format, &q_type, q_swizzle))
|
||||
continue;
|
||||
|
||||
if (q_format != gl_format || q_type != gl_type)
|
||||
@@ -183,16 +181,13 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
Download *download = download_;
|
||||
GLenum gl_internal_format, gl_format, gl_type;
|
||||
GLint gl_swizzle[4];
|
||||
int major, minor;
|
||||
|
||||
format = gdk_texture_get_format (texture),
|
||||
expected_stride = texture->width * gdk_memory_format_bytes_per_pixel (download->format);
|
||||
gdk_gl_context_get_version (context, &major, &minor);
|
||||
|
||||
if (!gdk_gl_context_get_use_es (context) &&
|
||||
gdk_memory_format_gl_format (format,
|
||||
FALSE,
|
||||
major, minor,
|
||||
context,
|
||||
&gl_internal_format,
|
||||
&gl_format, &gl_type, gl_swizzle))
|
||||
{
|
||||
@@ -243,7 +238,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
{
|
||||
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, &gl_read_format);
|
||||
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, &gl_read_type);
|
||||
if (!gdk_gl_texture_find_format (TRUE, major, minor, gdk_memory_format_alpha (format), gl_read_format, gl_read_type, &actual_format))
|
||||
if (!gdk_gl_texture_find_format (context, gdk_memory_format_alpha (format), gl_read_format, gl_read_type, &actual_format))
|
||||
{
|
||||
gl_read_format = GL_RGBA;
|
||||
gl_read_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkglcontextprivate.h"
|
||||
|
||||
#include "gsk/gl/fp16private.h"
|
||||
|
||||
@@ -93,10 +94,17 @@ name ## _from_float (guchar *dest_data, \
|
||||
TYPED_FUNCS (b8g8r8a8_premultiplied, guchar, 2, 1, 0, 3, 4, 255)
|
||||
TYPED_FUNCS (a8r8g8b8_premultiplied, guchar, 1, 2, 3, 0, 4, 255)
|
||||
TYPED_FUNCS (r8g8b8a8_premultiplied, guchar, 0, 1, 2, 3, 4, 255)
|
||||
TYPED_FUNCS (a8b8g8r8_premultiplied, guchar, 3, 2, 1, 0, 4, 255)
|
||||
TYPED_FUNCS (b8g8r8a8, guchar, 2, 1, 0, 3, 4, 255)
|
||||
TYPED_FUNCS (a8r8g8b8, guchar, 1, 2, 3, 0, 4, 255)
|
||||
TYPED_FUNCS (r8g8b8a8, guchar, 0, 1, 2, 3, 4, 255)
|
||||
TYPED_FUNCS (a8b8g8r8, guchar, 3, 2, 1, 0, 4, 255)
|
||||
|
||||
TYPED_FUNCS (r8g8b8x8, guchar, 0, 1, 2, -1, 4, 255)
|
||||
TYPED_FUNCS (x8r8g8b8, guchar, 1, 2, 3, -1, 4, 255)
|
||||
TYPED_FUNCS (b8g8r8x8, guchar, 2, 1, 0, -1, 4, 255)
|
||||
TYPED_FUNCS (x8b8g8r8, guchar, 3, 2, 1, -1, 4, 255)
|
||||
|
||||
TYPED_FUNCS (r8g8b8, guchar, 0, 1, 2, -1, 3, 255)
|
||||
TYPED_FUNCS (b8g8r8, guchar, 2, 1, 0, -1, 3, 255)
|
||||
TYPED_FUNCS (r16g16b16, guint16, 0, 1, 2, -1, 6, 65535)
|
||||
@@ -352,7 +360,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
b8g8r8a8_premultiplied_to_float,
|
||||
b8g8r8a8_premultiplied_from_float,
|
||||
@@ -377,12 +385,22 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
r8g8b8a8_premultiplied_to_float,
|
||||
r8g8b8a8_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
a8b8g8r8_premultiplied_to_float,
|
||||
a8b8g8r8_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_B8G8R8A8] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
b8g8r8a8_to_float,
|
||||
b8g8r8a8_from_float,
|
||||
@@ -417,6 +435,46 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
a8b8g8r8_to_float,
|
||||
a8b8g8r8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_B8G8R8X8] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
|
||||
b8g8r8x8_to_float,
|
||||
b8g8r8x8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_X8R8G8B8] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
|
||||
x8r8g8b8_to_float,
|
||||
x8r8g8b8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R8G8B8X8] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
{ 0, 0, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
|
||||
r8g8b8x8_to_float,
|
||||
r8g8b8x8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_X8B8G8R8] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
GDK_MEMORY_U8,
|
||||
{ G_MAXUINT, G_MAXUINT, G_MAXUINT, G_MAXUINT },
|
||||
{ GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } },
|
||||
x8b8g8r8_to_float,
|
||||
x8b8g8r8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R8G8B8] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
3,
|
||||
@@ -511,7 +569,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
16,
|
||||
G_ALIGNOF (float),
|
||||
TRUE,
|
||||
GDK_MEMORY_FLOAT32,
|
||||
{ 0, 0, 3, 0 },
|
||||
{ GL_RGBA32F, GL_RGBA, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
|
||||
r32g32b32a32_float_to_float,
|
||||
@@ -733,14 +791,19 @@ gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth)
|
||||
|
||||
gboolean
|
||||
gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
guint gl_major,
|
||||
guint gl_minor,
|
||||
GdkGLContext *context,
|
||||
guint *out_internal_format,
|
||||
guint *out_format,
|
||||
guint *out_type,
|
||||
GLint out_swizzle[4])
|
||||
{
|
||||
int gl_major;
|
||||
int gl_minor;
|
||||
gboolean gles;
|
||||
|
||||
gdk_gl_context_get_version (context, &gl_major, &gl_minor);
|
||||
gles = gdk_gl_context_get_use_es (context);
|
||||
|
||||
*out_internal_format = memory_formats[format].gl.internal_format;
|
||||
*out_format = memory_formats[format].gl.format;
|
||||
*out_type = memory_formats[format].gl.type;
|
||||
@@ -752,6 +815,9 @@ gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
(memory_formats[format].min_gl_version.gles_major == gl_major &&
|
||||
memory_formats[format].min_gl_version.gles_minor > gl_minor))
|
||||
return FALSE;
|
||||
|
||||
if (*out_format == GL_BGRA && !gdk_gl_context_has_bgra (context))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkenums.h"
|
||||
#include "gdktypes.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
@@ -46,9 +47,7 @@ GdkMemoryDepth gdk_memory_depth_merge (GdkMemoryDepth
|
||||
GdkMemoryDepth depth2) G_GNUC_CONST;
|
||||
GdkMemoryFormat gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth) G_GNUC_CONST;
|
||||
gboolean gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
guint gl_major,
|
||||
guint gl_minor,
|
||||
GdkGLContext *context,
|
||||
guint *out_internal_format,
|
||||
guint *out_format,
|
||||
guint *out_type,
|
||||
|
||||
@@ -493,6 +493,12 @@ gdk_surface_real_get_scale (GdkSurface *surface)
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
static GdkSubsurface *
|
||||
gdk_surface_real_create_subsurface (GdkSurface *surface)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_constructed (GObject *object)
|
||||
{
|
||||
@@ -515,6 +521,7 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
|
||||
|
||||
klass->beep = gdk_surface_real_beep;
|
||||
klass->get_scale = gdk_surface_real_get_scale;
|
||||
klass->create_subsurface = gdk_surface_real_create_subsurface;
|
||||
|
||||
/**
|
||||
* GdkSurface:cursor: (attributes org.gtk.Property.get=gdk_surface_get_cursor org.gtk.Property.set=gdk_surface_set_cursor)
|
||||
@@ -3054,3 +3061,40 @@ gdk_surface_leave_monitor (GdkSurface *surface,
|
||||
{
|
||||
g_signal_emit (surface, signals[LEAVE_MONITOR], 0, monitor);
|
||||
}
|
||||
|
||||
GdkSubsurface *
|
||||
gdk_surface_create_subsurface (GdkSurface *surface)
|
||||
{
|
||||
return GDK_SURFACE_GET_CLASS (surface)->create_subsurface (surface);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_subsurface_destroy (GdkSubsurface *subsurface)
|
||||
{
|
||||
subsurface->class->destroy (subsurface);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *bounds)
|
||||
{
|
||||
subsurface->class->attach (subsurface, texture, bounds);
|
||||
}
|
||||
|
||||
/* If sibling is NULL, place the subsurface above its parent */
|
||||
void
|
||||
gdk_subsurface_place_above (GdkSubsurface *subsurface,
|
||||
GdkSubsurface *sibling)
|
||||
{
|
||||
subsurface->class->place_above (subsurface, sibling);
|
||||
}
|
||||
|
||||
/* If sibling is NULL, place the subsurface below its parent */
|
||||
void
|
||||
gdk_subsurface_place_below (GdkSubsurface *subsurface,
|
||||
GdkSubsurface *sibling)
|
||||
{
|
||||
subsurface->class->place_below (subsurface, sibling);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,14 @@
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdksurface.h"
|
||||
#include "gdktoplevel.h"
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GdkSubsurface GdkSubsurface;
|
||||
|
||||
typedef struct _GskRenderNode GskRenderNode;
|
||||
|
||||
struct _GdkSurface
|
||||
{
|
||||
GObject parent_instance;
|
||||
@@ -146,6 +151,9 @@ struct _GdkSurfaceClass
|
||||
cairo_region_t *region);
|
||||
void (* request_layout) (GdkSurface *surface);
|
||||
gboolean (* compute_size) (GdkSurface *surface);
|
||||
|
||||
GdkSubsurface *
|
||||
(* create_subsurface) (GdkSurface *surface);
|
||||
};
|
||||
|
||||
#define GDK_SURFACE_DESTROYED(d) (((GdkSurface *)(d))->destroyed)
|
||||
@@ -334,7 +342,34 @@ void gdk_surface_request_motion (GdkSurface *surface);
|
||||
|
||||
gboolean gdk_surface_supports_edge_constraints (GdkSurface *surface);
|
||||
|
||||
GdkSubsurface * gdk_surface_create_subsurface (GdkSurface *surface);
|
||||
|
||||
typedef struct _GdkSubsurfaceClass GdkSubsurfaceClass;
|
||||
struct _GdkSubsurfaceClass
|
||||
{
|
||||
void (* destroy) (GdkSubsurface *subsurface);
|
||||
void (* attach) (GdkSubsurface *subsurface,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *bounds);
|
||||
void (* place_above) (GdkSubsurface *subsurface,
|
||||
GdkSubsurface *sibling);
|
||||
void (* place_below) (GdkSubsurface *subsurface,
|
||||
GdkSubsurface *sibling);
|
||||
};
|
||||
|
||||
struct _GdkSubsurface
|
||||
{
|
||||
const GdkSubsurfaceClass *class;
|
||||
};
|
||||
|
||||
void gdk_subsurface_destroy (GdkSubsurface *subsurface);
|
||||
void gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *bounds);
|
||||
void gdk_subsurface_place_above (GdkSubsurface *subsurface,
|
||||
GdkSubsurface *sibling);
|
||||
void gdk_subsurface_place_below (GdkSubsurface *subsurface,
|
||||
GdkSubsurface *sibling);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -1475,6 +1475,13 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
gboolean validate = FALSE, have_debug_report = FALSE;
|
||||
VkResult res;
|
||||
|
||||
if (gdk_display_get_debug_flags (display) & GDK_DEBUG_VULKAN_DISABLE)
|
||||
{
|
||||
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
|
||||
_("Vulkan support disabled via GDK_DEBUG"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GDK_DISPLAY_GET_CLASS (display)->vk_extension_name == NULL)
|
||||
{
|
||||
g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
|
||||
|
||||
@@ -329,6 +329,7 @@ gdk_save_png (GdkTexture *texture)
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
@@ -340,6 +341,10 @@ gdk_save_png (GdkTexture *texture)
|
||||
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
case GDK_MEMORY_R8G8B8X8:
|
||||
case GDK_MEMORY_X8R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8X8:
|
||||
case GDK_MEMORY_X8B8G8R8:
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
png_format = PNG_COLOR_TYPE_RGB;
|
||||
depth = 8;
|
||||
|
||||
@@ -236,12 +236,17 @@ static const FormatData format_data[] = {
|
||||
[GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_B8G8R8A8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_A8R8G8B8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_R8G8B8A8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_A8B8G8R8] = { GDK_MEMORY_R8G8B8A8, 8, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_R8G8B8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_B8G8R8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_R8G8B8X8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_X8R8G8B8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_B8G8R8X8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_X8B8G8R8] = { GDK_MEMORY_R8G8B8, 8, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_R16G16B16] = { GDK_MEMORY_R16G16B16, 16, 3, SAMPLEFORMAT_UINT, 0, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = { GDK_MEMORY_R16G16B16A16_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_ASSOCALPHA, PHOTOMETRIC_RGB },
|
||||
[GDK_MEMORY_R16G16B16A16] = { GDK_MEMORY_R16G16B16A16, 16, 4, SAMPLEFORMAT_UINT, EXTRASAMPLE_UNASSALPHA, PHOTOMETRIC_RGB },
|
||||
|
||||
@@ -18,6 +18,7 @@ gdk_public_sources = files([
|
||||
'gdkdisplay.c',
|
||||
'gdkdisplaymanager.c',
|
||||
'gdkdmabuf.c',
|
||||
'gdkdmabufegl.c',
|
||||
'gdkdmabufformats.c',
|
||||
'gdkdmabufformatsbuilder.c',
|
||||
'gdkdmabuftexture.c',
|
||||
@@ -216,6 +217,7 @@ gdk_deps = [
|
||||
platform_gio_dep,
|
||||
pangocairo_dep,
|
||||
vulkan_dep,
|
||||
dmabuf_dep,
|
||||
png_dep,
|
||||
tiff_dep,
|
||||
jpeg_dep,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -267,45 +269,105 @@ postpone_on_globals_closure (GdkWaylandDisplay *display_wayland,
|
||||
g_list_append (display_wayland->on_has_globals_closures, closure);
|
||||
}
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
|
||||
static const char *
|
||||
get_format_name (uint32_t format,
|
||||
char name[10])
|
||||
{
|
||||
if (format == 0)
|
||||
g_strlcpy (name, "ARGB8888", 10);
|
||||
else if (format == 1)
|
||||
g_strlcpy (name, "XRGB8888", 10);
|
||||
else
|
||||
g_snprintf (name, 10, "4cc %c%c%c%c",
|
||||
(char) (format & 0xff),
|
||||
(char) ((format >> 8) & 0xff),
|
||||
(char) ((format >> 16) & 0xff),
|
||||
(char) ((format >> 24) & 0xff));
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
wl_shm_format (void *data,
|
||||
struct wl_shm *wl_shm,
|
||||
uint32_t format)
|
||||
{
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
char buf[10];
|
||||
#endif
|
||||
|
||||
GDK_DEBUG (MISC, "supported pixel format %s (0x%X)",
|
||||
get_format_name (format, buf), (guint) format);
|
||||
GDK_DEBUG (MISC, "supported shm pixel format %.4s (0x%X)", (char *) &format, format);
|
||||
}
|
||||
|
||||
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, " %.4s:%#" G_GINT64_MODIFIER "x", (char *) &f, 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 +444,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 +798,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;
|
||||
|
||||
@@ -75,7 +75,7 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
|
||||
WL_SURFACE_OFFSET_SINCE_VERSION)
|
||||
wl_surface_offset (impl->display_server.wl_surface, dx, dy);
|
||||
|
||||
/* We should do ths when setting up the EGLSurface, but we don't make_current then */
|
||||
/* We should do this when setting up the EGLSurface, but we don't make_current then */
|
||||
eglSwapInterval (gdk_display_get_egl_display (gdk_draw_context_get_display (draw_context)), 0);
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->end_frame (draw_context, painted);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <gdk/wayland/gdkdisplay-wayland.h>
|
||||
#include <gdk/wayland/gdkseat-wayland.h>
|
||||
|
||||
#include <gsk/gsk.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
|
||||
@@ -222,4 +223,3 @@ void gdk_wayland_surface_update_scale (GdkSurface *surface);
|
||||
|
||||
GdkModifierType gdk_wayland_keymap_get_gdk_modifiers (GdkKeymap *keymap,
|
||||
guint32 mods);
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ struct _GdkWaylandSurface
|
||||
uint32_t last_configure_serial;
|
||||
|
||||
int state_freeze_count;
|
||||
|
||||
GPtrArray *subsurfaces;
|
||||
};
|
||||
|
||||
typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
|
||||
|
||||
@@ -33,9 +33,11 @@
|
||||
#include "gdksurfaceprivate.h"
|
||||
#include "gdktoplevelprivate.h"
|
||||
#include "gdkdevice-wayland-private.h"
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
|
||||
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
|
||||
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -48,6 +50,7 @@
|
||||
#include "gdksurface-wayland-private.h"
|
||||
#include "gdktoplevel-wayland-private.h"
|
||||
|
||||
|
||||
/**
|
||||
* GdkWaylandSurface:
|
||||
*
|
||||
@@ -152,13 +155,17 @@ wl_region_from_cairo_region (GdkWaylandDisplay *display,
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Surface implementation */
|
||||
/* {{{ Surface implementation */
|
||||
|
||||
static void gdk_wayland_subsurface_destroy (GdkSubsurface *sub);
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_init (GdkWaylandSurface *impl)
|
||||
{
|
||||
impl->scale = GDK_FRACTIONAL_SCALE_INIT_INT (1);
|
||||
impl->viewport_dirty = TRUE;
|
||||
|
||||
impl->subsurfaces = g_ptr_array_new ();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -552,6 +559,7 @@ gdk_wayland_surface_finalize (GObject *object)
|
||||
|
||||
g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
|
||||
g_clear_pointer (&impl->input_region, cairo_region_destroy);
|
||||
g_clear_pointer (&impl->subsurfaces, g_ptr_array_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_surface_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -1135,6 +1143,17 @@ gdk_wayland_surface_set_input_region (GdkSurface *surface,
|
||||
impl->input_region_dirty = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_destroy_subsurfaces (GdkWaylandSurface *impl)
|
||||
{
|
||||
for (gsize i = 0; i < impl->subsurfaces->len; i++)
|
||||
{
|
||||
GdkSubsurface *sub = g_ptr_array_index (impl->subsurfaces, i);
|
||||
gdk_subsurface_destroy (sub);
|
||||
}
|
||||
g_ptr_array_set_size (impl->subsurfaces, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_destroy (GdkSurface *surface,
|
||||
gboolean foreign_destroy)
|
||||
@@ -1151,6 +1170,7 @@ gdk_wayland_surface_destroy (GdkSurface *surface,
|
||||
if (GDK_IS_TOPLEVEL (surface))
|
||||
gdk_wayland_toplevel_destroy (GDK_TOPLEVEL (surface));
|
||||
|
||||
gdk_wayland_surface_destroy_subsurfaces (GDK_WAYLAND_SURFACE (surface));
|
||||
gdk_wayland_surface_destroy_wl_surface (GDK_WAYLAND_SURFACE (surface));
|
||||
|
||||
frame_clock = gdk_surface_get_frame_clock (surface);
|
||||
@@ -1207,6 +1227,8 @@ gdk_wayland_surface_default_hide_surface (GdkWaylandSurface *surface)
|
||||
{
|
||||
}
|
||||
|
||||
static GdkSubsurface *gdk_wayland_surface_create_subsurface (GdkSurface *surface);
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
|
||||
{
|
||||
@@ -1230,6 +1252,7 @@ gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
|
||||
surface_class->get_scale = gdk_wayland_surface_get_scale;
|
||||
surface_class->set_opaque_region = gdk_wayland_surface_set_opaque_region;
|
||||
surface_class->request_layout = gdk_wayland_surface_request_layout;
|
||||
surface_class->create_subsurface = gdk_wayland_surface_create_subsurface;
|
||||
|
||||
klass->handle_configure = gdk_wayland_surface_default_handle_configure;
|
||||
klass->handle_frame = gdk_wayland_surface_default_handle_frame;
|
||||
@@ -1305,4 +1328,236 @@ gdk_wayland_surface_get_wl_surface (GdkSurface *surface)
|
||||
}
|
||||
|
||||
/* }}}} */
|
||||
/* {{{ Subsurface */
|
||||
|
||||
typedef struct {
|
||||
GdkSubsurface subsurface;
|
||||
|
||||
GdkWaylandSurface *parent;
|
||||
|
||||
struct wl_surface *wl_surface;
|
||||
struct wl_subsurface *wl_subsurface;
|
||||
struct wp_viewport *wp_viewport;
|
||||
} GdkWaylandSubsurface;
|
||||
|
||||
static void
|
||||
dmabuf_buffer_release (void *data,
|
||||
struct wl_buffer *wl_buffer)
|
||||
{
|
||||
GdkTexture *texture = data;
|
||||
|
||||
g_object_unref (texture);
|
||||
wl_buffer_destroy (wl_buffer);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener dmabuf_buffer_listener = {
|
||||
dmabuf_buffer_release,
|
||||
};
|
||||
|
||||
static struct wl_buffer *
|
||||
get_dmabuf_wl_buffer (GdkWaylandSubsurface *self,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self->parent)));
|
||||
const GdkDmabuf *dmabuf;
|
||||
struct zwp_linux_buffer_params_v1 *params;
|
||||
struct wl_buffer *wl_buffer;
|
||||
|
||||
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
|
||||
|
||||
params = zwp_linux_dmabuf_v1_create_params (display->linux_dmabuf);
|
||||
|
||||
for (gsize i = 0; i < dmabuf->n_planes; i++)
|
||||
zwp_linux_buffer_params_v1_add (params,
|
||||
dmabuf->planes[i].fd,
|
||||
i,
|
||||
dmabuf->planes[i].offset,
|
||||
dmabuf->planes[i].stride,
|
||||
dmabuf->modifier >> 32,
|
||||
dmabuf->modifier & 0xffffffff);
|
||||
|
||||
wl_buffer = zwp_linux_buffer_params_v1_create_immed (params,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture),
|
||||
dmabuf->fourcc,
|
||||
0);
|
||||
|
||||
wl_buffer_add_listener (wl_buffer, &dmabuf_buffer_listener, g_object_ref (texture));
|
||||
|
||||
return wl_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
shm_buffer_release (void *data,
|
||||
struct wl_buffer *wl_buffer)
|
||||
{
|
||||
cairo_surface_t *surface = data;
|
||||
|
||||
/* Note: the wl_buffer is destroyed as cairo user data */
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener shm_buffer_listener = {
|
||||
shm_buffer_release,
|
||||
};
|
||||
|
||||
static struct wl_buffer *
|
||||
get_shm_wl_buffer (GdkWaylandSubsurface *self,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self->parent)));
|
||||
int width, height;
|
||||
cairo_surface_t *surface;
|
||||
GdkTextureDownloader *downloader;
|
||||
struct wl_buffer *wl_buffer;
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
surface = gdk_wayland_display_create_shm_surface (display, width, height, &GDK_FRACTIONAL_SCALE_INIT_INT (1));
|
||||
|
||||
downloader = gdk_texture_downloader_new (texture);
|
||||
|
||||
gdk_texture_downloader_download_into (downloader,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
|
||||
gdk_texture_downloader_free (downloader);
|
||||
|
||||
wl_buffer = _gdk_wayland_shm_surface_get_wl_buffer (surface);
|
||||
wl_buffer_add_listener (wl_buffer, &shm_buffer_listener, surface);
|
||||
|
||||
return wl_buffer;
|
||||
}
|
||||
|
||||
static struct wl_buffer *
|
||||
get_wl_buffer (GdkWaylandSubsurface *self,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
if (GDK_IS_DMABUF_TEXTURE (texture))
|
||||
return get_dmabuf_wl_buffer (self, texture);
|
||||
else
|
||||
return get_shm_wl_buffer (self, texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *rect)
|
||||
{
|
||||
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
|
||||
|
||||
GDK_DEBUG (DMABUF,
|
||||
"Attaching texture %p at %f %f %f %f",
|
||||
texture,
|
||||
rect->origin.x, rect->origin.y, rect->size.width, rect->size.height);
|
||||
|
||||
if (rect)
|
||||
{
|
||||
wl_subsurface_set_position (self->wl_subsurface,
|
||||
floorf (rect->origin.x),
|
||||
floorf (rect->origin.y));
|
||||
wp_viewport_set_destination (self->wp_viewport,
|
||||
ceilf (rect->origin.x + rect->size.width) - floorf (rect->origin.x),
|
||||
ceilf (rect->origin.y + rect->size.height) - floorf (rect->origin.y));
|
||||
}
|
||||
|
||||
if (texture)
|
||||
{
|
||||
wl_surface_attach (self->wl_surface, get_wl_buffer (self, texture), 0, 0);
|
||||
wl_surface_damage_buffer (self->wl_surface,
|
||||
0, 0,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_surface_attach (self->wl_surface, NULL, 0, 0);
|
||||
}
|
||||
|
||||
wl_surface_commit (self->wl_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_subsurface_destroy (GdkSubsurface *sub)
|
||||
{
|
||||
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
|
||||
|
||||
g_clear_pointer (&self->wp_viewport, wp_viewport_destroy);
|
||||
g_clear_pointer (&self->wl_subsurface, wl_subsurface_destroy);
|
||||
g_clear_pointer (&self->wl_surface, wl_surface_destroy);
|
||||
|
||||
g_ptr_array_remove (self->parent->subsurfaces, self);
|
||||
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_subsurface_place_above (GdkSubsurface *sub,
|
||||
GdkSubsurface *sibling)
|
||||
{
|
||||
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
|
||||
GdkWaylandSubsurface *sib = (GdkWaylandSubsurface *)sibling;
|
||||
|
||||
g_return_if_fail (sib == NULL || self->parent == sib->parent);
|
||||
|
||||
wl_subsurface_place_above (self->wl_subsurface,
|
||||
sib ? sib->wl_surface : self->parent->display_server.wl_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_subsurface_place_below (GdkSubsurface *sub,
|
||||
GdkSubsurface *sibling)
|
||||
{
|
||||
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
|
||||
GdkWaylandSubsurface *sib = (GdkWaylandSubsurface *)sibling;
|
||||
|
||||
g_return_if_fail (sib == NULL || self->parent == sib->parent);
|
||||
|
||||
wl_subsurface_place_below (self->wl_subsurface,
|
||||
sib ? sib->wl_surface : self->parent->display_server.wl_surface);
|
||||
}
|
||||
|
||||
static const GdkSubsurfaceClass subsurface_class = {
|
||||
gdk_wayland_subsurface_destroy,
|
||||
gdk_wayland_subsurface_attach,
|
||||
gdk_wayland_subsurface_place_above,
|
||||
gdk_wayland_subsurface_place_below,
|
||||
};
|
||||
|
||||
static GdkSubsurface *
|
||||
gdk_wayland_surface_create_subsurface (GdkSurface *surface)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
|
||||
GdkWaylandSubsurface *sub;
|
||||
struct wl_region *wl_region;
|
||||
|
||||
if (display->viewporter == NULL)
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "Can't use subsurfaces without viewporter");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sub = g_new0 (GdkWaylandSubsurface, 1);
|
||||
|
||||
sub->subsurface.class = &subsurface_class;
|
||||
|
||||
sub->parent = impl;
|
||||
g_ptr_array_add (sub->parent->subsurfaces, sub);
|
||||
|
||||
sub->wl_surface = wl_compositor_create_surface (display->compositor);
|
||||
wl_region = wl_compositor_create_region (display->compositor);
|
||||
wl_surface_set_input_region (sub->wl_surface, wl_region);
|
||||
wl_region_destroy (wl_region);
|
||||
sub->wl_subsurface = wl_subcompositor_get_subsurface (display->subcompositor,
|
||||
sub->wl_surface,
|
||||
impl->display_server.wl_surface);
|
||||
sub->wp_viewport = wp_viewporter_get_viewport (display->viewporter, sub->wl_surface);
|
||||
|
||||
GDK_DEBUG (DMABUF, "Subsurface created");
|
||||
|
||||
return (GdkSubsurface *) sub;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -76,7 +76,8 @@ gsk_gl_attachment_state_bind_texture (GskGLAttachmentState *self,
|
||||
g_assert (self != NULL);
|
||||
g_assert (target == GL_TEXTURE_1D ||
|
||||
target == GL_TEXTURE_2D ||
|
||||
target == GL_TEXTURE_3D);
|
||||
target == GL_TEXTURE_3D ||
|
||||
target == GL_TEXTURE_EXTERNAL_OES);
|
||||
g_assert (texture >= GL_TEXTURE0 && texture <= GL_TEXTURE16);
|
||||
g_assert (texture - GL_TEXTURE0 < G_N_ELEMENTS (self->textures));
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@ typedef struct _GskGLBindFramebuffer GskGLBindFramebuffer;
|
||||
typedef struct _GskGLBindTexture GskGLBindTexture;
|
||||
|
||||
#define GSK_GL_N_FILTERS 3
|
||||
#define SAMPLER_EXTERNAL 9
|
||||
|
||||
G_STATIC_ASSERT (SAMPLER_EXTERNAL >= GSK_GL_N_FILTERS * GSK_GL_N_FILTERS);
|
||||
|
||||
static inline guint
|
||||
filter_index (GLint filter)
|
||||
|
||||
@@ -282,7 +282,10 @@ snapshot_attachments (const GskGLAttachmentState *state,
|
||||
{
|
||||
bind[count].id = state->textures[i].id;
|
||||
bind[count].texture = state->textures[i].texture;
|
||||
bind[count].sampler = state->textures[i].sampler;
|
||||
if (state->textures[i].target == GL_TEXTURE_EXTERNAL_OES)
|
||||
bind[count].sampler = SAMPLER_EXTERNAL;
|
||||
else
|
||||
bind[count].sampler = state->textures[i].sampler;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -1070,7 +1073,7 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
|
||||
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendEquation (GL_FUNC_ADD);
|
||||
|
||||
if (!gdk_gl_context_get_use_es (self->context))
|
||||
if (gdk_gl_context_has_vertex_arrays (self->context))
|
||||
{
|
||||
glGenVertexArrays (1, &vao_id);
|
||||
glBindVertexArray (vao_id);
|
||||
@@ -1190,12 +1193,23 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
|
||||
s->sync = NULL;
|
||||
}
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, bind->id);
|
||||
if (bind->sampler == SAMPLER_EXTERNAL)
|
||||
glBindTexture (GL_TEXTURE_EXTERNAL_OES, bind->id);
|
||||
else
|
||||
glBindTexture (GL_TEXTURE_2D, bind->id);
|
||||
textures[bind->texture] = bind->id;
|
||||
if (!self->has_samplers)
|
||||
{
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
|
||||
if (bind->sampler == SAMPLER_EXTERNAL)
|
||||
{
|
||||
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1205,8 +1219,16 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
|
||||
glBindSampler (bind->texture, self->samplers[bind->sampler]);
|
||||
else
|
||||
{
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
|
||||
if (bind->sampler == SAMPLER_EXTERNAL)
|
||||
{
|
||||
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS));
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS));
|
||||
}
|
||||
}
|
||||
samplers[bind->texture] = bind->sampler;
|
||||
}
|
||||
@@ -1257,7 +1279,7 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
|
||||
}
|
||||
|
||||
glDeleteBuffers (1, &vbo_id);
|
||||
if (!gdk_gl_context_get_use_es (self->context))
|
||||
if (gdk_gl_context_has_vertex_arrays (self->context))
|
||||
glDeleteVertexArrays (1, &vao_id);
|
||||
|
||||
gdk_profiler_set_int_counter (self->metrics.n_binds, n_binds);
|
||||
@@ -1324,7 +1346,7 @@ gsk_gl_command_queue_end_frame (GskGLCommandQueue *self)
|
||||
if (self->attachments->textures[i].id != 0)
|
||||
{
|
||||
glActiveTexture (GL_TEXTURE0 + i);
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
glBindTexture (self->attachments->textures[i].target, 0);
|
||||
|
||||
self->attachments->textures[i].id = 0;
|
||||
self->attachments->textures[i].changed = FALSE;
|
||||
@@ -1401,7 +1423,7 @@ gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
|
||||
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, texture_id);
|
||||
|
||||
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
@@ -1429,8 +1451,9 @@ gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
|
||||
}
|
||||
|
||||
/* Restore the previous texture if it was set */
|
||||
if (self->attachments->textures[0].id != 0)
|
||||
glBindTexture (GL_TEXTURE_2D, self->attachments->textures[0].id);
|
||||
if (self->attachments->textures[0].id != 0 &&
|
||||
self->attachments->textures[0].target == GL_TEXTURE_2D)
|
||||
glBindTexture (self->attachments->textures[0].target, self->attachments->textures[0].id);
|
||||
|
||||
return (int)texture_id;
|
||||
}
|
||||
@@ -1450,9 +1473,7 @@ gsk_gl_command_queue_create_framebuffer (GskGLCommandQueue *self)
|
||||
|
||||
static GdkMemoryFormat
|
||||
memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
gboolean use_es,
|
||||
guint major,
|
||||
guint minor,
|
||||
GdkGLContext *context,
|
||||
guint *gl_internalformat,
|
||||
guint *gl_format,
|
||||
guint *gl_type,
|
||||
@@ -1462,9 +1483,7 @@ memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
|
||||
/* First, try the format itself */
|
||||
if (gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
context,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1480,9 +1499,7 @@ memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
case GDK_MEMORY_FLOAT16:
|
||||
data_format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
if (gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
context,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1493,9 +1510,7 @@ memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
case GDK_MEMORY_U16:
|
||||
data_format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
if (gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
context,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1517,9 +1532,7 @@ memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
{
|
||||
data_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
if (gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
context,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1530,9 +1543,7 @@ memory_format_gl_format (GdkMemoryFormat data_format,
|
||||
/* If all else fails, pick the one format that's always supported */
|
||||
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
if (!gdk_memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
context,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1561,19 +1572,13 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
|
||||
GLenum gl_type;
|
||||
GLint gl_swizzle[4];
|
||||
gsize bpp;
|
||||
gboolean use_es;
|
||||
int major, minor;
|
||||
|
||||
use_es = gdk_gl_context_get_use_es (self->context);
|
||||
gdk_gl_context_get_version (self->context, &major, &minor);
|
||||
data_format = gdk_texture_get_format (texture);
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
data_format = memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
self->context,
|
||||
&gl_internalformat,
|
||||
&gl_format,
|
||||
&gl_type,
|
||||
@@ -1638,9 +1643,7 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
GLint gl_swizzle[4];
|
||||
gboolean use_es;
|
||||
int texture_id;
|
||||
int major, minor;
|
||||
|
||||
g_assert (GSK_IS_GL_COMMAND_QUEUE (self));
|
||||
|
||||
@@ -1673,13 +1676,9 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
|
||||
glBindTexture (GL_TEXTURE_2D, texture_id);
|
||||
|
||||
/* Initialize the texture */
|
||||
use_es = gdk_gl_context_get_use_es (self->context);
|
||||
gdk_gl_context_get_version (self->context, &major, &minor);
|
||||
data_format = gdk_texture_get_format (chunks[0].texture);
|
||||
data_format = memory_format_gl_format (data_format,
|
||||
use_es,
|
||||
major,
|
||||
minor,
|
||||
self->context,
|
||||
&gl_internalformat,
|
||||
&gl_format,
|
||||
&gl_type,
|
||||
|
||||
@@ -54,6 +54,7 @@ typedef struct _GskGLCommandBind
|
||||
*/
|
||||
guint texture : 4;
|
||||
|
||||
/* the sampler to use. We set sampler to 15 to indicate external textures */
|
||||
guint sampler : 4;
|
||||
|
||||
/* The identifier for the texture created with glGenTextures(). */
|
||||
@@ -234,8 +235,13 @@ struct _GskGLCommandQueue
|
||||
|
||||
/* Array of samplers that we use for mag/min filter handling. It is indexed
|
||||
* by the sampler_index() function.
|
||||
*
|
||||
* Note that when samplers are not supported (hello GLES), we fall back to
|
||||
* setting the texture filter, but that needs to be done for every texture.
|
||||
*
|
||||
* Also note that we don't use all of these samplers since some combinations
|
||||
* are invalid. An index of SAMPLER_EXTERNAL is used to indicate an external
|
||||
* texture, which needs special sampler treatment.
|
||||
*/
|
||||
GLuint samplers[GSK_GL_N_FILTERS * GSK_GL_N_FILTERS];
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ struct _GskGLCompiler
|
||||
|
||||
guint gl3 : 1;
|
||||
guint gles : 1;
|
||||
guint gles3 : 1;
|
||||
guint legacy : 1;
|
||||
guint debug_shaders : 1;
|
||||
};
|
||||
@@ -134,7 +135,10 @@ gsk_gl_compiler_new (GskGLDriver *driver,
|
||||
gdk_gl_context_get_version (context, &maj, &min);
|
||||
|
||||
if (maj >= 3)
|
||||
self->glsl_version = SHADER_VERSION_GLES3;
|
||||
{
|
||||
self->glsl_version = SHADER_VERSION_GLES3;
|
||||
self->gles3 = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->glsl_version = SHADER_VERSION_GLES;
|
||||
@@ -543,6 +547,7 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
|
||||
const char *legacy = "";
|
||||
const char *gl3 = "";
|
||||
const char *gles = "";
|
||||
const char *gles3 = "";
|
||||
int program_id;
|
||||
int vertex_id;
|
||||
int fragment_id;
|
||||
@@ -569,15 +574,17 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
|
||||
if (self->gles)
|
||||
gles = "#define GSK_GLES 1\n";
|
||||
|
||||
if (self->gles3)
|
||||
gles3 = "#define GSK_GLES3 1\n";
|
||||
|
||||
if (self->gl3)
|
||||
gl3 = "#define GSK_GL3 1\n";
|
||||
|
||||
vertex_id = glCreateShader (GL_VERTEX_SHADER);
|
||||
glShaderSource (vertex_id,
|
||||
10,
|
||||
11,
|
||||
(const char *[]) {
|
||||
version, debug, legacy, gl3, gles,
|
||||
clip,
|
||||
version, debug, legacy, gl3, gles, gles3, clip,
|
||||
get_shader_string (self->all_preamble),
|
||||
get_shader_string (self->vertex_preamble),
|
||||
get_shader_string (self->vertex_source),
|
||||
@@ -589,6 +596,7 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
|
||||
strlen (legacy),
|
||||
strlen (gl3),
|
||||
strlen (gles),
|
||||
strlen (gles3),
|
||||
strlen (clip),
|
||||
g_bytes_get_size (self->all_preamble),
|
||||
g_bytes_get_size (self->vertex_preamble),
|
||||
@@ -607,10 +615,9 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
|
||||
|
||||
fragment_id = glCreateShader (GL_FRAGMENT_SHADER);
|
||||
glShaderSource (fragment_id,
|
||||
10,
|
||||
11,
|
||||
(const char *[]) {
|
||||
version, debug, legacy, gl3, gles,
|
||||
clip,
|
||||
version, debug, legacy, gl3, gles, gles3, clip,
|
||||
get_shader_string (self->all_preamble),
|
||||
get_shader_string (self->fragment_preamble),
|
||||
get_shader_string (self->fragment_source),
|
||||
@@ -622,6 +629,7 @@ gsk_gl_compiler_compile (GskGLCompiler *self,
|
||||
strlen (legacy),
|
||||
strlen (gl3),
|
||||
strlen (gles),
|
||||
strlen (gles3),
|
||||
strlen (clip),
|
||||
g_bytes_get_size (self->all_preamble),
|
||||
g_bytes_get_size (self->fragment_preamble),
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
#include <gdk/gdkdmabuftextureprivate.h>
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GskGLDriver, gsk_gl_driver, G_TYPE_OBJECT)
|
||||
|
||||
@@ -224,6 +226,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 +242,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 +378,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; \
|
||||
@@ -400,6 +410,7 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
|
||||
} G_STMT_END;
|
||||
# include "gskglprograms.defs"
|
||||
#undef GSK_GL_DEFINE_PROGRAM
|
||||
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
|
||||
#undef GSK_GL_ADD_UNIFORM
|
||||
#undef GSK_GL_SHADER_SINGLE
|
||||
#undef GSK_GL_SHADER_JOINED
|
||||
@@ -702,6 +713,180 @@ gsk_gl_driver_cache_texture (GskGLDriver *self,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_DMABUF) && defined (HAVE_EGL)
|
||||
static void
|
||||
set_viewport_for_size (GskGLDriver *self,
|
||||
GskGLProgram *program,
|
||||
float width,
|
||||
float height)
|
||||
{
|
||||
float viewport[4] = { 0, 0, width, height };
|
||||
|
||||
gsk_gl_uniform_state_set4fv (program->uniforms,
|
||||
program->program_info,
|
||||
UNIFORM_SHARED_VIEWPORT, 0,
|
||||
1,
|
||||
(const float *)&viewport);
|
||||
self->stamps[UNIFORM_SHARED_VIEWPORT]++;
|
||||
}
|
||||
|
||||
#define ORTHO_NEAR_PLANE -10000
|
||||
#define ORTHO_FAR_PLANE 10000
|
||||
|
||||
static void
|
||||
set_projection_for_size (GskGLDriver *self,
|
||||
GskGLProgram *program,
|
||||
float width,
|
||||
float height)
|
||||
{
|
||||
graphene_matrix_t projection;
|
||||
|
||||
graphene_matrix_init_ortho (&projection, 0, width, 0, height, ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE);
|
||||
graphene_matrix_scale (&projection, 1, -1, 1);
|
||||
|
||||
gsk_gl_uniform_state_set_matrix (program->uniforms,
|
||||
program->program_info,
|
||||
UNIFORM_SHARED_PROJECTION, 0,
|
||||
&projection);
|
||||
self->stamps[UNIFORM_SHARED_PROJECTION]++;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_modelview (GskGLDriver *self,
|
||||
GskGLProgram *program)
|
||||
{
|
||||
graphene_matrix_t modelview;
|
||||
|
||||
graphene_matrix_init_identity (&modelview);
|
||||
|
||||
gsk_gl_uniform_state_set_matrix (program->uniforms,
|
||||
program->program_info,
|
||||
UNIFORM_SHARED_MODELVIEW, 0,
|
||||
&modelview);
|
||||
self->stamps[UNIFORM_SHARED_MODELVIEW]++;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_rect (GskGLCommandQueue *command_queue,
|
||||
float min_x,
|
||||
float min_y,
|
||||
float max_x,
|
||||
float max_y)
|
||||
{
|
||||
GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (command_queue);
|
||||
float min_u = 0;
|
||||
float max_u = 1;
|
||||
float min_v = 1;
|
||||
float max_v = 0;
|
||||
guint16 c = FP16_ZERO;
|
||||
|
||||
vertices[0] = (GskGLDrawVertex) { .position = { min_x, min_y }, .uv = { min_u, min_v }, .color = { c, c, c, c } };
|
||||
vertices[1] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { min_u, max_v }, .color = { c, c, c, c } };
|
||||
vertices[2] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { max_u, min_v }, .color = { c, c, c, c } };
|
||||
vertices[3] = (GskGLDrawVertex) { .position = { max_x, max_y }, .uv = { max_u, max_v }, .color = { c, c, c, c } };
|
||||
vertices[4] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { min_u, max_v }, .color = { c, c, c, c } };
|
||||
vertices[5] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { max_u, min_v }, .color = { c, c, c, c } };
|
||||
}
|
||||
|
||||
static unsigned int release_render_target (GskGLDriver *self,
|
||||
GskGLRenderTarget *render_target,
|
||||
gboolean release_texture,
|
||||
gboolean cache_texture);
|
||||
|
||||
static guint
|
||||
gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
|
||||
GdkDmabufTexture *texture)
|
||||
{
|
||||
GdkGLContext *context = self->command_queue->context;
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
int max_texture_size = self->command_queue->max_texture_size;
|
||||
const GdkDmabuf *dmabuf;
|
||||
guint texture_id;
|
||||
int width, height;
|
||||
GskGLProgram *program;
|
||||
GskGLRenderTarget *render_target;
|
||||
guint prev_fbo;
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
width = gdk_texture_get_width (GDK_TEXTURE (texture));
|
||||
height = gdk_texture_get_height (GDK_TEXTURE (texture));
|
||||
|
||||
if (width > max_texture_size || height > max_texture_size)
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "Can't import dmabuf bigger than MAX_TEXTURE_SIZE (%d)", max_texture_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dmabuf = gdk_dmabuf_texture_get_dmabuf (texture);
|
||||
|
||||
GDK_DEBUG (DMABUF, "DMA-buf Format %.4s:%#lx", (char *) &dmabuf->fourcc, dmabuf->modifier);
|
||||
|
||||
gdk_display_init_dmabuf (display);
|
||||
|
||||
if (!gdk_dmabuf_formats_contains (display->egl_external_formats, dmabuf->fourcc, dmabuf->modifier))
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "Import dmabuf as GL_TEXTURE_2D texture");
|
||||
return gdk_gl_context_import_dmabuf (context, width, height,
|
||||
dmabuf,
|
||||
GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
if (!gdk_gl_context_get_use_es (context))
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "Can't import external_only dmabuf outside of GLES");
|
||||
return 0;
|
||||
}
|
||||
|
||||
GDK_DEBUG (DMABUF, "Import dmabuf as GL_TEXTURE_EXTERNAL_OES texture");
|
||||
|
||||
texture_id = gdk_gl_context_import_dmabuf (context, width, height,
|
||||
dmabuf,
|
||||
GL_TEXTURE_EXTERNAL_OES);
|
||||
|
||||
if (texture_id == 0)
|
||||
return 0;
|
||||
|
||||
gsk_gl_driver_autorelease_texture (self, texture_id);
|
||||
|
||||
program = self->external;
|
||||
|
||||
gsk_gl_driver_create_render_target (self, width, height, GL_RGBA8, &render_target);
|
||||
|
||||
prev_fbo = gsk_gl_command_queue_bind_framebuffer (self->command_queue, render_target->framebuffer_id);
|
||||
gsk_gl_command_queue_clear (self->command_queue, 0, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
if (gsk_gl_command_queue_begin_draw (self->command_queue, program->program_info, width, height))
|
||||
{
|
||||
set_projection_for_size (self, program, width, height);
|
||||
set_viewport_for_size (self, program, width, height);
|
||||
reset_modelview (self, program);
|
||||
|
||||
gsk_gl_program_set_uniform_texture (program,
|
||||
UNIFORM_EXTERNAL_SOURCE, 0,
|
||||
GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE0, texture_id);
|
||||
|
||||
draw_rect (self->command_queue, 0, 0, width, height);
|
||||
|
||||
gsk_gl_command_queue_end_draw (self->command_queue);
|
||||
}
|
||||
|
||||
gsk_gl_command_queue_bind_framebuffer (self->command_queue, prev_fbo);
|
||||
|
||||
return release_render_target (self, render_target, FALSE, FALSE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static guint
|
||||
gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
|
||||
GdkDmabufTexture *texture)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DMABUF && HAVE_EGL */
|
||||
|
||||
/**
|
||||
* gsk_gl_driver_load_texture:
|
||||
* @self: a `GdkTexture`
|
||||
@@ -758,7 +943,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);
|
||||
@@ -961,6 +1150,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`
|
||||
@@ -986,36 +1216,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1600,8 +1801,9 @@ create_texture_from_texture_destroy (gpointer data)
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
|
||||
guint texture_id)
|
||||
gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
|
||||
guint texture_id,
|
||||
GdkMemoryFormat format)
|
||||
{
|
||||
GskGLTextureState *state;
|
||||
GdkGLTextureBuilder *builder;
|
||||
@@ -1629,6 +1831,7 @@ gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
|
||||
builder = gdk_gl_texture_builder_new ();
|
||||
gdk_gl_texture_builder_set_context (builder, self->command_queue->context);
|
||||
gdk_gl_texture_builder_set_id (builder, texture_id);
|
||||
gdk_gl_texture_builder_set_format (builder, format);
|
||||
gdk_gl_texture_builder_set_width (builder, texture->width);
|
||||
gdk_gl_texture_builder_set_height (builder, texture->height);
|
||||
gdk_gl_texture_builder_set_sync (builder, state->sync);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -149,7 +154,8 @@ void gsk_gl_driver_begin_frame (GskGLDriver *s
|
||||
void gsk_gl_driver_end_frame (GskGLDriver *self);
|
||||
void gsk_gl_driver_after_frame (GskGLDriver *self);
|
||||
GdkTexture * gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
|
||||
guint texture_id);
|
||||
guint texture_id,
|
||||
GdkMemoryFormat format);
|
||||
void gsk_gl_driver_cache_texture (GskGLDriver *self,
|
||||
const GskTextureKey *key,
|
||||
guint texture_id);
|
||||
|
||||
@@ -119,7 +119,11 @@ gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
|
||||
|
||||
memset (pixel_data, 255, sizeof pixel_data);
|
||||
|
||||
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
|
||||
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ())
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
|| gdk_gl_context_get_use_es (gdk_gl_context_get_current ())
|
||||
#endif
|
||||
)
|
||||
{
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
@@ -127,9 +131,8 @@ gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
|
||||
else
|
||||
{
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
|
||||
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
@@ -277,7 +280,7 @@ gsk_gl_glyph_library_upload_glyph (GskGLGlyphLibrary *self,
|
||||
|
||||
g_assert (texture_id > 0);
|
||||
|
||||
if G_UNLIKELY (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
|
||||
if (G_UNLIKELY (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ())))
|
||||
{
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data, width * 4,
|
||||
@@ -294,7 +297,7 @@ gsk_gl_glyph_library_upload_glyph (GskGLGlyphLibrary *self,
|
||||
{
|
||||
pixel_data = cairo_image_surface_get_data (surface);
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / 4);
|
||||
|
||||
@@ -111,7 +111,11 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
|
||||
gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
|
||||
"Uploading texture");
|
||||
|
||||
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
|
||||
if (!gdk_gl_context_has_bgra (gdk_gl_context_get_current ())
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
|| gdk_gl_context_get_use_es (gdk_gl_context_get_current ())
|
||||
#endif
|
||||
)
|
||||
{
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data, width * 4,
|
||||
@@ -125,7 +129,7 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
|
||||
{
|
||||
pixel_data = surface_data;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (icon_data);
|
||||
|
||||
@@ -87,3 +87,13 @@ GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
|
||||
GSK_GL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
|
||||
GSK_GL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
|
||||
GSK_GL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
|
||||
|
||||
/* Texture conversion shaders.
|
||||
*
|
||||
* Note: If you add new formats here, they need to be added
|
||||
* to the list of supported formats in gdk/gdkdmabuftexture.c.
|
||||
*/
|
||||
|
||||
GSK_GL_DEFINE_PROGRAM_NO_CLIP (external,
|
||||
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("external.glsl")),
|
||||
GSK_GL_ADD_UNIFORM (1, EXTERNAL_SOURCE, u_external_source))
|
||||
|
||||
@@ -332,6 +332,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
|
||||
GskGLRenderJob *job;
|
||||
GdkTexture *texture;
|
||||
guint texture_id;
|
||||
GdkMemoryFormat gdk_format;
|
||||
int width, height, max_size;
|
||||
int format;
|
||||
|
||||
@@ -375,9 +376,15 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
|
||||
|
||||
if (gsk_render_node_get_preferred_depth (root) != GDK_MEMORY_U8 &&
|
||||
gdk_gl_context_check_version (self->context, "3.0", "3.0"))
|
||||
format = GL_RGBA32F;
|
||||
{
|
||||
gdk_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
format = GL_RGBA32F;
|
||||
}
|
||||
else
|
||||
format = GL_RGBA8;
|
||||
{
|
||||
format = GL_RGBA8;
|
||||
gdk_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
}
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
|
||||
@@ -394,7 +401,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
|
||||
#endif
|
||||
gsk_gl_render_job_render_flipped (job, root);
|
||||
texture_id = gsk_gl_driver_release_render_target (self->driver, render_target, FALSE);
|
||||
texture = gsk_gl_driver_create_gdk_texture (self->driver, texture_id);
|
||||
texture = gsk_gl_driver_create_gdk_texture (self->driver, texture_id, gdk_format);
|
||||
gsk_gl_driver_end_frame (self->driver);
|
||||
gsk_gl_render_job_free (job);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <gsk/gskglshaderprivate.h>
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
#include <gdk/gdkmemorytextureprivate.h>
|
||||
#include <gdk/gdkdmabuftexture.h>
|
||||
#include <gsk/gsktransformprivate.h>
|
||||
#include <gsk/gskroundedrectprivate.h>
|
||||
#include <gsk/gskrectprivate.h>
|
||||
@@ -47,6 +48,7 @@
|
||||
#include "ninesliceprivate.h"
|
||||
#include "fp16private.h"
|
||||
|
||||
|
||||
#define ORTHO_NEAR_PLANE -10000
|
||||
#define ORTHO_FAR_PLANE 10000
|
||||
#define MAX_GRADIENT_STOPS 6
|
||||
@@ -3630,16 +3632,12 @@ 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);
|
||||
|
||||
/* Don't put GL or dmabuf textures into icon caches, they are already on the GPU side */
|
||||
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;
|
||||
|
||||
@@ -3653,16 +3651,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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3784,12 +3784,6 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
|
||||
GskTextureKey key;
|
||||
guint texture_id;
|
||||
|
||||
if (filter == GSK_SCALING_FILTER_LINEAR)
|
||||
{
|
||||
gsk_gl_render_job_visit_texture (job, texture, bounds);
|
||||
return;
|
||||
}
|
||||
|
||||
gsk_gl_render_job_untransform_bounds (job, &job->current_clip->rect.bounds, &clip_rect);
|
||||
|
||||
if (!graphene_rect_intersection (bounds, &clip_rect, &clip_rect))
|
||||
|
||||
28
gsk/gl/resources/external.glsl
Normal file
28
gsk/gl/resources/external.glsl
Normal file
@@ -0,0 +1,28 @@
|
||||
// VERTEX_SHADER:
|
||||
// external.glsl
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
vUv = vec2(aUv.x, aUv.y);
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
// external.glsl
|
||||
|
||||
#if defined(GSK_GLES) || defined(GSK_GLES3)
|
||||
uniform samplerExternalOES u_external_source;
|
||||
#else
|
||||
/* Just to make this compile, we won't use it without GLES */
|
||||
uniform sampler2D u_external_source;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
/* Open-code this here, since GskTexture() expects a sampler2D */
|
||||
#if defined(GSK_GLES) || defined(GSK_LEGACY)
|
||||
vec4 color = texture2D(u_external_source, vUv);
|
||||
#else
|
||||
vec4 color = texture(u_external_source, vUv);
|
||||
#endif
|
||||
gskSetOutputColor(color);
|
||||
}
|
||||
@@ -1,3 +1,9 @@
|
||||
#if defined(GSK_GLES3)
|
||||
#extension GL_OES_EGL_image_external_essl3 : require
|
||||
#elif defined (GSK_GLES)
|
||||
#extension GL_OES_EGL_image_external : require
|
||||
#endif
|
||||
|
||||
#ifndef GSK_LEGACY
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
@@ -684,3 +684,22 @@ gsk_renderer_set_debug_flags (GskRenderer *renderer,
|
||||
|
||||
priv->debug_flags = flags;
|
||||
}
|
||||
|
||||
/* Feed a texture through a renderer and return the resulting 'native' texture. */
|
||||
GdkTexture *
|
||||
gsk_renderer_convert_texture (GskRenderer *self,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
int width, height;
|
||||
GskRenderNode *node;
|
||||
GdkTexture *result;
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
node = gsk_texture_node_new (texture, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
result = gsk_renderer_render_texture (self, node, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
gsk_render_node_unref (node);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -56,5 +56,8 @@ GskDebugFlags gsk_renderer_get_debug_flags (GskRenderer
|
||||
void gsk_renderer_set_debug_flags (GskRenderer *renderer,
|
||||
GskDebugFlags flags);
|
||||
|
||||
GdkTexture * gsk_renderer_convert_texture (GskRenderer *renderer,
|
||||
GdkTexture *texture);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "gdk/gdkrgbaprivate.h"
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
#include "gdk/gdkmemoryformatprivate.h"
|
||||
#include <gtk/css/gtkcss.h>
|
||||
#include "gtk/css/gtkcssdataurlprivate.h"
|
||||
#include "gtk/css/gtkcssparserprivate.h"
|
||||
@@ -3169,45 +3170,20 @@ append_texture_param (Printer *p,
|
||||
g_hash_table_insert (p->named_textures, texture, new_name);
|
||||
}
|
||||
|
||||
switch (gdk_texture_get_format (texture))
|
||||
switch (gdk_memory_format_get_depth (gdk_texture_get_format (texture)))
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16:
|
||||
case GDK_MEMORY_G8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_G8A8:
|
||||
case GDK_MEMORY_G8:
|
||||
case GDK_MEMORY_G16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_G16A16:
|
||||
case GDK_MEMORY_G16:
|
||||
case GDK_MEMORY_A8:
|
||||
case GDK_MEMORY_A16:
|
||||
case GDK_MEMORY_U8:
|
||||
case GDK_MEMORY_U16:
|
||||
bytes = gdk_texture_save_to_png_bytes (texture);
|
||||
g_string_append (p->str, "url(\"data:image/png;base64,");
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
||||
case GDK_MEMORY_A16_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
||||
case GDK_MEMORY_A32_FLOAT:
|
||||
case GDK_MEMORY_FLOAT16:
|
||||
case GDK_MEMORY_FLOAT32:
|
||||
bytes = gdk_texture_save_to_tiff_bytes (texture);
|
||||
g_string_append (p->str, "url(\"data:image/tiff;base64,");
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ gsk_private_gl_shaders = [
|
||||
'gl/resources/custom.glsl',
|
||||
'gl/resources/filled_border.glsl',
|
||||
'gl/resources/mask.glsl',
|
||||
'gl/resources/external.glsl',
|
||||
]
|
||||
|
||||
gsk_public_sources = files([
|
||||
|
||||
@@ -80,6 +80,15 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(A, B, G, R), 0 },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
@@ -117,6 +126,17 @@ gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_B8G8R8X8:
|
||||
case GDK_MEMORY_X8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8X8:
|
||||
case GDK_MEMORY_X8B8G8R8:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
@@ -324,6 +344,7 @@ gsk_memory_format_get_fallback (GdkMemoryFormat format)
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
@@ -331,6 +352,10 @@ gsk_memory_format_get_fallback (GdkMemoryFormat format)
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
|
||||
case GDK_MEMORY_B8G8R8X8:
|
||||
case GDK_MEMORY_X8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8X8:
|
||||
case GDK_MEMORY_X8B8G8R8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
return GDK_MEMORY_R8G8B8;
|
||||
|
||||
|
||||
21
meson.build
21
meson.build
@@ -1,5 +1,5 @@
|
||||
project('gtk', 'c',
|
||||
version: '4.13.2',
|
||||
version: '4.13.3',
|
||||
default_options: [
|
||||
'buildtype=debugoptimized',
|
||||
'warning_level=1',
|
||||
@@ -162,7 +162,6 @@ check_headers = [
|
||||
'inttypes.h',
|
||||
'linux/input.h',
|
||||
'linux/memfd.h',
|
||||
'linux/dma-buf.h',
|
||||
'locale.h',
|
||||
'memory.h',
|
||||
'stdint.h',
|
||||
@@ -186,10 +185,6 @@ foreach h : check_headers
|
||||
endif
|
||||
endforeach
|
||||
|
||||
if os_linux and not cc.has_header('linux/dma-buf.h')
|
||||
error('OS is Linux, but linux/dma-buf.h not found.')
|
||||
endif
|
||||
|
||||
# Maths functions might be implemented in libm
|
||||
libm = cc.find_library('m', required: false)
|
||||
|
||||
@@ -623,6 +618,20 @@ else
|
||||
vulkan_pkg_found = false
|
||||
endif
|
||||
|
||||
if cc.has_header('linux/dma-buf.h')
|
||||
dmabuf_dep = dependency('libdrm',
|
||||
required: os_linux)
|
||||
else
|
||||
if os_linux
|
||||
error('OS is Linux, but linux/dma-buf.h not found.')
|
||||
endif
|
||||
dmabuf_dep = dependency('', required: false)
|
||||
endif
|
||||
cdata.set('HAVE_DMABUF', dmabuf_dep.found())
|
||||
# We only care about drm_fourcc.h for all the fourccs,
|
||||
# but not about linking to libdrm
|
||||
dmabuf_dep = dmabuf_dep.partial_dependency(includes: true, compile_args: true)
|
||||
|
||||
cloudproviders_dep = dependency('cloudproviders',
|
||||
required: get_option('cloudproviders'),
|
||||
version: cloudproviders_req,
|
||||
|
||||
@@ -23,6 +23,7 @@ gdk/gdkseat.c
|
||||
gdk/gdksurface.c
|
||||
gdk/gdktexture.c
|
||||
gdk/gdktoplevel.c
|
||||
gdk/gdkvulkancontext.c
|
||||
gdk/keynamesprivate.h
|
||||
gdk/loaders/gdkjpeg.c
|
||||
gdk/loaders/gdkpng.c
|
||||
|
||||
34
po/tr.po
34
po/tr.po
@@ -22,9 +22,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gtk\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gtk/-/issues/\n"
|
||||
"POT-Creation-Date: 2023-10-13 09:55+0000\n"
|
||||
"PO-Revision-Date: 2023-10-14 08:00+0300\n"
|
||||
"Last-Translator: Emin Tufan Çetin <etcetin@gmail.com>\n"
|
||||
"POT-Creation-Date: 2023-10-16 11:58+0000\n"
|
||||
"PO-Revision-Date: 2023-10-17 18:20+0300\n"
|
||||
"Last-Translator: Sabri Ünal <libreajans@gmail.com>\n"
|
||||
"Language-Team: Türkçe <takim@gnome.org.tr>\n"
|
||||
"Language: tr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -61,58 +61,58 @@ msgstr "İçerikler “%s” olarak sağlanamıyor"
|
||||
msgid "Cannot provide contents as %s"
|
||||
msgstr "İçerikler %s olarak sağlanamıyor"
|
||||
|
||||
#: gdk/gdkdisplay.c:163 gdk/gdkglcontext.c:442
|
||||
#: gdk/gdkdisplay.c:164 gdk/gdkglcontext.c:442
|
||||
msgid "The current backend does not support OpenGL"
|
||||
msgstr "Şimdiki arka uç OpenGL’i desteklemiyor"
|
||||
|
||||
#: gdk/gdkdisplay.c:1258 gdk/gdksurface.c:1252
|
||||
#: gdk/gdkdisplay.c:1259 gdk/gdksurface.c:1252
|
||||
msgid "Vulkan support disabled via GDK_DEBUG"
|
||||
msgstr "Vulkan desteği GDK_DEBUG yoluyla devre dışı bırakılmış"
|
||||
|
||||
#: gdk/gdkdisplay.c:1290
|
||||
#: gdk/gdkdisplay.c:1291
|
||||
msgid "GL support disabled via GDK_DEBUG"
|
||||
msgstr "GL desteği, GDK_DEBUG yoluyla devre dışı bırakılmış"
|
||||
|
||||
#: gdk/gdkdisplay.c:1588
|
||||
#: gdk/gdkdisplay.c:1589
|
||||
msgid "No EGL configuration available"
|
||||
msgstr "Kullanılabilir EGL yapılandırması yok"
|
||||
|
||||
#: gdk/gdkdisplay.c:1596
|
||||
#: gdk/gdkdisplay.c:1597
|
||||
msgid "Failed to get EGL configurations"
|
||||
msgstr "EGL yapılandırmaları alınamadı"
|
||||
|
||||
#: gdk/gdkdisplay.c:1626
|
||||
#: gdk/gdkdisplay.c:1627
|
||||
msgid "No EGL configuration with required features found"
|
||||
msgstr "Gerekli özellikleri olan EGL yapılandırması bulunamadı"
|
||||
|
||||
#: gdk/gdkdisplay.c:1633
|
||||
#: gdk/gdkdisplay.c:1634
|
||||
msgid "No perfect EGL configuration found"
|
||||
msgstr "Kusursuz EGL yapılandırması bulunamadı"
|
||||
|
||||
#: gdk/gdkdisplay.c:1675
|
||||
#: gdk/gdkdisplay.c:1676
|
||||
#, c-format
|
||||
msgid "EGL implementation is missing extension %s"
|
||||
msgid_plural "EGL implementation is missing %2$d extensions: %1$s"
|
||||
msgstr[0] "EGL uygulamasında %2$d eksik uzantı: %1$s"
|
||||
|
||||
# https://twitter.com/mserdark/status/932936929213079559
|
||||
#: gdk/gdkdisplay.c:1708
|
||||
#: gdk/gdkdisplay.c:1709
|
||||
msgid "libEGL not available in this sandbox"
|
||||
msgstr "libEGL bu kum havuzunda kullanılamıyor"
|
||||
|
||||
#: gdk/gdkdisplay.c:1709
|
||||
#: gdk/gdkdisplay.c:1710
|
||||
msgid "libEGL not available"
|
||||
msgstr "libEGL kullanılamıyor"
|
||||
|
||||
#: gdk/gdkdisplay.c:1719
|
||||
#: gdk/gdkdisplay.c:1720
|
||||
msgid "Failed to create EGL display"
|
||||
msgstr "EGL ekranı oluşturulamadı"
|
||||
|
||||
#: gdk/gdkdisplay.c:1729
|
||||
#: gdk/gdkdisplay.c:1730
|
||||
msgid "Could not initialize EGL display"
|
||||
msgstr "EGL ekranı ilklendirilemedi"
|
||||
|
||||
#: gdk/gdkdisplay.c:1740
|
||||
#: gdk/gdkdisplay.c:1741
|
||||
#, c-format
|
||||
msgid "EGL version %d.%d is too old. GTK requires %d.%d"
|
||||
msgstr "EGL sürümü %d.%d çok eski. GTK, %d.%d gerektiriyor"
|
||||
@@ -3154,7 +3154,7 @@ msgstr "Birim ayrılamadı"
|
||||
#. Allow to cancel the operation
|
||||
#: gtk/gtkplacesview.c:1445
|
||||
msgid "Cance_l"
|
||||
msgstr "İpta_l"
|
||||
msgstr "İ_ptal"
|
||||
|
||||
#: gtk/gtkplacesview.c:1592
|
||||
msgid "AppleTalk"
|
||||
|
||||
@@ -125,7 +125,10 @@ gtk_tests = [
|
||||
]
|
||||
|
||||
if os_unix
|
||||
gtk_tests += [['testfontchooserdialog']]
|
||||
gtk_tests += [
|
||||
['testfontchooserdialog'],
|
||||
['testdmabuf'],
|
||||
]
|
||||
endif
|
||||
|
||||
if x11_enabled
|
||||
@@ -146,3 +149,11 @@ foreach t: gtk_tests
|
||||
dependencies: [libgtk_dep, libm],
|
||||
)
|
||||
endforeach
|
||||
|
||||
executable('testsubsurface',
|
||||
sources: '@0@.c'.format('testsubsurface'),
|
||||
c_args: common_cflags + ['-DGTK_COMPILATION'],
|
||||
dependencies: libgtk_static_dep,
|
||||
install: false,
|
||||
)
|
||||
|
||||
|
||||
525
tests/testdmabuf.c
Normal file
525
tests/testdmabuf.c
Normal file
@@ -0,0 +1,525 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/dma-heap.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
/* For this to work, you may need to give /dev/dma_heap/system
|
||||
* lax permissions.
|
||||
*/
|
||||
|
||||
static int dma_heap_fd = -1;
|
||||
|
||||
static gboolean
|
||||
initialize_dma_heap (void)
|
||||
{
|
||||
dma_heap_fd = open ("/dev/dma_heap/system", O_RDONLY | O_CLOEXEC);
|
||||
return dma_heap_fd != -1;
|
||||
}
|
||||
|
||||
static int
|
||||
allocate_dma_buf (gsize size)
|
||||
{
|
||||
struct dma_heap_allocation_data heap_data;
|
||||
int ret;
|
||||
|
||||
heap_data.len = size;
|
||||
heap_data.fd = 0;
|
||||
heap_data.fd_flags = O_RDWR | O_CLOEXEC;
|
||||
heap_data.heap_flags = 0;
|
||||
|
||||
ret = ioctl (dma_heap_fd, DMA_HEAP_IOCTL_ALLOC, &heap_data);
|
||||
if (ret)
|
||||
g_error ("dma-buf allocation failed");
|
||||
|
||||
return heap_data.fd;
|
||||
}
|
||||
|
||||
static int
|
||||
allocate_memfd (gsize size)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = memfd_create ("buffer", MFD_CLOEXEC);
|
||||
if (fd == -1)
|
||||
g_error ("memfd allocation failed");
|
||||
|
||||
ftruncate (fd, size);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int
|
||||
allocate_buffer (gsize size)
|
||||
{
|
||||
if (dma_heap_fd != -1)
|
||||
return allocate_dma_buf (size);
|
||||
else
|
||||
return allocate_memfd (size);
|
||||
}
|
||||
|
||||
static void
|
||||
populate_buffer (int fd,
|
||||
const guchar *data,
|
||||
gsize size)
|
||||
{
|
||||
guchar *buf;
|
||||
|
||||
buf = mmap (NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
memcpy (buf, data, size);
|
||||
munmap (buf, size);
|
||||
}
|
||||
|
||||
|
||||
/* The YUV conversion code is adapted from weston/tests/yuv-buffer-test.c */
|
||||
|
||||
/*
|
||||
* Based on Rec. ITU-R BT.601-7
|
||||
*
|
||||
* This is intended to be obvious and accurate, not fast.
|
||||
*/
|
||||
static void
|
||||
x8r8g8b8_to_ycbcr8_bt601 (guint32 xrgb,
|
||||
guchar *y_out,
|
||||
guchar *cb_out,
|
||||
guchar *cr_out)
|
||||
{
|
||||
double y, cb, cr;
|
||||
double r = (xrgb >> 16) & 0xff;
|
||||
double g = (xrgb >> 8) & 0xff;
|
||||
double b = (xrgb >> 0) & 0xff;
|
||||
|
||||
/* normalize to [0.0, 1.0] */
|
||||
r /= 255.0;
|
||||
g /= 255.0;
|
||||
b /= 255.0;
|
||||
|
||||
/* Y normalized to [0.0, 1.0], Cb and Cr [-0.5, 0.5] */
|
||||
y = 0.299 * r + 0.587 * g + 0.114 * b;
|
||||
cr = (r - y) / 1.402;
|
||||
cb = (b - y) / 1.772;
|
||||
|
||||
/* limited range quantization to 8 bit */
|
||||
*y_out = round(219.0 * y + 16.0);
|
||||
if (cr_out)
|
||||
*cr_out = round(224.0 * cr + 128.0);
|
||||
if (cb_out)
|
||||
*cb_out = round(224.0 * cb + 128.0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 3 plane YCbCr
|
||||
* plane 0: Y plane, [7:0] Y
|
||||
* plane 1: Cb plane, [7:0] Cb
|
||||
* plane 2: Cr plane, [7:0] Cr
|
||||
* YUV420: 2x2 subsampled Cb (1) and Cr (2) planes
|
||||
* YUV444: no subsampling
|
||||
*/
|
||||
static guchar *
|
||||
y_u_v_create_buffer (uint32_t drm_format,
|
||||
guchar *rgb_data,
|
||||
int rgb_width,
|
||||
int rgb_height,
|
||||
int *size,
|
||||
int *u_offset,
|
||||
int *v_offset)
|
||||
{
|
||||
gsize bytes;
|
||||
int x, y;
|
||||
guint32 *rgb_row;
|
||||
guchar *y_base;
|
||||
guchar *u_base;
|
||||
guchar *v_base;
|
||||
guchar *y_row;
|
||||
guchar *u_row;
|
||||
guchar *v_row;
|
||||
guint32 argb;
|
||||
int sub = (drm_format == DRM_FORMAT_YUV420) ? 2 : 1;
|
||||
guchar *buf;
|
||||
|
||||
g_assert (drm_format == DRM_FORMAT_YUV420 ||
|
||||
drm_format == DRM_FORMAT_YUV444);
|
||||
|
||||
/* Full size Y plus quarter U and V */
|
||||
bytes = rgb_width * rgb_height +
|
||||
(rgb_width / sub) * (rgb_height / sub) * 2;
|
||||
|
||||
buf = g_new (guchar, bytes);
|
||||
|
||||
*size = bytes;
|
||||
*u_offset = rgb_width * rgb_height;
|
||||
*v_offset = *u_offset + (rgb_width / sub) * (rgb_height / sub);
|
||||
|
||||
y_base = buf;
|
||||
u_base = y_base + rgb_width * rgb_height;
|
||||
v_base = u_base + (rgb_width / sub) * (rgb_height / sub);
|
||||
|
||||
for (y = 0; y < rgb_height; y++)
|
||||
{
|
||||
rgb_row = (guint32 *) (rgb_data + y * 4 * rgb_width);
|
||||
y_row = y_base + y * rgb_width;
|
||||
u_row = u_base + (y / sub) * (rgb_width / sub);
|
||||
v_row = v_base + (y / sub) * (rgb_width / sub);
|
||||
|
||||
for (x = 0; x < rgb_width; x++)
|
||||
{
|
||||
/*
|
||||
* Sub-sample the source image instead, so that U and V
|
||||
* sub-sampling does not require proper
|
||||
* filtering/averaging/siting.
|
||||
*/
|
||||
argb = rgb_row[x];
|
||||
|
||||
/*
|
||||
* A stupid way of "sub-sampling" chroma. This does not
|
||||
* do the necessary filtering/averaging/siting or
|
||||
* alternate Cb/Cr rows.
|
||||
*/
|
||||
if ((y & (sub - 1)) == 0 && (x & (sub - 1)) == 0)
|
||||
x8r8g8b8_to_ycbcr8_bt601 (argb, y_row + x, u_row + x / sub, v_row + x / sub);
|
||||
else
|
||||
x8r8g8b8_to_ycbcr8_bt601 (argb, y_row + x, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* 2 plane YCbCr
|
||||
* plane 0 = Y plane, [7:0] Y
|
||||
* plane 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
|
||||
* 2x2 subsampled Cr:Cb plane
|
||||
*/
|
||||
static guchar *
|
||||
nv12_create_buffer (uint32_t drm_format,
|
||||
guchar *rgb_data,
|
||||
int rgb_width,
|
||||
int rgb_height,
|
||||
int *size,
|
||||
int *uv_offset)
|
||||
{
|
||||
size_t bytes;
|
||||
int x, y;
|
||||
uint32_t *rgb_row;
|
||||
uint8_t *y_base;
|
||||
uint8_t *uv_base;
|
||||
uint8_t *y_row;
|
||||
uint16_t *uv_row;
|
||||
uint32_t argb;
|
||||
uint8_t cr;
|
||||
uint8_t cb;
|
||||
guchar *buf;
|
||||
|
||||
g_assert (drm_format == DRM_FORMAT_NV12);
|
||||
|
||||
/* Full size Y plane, half size UV plane */
|
||||
bytes = rgb_width * rgb_height +
|
||||
rgb_width * (rgb_height / 2);
|
||||
*size = bytes;
|
||||
|
||||
buf = g_new0 (guchar, bytes);
|
||||
|
||||
*uv_offset = rgb_width * rgb_height;
|
||||
y_base = buf;
|
||||
uv_base = y_base + rgb_width * rgb_height;
|
||||
|
||||
for (y = 0; y < rgb_height; y++)
|
||||
{
|
||||
rgb_row = (uint32_t *) (rgb_data + y * 4 * rgb_width);
|
||||
y_row = y_base + y * rgb_width;
|
||||
uv_row = (uint16_t *) (uv_base + (y / 2) * rgb_width);
|
||||
|
||||
for (x = 0; x < rgb_width; x++)
|
||||
{
|
||||
/*
|
||||
* Sub-sample the source image instead, so that U and V
|
||||
* sub-sampling does not require proper
|
||||
* filtering/averaging/siting.
|
||||
*/
|
||||
argb = rgb_row[x];
|
||||
|
||||
/*
|
||||
* A stupid way of "sub-sampling" chroma. This does not
|
||||
* do the necessary filtering/averaging/siting.
|
||||
*/
|
||||
if ((y & 1) == 0 && (x & 1) == 0)
|
||||
{
|
||||
x8r8g8b8_to_ycbcr8_bt601(argb, y_row + x, &cb, &cr);
|
||||
*(uv_row + x / 2) = ((uint16_t)cr << 8) | cb;
|
||||
}
|
||||
else
|
||||
{
|
||||
x8r8g8b8_to_ycbcr8_bt601(argb, y_row + x, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
texture_builder_set_planes (GdkDmabufTextureBuilder *builder,
|
||||
gboolean disjoint,
|
||||
const guchar *buf,
|
||||
unsigned size,
|
||||
unsigned n_planes,
|
||||
unsigned strides[4],
|
||||
unsigned sizes[4])
|
||||
{
|
||||
gdk_dmabuf_texture_builder_set_n_planes (builder, n_planes);
|
||||
|
||||
if (disjoint)
|
||||
{
|
||||
unsigned offset = 0;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
int fd = allocate_buffer (sizes[i]);
|
||||
populate_buffer (fd, buf + offset, sizes[i]);
|
||||
|
||||
gdk_dmabuf_texture_builder_set_fd (builder, i, fd);
|
||||
gdk_dmabuf_texture_builder_set_stride (builder, i, strides[i]);
|
||||
gdk_dmabuf_texture_builder_set_offset (builder, i, 0);
|
||||
offset += sizes[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned offset = 0;
|
||||
unsigned i;
|
||||
int fd = allocate_buffer (size);
|
||||
populate_buffer (fd, buf, size);
|
||||
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
gdk_dmabuf_texture_builder_set_fd (builder, i, fd);
|
||||
gdk_dmabuf_texture_builder_set_stride (builder, i, strides[i]);
|
||||
gdk_dmabuf_texture_builder_set_offset (builder, i, offset);
|
||||
offset += sizes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
make_dmabuf_texture (const char *filename,
|
||||
guint32 format,
|
||||
gboolean disjoint)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
int width, height;
|
||||
gsize rgb_stride, rgb_size;
|
||||
guchar *rgb_data;
|
||||
int fd;
|
||||
GdkDmabufTextureBuilder *builder;
|
||||
GError *error = NULL;
|
||||
|
||||
if (initialize_dma_heap ())
|
||||
g_print ("Using dma_heap\n");
|
||||
else
|
||||
g_print ("Using memfd\n");
|
||||
|
||||
texture = gdk_texture_new_from_filename (filename, NULL);
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
rgb_stride = 4 * width;
|
||||
rgb_size = rgb_stride * height;
|
||||
|
||||
rgb_data = g_new0 (guchar, rgb_size);
|
||||
|
||||
gdk_texture_download (texture, rgb_data, rgb_stride);
|
||||
|
||||
g_object_unref (texture);
|
||||
|
||||
builder = gdk_dmabuf_texture_builder_new ();
|
||||
|
||||
gdk_dmabuf_texture_builder_set_display (builder, gdk_display_get_default ());
|
||||
gdk_dmabuf_texture_builder_set_width (builder, width);
|
||||
gdk_dmabuf_texture_builder_set_height (builder, height);
|
||||
gdk_dmabuf_texture_builder_set_fourcc (builder, format);
|
||||
gdk_dmabuf_texture_builder_set_modifier (builder, DRM_FORMAT_MOD_LINEAR);
|
||||
|
||||
if (format == DRM_FORMAT_XRGB8888 ||
|
||||
format == DRM_FORMAT_ARGB8888)
|
||||
{
|
||||
gdk_dmabuf_texture_builder_set_n_planes (builder, 1);
|
||||
|
||||
fd = allocate_buffer (rgb_size);
|
||||
populate_buffer (fd, rgb_data, rgb_size);
|
||||
|
||||
gdk_dmabuf_texture_builder_set_fd (builder, 0, fd);
|
||||
gdk_dmabuf_texture_builder_set_stride (builder, 0, rgb_stride);
|
||||
}
|
||||
else if (format == DRM_FORMAT_YUV420)
|
||||
{
|
||||
guchar *buf;
|
||||
int size, u_offset, v_offset;
|
||||
|
||||
buf = y_u_v_create_buffer (format, rgb_data, width, height, &size, &u_offset, &v_offset);
|
||||
|
||||
texture_builder_set_planes (builder,
|
||||
disjoint,
|
||||
buf,
|
||||
size,
|
||||
3,
|
||||
(unsigned[4]) { width, width / 2, width / 2 },
|
||||
(unsigned[4]) { width * height, width * height / 4, width * height / 4 });
|
||||
|
||||
g_free (buf);
|
||||
}
|
||||
else if (format == DRM_FORMAT_NV12)
|
||||
{
|
||||
guchar *buf;
|
||||
int size, uv_offset;
|
||||
|
||||
buf = nv12_create_buffer (format, rgb_data, width, height, &size, &uv_offset);
|
||||
|
||||
texture_builder_set_planes (builder,
|
||||
disjoint,
|
||||
buf,
|
||||
size,
|
||||
2,
|
||||
(unsigned[4]) { width, width, },
|
||||
(unsigned[4]) { width * height, width * height / 2 });
|
||||
|
||||
g_free (buf);
|
||||
}
|
||||
|
||||
g_free (rgb_data);
|
||||
|
||||
texture = gdk_dmabuf_texture_builder_build (builder, NULL, NULL, &error);
|
||||
if (!texture)
|
||||
g_error ("Failed to create dmabuf texture: %s", error->message);
|
||||
|
||||
g_object_unref (builder);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static guint32 supported_formats[] = {
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_YUV420,
|
||||
DRM_FORMAT_NV12,
|
||||
};
|
||||
|
||||
static gboolean
|
||||
format_is_supported (guint32 fmt)
|
||||
{
|
||||
for (int i = 0; i < G_N_ELEMENTS (supported_formats); i++)
|
||||
{
|
||||
if (supported_formats[i] == fmt)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static char *
|
||||
supported_formats_to_string (void)
|
||||
{
|
||||
GString *s;
|
||||
|
||||
s = g_string_new ("");
|
||||
for (int i = 0; i < G_N_ELEMENTS (supported_formats); i++)
|
||||
{
|
||||
if (s->len)
|
||||
g_string_append (s, ", ");
|
||||
g_string_append_printf (s, "%.4s", (char *)&supported_formats[i]);
|
||||
}
|
||||
|
||||
return g_string_free (s, FALSE);
|
||||
}
|
||||
|
||||
G_GNUC_NORETURN
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
char *formats = supported_formats_to_string ();
|
||||
g_print ("Usage: testdmabuf [--undecorated] [--disjoint][--download-to FILE] FORMAT FILE\n"
|
||||
"Supported formats: %s\n", formats);
|
||||
g_free (formats);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
static guint32
|
||||
parse_format (const char *a)
|
||||
{
|
||||
if (strlen (a) == 4)
|
||||
{
|
||||
guint32 format = fourcc_code (a[0], a[1], a[2], a[3]);
|
||||
if (format_is_supported (format))
|
||||
return format;
|
||||
}
|
||||
|
||||
usage ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GtkWidget *window, *picture;
|
||||
char *filename;
|
||||
guint32 format;
|
||||
gboolean disjoint = FALSE;
|
||||
gboolean decorated = TRUE;
|
||||
unsigned int i;
|
||||
const char *save_filename = NULL;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (g_str_equal (argv[i], "--disjoint"))
|
||||
disjoint = TRUE;
|
||||
else if (g_str_equal (argv[i], "--undecorated"))
|
||||
decorated = FALSE;
|
||||
else if (g_str_equal (argv[i], "--download-to"))
|
||||
{
|
||||
i++;
|
||||
if (i == argc)
|
||||
usage ();
|
||||
|
||||
save_filename = argv[i];
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (argc - i != 2)
|
||||
{
|
||||
usage ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
format = parse_format (argv[argc - 2]);
|
||||
filename = argv[argc - 1];
|
||||
|
||||
gtk_init ();
|
||||
|
||||
/* Get the list of supported formats with GDK_DEBUG=opengl */
|
||||
gdk_display_get_dmabuf_formats (gdk_display_get_default ());
|
||||
|
||||
texture = make_dmabuf_texture (filename, format, disjoint);
|
||||
|
||||
if (save_filename)
|
||||
gdk_texture_save_to_png (texture, save_filename);
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_decorated (GTK_WINDOW (window), decorated);
|
||||
|
||||
picture = gtk_picture_new_for_paintable (GDK_PAINTABLE (texture));
|
||||
|
||||
gtk_window_set_child (GTK_WINDOW (window), picture);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
|
||||
while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
257
tests/testsubsurface.c
Normal file
257
tests/testsubsurface.c
Normal file
@@ -0,0 +1,257 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtk/gtkwidgetprivate.h"
|
||||
#include "gdk/gdksurfaceprivate.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/dma-heap.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
static int dma_heap_fd = -1;
|
||||
|
||||
static gboolean
|
||||
initialize_dma_heap (void)
|
||||
{
|
||||
dma_heap_fd = open ("/dev/dma_heap/system", O_RDONLY | O_CLOEXEC);
|
||||
return dma_heap_fd != -1;
|
||||
}
|
||||
|
||||
static int
|
||||
allocate_dma_buf (gsize size)
|
||||
{
|
||||
struct dma_heap_allocation_data heap_data;
|
||||
int ret;
|
||||
|
||||
heap_data.len = size;
|
||||
heap_data.fd = 0;
|
||||
heap_data.fd_flags = O_RDWR | O_CLOEXEC;
|
||||
heap_data.heap_flags = 0;
|
||||
|
||||
ret = ioctl (dma_heap_fd, DMA_HEAP_IOCTL_ALLOC, &heap_data);
|
||||
if (ret)
|
||||
g_error ("dma-buf allocation failed");
|
||||
|
||||
return heap_data.fd;
|
||||
}
|
||||
|
||||
static void
|
||||
free_dmabuf (gpointer data)
|
||||
{
|
||||
close (GPOINTER_TO_INT (data));
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
make_dmabuf_color_texture (int width,
|
||||
int height,
|
||||
GdkRGBA *color)
|
||||
{
|
||||
int fd;
|
||||
guchar *buf;
|
||||
GdkDmabufTextureBuilder *builder;
|
||||
GdkTexture *texture;
|
||||
gsize stride, size;
|
||||
GError *error = NULL;
|
||||
|
||||
stride = width * 4;
|
||||
size = height * stride;
|
||||
fd = allocate_dma_buf (size);
|
||||
|
||||
buf = mmap (NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
|
||||
for (gsize i = 0; i < width * height * 4; i += 4)
|
||||
{
|
||||
buf[i] = 255 * color->blue;
|
||||
buf[i + 1] = 255 * color->green;
|
||||
buf[i + 2] = 255 * color->red;
|
||||
buf[i + 3] = 255 * color->alpha;
|
||||
}
|
||||
|
||||
munmap (buf, size);
|
||||
|
||||
builder = gdk_dmabuf_texture_builder_new ();
|
||||
gdk_dmabuf_texture_builder_set_display (builder, gdk_display_get_default ());
|
||||
gdk_dmabuf_texture_builder_set_width (builder, width);
|
||||
gdk_dmabuf_texture_builder_set_height (builder, height);
|
||||
gdk_dmabuf_texture_builder_set_fourcc (builder, DRM_FORMAT_ARGB8888);
|
||||
gdk_dmabuf_texture_builder_set_modifier (builder, DRM_FORMAT_MOD_LINEAR);
|
||||
gdk_dmabuf_texture_builder_set_n_planes (builder, 1);
|
||||
gdk_dmabuf_texture_builder_set_fd (builder, 0, fd);
|
||||
gdk_dmabuf_texture_builder_set_offset (builder, 0, 0);
|
||||
gdk_dmabuf_texture_builder_set_stride (builder, 0, stride);
|
||||
|
||||
texture = gdk_dmabuf_texture_builder_build (builder, free_dmabuf, GINT_TO_POINTER (fd), &error);
|
||||
if (texture == NULL)
|
||||
g_error ("%s", error->message);
|
||||
|
||||
g_object_unref (builder);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
make_shm_color_texture (int width,
|
||||
int height,
|
||||
GdkRGBA *color)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
|
||||
stride = 4 * width;
|
||||
data = g_new (guchar, stride * height);
|
||||
|
||||
surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
width, height,
|
||||
stride);
|
||||
cr = cairo_create (surface);
|
||||
gdk_cairo_set_source_rgba (cr, color);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
bytes = g_bytes_new_take (data, stride * height);
|
||||
texture = gdk_memory_texture_new (width, height, GDK_MEMORY_DEFAULT, bytes, stride);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
make_color_texture (int width,
|
||||
int height,
|
||||
GdkRGBA *color)
|
||||
{
|
||||
if (dma_heap_fd != -1)
|
||||
return make_dmabuf_color_texture (width, height, color);
|
||||
else
|
||||
return make_shm_color_texture (width, height, color);
|
||||
}
|
||||
|
||||
static GdkSubsurface *
|
||||
add_subsurface (GtkWidget *window,
|
||||
GdkRGBA *color,
|
||||
const graphene_rect_t *rect)
|
||||
{
|
||||
GdkSurface *surface;
|
||||
GdkSubsurface *subsurface;
|
||||
GdkTexture *texture;
|
||||
|
||||
surface = gtk_widget_get_surface (GTK_WIDGET (window));
|
||||
|
||||
subsurface = gdk_surface_create_subsurface (surface);
|
||||
|
||||
texture = make_color_texture (20, 20, color);
|
||||
|
||||
gdk_subsurface_attach (subsurface, texture, rect);
|
||||
|
||||
g_object_unref (texture);
|
||||
|
||||
return subsurface;
|
||||
}
|
||||
|
||||
static GdkSubsurface *red, *blue;
|
||||
|
||||
static void red_above_blue (GtkButton *button) { gdk_subsurface_place_above (red, blue); }
|
||||
static void red_below_blue (GtkButton *button) { gdk_subsurface_place_below (red, blue); }
|
||||
static void blue_above_red (GtkButton *button) { gdk_subsurface_place_above (blue, red); }
|
||||
static void blue_below_red (GtkButton *button) { gdk_subsurface_place_below (blue, red); }
|
||||
static void red_above_main (GtkButton *button) { gdk_subsurface_place_above (red, NULL); }
|
||||
static void red_below_main (GtkButton *button) { gdk_subsurface_place_below (red, NULL); }
|
||||
static void blue_above_main (GtkButton *button) { gdk_subsurface_place_above (blue, NULL); }
|
||||
static void blue_below_main (GtkButton *button) { gdk_subsurface_place_below (blue, NULL); }
|
||||
|
||||
static GtkWidget *
|
||||
make_button (const char *name, gpointer cb)
|
||||
{
|
||||
GtkWidget *button;
|
||||
|
||||
button = gtk_button_new_with_label (name);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (cb), NULL);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
static void
|
||||
change_colors (GtkButton *button)
|
||||
{
|
||||
GdkRGBA color;
|
||||
GdkTexture *texture;
|
||||
|
||||
color.red = g_random_double_range (0.5, 1);
|
||||
color.green = g_random_double_range (0, 0.5);
|
||||
color.blue = g_random_double_range (0, 0.5);
|
||||
color.alpha = 1;
|
||||
|
||||
texture = make_color_texture (20, 20, &color);
|
||||
gdk_subsurface_attach (red, texture, &GRAPHENE_RECT_INIT (200, 100, 50, 50));
|
||||
g_object_unref (texture);
|
||||
|
||||
color.red = g_random_double_range (0, 0.5);
|
||||
color.green = g_random_double_range (0, 0.5);
|
||||
color.blue = g_random_double_range (0.5, 1);
|
||||
color.alpha = 1;
|
||||
|
||||
texture = make_color_texture (20, 20, &color);
|
||||
gdk_subsurface_attach (blue, texture, &GRAPHENE_RECT_INIT (180, 120, 100, 20));
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
make_buttons (void)
|
||||
{
|
||||
GtkWidget *box;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_box_append (GTK_BOX (box), make_button ("Red above blue", red_above_blue));
|
||||
gtk_box_append (GTK_BOX (box), make_button ("Red below blue", red_below_blue));
|
||||
gtk_box_append (GTK_BOX (box), make_button ("Red above main", red_above_main));
|
||||
gtk_box_append (GTK_BOX (box), make_button ("Red below main", red_below_main));
|
||||
gtk_box_append (GTK_BOX (box), make_button ("Blue above red", blue_above_red));
|
||||
gtk_box_append (GTK_BOX (box), make_button ("Blue below red", blue_below_red));
|
||||
gtk_box_append (GTK_BOX (box), make_button ("Blue above main", blue_above_main));
|
||||
gtk_box_append (GTK_BOX (box), make_button ("Blue below main", blue_below_main));
|
||||
gtk_box_append (GTK_BOX (box), make_button ("Change colors", change_colors));
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *window, *box;
|
||||
|
||||
gtk_init ();
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 210, -1);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
|
||||
|
||||
gtk_widget_realize (window);
|
||||
|
||||
if (initialize_dma_heap ())
|
||||
g_print ("Using dambufs\n");
|
||||
else
|
||||
g_print ("Failed to initialize dma-heap, using shm\n");
|
||||
|
||||
red = add_subsurface (window, &(GdkRGBA) { 1, 0, 0, 1 }, &GRAPHENE_RECT_INIT (200, 100, 50, 50));
|
||||
blue = add_subsurface (window, &(GdkRGBA) { 0, 0, 1, 1 }, &GRAPHENE_RECT_INIT (180, 120, 100, 20));
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), make_buttons ());
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
|
||||
while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
295
testsuite/gdk/dmabuftexture.c
Normal file
295
testsuite/gdk/dmabuftexture.c
Normal file
@@ -0,0 +1,295 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkdisplayprivate.h>
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdkdmabuftextureprivate.h>
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
test_dmabuf_formats (void)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkDmabufFormats *formats;
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
|
||||
formats = gdk_display_get_dmabuf_formats (display);
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
/* We always have basic linear formats */
|
||||
g_assert_true (gdk_dmabuf_formats_get_n_formats (formats) >= 6);
|
||||
|
||||
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR));
|
||||
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_LINEAR));
|
||||
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_BGRA8888, DRM_FORMAT_MOD_LINEAR));
|
||||
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_ABGR16161616F, DRM_FORMAT_MOD_LINEAR));
|
||||
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_RGB888, DRM_FORMAT_MOD_LINEAR));
|
||||
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_BGR888, DRM_FORMAT_MOD_LINEAR));
|
||||
#else
|
||||
g_assert_true (gdk_dmabuf_formats_get_n_formats (formats) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
make_surface (int width,
|
||||
int height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
guchar *data;
|
||||
int stride;
|
||||
|
||||
stride = width * 4;
|
||||
data = g_malloc (stride * height);
|
||||
surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
width, height, stride);
|
||||
cr = cairo_create (surface);
|
||||
cairo_set_source_rgb (cr, 1, 0, 0);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
upload_gl_texture (GdkGLContext *context,
|
||||
cairo_surface_t *surface)
|
||||
{
|
||||
unsigned int id;
|
||||
int width, height;
|
||||
|
||||
width = cairo_image_surface_get_width (surface);
|
||||
height = cairo_image_surface_get_height (surface);
|
||||
|
||||
glGenTextures (1, &id);
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, id);
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE,
|
||||
cairo_image_surface_get_data (surface));
|
||||
|
||||
g_assert_true (glGetError () == GL_NO_ERROR);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static void
|
||||
export_dmabuf (GdkGLContext *context,
|
||||
unsigned int texture_id,
|
||||
GdkDmabuf *dmabuf)
|
||||
{
|
||||
gboolean ret;
|
||||
|
||||
ret = gdk_gl_context_export_dmabuf (context, texture_id, dmabuf);
|
||||
|
||||
g_assert_true (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
free_dmabuf (gpointer data)
|
||||
{
|
||||
GdkDmabuf *dmabuf = data;
|
||||
|
||||
for (int i = 0; i < dmabuf->n_planes; i++)
|
||||
close (dmabuf->planes[i].fd);
|
||||
|
||||
g_free (dmabuf);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
make_dmabuf_texture (GdkDisplay *display,
|
||||
int width,
|
||||
int height,
|
||||
gboolean premultiplied,
|
||||
GdkDmabuf *dmabuf)
|
||||
{
|
||||
GdkDmabufTextureBuilder *builder;
|
||||
GdkTexture *texture;
|
||||
GdkDmabuf *dmabuf2;
|
||||
|
||||
builder = gdk_dmabuf_texture_builder_new ();
|
||||
|
||||
gdk_dmabuf_texture_builder_set_display (builder, display);
|
||||
gdk_dmabuf_texture_builder_set_width (builder, width);
|
||||
gdk_dmabuf_texture_builder_set_premultiplied (builder, premultiplied);
|
||||
gdk_dmabuf_texture_builder_set_height (builder, height);
|
||||
gdk_dmabuf_texture_builder_set_fourcc (builder, dmabuf->fourcc);
|
||||
gdk_dmabuf_texture_builder_set_modifier (builder, dmabuf->modifier);
|
||||
gdk_dmabuf_texture_builder_set_n_planes (builder, dmabuf->n_planes);
|
||||
for (int i = 0; i < dmabuf->n_planes; i++)
|
||||
{
|
||||
gdk_dmabuf_texture_builder_set_fd (builder, i, dmabuf->planes[i].fd);
|
||||
gdk_dmabuf_texture_builder_set_stride (builder, i, dmabuf->planes[i].stride);
|
||||
gdk_dmabuf_texture_builder_set_offset (builder, i, dmabuf->planes[i].offset);
|
||||
}
|
||||
|
||||
dmabuf2 = g_new (GdkDmabuf, 1);
|
||||
memcpy (dmabuf2, dmabuf, sizeof (GdkDmabuf));
|
||||
|
||||
texture = gdk_dmabuf_texture_builder_build (builder, free_dmabuf, dmabuf2, NULL);
|
||||
|
||||
g_assert_true (texture != NULL);
|
||||
|
||||
g_object_unref (builder);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/* Make a dmabuftexture by exporting a GL texture,
|
||||
* then download it and compare with the original
|
||||
*/
|
||||
static void
|
||||
test_dmabuf_export (void)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkGLContext *context;
|
||||
GError *error = NULL;
|
||||
cairo_surface_t *surface;
|
||||
unsigned int texture_id;
|
||||
GdkDmabuf dmabuf;
|
||||
GdkTexture *texture;
|
||||
guchar *data;
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
if (!gdk_display_prepare_gl (display, &error))
|
||||
{
|
||||
g_test_skip_printf ("no GL support: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gdk_dmabuf_formats_get_n_formats (gdk_display_get_dmabuf_formats (display)) == 0)
|
||||
{
|
||||
g_test_skip_printf ("no dmabuf support");
|
||||
return;
|
||||
}
|
||||
|
||||
context = gdk_display_create_gl_context (display, &error);
|
||||
g_assert_nonnull (context);
|
||||
g_assert_no_error (error);
|
||||
|
||||
gdk_gl_context_realize (context, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
surface = make_surface (64, 64);
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
texture_id = upload_gl_texture (context, surface);
|
||||
export_dmabuf (context, texture_id, &dmabuf);
|
||||
texture = make_dmabuf_texture (display, 64, 64, TRUE, &dmabuf);
|
||||
|
||||
data = g_malloc (64 * 64 * 4);
|
||||
gdk_texture_download (texture, data, 64 * 4);
|
||||
|
||||
g_assert_true (memcmp (cairo_image_surface_get_data (surface), data, 64 * 64 * 4) == 0);
|
||||
|
||||
g_free (data);
|
||||
g_object_unref (texture);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
glDeleteTextures (1, &texture_id);
|
||||
|
||||
g_object_unref (context);
|
||||
}
|
||||
|
||||
/* Make a dmabuftexture by exporting a GL texture,
|
||||
* then import it into another GL context, download
|
||||
* the resulting texture, and compare it to the original.
|
||||
*/
|
||||
static void
|
||||
test_dmabuf_import (void)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkGLContext *context;
|
||||
GdkGLContext *context2;
|
||||
GError *error = NULL;
|
||||
cairo_surface_t *surface;
|
||||
unsigned int texture_id;
|
||||
unsigned int texture_id2;
|
||||
GdkDmabuf dmabuf;
|
||||
const GdkDmabuf *dmabuf2;
|
||||
GdkTexture *texture;
|
||||
GdkTexture *texture2;
|
||||
GdkGLTextureBuilder *builder;
|
||||
guchar *data;
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
if (!gdk_display_prepare_gl (display, &error))
|
||||
{
|
||||
g_test_skip_printf ("no GL support: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gdk_dmabuf_formats_get_n_formats (gdk_display_get_dmabuf_formats (display)) == 0)
|
||||
{
|
||||
g_test_skip_printf ("no dmabuf support");
|
||||
return;
|
||||
}
|
||||
|
||||
context = gdk_display_create_gl_context (display, &error);
|
||||
g_assert_nonnull (context);
|
||||
g_assert_no_error (error);
|
||||
|
||||
gdk_gl_context_realize (context, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
surface = make_surface (64, 64);
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
texture_id = upload_gl_texture (context, surface);
|
||||
export_dmabuf (context, texture_id, &dmabuf);
|
||||
texture = make_dmabuf_texture (display, 64, 64, TRUE, &dmabuf);
|
||||
|
||||
context2 = gdk_display_create_gl_context (display, &error);
|
||||
g_assert_nonnull (context2);
|
||||
g_assert_no_error (error);
|
||||
|
||||
gdk_gl_context_realize (context2, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
dmabuf2 = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
|
||||
texture_id2 = gdk_gl_context_import_dmabuf (context2, 64, 64, dmabuf2, GL_TEXTURE_2D);
|
||||
|
||||
builder = gdk_gl_texture_builder_new ();
|
||||
gdk_gl_texture_builder_set_context (builder, context2);
|
||||
gdk_gl_texture_builder_set_id (builder, texture_id2);
|
||||
gdk_gl_texture_builder_set_width (builder, 64);
|
||||
gdk_gl_texture_builder_set_height (builder, 64);
|
||||
gdk_gl_texture_builder_set_format (builder, GDK_MEMORY_A8R8G8B8_PREMULTIPLIED);
|
||||
texture2 = gdk_gl_texture_builder_build (builder, NULL, NULL);
|
||||
|
||||
data = g_malloc (64 * 64 * 4);
|
||||
gdk_texture_download (texture2, data, 64 * 4);
|
||||
|
||||
g_assert_true (memcmp (cairo_image_surface_get_data (surface), data, 64 * 64 * 4) == 0);
|
||||
|
||||
g_free (data);
|
||||
g_object_unref (texture);
|
||||
g_object_unref (texture2);
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
glDeleteTextures (1, &texture_id);
|
||||
|
||||
g_object_unref (context);
|
||||
g_object_unref (context2);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
gtk_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/dmabuf/formats", test_dmabuf_formats);
|
||||
g_test_add_func ("/dmabuf/export", test_dmabuf_export);
|
||||
g_test_add_func ("/dmabuf/import", test_dmabuf_import);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -102,10 +102,15 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_B8G8R8X8:
|
||||
case GDK_MEMORY_X8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8X8:
|
||||
case GDK_MEMORY_X8B8G8R8:
|
||||
case GDK_MEMORY_G16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_G16A16:
|
||||
case GDK_MEMORY_A32_FLOAT:
|
||||
@@ -145,10 +150,15 @@ gdk_memory_format_get_channel_type (GdkMemoryFormat format)
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_B8G8R8X8:
|
||||
case GDK_MEMORY_X8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8X8:
|
||||
case GDK_MEMORY_X8B8G8R8:
|
||||
case GDK_MEMORY_G8:
|
||||
case GDK_MEMORY_G8A8:
|
||||
case GDK_MEMORY_G8A8_PREMULTIPLIED:
|
||||
@@ -197,10 +207,15 @@ gdk_memory_format_n_colors (GdkMemoryFormat format)
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_B8G8R8X8:
|
||||
case GDK_MEMORY_X8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8X8:
|
||||
case GDK_MEMORY_X8B8G8R8:
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
@@ -242,11 +257,16 @@ gdk_memory_format_has_alpha (GdkMemoryFormat format)
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
case GDK_MEMORY_G8:
|
||||
case GDK_MEMORY_G16:
|
||||
case GDK_MEMORY_B8G8R8X8:
|
||||
case GDK_MEMORY_X8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8X8:
|
||||
case GDK_MEMORY_X8B8G8R8:
|
||||
return FALSE;
|
||||
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
@@ -282,6 +302,7 @@ gdk_memory_format_is_premultiplied (GdkMemoryFormat format)
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
@@ -302,6 +323,10 @@ gdk_memory_format_is_premultiplied (GdkMemoryFormat format)
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_B8G8R8X8:
|
||||
case GDK_MEMORY_X8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8X8:
|
||||
case GDK_MEMORY_X8B8G8R8:
|
||||
case GDK_MEMORY_R16G16B16A16:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
||||
@@ -321,45 +346,7 @@ gdk_memory_format_is_premultiplied (GdkMemoryFormat format)
|
||||
static gboolean
|
||||
gdk_memory_format_is_deep (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_G8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_G8:
|
||||
case GDK_MEMORY_G8A8:
|
||||
case GDK_MEMORY_A8:
|
||||
return FALSE;
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
case GDK_MEMORY_G16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
case GDK_MEMORY_R16G16B16A16:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
||||
case GDK_MEMORY_G16:
|
||||
case GDK_MEMORY_G16A16:
|
||||
case GDK_MEMORY_A16:
|
||||
case GDK_MEMORY_A16_FLOAT:
|
||||
case GDK_MEMORY_A32_FLOAT:
|
||||
return TRUE;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
return gdk_memory_format_get_channel_type (format) != CHANNEL_UINT_8;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -373,6 +360,7 @@ gdk_memory_format_pixel_equal (GdkMemoryFormat format,
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
@@ -385,6 +373,14 @@ gdk_memory_format_pixel_equal (GdkMemoryFormat format,
|
||||
case GDK_MEMORY_G8A8_PREMULTIPLIED:
|
||||
return memcmp (pixel1, pixel2, gdk_memory_format_bytes_per_pixel (format)) == 0;
|
||||
|
||||
case GDK_MEMORY_B8G8R8X8:
|
||||
case GDK_MEMORY_R8G8B8X8:
|
||||
return memcmp (pixel1, pixel2, 3) == 0;
|
||||
|
||||
case GDK_MEMORY_X8R8G8B8:
|
||||
case GDK_MEMORY_X8B8G8R8:
|
||||
return memcmp (pixel1 + 1, pixel2 + 1, 3) == 0;
|
||||
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16A16:
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
@@ -581,6 +577,9 @@ texture_builder_set_pixel (TextureBuilder *builder,
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
set_pixel_u8 (data, 0, 1, 2, 3, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
set_pixel_u8 (data, 3, 2, 1, 0, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
set_pixel_u8 (data, 2, 1, 0, 3, FALSE, color);
|
||||
break;
|
||||
@@ -593,6 +592,18 @@ texture_builder_set_pixel (TextureBuilder *builder,
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
set_pixel_u8 (data, 3, 2, 1, 0, FALSE, color);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8X8:
|
||||
set_pixel_u8 (data, 2, 1, 0, -1, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_X8R8G8B8:
|
||||
set_pixel_u8 (data, 1, 2, 3, -1, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8X8:
|
||||
set_pixel_u8 (data, 0, 1, 2, -1, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_X8B8G8R8:
|
||||
set_pixel_u8 (data, 3, 2, 1, -1, TRUE, color);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
set_pixel_u8 (data, 0, 1, 2, -1, TRUE, color);
|
||||
break;
|
||||
|
||||
@@ -52,19 +52,24 @@ foreach t : tests
|
||||
endforeach
|
||||
|
||||
internal_tests = [
|
||||
'image',
|
||||
'texture',
|
||||
'gltexture',
|
||||
{ 'name': 'image' },
|
||||
{ 'name': 'texture' },
|
||||
{ 'name': 'gltexture' },
|
||||
{ 'name': 'dmabuftexture', 'suites': 'failing' },
|
||||
]
|
||||
|
||||
foreach t : internal_tests
|
||||
test_exe = executable(t, '@0@.c'.format(t),
|
||||
test_name = t.get('name')
|
||||
test_exe = executable(test_name,
|
||||
sources: '@0@.c'.format(test_name),
|
||||
c_args: common_cflags + ['-DGTK_COMPILATION'],
|
||||
dependencies: libgtk_static_dep,
|
||||
install: false,
|
||||
)
|
||||
|
||||
test(t, test_exe,
|
||||
suites = ['gdk'] + t.get('suites', [])
|
||||
|
||||
test(test_name, test_exe,
|
||||
args: [ '--tap', '-k' ],
|
||||
protocol: 'tap',
|
||||
env: [
|
||||
@@ -72,6 +77,6 @@ foreach t : internal_tests
|
||||
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
|
||||
'DBUS_SESSION_BUS_ADDRESS=',
|
||||
],
|
||||
suite: 'gdk',
|
||||
suite: suites,
|
||||
)
|
||||
endforeach
|
||||
|
||||
@@ -1 +1,10 @@
|
||||
linear-gradient { }
|
||||
linear-gradient {
|
||||
stops: 0.2 red,
|
||||
0.2 blue,
|
||||
0.4 blue,
|
||||
0.4 yellow,
|
||||
0.6 yellow,
|
||||
0.6 lime,
|
||||
0.8 lime,
|
||||
0.8 teal;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 166 B |
@@ -1,4 +1,5 @@
|
||||
opacity {
|
||||
opacity: 0.6;
|
||||
child: transform {
|
||||
transform: translate(15, 15);
|
||||
child: container {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 127 B After Width: | Height: | Size: 127 B |
30
testsuite/gsk/compare/texture-scale-filters-3d.node
Normal file
30
testsuite/gsk/compare/texture-scale-filters-3d.node
Normal file
@@ -0,0 +1,30 @@
|
||||
texture-scale {
|
||||
bounds: 4 4 24 24;
|
||||
filter: nearest;
|
||||
texture: "texture1" url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJ0lEQVQYlWNkYPjwnwEPYMInSbqC\
|
||||
AwwCDAcYBPCb4HAAlc9Ie0cCAB8uBo20gfbVAAAAAElFTkSuQmCC\
|
||||
");
|
||||
}
|
||||
repeat {
|
||||
bounds: 32 0 32 32;
|
||||
child: texture-scale {
|
||||
bounds: 0 0 1 1;
|
||||
filter: nearest;
|
||||
texture: "texture1";
|
||||
}
|
||||
}
|
||||
repeat {
|
||||
bounds: 0 32 32 32;
|
||||
child: texture-scale {
|
||||
bounds: 0 0 1 1;
|
||||
texture: "texture1";
|
||||
}
|
||||
}
|
||||
repeat {
|
||||
bounds: 32 32 32 32;
|
||||
child: texture-scale {
|
||||
bounds: 0 0 1 1;
|
||||
filter: trilinear;
|
||||
texture: "texture1";
|
||||
}
|
||||
}
|
||||
BIN
testsuite/gsk/compare/texture-scale-filters-3d.png
Normal file
BIN
testsuite/gsk/compare/texture-scale-filters-3d.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 295 B |
@@ -98,6 +98,7 @@ compare_render_tests = [
|
||||
'shadow-opacity',
|
||||
'shrink-rounded-border',
|
||||
'stroke',
|
||||
'texture-scale-filters-3d',
|
||||
'texture-scale-magnify-10000x',
|
||||
'texture-scale-magnify-rotate',
|
||||
'texture-scale-stripes',
|
||||
|
||||
@@ -182,6 +182,10 @@ test_type (gconstpointer data)
|
||||
strcmp (pspec->name, "storable-formats") == 0)
|
||||
check = FALSE;
|
||||
|
||||
if (g_type_is_a (type, GDK_TYPE_DMABUF_TEXTURE_BUILDER) &&
|
||||
strcmp (pspec->name, "display") == 0)
|
||||
check = FALSE;
|
||||
|
||||
/* set in the constructor */
|
||||
if (g_type_is_a (type, GSK_TYPE_GL_SHADER) &&
|
||||
strcmp (pspec->name, "source") == 0)
|
||||
|
||||
Reference in New Issue
Block a user