Compare commits
15 Commits
gdk-win32-
...
cicp-narro
Author | SHA1 | Date | |
---|---|---|---|
|
42fcaa95c9 | ||
|
5ab0aa23e8 | ||
|
a6e898417a | ||
|
6a2d662bb9 | ||
|
0ef7bb990b | ||
|
270b2afcd4 | ||
|
5d7bd3db87 | ||
|
ea564c4eea | ||
|
bc82f31606 | ||
|
b5e5389846 | ||
|
490779c007 | ||
|
d4713a3b26 | ||
|
8d6693fffb | ||
|
3b89704da3 | ||
|
7d3efe0a11 |
@@ -209,7 +209,10 @@ gdk_cicp_params_class_init (GdkCicpParamsClass *klass)
|
||||
* Supported values:
|
||||
*
|
||||
* - 0: RGB
|
||||
* - 1: BT.709
|
||||
* - 2: unspecified
|
||||
* - 5,6: BT.601
|
||||
* - 9: BT.2020
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
|
@@ -222,3 +222,39 @@ static const float srgb_to_rec2020[9] = {
|
||||
0.069108, 0.919519, 0.011360,
|
||||
0.016394, 0.088011, 0.895380,
|
||||
};
|
||||
|
||||
static const float rgb_to_bt601[9] = {
|
||||
0.299000, 0.587000, 0.114000,
|
||||
-0.168736, -0.331264, 0.500000,
|
||||
0.500000, -0.418688, -0.081312,
|
||||
};
|
||||
|
||||
static const float bt601_to_rgb[9] = {
|
||||
1.000000, 0.000000, 1.402000,
|
||||
1.000000, -0.344136, -0.714136,
|
||||
1.000000, 1.772000, 0.000000,
|
||||
};
|
||||
|
||||
static const float rgb_to_bt709[9] = {
|
||||
0.212600, 0.715200, 0.072200,
|
||||
-0.114572, -0.385428, 0.500000,
|
||||
0.500000, -0.454153, -0.045847,
|
||||
};
|
||||
|
||||
static const float bt709_to_rgb[9] = {
|
||||
1.000000, 0.000000, 1.574800,
|
||||
1.000000, -0.187324, -0.468124,
|
||||
1.000000, 1.855600, -0.000000,
|
||||
};
|
||||
|
||||
static const float rgb_to_bt2020[9] = {
|
||||
0.262700, 0.678000, 0.059300,
|
||||
-0.139630, -0.360370, 0.500000,
|
||||
0.500000, -0.459786, -0.040214,
|
||||
};
|
||||
|
||||
static const float bt2020_to_rgb[9] = {
|
||||
1.000000, -0.000000, 1.474600,
|
||||
1.000000, -0.164553, -0.571353,
|
||||
1.000000, 1.881400, -0.000000,
|
||||
};
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define GDK_COLOR_STATE_IMPL
|
||||
#include "gdkcolorstateprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
@@ -411,7 +412,7 @@ GdkDefaultColorState gdk_default_color_states[] = {
|
||||
},
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
/* {{{ Cicp implementation */
|
||||
|
||||
typedef struct _GdkCicpColorState GdkCicpColorState;
|
||||
@@ -431,25 +432,128 @@ struct _GdkCicpColorState
|
||||
float *from_srgb;
|
||||
float *from_rec2020;
|
||||
|
||||
const float *from_yuv;
|
||||
const float *to_yuv;
|
||||
|
||||
GdkCicp cicp;
|
||||
};
|
||||
|
||||
/* {{{ Conversion functions */
|
||||
|
||||
#define cicp ((GdkCicpColorState *)self)
|
||||
#define TRANSFORM_FROM_CICP(name, matrix, oetf) \
|
||||
static void \
|
||||
name (GdkColorState *color_state, \
|
||||
float (*values)[4], \
|
||||
gsize n_values) \
|
||||
{ \
|
||||
GdkCicpColorState *self = (GdkCicpColorState *) color_state; \
|
||||
\
|
||||
for (gsize i = 0; i < n_values; i++) \
|
||||
{ \
|
||||
if (self->cicp.range == GDK_CICP_RANGE_NARROW) \
|
||||
{ \
|
||||
values[i][0] = CLAMP ((values[i][0] - 16.0/255.0) * 255.0 / 219.0, -10, 10); \
|
||||
values[i][1] = CLAMP ((values[i][1] - 16.0/255.0) * 255.0 / 224.0, -10, 10); \
|
||||
values[i][2] = CLAMP ((values[i][2] - 16.0/255.0) * 255.0 / 224.0, -10, 10); \
|
||||
} \
|
||||
if (self->from_yuv) \
|
||||
{ \
|
||||
float res[3]; \
|
||||
values[i][1] -= 0.5; \
|
||||
values[i][2] -= 0.5; \
|
||||
res[0] = self->from_yuv[0] * values[i][0] + self->from_yuv[1] * values[i][1] + self->from_yuv[2] * values[i][2]; \
|
||||
res[1] = self->from_yuv[3] * values[i][0] + self->from_yuv[4] * values[i][1] + self->from_yuv[5] * values[i][2]; \
|
||||
res[2] = self->from_yuv[6] * values[i][0] + self->from_yuv[7] * values[i][1] + self->from_yuv[8] * values[i][2]; \
|
||||
values[i][0] = res[0]; \
|
||||
values[i][1] = res[1]; \
|
||||
values[i][2] = res[2]; \
|
||||
} \
|
||||
if (self->eotf != NONE) \
|
||||
{ \
|
||||
values[i][0] = self->eotf (values[i][0]); \
|
||||
values[i][1] = self->eotf (values[i][1]); \
|
||||
values[i][2] = self->eotf (values[i][2]); \
|
||||
} \
|
||||
if (self->matrix != IDENTITY) \
|
||||
{ \
|
||||
float res[3]; \
|
||||
res[0] = self->matrix[0] * values[i][0] + self->matrix[1] * values[i][1] + self->matrix[2] * values[i][2]; \
|
||||
res[1] = self->matrix[3] * values[i][0] + self->matrix[4] * values[i][1] + self->matrix[5] * values[i][2]; \
|
||||
res[2] = self->matrix[6] * values[i][0] + self->matrix[7] * values[i][1] + self->matrix[8] * values[i][2]; \
|
||||
values[i][0] = res[0]; \
|
||||
values[i][1] = res[1]; \
|
||||
values[i][2] = res[2]; \
|
||||
} \
|
||||
if (oetf != NONE) \
|
||||
{ \
|
||||
values[i][0] = oetf (values[i][0]); \
|
||||
values[i][1] = oetf (values[i][1]); \
|
||||
values[i][2] = oetf (values[i][2]); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
TRANSFORM(gdk_cicp_to_srgb, cicp->eotf, cicp->to_srgb, srgb_oetf)
|
||||
TRANSFORM(gdk_cicp_to_srgb_linear, cicp->eotf, cicp->to_srgb, NONE)
|
||||
TRANSFORM(gdk_cicp_to_rec2100_pq, cicp->eotf, cicp->to_rec2020, pq_oetf)
|
||||
TRANSFORM(gdk_cicp_to_rec2100_linear, cicp->eotf, cicp->to_rec2020, NONE)
|
||||
TRANSFORM(gdk_cicp_from_srgb, srgb_eotf, cicp->from_srgb, cicp->oetf)
|
||||
TRANSFORM(gdk_cicp_from_srgb_linear, NONE, cicp->from_srgb, cicp->oetf)
|
||||
TRANSFORM(gdk_cicp_from_rec2100_pq, pq_eotf, cicp->from_rec2020, cicp->oetf)
|
||||
TRANSFORM(gdk_cicp_from_rec2100_linear, NONE, cicp->from_rec2020, cicp->oetf)
|
||||
#define TRANSFORM_TO_CICP(name, eotf, matrix) \
|
||||
static void \
|
||||
name (GdkColorState *color_state, \
|
||||
float (*values)[4], \
|
||||
gsize n_values) \
|
||||
{ \
|
||||
GdkCicpColorState *self = (GdkCicpColorState *) color_state; \
|
||||
\
|
||||
for (gsize i = 0; i < n_values; i++) \
|
||||
{ \
|
||||
if (eotf != NONE) \
|
||||
{ \
|
||||
values[i][0] = eotf (values[i][0]); \
|
||||
values[i][1] = eotf (values[i][1]); \
|
||||
values[i][2] = eotf (values[i][2]); \
|
||||
} \
|
||||
if (self->matrix != IDENTITY) \
|
||||
{ \
|
||||
float res[3]; \
|
||||
res[0] = self->matrix[0] * values[i][0] + self->matrix[1] * values[i][1] + self->matrix[2] * values[i][2]; \
|
||||
res[1] = self->matrix[3] * values[i][0] + self->matrix[4] * values[i][1] + self->matrix[5] * values[i][2]; \
|
||||
res[2] = self->matrix[6] * values[i][0] + self->matrix[7] * values[i][1] + self->matrix[8] * values[i][2]; \
|
||||
values[i][0] = res[0]; \
|
||||
values[i][1] = res[1]; \
|
||||
values[i][2] = res[2]; \
|
||||
} \
|
||||
if (self->oetf != NONE) \
|
||||
{ \
|
||||
values[i][0] = self->oetf (values[i][0]); \
|
||||
values[i][1] = self->oetf (values[i][1]); \
|
||||
values[i][2] = self->oetf (values[i][2]); \
|
||||
} \
|
||||
if (self->to_yuv) \
|
||||
{ \
|
||||
float res[3]; \
|
||||
res[0] = self->to_yuv[0] * values[i][0] + self->to_yuv[1] * values[i][1] + self->to_yuv[2] * values[i][2]; \
|
||||
res[1] = self->to_yuv[3] * values[i][0] + self->to_yuv[4] * values[i][1] + self->to_yuv[5] * values[i][2]; \
|
||||
res[2] = self->to_yuv[6] * values[i][0] + self->to_yuv[7] * values[i][1] + self->to_yuv[8] * values[i][2]; \
|
||||
values[i][0] = res[0]; \
|
||||
values[i][1] = res[1] + 0.5; \
|
||||
values[i][2] = res[2] + 0.5; \
|
||||
} \
|
||||
if (self->cicp.range == GDK_CICP_RANGE_NARROW) \
|
||||
{ \
|
||||
values[i][0] = values[i][0] * 219.0 / 255.0 + 16.0 / 255.0; \
|
||||
values[i][1] = values[i][1] * 224.0 / 255.0 + 16.0 / 255.0; \
|
||||
values[i][2] = values[i][2] * 224.0 / 255.0 + 16.0 / 255.0; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#undef cicp
|
||||
TRANSFORM_FROM_CICP(gdk_cicp_to_srgb, to_srgb, srgb_oetf)
|
||||
TRANSFORM_FROM_CICP(gdk_cicp_to_srgb_linear, to_srgb, NONE)
|
||||
TRANSFORM_FROM_CICP(gdk_cicp_to_rec2100_pq, to_rec2020, pq_oetf)
|
||||
TRANSFORM_FROM_CICP(gdk_cicp_to_rec2100_linear, to_rec2020, NONE)
|
||||
|
||||
TRANSFORM_TO_CICP(gdk_cicp_from_srgb, srgb_eotf, from_srgb)
|
||||
TRANSFORM_TO_CICP(gdk_cicp_from_srgb_linear, NONE, from_srgb)
|
||||
TRANSFORM_TO_CICP(gdk_cicp_from_rec2100_pq, pq_eotf, from_rec2020)
|
||||
TRANSFORM_TO_CICP(gdk_cicp_from_rec2100_linear, NONE, from_rec2020)
|
||||
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
/* {{{ Vfuncs */
|
||||
|
||||
@@ -555,7 +659,7 @@ gdk_cicp_color_state_get_cicp (GdkColorState *color_state)
|
||||
return &self->cicp;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
static const
|
||||
GdkColorStateClass GDK_CICP_COLOR_STATE_CLASS = {
|
||||
@@ -568,6 +672,46 @@ GdkColorStateClass GDK_CICP_COLOR_STATE_CLASS = {
|
||||
.get_cicp = gdk_cicp_color_state_get_cicp,
|
||||
};
|
||||
|
||||
GdkCicpColorState gdk_color_state_bt601_narrow = {
|
||||
.parent = {
|
||||
.klass = &GDK_CICP_COLOR_STATE_CLASS,
|
||||
.ref_count = 1,
|
||||
.depth = GDK_MEMORY_FLOAT16,
|
||||
.rendering_color_state = GDK_COLOR_STATE_REC2100_LINEAR,
|
||||
},
|
||||
.name = "cicp-1/13/6/0",
|
||||
.no_srgb = NULL,
|
||||
.cicp = { 1, 13, 6, 0 },
|
||||
.eotf = srgb_eotf,
|
||||
.oetf = srgb_oetf,
|
||||
.to_yuv = rgb_to_bt601,
|
||||
.from_yuv = bt601_to_rgb,
|
||||
.to_srgb = IDENTITY,
|
||||
.to_rec2020 = (float *) srgb_to_rec2020,
|
||||
.from_srgb = IDENTITY,
|
||||
.from_rec2020 = (float *) rec2020_to_srgb,
|
||||
};
|
||||
|
||||
GdkCicpColorState gdk_color_state_bt601_full = {
|
||||
.parent = {
|
||||
.klass = &GDK_CICP_COLOR_STATE_CLASS,
|
||||
.ref_count = 1,
|
||||
.depth = GDK_MEMORY_FLOAT16,
|
||||
.rendering_color_state = GDK_COLOR_STATE_REC2100_LINEAR,
|
||||
},
|
||||
.name = "cicp-1/13/6/1",
|
||||
.no_srgb = NULL,
|
||||
.cicp = { 1, 13, 6, 1 },
|
||||
.eotf = srgb_eotf,
|
||||
.oetf = srgb_oetf,
|
||||
.to_yuv = rgb_to_bt601,
|
||||
.from_yuv = bt601_to_rgb,
|
||||
.to_srgb = IDENTITY,
|
||||
.to_rec2020 = (float *) srgb_to_rec2020,
|
||||
.from_srgb = IDENTITY,
|
||||
.from_rec2020 = (float *) rec2020_to_srgb,
|
||||
};
|
||||
|
||||
static inline float *
|
||||
multiply (float res[9],
|
||||
const float m1[9],
|
||||
@@ -592,14 +736,8 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
|
||||
GdkTransferFunc oetf;
|
||||
gconstpointer to_xyz;
|
||||
gconstpointer from_xyz;
|
||||
|
||||
if (cicp->range == GDK_CICP_RANGE_NARROW || cicp->matrix_coefficients != 0)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("cicp: Narrow range or YUV not supported"));
|
||||
return NULL;
|
||||
}
|
||||
gconstpointer to_yuv = NULL;
|
||||
gconstpointer from_yuv = NULL;
|
||||
|
||||
if (cicp->color_primaries == 2 ||
|
||||
cicp->transfer_function == 2 ||
|
||||
@@ -613,10 +751,16 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
|
||||
|
||||
for (guint i = 0; i < GDK_COLOR_STATE_N_IDS; i++)
|
||||
{
|
||||
if (gdk_cicp_equivalent (cicp, &gdk_default_color_states[i].cicp))
|
||||
if (gdk_cicp_equal (cicp, &gdk_default_color_states[i].cicp))
|
||||
return (GdkColorState *) &gdk_default_color_states[i];
|
||||
}
|
||||
|
||||
if (gdk_cicp_equal (cicp, &gdk_color_state_bt601_narrow.cicp))
|
||||
return gdk_color_state_ref ((GdkColorState *) &gdk_color_state_bt601_narrow);
|
||||
|
||||
if (gdk_cicp_equal (cicp, &gdk_color_state_bt601_full.cicp))
|
||||
return gdk_color_state_ref ((GdkColorState *) &gdk_color_state_bt601_full);
|
||||
|
||||
switch (cicp->transfer_function)
|
||||
{
|
||||
case 1:
|
||||
@@ -669,6 +813,7 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
|
||||
from_xyz = xyz_to_pal;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
to_xyz = ntsc_to_xyz;
|
||||
from_xyz = xyz_to_ntsc;
|
||||
break;
|
||||
@@ -692,6 +837,34 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (cicp->matrix_coefficients)
|
||||
{
|
||||
case 0:
|
||||
to_yuv = IDENTITY;
|
||||
from_yuv = IDENTITY;
|
||||
break;
|
||||
case 1:
|
||||
to_yuv = rgb_to_bt709;
|
||||
from_yuv = bt709_to_rgb;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
to_yuv = rgb_to_bt601;
|
||||
from_yuv = bt601_to_rgb;
|
||||
break;
|
||||
case 9:
|
||||
to_yuv = rgb_to_bt2020;
|
||||
from_yuv = bt2020_to_rgb;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("cicp: Matrix coefficients %u, %s not supported"),
|
||||
cicp->matrix_coefficients,
|
||||
cicp->range == GDK_CICP_RANGE_NARROW ? "narrow" : "full");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self = g_new0 (GdkCicpColorState, 1);
|
||||
|
||||
self->parent.klass = &GDK_CICP_COLOR_STATE_CLASS;
|
||||
@@ -704,6 +877,9 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
|
||||
|
||||
memcpy (&self->cicp, cicp, sizeof (GdkCicp));
|
||||
|
||||
self->to_yuv = to_yuv;
|
||||
self->from_yuv = from_yuv;
|
||||
|
||||
self->eotf = eotf;
|
||||
self->oetf = oetf;
|
||||
|
||||
|
@@ -185,3 +185,11 @@ gdk_color_state_get_cicp (GdkColorState *self)
|
||||
|
||||
GdkColorState * gdk_color_state_new_for_cicp (const GdkCicp *cicp,
|
||||
GError **error);
|
||||
|
||||
#ifndef GDK_COLOR_STATE_IMPL
|
||||
extern GdkColorState gdk_color_state_bt601_narrow;
|
||||
extern GdkColorState gdk_color_state_bt601_full;
|
||||
#endif
|
||||
|
||||
#define GDK_COLOR_STATE_YUV ((GdkColorState *) &gdk_color_state_bt601_narrow)
|
||||
#define GDK_COLOR_STATE_JPEG ((GdkColorState *) &gdk_color_state_bt601_full)
|
||||
|
157
gdk/gdkdmabuf.c
157
gdk/gdkdmabuf.c
@@ -24,6 +24,7 @@
|
||||
#include "gdkdmabuffourccprivate.h"
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkcolorstate.h"
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <sys/mman.h>
|
||||
@@ -133,49 +134,6 @@ download_memcpy_3_1 (guchar *dst_data,
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _YUVCoefficients YUVCoefficients;
|
||||
|
||||
struct _YUVCoefficients
|
||||
{
|
||||
int v_to_r;
|
||||
int u_to_g;
|
||||
int v_to_g;
|
||||
int u_to_b;
|
||||
};
|
||||
|
||||
/* 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,
|
||||
@@ -226,14 +184,21 @@ download_nv12 (guchar *dst_data,
|
||||
{
|
||||
for (x = 0; x < width; x += X_SUB)
|
||||
{
|
||||
int r, g, b;
|
||||
int u_, v_;
|
||||
gsize xs, ys;
|
||||
|
||||
get_uv_values (&itu601_narrow, uv_data[x / X_SUB * 2 + U], uv_data[x / X_SUB * 2 + V], &r, &g, &b);
|
||||
u_ = uv_data[x / X_SUB * 2 + U];
|
||||
v_ = uv_data[x / X_SUB * 2 + V];
|
||||
|
||||
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);
|
||||
{
|
||||
guint8 *rgb = &dst_data[3 * (x + xs) + dst_stride * ys];
|
||||
|
||||
rgb[0] = y_data[x + xs + y_stride * ys];
|
||||
rgb[1] = u_;
|
||||
rgb[2] = v_;
|
||||
}
|
||||
}
|
||||
dst_data += Y_SUB * dst_stride;
|
||||
y_data += Y_SUB * y_stride;
|
||||
@@ -241,35 +206,6 @@ download_nv12 (guchar *dst_data,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
get_uv_values16 (const YUVCoefficients *coeffs,
|
||||
guint16 u,
|
||||
guint16 v,
|
||||
gint64 *out_r,
|
||||
gint64 *out_g,
|
||||
gint64 *out_b)
|
||||
{
|
||||
gint64 u2 = (gint64) u - 32767;
|
||||
gint64 v2 = (gint64) v - 32767;
|
||||
*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_values16 (guint16 rgb[3],
|
||||
guint16 y,
|
||||
gint64 r,
|
||||
gint64 g,
|
||||
gint64 b)
|
||||
{
|
||||
gint64 y2 = (gint64) y * 65536;
|
||||
|
||||
rgb[0] = CLAMP ((y2 + r) >> 16, 0, 65535);
|
||||
rgb[1] = CLAMP ((y2 + g) >> 16, 0, 65535);
|
||||
rgb[2] = CLAMP ((y2 + b) >> 16, 0, 65535);
|
||||
}
|
||||
|
||||
static void
|
||||
download_p010 (guchar *dst,
|
||||
gsize dst_stride,
|
||||
@@ -284,7 +220,7 @@ download_p010 (guchar *dst,
|
||||
guint16 *dst_data;
|
||||
gsize x, y, y_stride, uv_stride;
|
||||
gsize U, V, X_SUB, Y_SUB;
|
||||
guint16 SIZE, MASK;
|
||||
guint16 SIZE;
|
||||
|
||||
switch (dmabuf->fourcc)
|
||||
{
|
||||
@@ -304,7 +240,6 @@ download_p010 (guchar *dst,
|
||||
g_assert_not_reached ();
|
||||
return;
|
||||
}
|
||||
MASK = 0xFFFF << (16 - SIZE);
|
||||
|
||||
y_stride = dmabuf->planes[0].stride / 2;
|
||||
y_data = (const guint16 *) (src_data[0] + dmabuf->planes[0].offset);
|
||||
@@ -319,22 +254,24 @@ download_p010 (guchar *dst,
|
||||
{
|
||||
for (x = 0; x < width; x += X_SUB)
|
||||
{
|
||||
gint64 r, g, b;
|
||||
gsize xs, ys;
|
||||
guint16 u, v;
|
||||
guint16 u_, v_;
|
||||
|
||||
u = uv_data[x / X_SUB * 2 + U];
|
||||
u = (u & MASK) | (u >> SIZE);
|
||||
v = uv_data[x / X_SUB * 2 + V];
|
||||
v = (v & MASK) | (v >> SIZE);
|
||||
get_uv_values16 (&itu601_narrow, u, v, &r, &g, &b);
|
||||
u_ = uv_data[x / X_SUB * 2 + U];
|
||||
u_ = u_ | (u_ >> SIZE);
|
||||
v_ = uv_data[x / X_SUB * 2 + V];
|
||||
v_ = v_ | (v_ >> SIZE);
|
||||
|
||||
for (ys = 0; ys < Y_SUB && y + ys < height; ys++)
|
||||
for (xs = 0; xs < X_SUB && x + xs < width; xs++)
|
||||
{
|
||||
guint16 *rgb = &dst_data[3 * (x + xs) + dst_stride * ys];
|
||||
guint16 y_ = y_data[x + xs + y_stride * ys];
|
||||
y_ = (y_ & MASK) | (y_ >> SIZE);
|
||||
set_rgb_values16 (&dst_data[3 * (x + xs) + dst_stride * ys], y_, r, g, b);
|
||||
y_ = y_ | (y_ >> SIZE);
|
||||
|
||||
rgb[0] = y_;
|
||||
rgb[1] = u_;
|
||||
rgb[2] = v_;
|
||||
}
|
||||
}
|
||||
dst_data += Y_SUB * dst_stride;
|
||||
@@ -408,14 +345,21 @@ download_yuv_3 (guchar *dst_data,
|
||||
{
|
||||
for (x = 0; x < width; x += X_SUB)
|
||||
{
|
||||
int r, g, b;
|
||||
int u_, v_;
|
||||
gsize xs, ys;
|
||||
|
||||
get_uv_values (&itu601_narrow, u_data[x / X_SUB], v_data[x / X_SUB], &r, &g, &b);
|
||||
u_ = u_data[x / X_SUB];
|
||||
v_ = v_data[x / X_SUB];
|
||||
|
||||
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);
|
||||
{
|
||||
guint8 *rgb = &dst_data[3 * (x + xs) + dst_stride * ys];
|
||||
|
||||
rgb[0] = y_data[x + xs + y_stride * ys];
|
||||
rgb[1] = u_;
|
||||
rgb[2] = v_;
|
||||
}
|
||||
}
|
||||
dst_data += Y_SUB * dst_stride;
|
||||
y_data += Y_SUB * y_stride;
|
||||
@@ -465,12 +409,23 @@ download_yuyv (guchar *dst_data,
|
||||
{
|
||||
for (x = 0; x < width; x += 2)
|
||||
{
|
||||
int r, g, b;
|
||||
guint8 *rgb;
|
||||
int u_, v_;
|
||||
|
||||
get_uv_values (&itu601_narrow, 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);
|
||||
u_ = src_data[2 * x + U];
|
||||
v_ = src_data[2 * x + V];
|
||||
|
||||
rgb = &dst_data[3 * x];
|
||||
rgb[0] = src_data[2 * x + Y1];
|
||||
rgb[1] = u_;
|
||||
rgb[2] = v_;
|
||||
if (x + 1 < width)
|
||||
set_rgb_values (&dst_data[3 * (x + 1)], src_data[2 * x + Y2], r, g, b);
|
||||
{
|
||||
rgb = &dst_data[3 * (x + 1)];
|
||||
rgb[0] = src_data[2 * x + Y2];
|
||||
rgb[1] = u_;
|
||||
rgb[2] = v_;
|
||||
}
|
||||
}
|
||||
dst_data += dst_stride;
|
||||
src_data += src_stride;
|
||||
@@ -2139,14 +2094,14 @@ gdk_dmabuf_do_download_mmap (GdkTexture *texture,
|
||||
needs_unmap[i] = TRUE;
|
||||
}
|
||||
|
||||
info->download (data,
|
||||
stride,
|
||||
gdk_texture_get_format (texture),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture),
|
||||
dmabuf,
|
||||
src_data,
|
||||
sizes);
|
||||
info->download (data,
|
||||
stride,
|
||||
gdk_texture_get_format (texture),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture),
|
||||
dmabuf,
|
||||
src_data,
|
||||
sizes);
|
||||
|
||||
out:
|
||||
for (i = 0; i < dmabuf->n_planes; i++)
|
||||
|
@@ -209,12 +209,15 @@ gdk_dmabuf_egl_create_image (GdkDisplay *display,
|
||||
int width,
|
||||
int height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
int color_space_hint,
|
||||
int range_hint,
|
||||
int target)
|
||||
{
|
||||
EGLDisplay egl_display = gdk_display_get_egl_display (display);
|
||||
EGLint attribs[64];
|
||||
int i;
|
||||
EGLImage image;
|
||||
gboolean is_yuv;
|
||||
|
||||
g_return_val_if_fail (width > 0, 0);
|
||||
g_return_val_if_fail (height > 0, 0);
|
||||
@@ -228,6 +231,25 @@ gdk_dmabuf_egl_create_image (GdkDisplay *display,
|
||||
return EGL_NO_IMAGE;
|
||||
}
|
||||
|
||||
if (gdk_dmabuf_fourcc_is_yuv (dmabuf->fourcc, &is_yuv) && is_yuv)
|
||||
{
|
||||
if (color_space_hint == 0 || range_hint == 0)
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (display, DMABUF,
|
||||
"Can't import yuv dmabuf into GL without color space hints");
|
||||
return EGL_NO_IMAGE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (color_space_hint != 0 || range_hint != 0)
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (display, DMABUF,
|
||||
"Can't import non-yuv dmabuf into GL with color space hints");
|
||||
return EGL_NO_IMAGE;
|
||||
}
|
||||
}
|
||||
|
||||
GDK_DISPLAY_DEBUG (display, DMABUF,
|
||||
"Importing dmabuf (format: %.4s:%#" G_GINT64_MODIFIER "x, planes: %u) into GL",
|
||||
(char *) &dmabuf->fourcc, dmabuf->modifier, dmabuf->n_planes);
|
||||
@@ -241,10 +263,16 @@ gdk_dmabuf_egl_create_image (GdkDisplay *display,
|
||||
attribs[i++] = height;
|
||||
attribs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||
attribs[i++] = dmabuf->fourcc;
|
||||
attribs[i++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attribs[i++] = EGL_ITU_REC601_EXT;
|
||||
attribs[i++] = EGL_SAMPLE_RANGE_HINT_EXT;
|
||||
attribs[i++] = EGL_YUV_NARROW_RANGE_EXT;
|
||||
if (color_space_hint != 0)
|
||||
{
|
||||
attribs[i++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attribs[i++] = color_space_hint;
|
||||
}
|
||||
if (range_hint != 0)
|
||||
{
|
||||
attribs[i++] = EGL_SAMPLE_RANGE_HINT_EXT;
|
||||
attribs[i++] = range_hint;
|
||||
}
|
||||
|
||||
#define ADD_PLANE(plane) \
|
||||
{ \
|
||||
@@ -289,4 +317,48 @@ gdk_dmabuf_egl_create_image (GdkDisplay *display,
|
||||
return image;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_dmabuf_get_egl_yuv_hints (const GdkDmabuf *dmabuf,
|
||||
GdkColorState *color_state,
|
||||
int *color_space_hint,
|
||||
int *range_hint)
|
||||
{
|
||||
gboolean is_yuv;
|
||||
const GdkCicp *cicp;
|
||||
|
||||
cicp = gdk_color_state_get_cicp (color_state);
|
||||
|
||||
if (cicp &&
|
||||
gdk_dmabuf_fourcc_is_yuv (dmabuf->fourcc, &is_yuv) && is_yuv)
|
||||
{
|
||||
if (cicp->range == GDK_CICP_RANGE_NARROW)
|
||||
*range_hint = EGL_YUV_NARROW_RANGE_EXT;
|
||||
else
|
||||
*range_hint = EGL_YUV_FULL_RANGE_EXT;
|
||||
|
||||
switch (cicp->matrix_coefficients)
|
||||
{
|
||||
case 1:
|
||||
*color_space_hint = EGL_ITU_REC709_EXT;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
*color_space_hint = EGL_ITU_REC601_EXT;
|
||||
break;
|
||||
case 9:
|
||||
*color_space_hint = EGL_ITU_REC2020_EXT;
|
||||
break;
|
||||
default:
|
||||
*color_space_hint = 0;
|
||||
*range_hint = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*color_space_hint = 0;
|
||||
*range_hint = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_DMABUF && HAVE_EGL */
|
||||
|
@@ -13,6 +13,13 @@ EGLImage gdk_dmabuf_egl_create_image (GdkDisplay
|
||||
int width,
|
||||
int height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
int color_state_hint,
|
||||
int range_hint,
|
||||
int target);
|
||||
|
||||
void gdk_dmabuf_get_egl_yuv_hints (const GdkDmabuf *dmabuf,
|
||||
GdkColorState *color_state,
|
||||
int *color_space_hint,
|
||||
int *range_hint);
|
||||
|
||||
#endif /* HAVE_DMABUF && HAVE_EGL */
|
||||
|
@@ -208,12 +208,9 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
|
||||
gboolean is_yuv;
|
||||
|
||||
if (gdk_dmabuf_fourcc_is_yuv (dmabuf.fourcc, &is_yuv) && is_yuv)
|
||||
{
|
||||
g_warning_once ("FIXME: Implement the proper colorstate for YUV dmabufs");
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
}
|
||||
color_state = GDK_COLOR_STATE_YUV;
|
||||
else
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
color_state = GDK_COLOR_STATE_SRGB;
|
||||
}
|
||||
|
||||
self = g_object_new (GDK_TYPE_DMABUF_TEXTURE,
|
||||
|
@@ -2179,6 +2179,8 @@ gdk_gl_context_import_dmabuf_for_target (GdkGLContext *self,
|
||||
int width,
|
||||
int height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
int color_space_hint,
|
||||
int range_hint,
|
||||
int target)
|
||||
{
|
||||
#if defined(HAVE_EGL) && defined(HAVE_DMABUF)
|
||||
@@ -2190,6 +2192,8 @@ gdk_gl_context_import_dmabuf_for_target (GdkGLContext *self,
|
||||
width,
|
||||
height,
|
||||
dmabuf,
|
||||
color_space_hint,
|
||||
range_hint,
|
||||
target);
|
||||
if (image == EGL_NO_IMAGE)
|
||||
return 0;
|
||||
@@ -2213,6 +2217,8 @@ gdk_gl_context_import_dmabuf (GdkGLContext *self,
|
||||
int width,
|
||||
int height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
int color_space_hint,
|
||||
int range_hint,
|
||||
gboolean *external)
|
||||
{
|
||||
GdkDisplay *display = gdk_gl_context_get_display (self);
|
||||
@@ -2229,6 +2235,8 @@ gdk_gl_context_import_dmabuf (GdkGLContext *self,
|
||||
texture_id = gdk_gl_context_import_dmabuf_for_target (self,
|
||||
width, height,
|
||||
dmabuf,
|
||||
color_space_hint,
|
||||
range_hint,
|
||||
GL_TEXTURE_2D);
|
||||
if (texture_id == 0)
|
||||
{
|
||||
@@ -2258,6 +2266,8 @@ gdk_gl_context_import_dmabuf (GdkGLContext *self,
|
||||
texture_id = gdk_gl_context_import_dmabuf_for_target (self,
|
||||
width, height,
|
||||
dmabuf,
|
||||
color_space_hint,
|
||||
range_hint,
|
||||
GL_TEXTURE_EXTERNAL_OES);
|
||||
if (texture_id == 0)
|
||||
{
|
||||
@@ -2290,6 +2300,8 @@ gdk_gl_context_import_dmabuf (GdkGLContext *self,
|
||||
texture_id = gdk_gl_context_import_dmabuf_for_target (self,
|
||||
width, height,
|
||||
dmabuf,
|
||||
color_space_hint,
|
||||
range_hint,
|
||||
target);
|
||||
|
||||
if (texture_id == 0)
|
||||
|
@@ -184,6 +184,8 @@ guint gdk_gl_context_import_dmabuf (GdkGLContext
|
||||
int width,
|
||||
int height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
int color_space_hint,
|
||||
int range_hint,
|
||||
gboolean *external);
|
||||
|
||||
gboolean gdk_gl_context_export_dmabuf (GdkGLContext *self,
|
||||
|
@@ -149,37 +149,39 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
g_bytes_get_size (input_bytes));
|
||||
|
||||
jpeg_read_header (&info, TRUE);
|
||||
|
||||
if (info.jpeg_color_space == JCS_GRAYSCALE)
|
||||
{
|
||||
color_state = GDK_COLOR_STATE_SRGB;
|
||||
info.out_color_space = JCS_GRAYSCALE;
|
||||
format = GDK_MEMORY_G8;
|
||||
}
|
||||
else if (info.jpeg_color_space == JCS_YCbCr)
|
||||
{
|
||||
color_state = GDK_COLOR_STATE_JPEG;
|
||||
info.out_color_space = JCS_YCbCr;
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
}
|
||||
else if (info.jpeg_color_space == JCS_CMYK)
|
||||
{
|
||||
color_state = GDK_COLOR_STATE_SRGB;
|
||||
info.out_color_space = JCS_CMYK;
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
}
|
||||
else
|
||||
{
|
||||
color_state = GDK_COLOR_STATE_SRGB;
|
||||
info.out_color_space = JCS_RGB;
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
}
|
||||
|
||||
jpeg_start_decompress (&info);
|
||||
|
||||
width = info.output_width;
|
||||
height = info.output_height;
|
||||
stride = gdk_memory_format_bytes_per_pixel (format) * width;
|
||||
|
||||
color_state = GDK_COLOR_STATE_SRGB;
|
||||
|
||||
switch ((int)info.out_color_space)
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
stride = width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
format = GDK_MEMORY_G8;
|
||||
break;
|
||||
case JCS_RGB:
|
||||
stride = 3 * width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
stride = 4 * width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT,
|
||||
_("Unsupported JPEG colorspace (%d)"), info.out_color_space);
|
||||
jpeg_destroy_decompress (&info);
|
||||
return NULL;
|
||||
}
|
||||
data = g_try_malloc_n (stride, height);
|
||||
|
||||
if (!data)
|
||||
{
|
||||
@@ -215,7 +217,6 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
|
||||
texture = gdk_memory_texture_builder_build (builder);
|
||||
|
||||
gdk_color_state_unref (color_state);
|
||||
g_object_unref (builder);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
@@ -239,6 +240,7 @@ gdk_save_jpeg (GdkTexture *texture)
|
||||
gsize texstride;
|
||||
guchar *row;
|
||||
int width, height;
|
||||
GdkColorState *color_state;
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
@@ -268,13 +270,24 @@ gdk_save_jpeg (GdkTexture *texture)
|
||||
jpeg_set_defaults (&info);
|
||||
jpeg_set_quality (&info, 75, TRUE);
|
||||
|
||||
color_state = gdk_texture_get_color_state (texture);
|
||||
if (gdk_color_state_equal (color_state, GDK_COLOR_STATE_JPEG))
|
||||
{
|
||||
info.in_color_space = JCS_YCbCr;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.in_color_space = JCS_RGB;
|
||||
color_state = GDK_COLOR_STATE_SRGB;
|
||||
}
|
||||
|
||||
info.mem->max_memory_to_use = 300 * 1024 * 1024;
|
||||
|
||||
jpeg_mem_dest (&info, &data, &size);
|
||||
|
||||
gdk_texture_downloader_init (&downloader, texture);
|
||||
gdk_texture_downloader_set_format (&downloader, GDK_MEMORY_R8G8B8);
|
||||
gdk_texture_downloader_set_color_state (&downloader, GDK_COLOR_STATE_SRGB);
|
||||
gdk_texture_downloader_set_color_state (&downloader, color_state);
|
||||
texbytes = gdk_texture_downloader_download_bytes (&downloader, &texstride);
|
||||
gdk_texture_downloader_finish (&downloader);
|
||||
texdata = g_bytes_get_data (texbytes, NULL);
|
||||
|
@@ -43,6 +43,7 @@
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
#include <gdk/gdkdmabufeglprivate.h>
|
||||
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
#include <gdk/gdkdmabuftextureprivate.h>
|
||||
@@ -811,6 +812,8 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
|
||||
gboolean external;
|
||||
GdkMemoryFormat format;
|
||||
gboolean premultiply;
|
||||
GdkColorState *color_state;
|
||||
int color_space, range;
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
@@ -828,10 +831,16 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
|
||||
dmabuf = gdk_dmabuf_texture_get_dmabuf (texture);
|
||||
format = gdk_texture_get_format (GDK_TEXTURE (texture));
|
||||
premultiply = gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT;
|
||||
color_state = gdk_texture_get_color_state (GDK_TEXTURE (texture));
|
||||
|
||||
gdk_dmabuf_get_egl_yuv_hints (dmabuf, color_state, &color_space, &range);
|
||||
|
||||
|
||||
texture_id = gdk_gl_context_import_dmabuf (context,
|
||||
width, height,
|
||||
dmabuf,
|
||||
color_space,
|
||||
range,
|
||||
&external);
|
||||
if (texture_id == 0)
|
||||
return 0;
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include "gskglimageprivate.h"
|
||||
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkdmabufeglprivate.h"
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
@@ -92,7 +93,7 @@ gsk_gl_frame_upload_texture (GskGpuFrame *frame,
|
||||
gdk_gl_texture_get_id (gl_texture),
|
||||
FALSE,
|
||||
gdk_gl_texture_has_mipmap (gl_texture) ? (GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_MIPMAP) : 0);
|
||||
|
||||
|
||||
/* This is a hack, but it works */
|
||||
sync = gdk_gl_texture_get_sync (gl_texture);
|
||||
if (sync)
|
||||
@@ -105,19 +106,56 @@ gsk_gl_frame_upload_texture (GskGpuFrame *frame,
|
||||
{
|
||||
gboolean external;
|
||||
GLuint tex_id;
|
||||
int color_space_hint = 0;
|
||||
int range_hint = 0;
|
||||
|
||||
#if defined (HAVE_DMABUF) && defined (HAVE_EGL)
|
||||
gdk_dmabuf_get_egl_yuv_hints (gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture)),
|
||||
gdk_texture_get_color_state (texture),
|
||||
&color_space_hint,
|
||||
&range_hint);
|
||||
#endif
|
||||
|
||||
tex_id = gdk_gl_context_import_dmabuf (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture),
|
||||
gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture)),
|
||||
color_space_hint,
|
||||
range_hint,
|
||||
&external);
|
||||
|
||||
if (tex_id)
|
||||
{
|
||||
GskGpuImageFlags flags = 0;
|
||||
|
||||
if (external)
|
||||
flags |= GSK_GPU_IMAGE_EXTERNAL | GSK_GPU_IMAGE_NO_BLIT;
|
||||
|
||||
#if defined (HAVE_DMABUF) && defined (HAVE_EGL)
|
||||
switch (color_space_hint)
|
||||
{
|
||||
case EGL_ITU_REC709_EXT:
|
||||
flags |= GSK_GPU_IMAGE_BT709;
|
||||
break;
|
||||
case EGL_ITU_REC601_EXT:
|
||||
flags |= GSK_GPU_IMAGE_BT601;
|
||||
break;
|
||||
case EGL_ITU_REC2020_EXT:
|
||||
flags |= GSK_GPU_IMAGE_BT2020;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (range_hint == EGL_YUV_NARROW_RANGE_EXT)
|
||||
flags |= GSK_GPU_IMAGE_NARROW_RANGE;
|
||||
#endif
|
||||
|
||||
return gsk_gl_image_new_for_texture (GSK_GL_DEVICE (gsk_gpu_frame_get_device (frame)),
|
||||
texture,
|
||||
tex_id,
|
||||
TRUE,
|
||||
(external ? GSK_GPU_IMAGE_EXTERNAL | GSK_GPU_IMAGE_NO_BLIT : 0));
|
||||
flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -682,7 +682,7 @@ gsk_gpu_cache_lookup_tile (GskGpuCache *self,
|
||||
|
||||
gsk_gpu_cached_use (self, (GskGpuCached *) tile);
|
||||
|
||||
*out_color_state = tile->color_state;
|
||||
*out_color_state = gdk_color_state_ref (tile->color_state);
|
||||
|
||||
return g_object_ref (tile->image);
|
||||
}
|
||||
|
@@ -36,7 +36,8 @@ gsk_gpu_convert_cicp_op_print_instance (GskGpuShaderOp *shader,
|
||||
g_string_append_printf (string, "cicp %u/%u/%u/%u",
|
||||
instance->color_primaries,
|
||||
instance->transfer_function,
|
||||
0, 1);
|
||||
instance->matrix_coefficients,
|
||||
instance->range);
|
||||
}
|
||||
|
||||
static const GskGpuShaderOpClass GSK_GPU_CONVERT_OP_CLASS = {
|
||||
@@ -88,6 +89,8 @@ gsk_gpu_convert_from_cicp_op (GskGpuFrame *frame,
|
||||
instance->opacity = opacity;
|
||||
instance->color_primaries = cicp->color_primaries;
|
||||
instance->transfer_function = cicp->transfer_function;
|
||||
instance->matrix_coefficients = cicp->matrix_coefficients;
|
||||
instance->range = cicp->range == GDK_CICP_RANGE_NARROW ? 0 : 1;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -118,4 +121,6 @@ gsk_gpu_convert_to_cicp_op (GskGpuFrame *frame,
|
||||
instance->opacity = opacity;
|
||||
instance->color_primaries = cicp->color_primaries;
|
||||
instance->transfer_function = cicp->transfer_function;
|
||||
instance->matrix_coefficients = cicp->matrix_coefficients;
|
||||
instance->range = cicp->range == GDK_CICP_RANGE_NARROW ? 0 : 1;
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskgpuimageprivate.h"
|
||||
#include "gdkcolorstateprivate.h"
|
||||
|
||||
typedef struct _GskGpuImagePrivate GskGpuImagePrivate;
|
||||
|
||||
@@ -162,3 +163,61 @@ gsk_gpu_image_get_projection_matrix (GskGpuImage *self,
|
||||
{
|
||||
GSK_GPU_IMAGE_GET_CLASS (self)->get_projection_matrix (self, out_projection);
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
gsk_gpu_image_adjust_color_state (GskGpuImage *self,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
GskGpuImagePrivate *priv = gsk_gpu_image_get_instance_private (self);
|
||||
GdkColorState *adjusted;
|
||||
GdkCicp cicp;
|
||||
|
||||
adjusted = gdk_color_state_ref (color_state);
|
||||
|
||||
if (priv->flags & GSK_GPU_IMAGE_SRGB)
|
||||
{
|
||||
GdkColorState *no_srgb;
|
||||
|
||||
no_srgb = gdk_color_state_get_no_srgb_tf (adjusted);
|
||||
g_assert (no_srgb);
|
||||
|
||||
gdk_color_state_unref (adjusted);
|
||||
adjusted = gdk_color_state_ref (no_srgb);
|
||||
}
|
||||
|
||||
if (!gdk_color_state_get_cicp (adjusted))
|
||||
return adjusted;
|
||||
|
||||
cicp = *gdk_color_state_get_cicp (adjusted);
|
||||
|
||||
if (priv->flags & GSK_GPU_IMAGE_NARROW_RANGE)
|
||||
cicp.range = GDK_CICP_RANGE_FULL;
|
||||
|
||||
switch (priv->flags & GSK_GPU_IMAGE_YUV)
|
||||
{
|
||||
case GSK_GPU_IMAGE_BT709:
|
||||
g_assert (cicp.matrix_coefficients == 1);
|
||||
cicp.matrix_coefficients = 0;
|
||||
break;
|
||||
case GSK_GPU_IMAGE_BT601:
|
||||
g_assert (cicp.matrix_coefficients == 5 ||
|
||||
cicp.matrix_coefficients == 6);
|
||||
cicp.matrix_coefficients = 0;
|
||||
break;
|
||||
case GSK_GPU_IMAGE_BT2020:
|
||||
g_assert (cicp.matrix_coefficients == 9);
|
||||
cicp.matrix_coefficients = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!gdk_cicp_equal (&cicp, gdk_color_state_get_cicp (adjusted)))
|
||||
{
|
||||
gdk_color_state_unref (adjusted);
|
||||
adjusted = gdk_color_state_new_for_cicp (&cicp, NULL);
|
||||
g_assert (adjusted);
|
||||
}
|
||||
|
||||
return adjusted;
|
||||
}
|
||||
|
@@ -48,6 +48,9 @@ void gsk_gpu_image_set_flags (GskGpuI
|
||||
void gsk_gpu_image_get_projection_matrix (GskGpuImage *self,
|
||||
graphene_matrix_t *out_projection);
|
||||
|
||||
GdkColorState * gsk_gpu_image_adjust_color_state (GskGpuImage *self,
|
||||
GdkColorState *color_state);
|
||||
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuImage, g_object_unref)
|
||||
|
||||
|
@@ -1659,7 +1659,6 @@ gsk_gpu_lookup_texture (GskGpuFrame *frame,
|
||||
GdkColorState **out_image_cs)
|
||||
{
|
||||
GskGpuCache *cache;
|
||||
GdkColorState *image_cs;
|
||||
GskGpuImage *image;
|
||||
|
||||
cache = gsk_gpu_device_get_cache (gsk_gpu_frame_get_device (frame));
|
||||
@@ -1667,7 +1666,7 @@ gsk_gpu_lookup_texture (GskGpuFrame *frame,
|
||||
image = gsk_gpu_cache_lookup_texture_image (cache, texture, ccs);
|
||||
if (image)
|
||||
{
|
||||
*out_image_cs = ccs;
|
||||
*out_image_cs = gdk_color_state_ref (ccs);
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -1677,17 +1676,14 @@ gsk_gpu_lookup_texture (GskGpuFrame *frame,
|
||||
|
||||
/* Happens ie for oversized textures */
|
||||
if (image == NULL)
|
||||
return NULL;
|
||||
|
||||
image_cs = gdk_texture_get_color_state (texture);
|
||||
|
||||
if (gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_SRGB)
|
||||
{
|
||||
image_cs = gdk_color_state_get_no_srgb_tf (image_cs);
|
||||
g_assert (image_cs);
|
||||
*out_image_cs = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*out_image_cs = image_cs;
|
||||
*out_image_cs = gsk_gpu_image_adjust_color_state (image,
|
||||
gdk_texture_get_color_state (texture));
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -1721,7 +1717,6 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
|
||||
GskGpuCache *cache;
|
||||
GskGpuDevice *device;
|
||||
GskGpuImage *tile;
|
||||
GdkColorState *tile_cs;
|
||||
GskGpuSampler sampler;
|
||||
gboolean need_mipmap;
|
||||
GdkMemoryTexture *memtex;
|
||||
@@ -1748,6 +1743,8 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
|
||||
{
|
||||
for (x = 0; x < n_width; x++)
|
||||
{
|
||||
GdkColorState *tile_cs = NULL;
|
||||
|
||||
graphene_rect_t tile_rect = GRAPHENE_RECT_INIT (texture_bounds->origin.x + scaled_tile_width * x,
|
||||
texture_bounds->origin.y + scaled_tile_height * y,
|
||||
scaled_tile_width,
|
||||
@@ -1776,13 +1773,8 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
|
||||
goto out;
|
||||
}
|
||||
|
||||
tile_cs = gdk_texture_get_color_state (texture);
|
||||
if (gsk_gpu_image_get_flags (tile) & GSK_GPU_IMAGE_SRGB)
|
||||
{
|
||||
tile_cs = gdk_color_state_get_no_srgb_tf (tile_cs);
|
||||
g_assert (tile_cs);
|
||||
}
|
||||
|
||||
tile_cs = gsk_gpu_image_adjust_color_state (tile,
|
||||
gdk_texture_get_color_state (texture));
|
||||
gsk_gpu_cache_cache_tile (cache, texture, y * n_width + x, tile, tile_cs);
|
||||
}
|
||||
|
||||
@@ -1790,7 +1782,8 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
|
||||
(gsk_gpu_image_get_flags (tile) & (GSK_GPU_IMAGE_STRAIGHT_ALPHA | GSK_GPU_IMAGE_CAN_MIPMAP)) != GSK_GPU_IMAGE_CAN_MIPMAP)
|
||||
{
|
||||
tile = gsk_gpu_copy_image (self->frame, self->ccs, tile, tile_cs, TRUE);
|
||||
tile_cs = self->ccs;
|
||||
gdk_color_state_unref (tile_cs);
|
||||
tile_cs = gdk_color_state_ref (self->ccs);
|
||||
gsk_gpu_cache_cache_tile (cache, texture, y * n_width + x, tile, tile_cs);
|
||||
}
|
||||
if (need_mipmap && !(gsk_gpu_image_get_flags (tile) & GSK_GPU_IMAGE_MIPMAP))
|
||||
@@ -1803,6 +1796,7 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
|
||||
&tile_rect,
|
||||
&tile_rect);
|
||||
|
||||
gdk_color_state_unref (tile_cs);
|
||||
g_object_unref (tile);
|
||||
}
|
||||
}
|
||||
@@ -1891,7 +1885,8 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
|
||||
!gdk_color_state_equal (image_cs, self->ccs))
|
||||
{
|
||||
image = gsk_gpu_copy_image (self->frame, self->ccs, image, image_cs, TRUE);
|
||||
image_cs = self->ccs;
|
||||
gdk_color_state_unref (image_cs);
|
||||
image_cs = gdk_color_state_ref (self->ccs);
|
||||
gsk_gpu_cache_cache_texture_image (gsk_gpu_device_get_cache (gsk_gpu_frame_get_device (self->frame)),
|
||||
texture,
|
||||
image,
|
||||
@@ -1918,6 +1913,7 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
|
||||
&node->bounds);
|
||||
}
|
||||
|
||||
gdk_color_state_unref (image_cs);
|
||||
g_object_unref (image);
|
||||
}
|
||||
|
||||
@@ -1964,6 +1960,7 @@ gsk_gpu_get_texture_node_as_image (GskGpuFrame *frame,
|
||||
}
|
||||
|
||||
*out_bounds = node->bounds;
|
||||
gdk_color_state_unref (image_cs);
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -2002,6 +1999,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
|
||||
/* now intersect with actual node bounds */
|
||||
if (!gsk_rect_intersection (&clip_bounds, &node->bounds, &clip_bounds))
|
||||
{
|
||||
gdk_color_state_unref (image_cs);
|
||||
g_object_unref (image);
|
||||
return;
|
||||
}
|
||||
@@ -2044,7 +2042,8 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
|
||||
!gdk_color_state_equal (image_cs, self->ccs))
|
||||
{
|
||||
image = gsk_gpu_copy_image (self->frame, self->ccs, image, image_cs, need_mipmap);
|
||||
image_cs = self->ccs;
|
||||
gdk_color_state_unref (image_cs);
|
||||
image_cs = gdk_color_state_ref (self->ccs);
|
||||
gsk_gpu_cache_cache_texture_image (gsk_gpu_device_get_cache (gsk_gpu_frame_get_device (self->frame)),
|
||||
texture,
|
||||
image,
|
||||
@@ -2064,6 +2063,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
|
||||
&node->bounds,
|
||||
});
|
||||
|
||||
gdk_color_state_unref (image_cs);
|
||||
g_object_unref (image);
|
||||
}
|
||||
|
||||
|
@@ -29,8 +29,14 @@ typedef enum {
|
||||
GSK_GPU_IMAGE_FILTERABLE = (1 << 6),
|
||||
GSK_GPU_IMAGE_RENDERABLE = (1 << 7),
|
||||
GSK_GPU_IMAGE_SRGB = (1 << 8),
|
||||
GSK_GPU_IMAGE_NARROW_RANGE = (1 << 9),
|
||||
GSK_GPU_IMAGE_BT601 = (1 << 10),
|
||||
GSK_GPU_IMAGE_BT709 = (2 << 10),
|
||||
GSK_GPU_IMAGE_BT2020 = (3 << 10),
|
||||
} GskGpuImageFlags;
|
||||
|
||||
#define GSK_GPU_IMAGE_YUV (GSK_GPU_IMAGE_BT2020)
|
||||
|
||||
typedef enum {
|
||||
GSK_GPU_SAMPLER_DEFAULT,
|
||||
GSK_GPU_SAMPLER_TRANSPARENT,
|
||||
|
@@ -187,6 +187,7 @@ gsk_vulkan_frame_upload_texture (GskGpuFrame *frame,
|
||||
image = gsk_vulkan_image_new_for_dmabuf (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture),
|
||||
gdk_texture_get_color_state (texture),
|
||||
&dmabuf,
|
||||
gdk_memory_format_alpha (gdk_texture_get_format (texture)) == GDK_MEMORY_ALPHA_PREMULTIPLIED);
|
||||
|
||||
@@ -209,6 +210,7 @@ gsk_vulkan_frame_upload_texture (GskGpuFrame *frame,
|
||||
image = gsk_vulkan_image_new_for_dmabuf (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture),
|
||||
gdk_texture_get_color_state (texture),
|
||||
gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture)),
|
||||
gdk_memory_format_alpha (gdk_texture_get_format (texture)) == GDK_MEMORY_ALPHA_PREMULTIPLIED);
|
||||
if (image)
|
||||
|
@@ -844,6 +844,7 @@ GskGpuImage *
|
||||
gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device,
|
||||
gsize width,
|
||||
gsize height,
|
||||
GdkColorState *color_state,
|
||||
const GdkDmabuf *dmabuf,
|
||||
gboolean premultiplied)
|
||||
{
|
||||
@@ -859,6 +860,7 @@ gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device,
|
||||
GdkMemoryFormat format;
|
||||
GskGpuImageFlags flags;
|
||||
gboolean is_yuv;
|
||||
const GdkCicp *cicp;
|
||||
|
||||
if (!gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_DMABUF))
|
||||
{
|
||||
@@ -968,13 +970,36 @@ gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gsk_gpu_image_setup (GSK_GPU_IMAGE (self),
|
||||
flags |
|
||||
(gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT ? GSK_GPU_IMAGE_STRAIGHT_ALPHA : 0) |
|
||||
(is_yuv ? (GSK_GPU_IMAGE_EXTERNAL | GSK_GPU_IMAGE_NO_BLIT) : 0) |
|
||||
(gsk_component_mapping_is_framebuffer_compatible (&vk_components) ? 0 : GSK_GPU_IMAGE_NO_BLIT),
|
||||
format,
|
||||
width, height);
|
||||
if (is_yuv)
|
||||
flags |= GSK_GPU_IMAGE_EXTERNAL | GSK_GPU_IMAGE_NO_BLIT;
|
||||
|
||||
if (gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
flags |= GSK_GPU_IMAGE_STRAIGHT_ALPHA;
|
||||
|
||||
if (!gsk_component_mapping_is_framebuffer_compatible (&vk_components))
|
||||
flags |= GSK_GPU_IMAGE_NO_BLIT;
|
||||
|
||||
cicp = gdk_color_state_get_cicp (color_state);
|
||||
switch (cicp->matrix_coefficients)
|
||||
{
|
||||
case 1:
|
||||
flags |= GSK_GPU_IMAGE_BT709;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
flags |= GSK_GPU_IMAGE_BT601;
|
||||
break;
|
||||
case 9:
|
||||
flags |= GSK_GPU_IMAGE_BT2020;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cicp->range == GDK_CICP_RANGE_NARROW)
|
||||
flags |= GSK_GPU_IMAGE_NARROW_RANGE;
|
||||
|
||||
gsk_gpu_image_setup (GSK_GPU_IMAGE (self), flags, format, width, height);
|
||||
|
||||
self->allocator = gsk_vulkan_device_get_external_allocator (device);
|
||||
gsk_vulkan_allocator_ref (self->allocator);
|
||||
|
@@ -42,6 +42,7 @@ GskGpuImage * gsk_vulkan_image_new_dmabuf (GskVulk
|
||||
GskGpuImage * gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device,
|
||||
gsize width,
|
||||
gsize height,
|
||||
GdkColorState *color_state,
|
||||
const GdkDmabuf *dmabuf,
|
||||
gboolean premultiplied);
|
||||
GdkTexture * gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self);
|
||||
|
@@ -14,6 +14,8 @@ PASS(2) vec2 _tex_coord;
|
||||
PASS_FLAT(3) float _opacity;
|
||||
PASS_FLAT(4) uint _transfer_function;
|
||||
PASS_FLAT(5) mat3 _mat;
|
||||
PASS_FLAT(8) mat3 _yuv;
|
||||
PASS_FLAT(11) uint _range;
|
||||
|
||||
#ifdef GSK_VERTEX_SHADER
|
||||
|
||||
@@ -22,6 +24,8 @@ IN(1) vec4 in_tex_rect;
|
||||
IN(2) float in_opacity;
|
||||
IN(3) uint in_color_primaries;
|
||||
IN(4) uint in_transfer_function;
|
||||
IN(5) uint in_matrix_coefficients;
|
||||
IN(6) uint in_range;
|
||||
|
||||
|
||||
const mat3 identity = mat3(
|
||||
@@ -90,6 +94,42 @@ const mat3 xyz_to_p3 = mat3(
|
||||
-0.4027108, 0.0236247, 0.9568845
|
||||
);
|
||||
|
||||
const mat3 rgb_to_bt601 = mat3(
|
||||
0.299000, -0.168736, 0.500000,
|
||||
0.587000, -0.331264, -0.418688,
|
||||
0.114000, 0.500000, -0.081312
|
||||
);
|
||||
|
||||
const mat3 bt601_to_rgb = mat3(
|
||||
1.000000, 1.000000, 1.000000,
|
||||
0.000000, -0.344136, 1.772000,
|
||||
1.402000, -0.714136, 0.000000
|
||||
);
|
||||
|
||||
const mat3 rgb_to_bt709 = mat3(
|
||||
0.212600, -0.114572, 0.500000,
|
||||
0.715200, -0.385428, -0.454153,
|
||||
0.072200, 0.500000, -0.045847
|
||||
);
|
||||
|
||||
const mat3 bt709_to_rgb = mat3(
|
||||
1.000000, 1.000000, 1.000000,
|
||||
0.000000, -0.187324, 1.855600,
|
||||
1.574800, -0.468124, -0.000000
|
||||
);
|
||||
|
||||
const mat3 rgb_to_bt2020 = mat3(
|
||||
0.262700, -0.139630, 0.500000,
|
||||
0.678000, -0.360370, -0.459786,
|
||||
0.059300, 0.500000, -0.040214
|
||||
);
|
||||
|
||||
const mat3 bt2020_to_rgb = mat3(
|
||||
1.000000, 1.000000, 1.000000,
|
||||
-0.000000, -0.164553, 1.881400,
|
||||
1.474600, -0.571353, -0.000000
|
||||
);
|
||||
|
||||
mat3
|
||||
cicp_to_xyz (uint cp)
|
||||
{
|
||||
@@ -121,6 +161,34 @@ cicp_from_xyz (uint cp)
|
||||
}
|
||||
|
||||
|
||||
mat3
|
||||
yuv_to_rgb (uint mc)
|
||||
{
|
||||
switch (mc)
|
||||
{
|
||||
case 0u: return identity;
|
||||
case 1u: return bt709_to_rgb;
|
||||
case 5u:
|
||||
case 6u: return bt601_to_rgb;
|
||||
case 9u: return bt2020_to_rgb;
|
||||
}
|
||||
return mat3(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0);
|
||||
}
|
||||
|
||||
mat3
|
||||
rgb_to_yuv (uint mc)
|
||||
{
|
||||
switch (mc)
|
||||
{
|
||||
case 0u: return identity;
|
||||
case 1u: return rgb_to_bt709;
|
||||
case 5u:
|
||||
case 6u: return rgb_to_bt601;
|
||||
case 9u: return rgb_to_bt2020;
|
||||
}
|
||||
return mat3(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0);
|
||||
}
|
||||
|
||||
void
|
||||
run (out vec2 pos)
|
||||
{
|
||||
@@ -133,6 +201,7 @@ run (out vec2 pos)
|
||||
_tex_coord = rect_get_coord (rect_from_gsk (in_tex_rect), pos);
|
||||
_opacity = in_opacity;
|
||||
_transfer_function = in_transfer_function;
|
||||
_range = in_range;
|
||||
|
||||
if (HAS_VARIATION (VARIATION_REVERSE))
|
||||
{
|
||||
@@ -141,6 +210,8 @@ run (out vec2 pos)
|
||||
_mat = cicp_from_xyz (in_color_primaries) * srgb_to_xyz;
|
||||
else
|
||||
_mat = cicp_from_xyz (in_color_primaries) * rec2020_to_xyz;
|
||||
|
||||
_yuv = rgb_to_yuv (in_matrix_coefficients);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -149,6 +220,8 @@ run (out vec2 pos)
|
||||
_mat = xyz_to_srgb * cicp_to_xyz (in_color_primaries);
|
||||
else
|
||||
_mat = xyz_to_rec2020 * cicp_to_xyz (in_color_primaries);
|
||||
|
||||
_yuv = yuv_to_rgb (in_matrix_coefficients);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,6 +402,18 @@ convert_color_from_cicp (vec4 color,
|
||||
if (from_premul)
|
||||
color = color_unpremultiply (color);
|
||||
|
||||
if (_range == 0u)
|
||||
{
|
||||
color.r = (color.r - 16.0/255.0) * 255.0/219.0;
|
||||
color.g = (color.g - 16.0/255.0) * 255.0/224.0;
|
||||
color.b = (color.b - 16.0/255.0) * 255.0/224.0;
|
||||
}
|
||||
|
||||
color.g -= 0.5;
|
||||
color.b -= 0.5;
|
||||
|
||||
color.rgb = _yuv * color.rgb;
|
||||
|
||||
color.rgb = apply_cicp_eotf (color.rgb, _transfer_function);
|
||||
color.rgb = _mat * color.rgb;
|
||||
color.rgb = apply_oetf (color.rgb, to);
|
||||
@@ -352,6 +437,18 @@ convert_color_to_cicp (vec4 color,
|
||||
color.rgb = _mat * color.rgb;
|
||||
color.rgb = apply_cicp_oetf (color.rgb, _transfer_function);
|
||||
|
||||
color.rgb = _yuv * color.rgb;
|
||||
|
||||
color.g += 0.5;
|
||||
color.b += 0.5;
|
||||
|
||||
if (_range == 0u)
|
||||
{
|
||||
color.r = color.r * 219.0/255.0 + 16.0/255.0;
|
||||
color.g = color.g * 224.0/255.0 + 16.0/255.0;
|
||||
color.b = color.b * 224.0/255.0 + 16.0/255.0;
|
||||
}
|
||||
|
||||
if (to_premul)
|
||||
color = color_premultiply (color);
|
||||
|
||||
|
@@ -24,6 +24,8 @@
|
||||
|
||||
#include "gtkgstpaintableprivate.h"
|
||||
|
||||
#include "gdk/gdkdmabuffourccprivate.h"
|
||||
|
||||
#if GST_GL_HAVE_WINDOW_X11 && (GST_GL_HAVE_PLATFORM_GLX || GST_GL_HAVE_PLATFORM_EGL) && defined (GDK_WINDOWING_X11)
|
||||
#define HAVE_GST_X11_SUPPORT
|
||||
#include <gdk/x11/gdkx.h>
|
||||
@@ -168,7 +170,8 @@ add_drm_formats_and_modifiers (GstCaps *caps,
|
||||
|
||||
static GdkColorState *
|
||||
gtk_gst_color_state_from_colorimetry (GtkGstSink *self,
|
||||
const GstVideoColorimetry *colorimetry)
|
||||
const GstVideoColorimetry *colorimetry,
|
||||
gconstpointer drm)
|
||||
{
|
||||
GdkCicpParams *params;
|
||||
GdkColorState *color_state;
|
||||
@@ -186,18 +189,92 @@ gtk_gst_color_state_from_colorimetry (GtkGstSink *self,
|
||||
else
|
||||
gdk_cicp_params_set_transfer_function (params, gst_video_transfer_function_to_iso (colorimetry->transfer));
|
||||
|
||||
#if 0
|
||||
gdk_cicp_params_set_range (params, colorimetry->range == GST_VIDEO_COLOR_RANGE_16_235 ? GDK_CICP_RANGE_NARROW : GDK_CICP_RANGE_FULL);
|
||||
|
||||
if (colorimetry->matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN)
|
||||
gdk_cicp_params_set_matrix_coefficients (params, 6);
|
||||
{
|
||||
gdk_cicp_params_set_matrix_coefficients (params, 0);
|
||||
#ifdef HAVE_GSTREAMER_DRM
|
||||
const GstVideoInfoDmaDrm *drm_info = drm;
|
||||
if (drm_info)
|
||||
{
|
||||
switch (drm_info->drm_fourcc)
|
||||
{
|
||||
case DRM_FORMAT_YUYV:
|
||||
case DRM_FORMAT_YVYU:
|
||||
case DRM_FORMAT_VYUY:
|
||||
case DRM_FORMAT_UYVY:
|
||||
case DRM_FORMAT_AYUV:
|
||||
case DRM_FORMAT_AVUY8888:
|
||||
case DRM_FORMAT_XYUV8888:
|
||||
case DRM_FORMAT_XVUY8888:
|
||||
case DRM_FORMAT_VUY888:
|
||||
case DRM_FORMAT_VUY101010:
|
||||
case DRM_FORMAT_Y210:
|
||||
case DRM_FORMAT_Y212:
|
||||
case DRM_FORMAT_Y216:
|
||||
case DRM_FORMAT_Y410:
|
||||
case DRM_FORMAT_Y412:
|
||||
case DRM_FORMAT_Y416:
|
||||
case DRM_FORMAT_XVYU2101010:
|
||||
case DRM_FORMAT_XVYU12_16161616:
|
||||
case DRM_FORMAT_XVYU16161616:
|
||||
case DRM_FORMAT_Y0L0:
|
||||
case DRM_FORMAT_X0L0:
|
||||
case DRM_FORMAT_Y0L2:
|
||||
case DRM_FORMAT_X0L2:
|
||||
case DRM_FORMAT_YUV420_8BIT:
|
||||
case DRM_FORMAT_YUV420_10BIT:
|
||||
case DRM_FORMAT_NV12:
|
||||
case DRM_FORMAT_NV21:
|
||||
case DRM_FORMAT_NV16:
|
||||
case DRM_FORMAT_NV61:
|
||||
case DRM_FORMAT_NV24:
|
||||
case DRM_FORMAT_NV42:
|
||||
case DRM_FORMAT_NV15:
|
||||
case DRM_FORMAT_P210:
|
||||
case DRM_FORMAT_P010:
|
||||
case DRM_FORMAT_P012:
|
||||
case DRM_FORMAT_P016:
|
||||
case DRM_FORMAT_P030:
|
||||
case DRM_FORMAT_Q410:
|
||||
case DRM_FORMAT_Q401:
|
||||
case DRM_FORMAT_YUV410:
|
||||
case DRM_FORMAT_YVU410:
|
||||
case DRM_FORMAT_YUV411:
|
||||
case DRM_FORMAT_YVU411:
|
||||
case DRM_FORMAT_YUV420:
|
||||
case DRM_FORMAT_YVU420:
|
||||
case DRM_FORMAT_YUV422:
|
||||
case DRM_FORMAT_YVU422:
|
||||
case DRM_FORMAT_YUV444:
|
||||
case DRM_FORMAT_YVU444:
|
||||
g_debug ("Assuming fourcc %.*s is yuv", 4, (char *)&drm_info->drm_fourcc);
|
||||
gdk_cicp_params_set_matrix_coefficients (params, 6);
|
||||
gdk_cicp_params_set_range (params, GDK_CICP_RANGE_NARROW);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
gdk_cicp_params_set_matrix_coefficients (params, gst_video_color_matrix_to_iso (colorimetry->matrix));
|
||||
|
||||
gdk_cicp_params_set_range (params, colorimetry->range == GST_VIDEO_COLOR_RANGE_0_255 ? GDK_CICP_RANGE_FULL : GDK_CICP_RANGE_NARROW);
|
||||
#else
|
||||
gdk_cicp_params_set_matrix_coefficients (params, 0);
|
||||
gdk_cicp_params_set_range (params, GDK_CICP_RANGE_FULL);
|
||||
#endif
|
||||
color_state = gdk_cicp_params_build_color_state (params, &error);
|
||||
g_debug ("cicp received: %u/%u/%u/%u",
|
||||
gst_video_color_primaries_to_iso (colorimetry->primaries),
|
||||
gst_video_transfer_function_to_iso (colorimetry->transfer),
|
||||
gst_video_color_matrix_to_iso (colorimetry->matrix),
|
||||
colorimetry->range == GST_VIDEO_COLOR_RANGE_0_255);
|
||||
|
||||
g_debug ("cicp used: %u/%u/%u/%u",
|
||||
gdk_cicp_params_get_color_primaries (params),
|
||||
gdk_cicp_params_get_transfer_function (params),
|
||||
gdk_cicp_params_get_matrix_coefficients (params),
|
||||
gdk_cicp_params_get_range (params));
|
||||
|
||||
g_object_unref (params);
|
||||
|
||||
if (color_state == NULL)
|
||||
@@ -281,7 +358,14 @@ gtk_gst_sink_set_caps (GstBaseSink *bsink,
|
||||
#endif
|
||||
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
self->color_state = gtk_gst_color_state_from_colorimetry (self, &self->v_info.colorimetry);
|
||||
self->color_state = gtk_gst_color_state_from_colorimetry (self,
|
||||
&self->v_info.colorimetry,
|
||||
#ifdef HAVE_GSTREAMER_DRM
|
||||
&self->drm_info
|
||||
#else
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
if (self->color_state == NULL)
|
||||
return FALSE;
|
||||
|
||||
|
@@ -48,6 +48,9 @@ static MatrixTest matrices[] = {
|
||||
{ "ntsc", ntsc_to_xyz, xyz_to_ntsc },
|
||||
{ "p3", p3_to_xyz, xyz_to_p3 },
|
||||
{ "srgb<>rec2020", rec2020_to_srgb, srgb_to_rec2020 },
|
||||
{ "bt601", bt601_to_rgb, rgb_to_bt601 },
|
||||
{ "bt709", bt709_to_rgb, rgb_to_bt709 },
|
||||
{ "bt2020", bt2020_to_rgb, rgb_to_bt2020 },
|
||||
};
|
||||
|
||||
#define IDX(i,j) 3*i+j
|
||||
|
@@ -127,9 +127,11 @@ test_convert (gconstpointer testdata)
|
||||
gsize width, height;
|
||||
GdkMemoryFormat test_format;
|
||||
|
||||
#if 0
|
||||
if (g_test_rand_bit ())
|
||||
test_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
else
|
||||
#endif
|
||||
test_format = GDK_MEMORY_R32G32B32A32_FLOAT;
|
||||
|
||||
path = g_test_build_filename (G_TEST_DIST, "image-data", "image.png", NULL);
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdkdmabuffourccprivate.h>
|
||||
#include <gdk/gdkdmabuftextureprivate.h>
|
||||
#include <gdk/gdkdmabufeglprivate.h>
|
||||
|
||||
static cairo_surface_t *
|
||||
make_surface (int width,
|
||||
@@ -191,6 +192,8 @@ test_dmabuf_import (void)
|
||||
GdkGLTextureBuilder *builder;
|
||||
guchar *data;
|
||||
gboolean external;
|
||||
GdkColorState *color_state;
|
||||
int color_space, range;
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
if (!gdk_display_prepare_gl (display, &error))
|
||||
@@ -229,7 +232,9 @@ test_dmabuf_import (void)
|
||||
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, &external);
|
||||
color_state = gdk_texture_get_color_state (texture);
|
||||
gdk_dmabuf_get_egl_yuv_hints (dmabuf2, color_state, &color_space, &range);
|
||||
texture_id2 = gdk_gl_context_import_dmabuf (context2, 64, 64, dmabuf2, color_space, range, &external);
|
||||
g_assert_cmpint (texture_id2, !=, 0);
|
||||
g_assert_false (external);
|
||||
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <stdlib.h>
|
||||
#include "../reftests/reftest-compare.h"
|
||||
#include "dmabufize.h"
|
||||
|
||||
|
||||
static char *arg_output_dir = NULL;
|
||||
@@ -15,6 +16,7 @@ static gboolean mask = FALSE;
|
||||
static gboolean replay = FALSE;
|
||||
static gboolean clip = FALSE;
|
||||
static gboolean colorflip = FALSE;
|
||||
static gboolean dmabuf = FALSE;
|
||||
|
||||
extern void
|
||||
replay_node (GskRenderNode *node, GtkSnapshot *snapshot);
|
||||
@@ -172,6 +174,7 @@ static const GOptionEntry options[] = {
|
||||
{ "replay", 0, 0, G_OPTION_ARG_NONE, &replay, "Do replay test", NULL },
|
||||
{ "clip", 0, 0, G_OPTION_ARG_NONE, &clip, "Do clip test", NULL },
|
||||
{ "colorflip", 0, 0, G_OPTION_ARG_NONE, &colorflip, "Swap colors", NULL },
|
||||
{ "dmabuf", 0, 0, G_OPTION_ARG_NONE, &dmabuf, "Turn into dmabufs", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -728,6 +731,37 @@ skip_clip:
|
||||
gsk_render_node_unref (node2);
|
||||
}
|
||||
|
||||
if (dmabuf)
|
||||
{
|
||||
GskRenderNode *node2;
|
||||
graphene_rect_t node_bounds;
|
||||
|
||||
gsk_render_node_get_bounds (node, &node_bounds);
|
||||
|
||||
node2 = dmabufize_node (node);
|
||||
|
||||
save_node (node2, node_file, "-dmabuf.node");
|
||||
|
||||
rendered_texture = gsk_renderer_render_texture (renderer, node2, NULL);
|
||||
save_image (rendered_texture, node_file, "-dmabuf.out.png");
|
||||
|
||||
reference_texture = gsk_renderer_render_texture (renderer, node, &node_bounds);
|
||||
save_image (reference_texture, node_file, "-dmabuf.ref.png");
|
||||
|
||||
diff_texture = reftest_compare_textures (rendered_texture, reference_texture);
|
||||
|
||||
if (diff_texture)
|
||||
{
|
||||
save_image (diff_texture, node_file, "-dmabuf.diff.png");
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
g_clear_object (&diff_texture);
|
||||
g_clear_object (&rendered_texture);
|
||||
g_clear_object (&reference_texture);
|
||||
gsk_render_node_unref (node2);
|
||||
}
|
||||
|
||||
gsk_render_node_unref (node);
|
||||
gsk_renderer_unrealize (renderer);
|
||||
g_object_unref (renderer);
|
||||
|
439
testsuite/gsk/dmabufize.c
Normal file
439
testsuite/gsk/dmabufize.c
Normal file
@@ -0,0 +1,439 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "udmabuf.h"
|
||||
#include "dmabufize.h"
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
static GdkTexture *
|
||||
dmabufize_texture (GdkTexture *texture)
|
||||
{
|
||||
guint32 fourcc = 0;
|
||||
guint32 bpp;
|
||||
gboolean premultiplied;
|
||||
gsize width;
|
||||
gsize height;
|
||||
gsize size;
|
||||
UDmabuf *udmabuf;
|
||||
GdkTextureDownloader *downloader;
|
||||
GdkDmabufTextureBuilder *builder;
|
||||
GdkTexture *texture2;
|
||||
|
||||
if (strcmp (G_OBJECT_TYPE_NAME (texture), "GdkMemoryTexture") != 0)
|
||||
return g_object_ref (texture);
|
||||
|
||||
switch ((int) gdk_texture_get_format (texture))
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
fourcc = DRM_FORMAT_ARGB8888;
|
||||
premultiplied = TRUE;
|
||||
bpp = 4;
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
fourcc = DRM_FORMAT_BGRA8888;
|
||||
premultiplied = TRUE;
|
||||
bpp = 4;
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
fourcc = DRM_FORMAT_ABGR8888;
|
||||
premultiplied = TRUE;
|
||||
bpp = 4;
|
||||
break;
|
||||
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
fourcc = DRM_FORMAT_RGBA8888;
|
||||
premultiplied = TRUE;
|
||||
bpp = 4;
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
fourcc = DRM_FORMAT_ARGB8888;
|
||||
premultiplied = FALSE;
|
||||
bpp = 4;
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
fourcc = DRM_FORMAT_BGRA8888;
|
||||
premultiplied = FALSE;
|
||||
bpp = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fourcc == 0)
|
||||
return g_object_ref (texture);
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
size = height * width * bpp;
|
||||
|
||||
udmabuf = udmabuf_allocate (size, NULL);
|
||||
|
||||
downloader = gdk_texture_downloader_new (texture);
|
||||
|
||||
gdk_texture_downloader_set_format (downloader, gdk_texture_get_format (texture));
|
||||
gdk_texture_downloader_set_color_state (downloader, gdk_texture_get_color_state (texture));
|
||||
|
||||
gdk_texture_downloader_download_into (downloader, (guchar *)udmabuf->data, width * bpp);
|
||||
|
||||
gdk_texture_downloader_free (downloader);
|
||||
|
||||
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, fourcc);
|
||||
gdk_dmabuf_texture_builder_set_modifier (builder, 0);
|
||||
gdk_dmabuf_texture_builder_set_premultiplied (builder, premultiplied);
|
||||
gdk_dmabuf_texture_builder_set_n_planes (builder, 1);
|
||||
gdk_dmabuf_texture_builder_set_fd (builder, 0, udmabuf->dmabuf_fd);
|
||||
gdk_dmabuf_texture_builder_set_stride (builder, 0, width * bpp);
|
||||
gdk_dmabuf_texture_builder_set_offset (builder, 0, 0);
|
||||
gdk_dmabuf_texture_builder_set_color_state (builder, gdk_texture_get_color_state (texture));
|
||||
texture2 = gdk_dmabuf_texture_builder_build (builder, udmabuf_free, udmabuf, NULL);
|
||||
|
||||
g_object_unref (builder);
|
||||
|
||||
return texture2;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_container_node (GskRenderNode *node)
|
||||
{
|
||||
guint n_nodes;
|
||||
GskRenderNode **nodes;
|
||||
|
||||
n_nodes = gsk_container_node_get_n_children (node);
|
||||
nodes = g_newa (GskRenderNode *, n_nodes);
|
||||
|
||||
for (int i = 0; i < n_nodes; i++)
|
||||
nodes[i] = dmabufize_node (gsk_container_node_get_child (node, i));
|
||||
|
||||
node = gsk_container_node_new (nodes, n_nodes);
|
||||
|
||||
for (int i = 0; i < n_nodes; i++)
|
||||
gsk_render_node_unref (nodes[i]);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_texture_node (GskRenderNode *node)
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
graphene_rect_t bounds;
|
||||
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
|
||||
texture = dmabufize_texture (texture);
|
||||
|
||||
node = gsk_texture_node_new (texture, &bounds);
|
||||
|
||||
g_object_unref (texture);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_texture_scale_node (GskRenderNode *node)
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_scale_node_get_texture (node);
|
||||
graphene_rect_t bounds;
|
||||
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
|
||||
texture = dmabufize_texture (texture);
|
||||
|
||||
node = gsk_texture_scale_node_new (texture, &bounds, gsk_texture_scale_node_get_filter (node));
|
||||
|
||||
g_object_unref (texture);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_transform_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_transform_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_transform_node_new (child, gsk_transform_node_get_transform (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_opacity_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_opacity_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_opacity_node_new (child, gsk_opacity_node_get_opacity (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_color_matrix_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_color_matrix_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_color_matrix_node_new (child, gsk_color_matrix_node_get_color_matrix (node),
|
||||
gsk_color_matrix_node_get_color_offset (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_repeat_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_repeat_node_get_child (node);
|
||||
graphene_rect_t bounds;
|
||||
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_repeat_node_new (&bounds,
|
||||
child,
|
||||
gsk_repeat_node_get_child_bounds (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_clip_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_clip_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_clip_node_new (child, gsk_clip_node_get_clip (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_rounded_clip_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_rounded_clip_node_new (child, gsk_rounded_clip_node_get_clip (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_shadow_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_shadow_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_shadow_node_new (child,
|
||||
gsk_shadow_node_get_shadow (node, 0),
|
||||
gsk_shadow_node_get_n_shadows (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_blend_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *top = gsk_blend_node_get_top_child (node);
|
||||
GskRenderNode *bottom = gsk_blend_node_get_bottom_child (node);
|
||||
|
||||
top = dmabufize_node (top);
|
||||
bottom = dmabufize_node (bottom);
|
||||
node = gsk_blend_node_new (bottom, top, gsk_blend_node_get_blend_mode (node));
|
||||
gsk_render_node_unref (top);
|
||||
gsk_render_node_unref (bottom);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_cross_fade_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *start = gsk_cross_fade_node_get_start_child (node);
|
||||
GskRenderNode *end = gsk_cross_fade_node_get_end_child (node);
|
||||
|
||||
start = dmabufize_node (start);
|
||||
end = dmabufize_node (end);
|
||||
node = gsk_cross_fade_node_new (start, end, gsk_cross_fade_node_get_progress (node));
|
||||
gsk_render_node_unref (start);
|
||||
gsk_render_node_unref (end);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_blur_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_blur_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_blur_node_new (child, gsk_blur_node_get_radius (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_debug_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_debug_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_debug_node_new (child, (char *)gsk_debug_node_get_message (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_mask_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *source = gsk_mask_node_get_source (node);
|
||||
GskRenderNode *mask = gsk_mask_node_get_mask (node);
|
||||
|
||||
source = dmabufize_node (source);
|
||||
mask = dmabufize_node (mask);
|
||||
node = gsk_mask_node_new (source, mask, gsk_mask_node_get_mask_mode (node));
|
||||
gsk_render_node_unref (source);
|
||||
gsk_render_node_unref (mask);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_fill_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_fill_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_fill_node_new (child, gsk_fill_node_get_path (node), gsk_fill_node_get_fill_rule (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_stroke_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_stroke_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_stroke_node_new (child, gsk_stroke_node_get_path (node), gsk_stroke_node_get_stroke (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
dmabufize_subsurface_node (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *child = gsk_subsurface_node_get_child (node);
|
||||
|
||||
child = dmabufize_node (child);
|
||||
node = gsk_subsurface_node_new (child, gsk_subsurface_node_get_subsurface (node));
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
GskRenderNode *
|
||||
dmabufize_node (GskRenderNode *node)
|
||||
{
|
||||
switch (gsk_render_node_get_node_type (node))
|
||||
{
|
||||
case GSK_CONTAINER_NODE:
|
||||
return dmabufize_container_node (node);
|
||||
|
||||
case GSK_CAIRO_NODE:
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_CONIC_GRADIENT_NODE:
|
||||
case GSK_BORDER_NODE:
|
||||
case GSK_INSET_SHADOW_NODE:
|
||||
case GSK_OUTSET_SHADOW_NODE:
|
||||
case GSK_TEXT_NODE:
|
||||
case GSK_GL_SHADER_NODE:
|
||||
return gsk_render_node_ref (node);
|
||||
|
||||
case GSK_TEXTURE_NODE:
|
||||
return dmabufize_texture_node (node);
|
||||
|
||||
case GSK_TEXTURE_SCALE_NODE:
|
||||
return dmabufize_texture_scale_node (node);
|
||||
|
||||
case GSK_TRANSFORM_NODE:
|
||||
return dmabufize_transform_node (node);
|
||||
|
||||
case GSK_OPACITY_NODE:
|
||||
return dmabufize_opacity_node (node);
|
||||
|
||||
case GSK_COLOR_MATRIX_NODE:
|
||||
return dmabufize_color_matrix_node (node);
|
||||
|
||||
case GSK_REPEAT_NODE:
|
||||
return dmabufize_repeat_node (node);
|
||||
|
||||
case GSK_CLIP_NODE:
|
||||
return dmabufize_clip_node (node);
|
||||
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
return dmabufize_rounded_clip_node (node);
|
||||
|
||||
case GSK_SHADOW_NODE:
|
||||
return dmabufize_shadow_node (node);
|
||||
|
||||
case GSK_BLEND_NODE:
|
||||
return dmabufize_blend_node (node);
|
||||
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
return dmabufize_cross_fade_node (node);
|
||||
|
||||
case GSK_BLUR_NODE:
|
||||
return dmabufize_blur_node (node);
|
||||
|
||||
case GSK_DEBUG_NODE:
|
||||
return dmabufize_debug_node (node);
|
||||
|
||||
case GSK_MASK_NODE:
|
||||
return dmabufize_mask_node (node);
|
||||
|
||||
case GSK_FILL_NODE:
|
||||
return dmabufize_fill_node (node);
|
||||
|
||||
case GSK_STROKE_NODE:
|
||||
return dmabufize_stroke_node (node);
|
||||
|
||||
case GSK_SUBSURFACE_NODE:
|
||||
return dmabufize_subsurface_node (node);
|
||||
|
||||
case GSK_NOT_A_RENDER_NODE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
GskRenderNode *
|
||||
dmabufize_node (GskRenderNode *node)
|
||||
{
|
||||
return gsk_render_node_ref (node);
|
||||
}
|
||||
|
||||
#endif
|
3
testsuite/gsk/dmabufize.h
Normal file
3
testsuite/gsk/dmabufize.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
GskRenderNode * dmabufize_node (GskRenderNode *node);
|
@@ -1,5 +1,5 @@
|
||||
compare_render = executable('compare-render',
|
||||
['compare-render.c', '../reftests/reftest-compare.c', 'replay-node.c'],
|
||||
['compare-render.c', '../reftests/reftest-compare.c', 'replay-node.c', 'udmabuf.c', 'dmabufize.c' ],
|
||||
dependencies: libgtk_dep,
|
||||
c_args: common_cflags,
|
||||
)
|
||||
|
149
testsuite/gsk/udmabuf.c
Normal file
149
testsuite/gsk/udmabuf.c
Normal file
@@ -0,0 +1,149 @@
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
|
||||
#include "udmabuf.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/udmabuf.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <errno.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
static int udmabuf_fd;
|
||||
|
||||
gboolean
|
||||
udmabuf_initialize (GError **error)
|
||||
{
|
||||
if (udmabuf_fd == 0)
|
||||
{
|
||||
udmabuf_fd = open ("/dev/udmabuf", O_RDWR);
|
||||
if (udmabuf_fd == -1)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Failed to open /dev/udmabuf: %s",
|
||||
g_strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
return udmabuf_fd != -1;
|
||||
}
|
||||
|
||||
void
|
||||
udmabuf_free (gpointer data)
|
||||
{
|
||||
UDmabuf *udmabuf = data;
|
||||
|
||||
munmap (udmabuf->data, udmabuf->size);
|
||||
close (udmabuf->mem_fd);
|
||||
close (udmabuf->dmabuf_fd);
|
||||
|
||||
g_free (udmabuf);
|
||||
}
|
||||
|
||||
#define align(x,y) (((x) + (y) - 1) & ~((y) - 1))
|
||||
|
||||
UDmabuf *
|
||||
udmabuf_allocate (size_t size,
|
||||
GError **error)
|
||||
{
|
||||
int mem_fd = -1;
|
||||
int dmabuf_fd = -1;
|
||||
uint64_t alignment;
|
||||
int res;
|
||||
gpointer data;
|
||||
UDmabuf *udmabuf;
|
||||
|
||||
if (udmabuf_fd == -1)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"udmabuf not available");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
alignment = sysconf (_SC_PAGE_SIZE);
|
||||
|
||||
size = align (size, alignment);
|
||||
|
||||
mem_fd = memfd_create ("gtk", MFD_ALLOW_SEALING);
|
||||
if (mem_fd == -1)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Failed to open /dev/udmabuf: %s",
|
||||
g_strerror (errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = ftruncate (mem_fd, size);
|
||||
if (res == -1)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"ftruncate failed: %s",
|
||||
g_strerror (errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fcntl (mem_fd, F_ADD_SEALS, F_SEAL_SHRINK) < 0)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"ftruncate failed: %s",
|
||||
g_strerror (errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dmabuf_fd = ioctl (udmabuf_fd,
|
||||
UDMABUF_CREATE,
|
||||
&(struct udmabuf_create) {
|
||||
.memfd = mem_fd,
|
||||
.flags = UDMABUF_FLAGS_CLOEXEC,
|
||||
.offset = 0,
|
||||
.size = size
|
||||
});
|
||||
|
||||
if (dmabuf_fd < 0)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"UDMABUF_CREATE ioctl failed: %s",
|
||||
g_strerror (errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
data = mmap (NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, mem_fd, 0);
|
||||
|
||||
if (!data)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"mmap failed: %s",
|
||||
g_strerror (errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
udmabuf = g_new0 (UDmabuf, 1);
|
||||
|
||||
udmabuf->mem_fd = mem_fd;
|
||||
udmabuf->dmabuf_fd = dmabuf_fd;
|
||||
udmabuf->size = size;
|
||||
udmabuf->data = data;
|
||||
|
||||
return udmabuf;
|
||||
|
||||
fail:
|
||||
if (mem_fd != -1)
|
||||
close (mem_fd);
|
||||
if (dmabuf_fd != -1)
|
||||
close (dmabuf_fd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
18
testsuite/gsk/udmabuf.h
Normal file
18
testsuite/gsk/udmabuf.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int mem_fd;
|
||||
int dmabuf_fd;
|
||||
size_t size;
|
||||
gpointer data;
|
||||
} UDmabuf;
|
||||
|
||||
void udmabuf_free (gpointer data);
|
||||
|
||||
gboolean udmabuf_initialize (GError **error);
|
||||
|
||||
UDmabuf *udmabuf_allocate (size_t size,
|
||||
GError **error);
|
Reference in New Issue
Block a user