mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-09-19 13:30:02 +00:00
gsk: Add a cicp convert shader
This shader receives cicp parameters via uniforms, and converts the texture data from or to the output colorstate. It computes the matrix in the vertex shader, and then picks the eotf/oetf according to the cicp parameters in the fragment shader.
This commit is contained in:
parent
64f4967867
commit
226652edb0
119
gsk/gpu/gskgpuconvertcicpop.c
Normal file
119
gsk/gpu/gskgpuconvertcicpop.c
Normal file
@ -0,0 +1,119 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskgpuconvertcicpopprivate.h"
|
||||
|
||||
#include "gskgpuframeprivate.h"
|
||||
#include "gskgpuprintprivate.h"
|
||||
#include "gskrectprivate.h"
|
||||
#include "gdk/gdkcolorstateprivate.h"
|
||||
|
||||
#include "gpu/shaders/gskgpuconvertcicpinstance.h"
|
||||
|
||||
typedef struct _GskGpuConvertCicpOp GskGpuConvertCicpOp;
|
||||
|
||||
struct _GskGpuConvertCicpOp
|
||||
{
|
||||
GskGpuShaderOp op;
|
||||
};
|
||||
|
||||
#define VARIATION_OPACITY (1u << 0)
|
||||
#define VARIATION_STRAIGHT_ALPHA (1u << 1)
|
||||
#define VARIATION_REVERSE (1u << 2)
|
||||
|
||||
static void
|
||||
gsk_gpu_convert_cicp_op_print_instance (GskGpuShaderOp *shader,
|
||||
gpointer instance_,
|
||||
GString *string)
|
||||
{
|
||||
GskGpuConvertcicpInstance *instance = (GskGpuConvertcicpInstance *) instance_;
|
||||
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image (string, shader->images[0]);
|
||||
if (shader->variation & VARIATION_STRAIGHT_ALPHA)
|
||||
gsk_gpu_print_string (string, "straight");
|
||||
g_string_append_printf (string, "cicp %u/%u/%u/%u",
|
||||
instance->color_primaries,
|
||||
instance->transfer_function,
|
||||
0, 1);
|
||||
}
|
||||
|
||||
static const GskGpuShaderOpClass GSK_GPU_CONVERT_OP_CLASS = {
|
||||
{
|
||||
GSK_GPU_OP_SIZE (GskGpuConvertCicpOp),
|
||||
GSK_GPU_STAGE_SHADER,
|
||||
gsk_gpu_shader_op_finish,
|
||||
gsk_gpu_shader_op_print,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
gsk_gpu_shader_op_vk_command,
|
||||
#endif
|
||||
gsk_gpu_shader_op_gl_command
|
||||
},
|
||||
"gskgpuconvertcicp",
|
||||
gsk_gpu_convertcicp_n_textures,
|
||||
sizeof (GskGpuConvertcicpInstance),
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
&gsk_gpu_convertcicp_info,
|
||||
#endif
|
||||
gsk_gpu_convert_cicp_op_print_instance,
|
||||
gsk_gpu_convertcicp_setup_attrib_locations,
|
||||
gsk_gpu_convertcicp_setup_vao
|
||||
};
|
||||
|
||||
void
|
||||
gsk_gpu_convert_from_cicp_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
const GdkCicp *cicp,
|
||||
GskGpuColorStates color_states,
|
||||
float opacity,
|
||||
gboolean straight_alpha,
|
||||
const graphene_point_t *offset,
|
||||
const GskGpuShaderImage *image)
|
||||
{
|
||||
GskGpuConvertcicpInstance *instance;
|
||||
|
||||
gsk_gpu_shader_op_alloc (frame,
|
||||
&GSK_GPU_CONVERT_OP_CLASS,
|
||||
color_states,
|
||||
(opacity < 1.0 ? VARIATION_OPACITY : 0) |
|
||||
(straight_alpha ? VARIATION_STRAIGHT_ALPHA : 0),
|
||||
clip,
|
||||
(GskGpuImage *[1]) { image->image },
|
||||
(GskGpuSampler[1]) { image->sampler },
|
||||
&instance);
|
||||
|
||||
gsk_gpu_rect_to_float (image->coverage, offset, instance->rect);
|
||||
gsk_gpu_rect_to_float (image->bounds, offset, instance->tex_rect);
|
||||
instance->opacity = opacity;
|
||||
instance->color_primaries = cicp->color_primaries;
|
||||
instance->transfer_function = cicp->transfer_function;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_convert_to_cicp_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
const GdkCicp *cicp,
|
||||
GskGpuColorStates color_states,
|
||||
float opacity,
|
||||
gboolean straight_alpha,
|
||||
const graphene_point_t *offset,
|
||||
const GskGpuShaderImage *image)
|
||||
{
|
||||
GskGpuConvertcicpInstance *instance;
|
||||
|
||||
gsk_gpu_shader_op_alloc (frame,
|
||||
&GSK_GPU_CONVERT_OP_CLASS,
|
||||
color_states,
|
||||
(opacity < 1.0 ? VARIATION_OPACITY : 0) |
|
||||
(straight_alpha ? VARIATION_STRAIGHT_ALPHA : 0) |
|
||||
VARIATION_REVERSE,
|
||||
clip,
|
||||
(GskGpuImage *[1]) { image->image },
|
||||
(GskGpuSampler[1]) { image->sampler },
|
||||
&instance);
|
||||
|
||||
gsk_gpu_rect_to_float (image->coverage, offset, instance->rect);
|
||||
gsk_gpu_rect_to_float (image->bounds, offset, instance->tex_rect);
|
||||
instance->opacity = opacity;
|
||||
instance->color_primaries = cicp->color_primaries;
|
||||
instance->transfer_function = cicp->transfer_function;
|
||||
}
|
29
gsk/gpu/gskgpuconvertcicpopprivate.h
Normal file
29
gsk/gpu/gskgpuconvertcicpopprivate.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskgpushaderopprivate.h"
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gsk_gpu_convert_from_cicp_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
const GdkCicp *cicp,
|
||||
GskGpuColorStates color_states,
|
||||
float opacity,
|
||||
gboolean straight_alpha,
|
||||
const graphene_point_t *offset,
|
||||
const GskGpuShaderImage *image);
|
||||
|
||||
|
||||
void gsk_gpu_convert_to_cicp_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
const GdkCicp *cicp,
|
||||
GskGpuColorStates color_states,
|
||||
float opacity,
|
||||
gboolean straight_alpha,
|
||||
const graphene_point_t *offset,
|
||||
const GskGpuShaderImage *image);
|
||||
|
||||
|
||||
G_END_DECLS
|
@ -24,6 +24,12 @@ color_unpremultiply (vec4 color)
|
||||
return color.a > 0.0 ? color / vec4 (color.aaa, 1.0) : color;
|
||||
}
|
||||
|
||||
float
|
||||
luminance (vec3 color)
|
||||
{
|
||||
return dot (vec3 (0.2126, 0.7152, 0.0722), color);
|
||||
}
|
||||
|
||||
vec4
|
||||
alt_color_alpha (vec4 color,
|
||||
float alpha)
|
||||
@ -90,6 +96,20 @@ pq_oetf (float v)
|
||||
return pow (((c1 + (c2 * pow (x, n))) / (1.0 + (c3 * pow (x, n)))), m);
|
||||
}
|
||||
|
||||
/* Note that these matrices are transposed from the C version */
|
||||
|
||||
const mat3 srgb_from_rec2020 = mat3(
|
||||
1.659944, -0.124350, -0.018466,
|
||||
-0.588220, 1.132559, -0.102459,
|
||||
-0.071724, -0.008210, 1.120924
|
||||
);
|
||||
|
||||
const mat3 rec2020_from_srgb = mat3(
|
||||
0.627610, 0.069029, 0.016649,
|
||||
0.329815, 0.919817, 0.089510,
|
||||
0.042574, 0.011154, 0.893842
|
||||
);
|
||||
|
||||
vec3
|
||||
apply_eotf (vec3 color,
|
||||
uint cs)
|
||||
@ -140,19 +160,6 @@ apply_oetf (vec3 color,
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that these matrices are transposed from the C version */
|
||||
const mat3 srgb_from_rec2020 = mat3(
|
||||
1.659944, -0.124350, -0.018466,
|
||||
-0.588220, 1.132559, -0.102459,
|
||||
-0.071724, -0.008210, 1.120924
|
||||
);
|
||||
|
||||
const mat3 rec2020_from_srgb = mat3(
|
||||
0.627610, 0.069029, 0.016649,
|
||||
0.329815, 0.919817, 0.089510,
|
||||
0.042574, 0.011154, 0.893842
|
||||
);
|
||||
|
||||
vec3
|
||||
convert_linear (vec3 color,
|
||||
uint from,
|
||||
@ -226,10 +233,4 @@ output_color_from_alt (vec4 color)
|
||||
OUTPUT_COLOR_SPACE, OUTPUT_PREMULTIPLIED);
|
||||
}
|
||||
|
||||
float
|
||||
luminance (vec3 color)
|
||||
{
|
||||
return dot (vec3 (0.2126, 0.7152, 0.0722), color);
|
||||
}
|
||||
|
||||
#endif /* _COLOR_ */
|
||||
|
346
gsk/gpu/shaders/gskgpuconvertcicp.glsl
Normal file
346
gsk/gpu/shaders/gskgpuconvertcicp.glsl
Normal file
@ -0,0 +1,346 @@
|
||||
#define GSK_N_TEXTURES 1
|
||||
|
||||
#include "common.glsl"
|
||||
|
||||
#define VARIATION_OPACITY (1u << 0)
|
||||
#define VARIATION_STRAIGHT_ALPHA (1u << 1)
|
||||
#define VARIATION_REVERSE (1u << 2)
|
||||
|
||||
#define HAS_VARIATION(var) ((GSK_VARIATION & var) == var)
|
||||
|
||||
PASS(0) vec2 _pos;
|
||||
PASS_FLAT(1) Rect _rect;
|
||||
PASS(2) vec2 _tex_coord;
|
||||
PASS_FLAT(3) float _opacity;
|
||||
PASS_FLAT(4) uint _transfer_function;
|
||||
PASS_FLAT(5) mat3 _mat;
|
||||
|
||||
#ifdef GSK_VERTEX_SHADER
|
||||
|
||||
IN(0) vec4 in_rect;
|
||||
IN(1) vec4 in_tex_rect;
|
||||
IN(2) float in_opacity;
|
||||
IN(3) uint in_color_primaries;
|
||||
IN(4) uint in_transfer_function;
|
||||
|
||||
|
||||
const mat3 identity = mat3(
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0
|
||||
);
|
||||
|
||||
const mat3 srgb_to_xyz = mat3(
|
||||
0.4125288, 0.2127102, 0.0193373,
|
||||
0.3581642, 0.7163284, 0.1193881,
|
||||
0.1774037, 0.0709615, 0.9343260
|
||||
);
|
||||
|
||||
const mat3 xyz_to_srgb = mat3(
|
||||
3.2409699, -0.9692436, 0.0556301,
|
||||
-1.5373832, 1.8759675, -0.2039770,
|
||||
-0.4986108, 0.0415551, 1.0569715
|
||||
);
|
||||
|
||||
const mat3 rec2020_to_xyz = mat3(
|
||||
0.6369615, 0.2627016, 0.0000000,
|
||||
0.1448079, 0.6788934, 0.0281098,
|
||||
0.1663273, 0.0584050, 1.0449416
|
||||
);
|
||||
|
||||
const mat3 xyz_to_rec2020 = mat3(
|
||||
1.7166512, -0.6666844, 0.0176399,
|
||||
-0.3556708, 1.6164812, -0.0427706,
|
||||
-0.2533663, 0.0157685, 0.9421031
|
||||
);
|
||||
|
||||
const mat3 pal_to_xyz = mat3(
|
||||
0.4305538, 0.2220043, 0.0201822,
|
||||
0.3415498, 0.7066548, 0.1295534,
|
||||
0.1783523, 0.0713409, 0.9393222
|
||||
);
|
||||
|
||||
const mat3 xyz_to_pal = mat3(
|
||||
3.0633611, -0.9692436, 0.0678610,
|
||||
-1.3933902, 1.8759675, -0.2287993,
|
||||
-0.4758237, 0.0415551, 1.0690896
|
||||
);
|
||||
|
||||
const mat3 ntsc_to_xyz = mat3(
|
||||
0.3935209, 0.2123764, 0.0187391,
|
||||
0.3652581, 0.7010599, 0.1119339,
|
||||
0.1916769, 0.0865638, 0.9583847
|
||||
);
|
||||
|
||||
const mat3 xyz_to_ntsc = mat3(
|
||||
3.5060033, -1.0690476, 0.0563066,
|
||||
-1.7397907, 1.9777789, -0.1969757,
|
||||
-0.5440583, 0.0351714, 1.0499523
|
||||
);
|
||||
|
||||
const mat3 p3_to_xyz = mat3(
|
||||
0.4865709, 0.2289746, 0.0000000,
|
||||
0.2656677, 0.6917385, 0.0451134,
|
||||
0.1982173, 0.0792869, 1.0439444
|
||||
);
|
||||
|
||||
const mat3 xyz_to_p3 = mat3(
|
||||
2.4934969, -0.8294890, 0.0358458,
|
||||
-0.9313836, 1.7626641, -0.0761724,
|
||||
-0.4027108, 0.0236247, 0.9568845
|
||||
);
|
||||
|
||||
mat3
|
||||
cicp_to_xyz (uint cp)
|
||||
{
|
||||
switch (cp)
|
||||
{
|
||||
case 1: return srgb_to_xyz;
|
||||
case 5: return pal_to_xyz;
|
||||
case 6: return ntsc_to_xyz;
|
||||
case 9: return rec2020_to_xyz;
|
||||
case 10: return identity;
|
||||
case 12: return p3_to_xyz;
|
||||
default: return identity;
|
||||
}
|
||||
}
|
||||
|
||||
mat3
|
||||
cicp_from_xyz (uint cp)
|
||||
{
|
||||
switch (cp)
|
||||
{
|
||||
case 1: return xyz_to_srgb;
|
||||
case 5: return xyz_to_pal;
|
||||
case 6: return xyz_to_ntsc;
|
||||
case 9: return xyz_to_rec2020;
|
||||
case 10: return identity;
|
||||
case 12: return xyz_to_p3;
|
||||
default: return identity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
run (out vec2 pos)
|
||||
{
|
||||
Rect r = rect_from_gsk (in_rect);
|
||||
|
||||
pos = rect_get_position (r);
|
||||
|
||||
_pos = pos;
|
||||
_rect = r;
|
||||
_tex_coord = rect_get_coord (rect_from_gsk (in_tex_rect), pos);
|
||||
_opacity = in_opacity;
|
||||
_transfer_function = in_transfer_function;
|
||||
|
||||
if (HAS_VARIATION (VARIATION_REVERSE))
|
||||
{
|
||||
if (OUTPUT_COLOR_SPACE == GDK_COLOR_STATE_ID_SRGB ||
|
||||
OUTPUT_COLOR_SPACE == GDK_COLOR_STATE_ID_SRGB_LINEAR)
|
||||
_mat = cicp_from_xyz (in_color_primaries) * srgb_to_xyz;
|
||||
else
|
||||
_mat = cicp_from_xyz (in_color_primaries) * rec2020_to_xyz;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OUTPUT_COLOR_SPACE == GDK_COLOR_STATE_ID_SRGB ||
|
||||
OUTPUT_COLOR_SPACE == GDK_COLOR_STATE_ID_SRGB_LINEAR)
|
||||
_mat = xyz_to_srgb * cicp_to_xyz (in_color_primaries);
|
||||
else
|
||||
_mat = xyz_to_rec2020 * cicp_to_xyz (in_color_primaries);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GSK_FRAGMENT_SHADER
|
||||
|
||||
|
||||
float
|
||||
bt709_eotf (float v)
|
||||
{
|
||||
if (v < 0.081)
|
||||
return v / 4.5;
|
||||
else
|
||||
return pow ((v + 0.099) / 1.099, 1.0/0.45);
|
||||
}
|
||||
|
||||
float
|
||||
bt709_oetf (float v)
|
||||
{
|
||||
if (v < 0.081)
|
||||
return v * 4.5;
|
||||
else
|
||||
return 1.099 * pow (v, 0.45) - 0.099;
|
||||
}
|
||||
|
||||
float
|
||||
hlg_eotf (float v)
|
||||
{
|
||||
const float a = 0.17883277;
|
||||
const float b = 0.28466892;
|
||||
const float c = 0.55991073;
|
||||
|
||||
if (v <= 0.5)
|
||||
return (v * v) / 3.0;
|
||||
else
|
||||
return exp (((v - c) / a) + b) / 12.0;
|
||||
}
|
||||
|
||||
float
|
||||
hlg_oetf (float v)
|
||||
{
|
||||
const float a = 0.17883277;
|
||||
const float b = 0.28466892;
|
||||
const float c = 0.55991073;
|
||||
|
||||
if (v <= 1.0 / 12.0)
|
||||
return sqrt (3.0 * v);
|
||||
else
|
||||
return a * log (12.0 * v - b) + c;
|
||||
}
|
||||
|
||||
vec3
|
||||
apply_cicp_eotf (vec3 color,
|
||||
uint transfer_function)
|
||||
{
|
||||
switch (transfer_function)
|
||||
{
|
||||
case 1:
|
||||
case 6:
|
||||
case 14:
|
||||
case 15:
|
||||
return vec3 (bt709_eotf (color.r),
|
||||
bt709_eotf (color.g),
|
||||
bt709_eotf (color.b));
|
||||
|
||||
case 8:
|
||||
return color;
|
||||
|
||||
case 13:
|
||||
return vec3 (srgb_eotf (color.r),
|
||||
srgb_eotf (color.g),
|
||||
srgb_eotf (color.b));
|
||||
|
||||
case 16:
|
||||
return vec3 (pq_eotf (color.r),
|
||||
pq_eotf (color.g),
|
||||
pq_eotf (color.b));
|
||||
|
||||
case 18:
|
||||
return vec3 (hlg_eotf (color.r),
|
||||
hlg_eotf (color.g),
|
||||
hlg_eotf (color.b));
|
||||
|
||||
default:
|
||||
return vec3 (1.0, 0.2, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
vec3
|
||||
apply_cicp_oetf (vec3 color,
|
||||
uint transfer_function)
|
||||
{
|
||||
switch (transfer_function)
|
||||
{
|
||||
case 1:
|
||||
case 6:
|
||||
case 14:
|
||||
case 15:
|
||||
return vec3 (bt709_oetf (color.r),
|
||||
bt709_oetf (color.g),
|
||||
bt709_oetf (color.b));
|
||||
|
||||
case 8:
|
||||
return color;
|
||||
|
||||
case 13:
|
||||
return vec3 (srgb_oetf (color.r),
|
||||
srgb_oetf (color.g),
|
||||
srgb_oetf (color.b));
|
||||
|
||||
case 16:
|
||||
return vec3 (pq_oetf (color.r),
|
||||
pq_oetf (color.g),
|
||||
pq_oetf (color.b));
|
||||
|
||||
case 18:
|
||||
return vec3 (hlg_oetf (color.r),
|
||||
hlg_oetf (color.g),
|
||||
hlg_oetf (color.b));
|
||||
|
||||
default:
|
||||
return vec3 (1.0, 0.2, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
vec4
|
||||
convert_color_from_cicp (vec4 color,
|
||||
bool from_premul,
|
||||
uint to,
|
||||
bool to_premul)
|
||||
{
|
||||
if (from_premul)
|
||||
color = color_unpremultiply (color);
|
||||
|
||||
color.rgb = apply_cicp_eotf (color.rgb, _transfer_function);
|
||||
color.rgb = _mat * color.rgb;
|
||||
color.rgb = apply_oetf (color.rgb, to);
|
||||
|
||||
if (to_premul)
|
||||
color = color_premultiply (color);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
vec4
|
||||
convert_color_to_cicp (vec4 color,
|
||||
bool to_premul,
|
||||
uint from,
|
||||
bool from_premul)
|
||||
{
|
||||
if (from_premul)
|
||||
color = color_unpremultiply (color);
|
||||
|
||||
color.rgb = apply_eotf (color.rgb, from);
|
||||
color.rgb = _mat * color.rgb;
|
||||
color.rgb = apply_cicp_oetf (color.rgb, _transfer_function);
|
||||
|
||||
if (to_premul)
|
||||
color = color_premultiply (color);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void
|
||||
run (out vec4 color,
|
||||
out vec2 position)
|
||||
{
|
||||
vec4 pixel;
|
||||
|
||||
if (HAS_VARIATION (VARIATION_STRAIGHT_ALPHA))
|
||||
pixel = gsk_texture_straight_alpha (GSK_TEXTURE0, _tex_coord);
|
||||
else
|
||||
pixel = texture (GSK_TEXTURE0, _tex_coord);
|
||||
|
||||
if (HAS_VARIATION (VARIATION_REVERSE))
|
||||
pixel = convert_color_to_cicp (color,
|
||||
ALT_PREMULTIPLIED,
|
||||
OUTPUT_COLOR_SPACE, OUTPUT_PREMULTIPLIED);
|
||||
else
|
||||
pixel = convert_color_from_cicp (color,
|
||||
ALT_PREMULTIPLIED,
|
||||
OUTPUT_COLOR_SPACE, OUTPUT_PREMULTIPLIED);
|
||||
|
||||
float alpha = rect_coverage (_rect, _pos);
|
||||
if (HAS_VARIATION (VARIATION_OPACITY))
|
||||
alpha *= _opacity;
|
||||
|
||||
color = output_color_alpha (pixel, alpha);
|
||||
|
||||
position = _pos;
|
||||
}
|
||||
|
||||
#endif
|
@ -20,6 +20,7 @@ gsk_private_gpu_shaders = files([
|
||||
'gskgpucolormatrix.glsl',
|
||||
'gskgpuconicgradient.glsl',
|
||||
'gskgpuconvert.glsl',
|
||||
'gskgpuconvertcicp.glsl',
|
||||
'gskgpucrossfade.glsl',
|
||||
'gskgpulineargradient.glsl',
|
||||
'gskgpumask.glsl',
|
||||
|
@ -88,6 +88,7 @@ gsk_private_sources = files([
|
||||
'gpu/gskgpucolorop.c',
|
||||
'gpu/gskgpuconicgradientop.c',
|
||||
'gpu/gskgpuconvertop.c',
|
||||
'gpu/gskgpuconvertcicpop.c',
|
||||
'gpu/gskgpucrossfadeop.c',
|
||||
'gpu/gskgpudownloadop.c',
|
||||
'gpu/gskgpudevice.c',
|
||||
|
Loading…
Reference in New Issue
Block a user