mirror of
https://salsa.debian.org/xorg-team/lib/pixman
synced 2026-02-05 22:37:34 +00:00
test/utils.c: Add support for separable blend mode ops to do_composite()
The implementations are copied from the floating point pipeline, but use double precision instead of single precision.
This commit is contained in:
parent
b29d74ef0c
commit
a42af27fc0
182
test/utils.c
182
test/utils.c
@ -4,6 +4,7 @@
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <float.h>
|
||||
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
#include <sys/time.h>
|
||||
@ -1099,6 +1100,152 @@ format_name (pixman_format_code_t format)
|
||||
return "<unknown format>";
|
||||
};
|
||||
|
||||
#define IS_ZERO(f) (-DBL_MIN < (f) && (f) < DBL_MIN)
|
||||
|
||||
typedef double (* blend_func_t) (double as, double s, double ad, double d);
|
||||
|
||||
static force_inline double
|
||||
blend_multiply (double sa, double s, double da, double d)
|
||||
{
|
||||
return d * s;
|
||||
}
|
||||
|
||||
static force_inline double
|
||||
blend_screen (double sa, double s, double da, double d)
|
||||
{
|
||||
return d * sa + s * da - s * d;
|
||||
}
|
||||
|
||||
static force_inline double
|
||||
blend_overlay (double sa, double s, double da, double d)
|
||||
{
|
||||
if (2 * d < da)
|
||||
return 2 * s * d;
|
||||
else
|
||||
return sa * da - 2 * (da - d) * (sa - s);
|
||||
}
|
||||
|
||||
static force_inline double
|
||||
blend_darken (double sa, double s, double da, double d)
|
||||
{
|
||||
s = s * da;
|
||||
d = d * sa;
|
||||
|
||||
if (s > d)
|
||||
return d;
|
||||
else
|
||||
return s;
|
||||
}
|
||||
|
||||
static force_inline double
|
||||
blend_lighten (double sa, double s, double da, double d)
|
||||
{
|
||||
s = s * da;
|
||||
d = d * sa;
|
||||
|
||||
if (s > d)
|
||||
return s;
|
||||
else
|
||||
return d;
|
||||
}
|
||||
|
||||
static force_inline double
|
||||
blend_color_dodge (double sa, double s, double da, double d)
|
||||
{
|
||||
if (IS_ZERO (d))
|
||||
return 0.0f;
|
||||
else if (d * sa >= sa * da - s * da)
|
||||
return sa * da;
|
||||
else if (IS_ZERO (sa - s))
|
||||
return sa * da;
|
||||
else
|
||||
return sa * sa * d / (sa - s);
|
||||
}
|
||||
|
||||
static force_inline double
|
||||
blend_color_burn (double sa, double s, double da, double d)
|
||||
{
|
||||
if (d >= da)
|
||||
return sa * da;
|
||||
else if (sa * (da - d) >= s * da)
|
||||
return 0.0f;
|
||||
else if (IS_ZERO (s))
|
||||
return 0.0f;
|
||||
else
|
||||
return sa * (da - sa * (da - d) / s);
|
||||
}
|
||||
|
||||
static force_inline double
|
||||
blend_hard_light (double sa, double s, double da, double d)
|
||||
{
|
||||
if (2 * s < sa)
|
||||
return 2 * s * d;
|
||||
else
|
||||
return sa * da - 2 * (da - d) * (sa - s);
|
||||
}
|
||||
|
||||
static force_inline double
|
||||
blend_soft_light (double sa, double s, double da, double d)
|
||||
{
|
||||
if (2 * s <= sa)
|
||||
{
|
||||
if (IS_ZERO (da))
|
||||
return d * sa;
|
||||
else
|
||||
return d * sa - d * (da - d) * (sa - 2 * s) / da;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IS_ZERO (da))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (4 * d <= da)
|
||||
return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3);
|
||||
else
|
||||
return d * sa + (sqrt (d * da) - d) * (2 * s - sa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static force_inline double
|
||||
blend_difference (double sa, double s, double da, double d)
|
||||
{
|
||||
double dsa = d * sa;
|
||||
double sda = s * da;
|
||||
|
||||
if (sda < dsa)
|
||||
return dsa - sda;
|
||||
else
|
||||
return sda - dsa;
|
||||
}
|
||||
|
||||
static force_inline double
|
||||
blend_exclusion (double sa, double s, double da, double d)
|
||||
{
|
||||
return s * da + d * sa - 2 * d * s;
|
||||
}
|
||||
|
||||
static double
|
||||
clamp (double d)
|
||||
{
|
||||
if (d > 1.0)
|
||||
return 1.0;
|
||||
else if (d < 0.0)
|
||||
return 0.0;
|
||||
else
|
||||
return d;
|
||||
}
|
||||
|
||||
static double
|
||||
blend_channel (double as, double s, double ad, double d,
|
||||
blend_func_t blend)
|
||||
{
|
||||
return clamp ((1 - ad) * s + (1 - as) * d + blend (as, s, ad, d));
|
||||
}
|
||||
|
||||
static double
|
||||
calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
|
||||
{
|
||||
@ -1336,6 +1483,21 @@ do_composite (pixman_op_t op,
|
||||
{
|
||||
color_t srcval, srcalpha;
|
||||
|
||||
static const blend_func_t blend_funcs[] =
|
||||
{
|
||||
blend_multiply,
|
||||
blend_screen,
|
||||
blend_overlay,
|
||||
blend_darken,
|
||||
blend_lighten,
|
||||
blend_color_dodge,
|
||||
blend_color_burn,
|
||||
blend_hard_light,
|
||||
blend_soft_light,
|
||||
blend_difference,
|
||||
blend_exclusion,
|
||||
};
|
||||
|
||||
if (mask == NULL)
|
||||
{
|
||||
srcval = *src;
|
||||
@ -1370,10 +1532,22 @@ do_composite (pixman_op_t op,
|
||||
srcalpha.a = src->a * mask->a;
|
||||
}
|
||||
|
||||
result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
|
||||
result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
|
||||
result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
|
||||
result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
|
||||
if (op >= PIXMAN_OP_MULTIPLY)
|
||||
{
|
||||
blend_func_t func = blend_funcs[op - PIXMAN_OP_MULTIPLY];
|
||||
|
||||
result->a = srcalpha.a + dst->a - srcalpha.a * dst->a;
|
||||
result->r = blend_channel (srcalpha.r, srcval.r, dst->a, dst->r, func);
|
||||
result->g = blend_channel (srcalpha.g, srcval.g, dst->a, dst->g, func);
|
||||
result->b = blend_channel (srcalpha.b, srcval.b, dst->a, dst->b, func);
|
||||
}
|
||||
else
|
||||
{
|
||||
result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
|
||||
result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
|
||||
result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
|
||||
result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
|
||||
Loading…
Reference in New Issue
Block a user