fix lowp gradients

They were not keeping their colors in gamut.  This is most visible in
the completely garbage gradients in --config narrow.

This fixes most of the egregious problems with --config narrow.

Change-Id: I488f6fd083207ce7a880fb0afe0eb778c427a929
Reviewed-on: https://skia-review.googlesource.com/152585
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
Mike Klein 2018-09-07 12:05:29 -04:00 committed by Skia Commit-Bot
parent 1b935e65d1
commit 24de648346
3 changed files with 36 additions and 18 deletions

View File

@ -71,6 +71,13 @@ struct SkJumper_GradientCtx {
float* fs[4];
float* bs[4];
float* ts;
bool interpolatedInPremul;
};
struct SkJumper_EvenlySpaced2StopGradientCtx {
float f[4];
float b[4];
bool interpolatedInPremul;
};
struct SkJumper_2PtConicalCtx {

View File

@ -3098,8 +3098,17 @@ STAGE_PP(check_decal_mask, SkJumper_DecalTileCtx* ctx) {
a = a & mask;
}
SI void round_F_to_U16(F R, F G, F B, F A, bool interpolatedInPremul,
U16* r, U16* g, U16* b, U16* a) {
auto round = [](F x) { return cast<U16>(x * 255.0f + 0.5f); };
SI U16 round_F_to_U16(F x) { return cast<U16>(x * 255.0f + 0.5f); }
F limit = interpolatedInPremul ? A
: 1;
*r = round(min(max(0,R), limit));
*g = round(min(max(0,G), limit));
*b = round(min(max(0,B), limit));
*a = round(A); // we assume alpha is already in [0,1].
}
SI void gradient_lookup(const SkJumper_GradientCtx* c, U32 idx, F t,
U16* r, U16* g, U16* b, U16* a) {
@ -3138,10 +3147,12 @@ SI void gradient_lookup(const SkJumper_GradientCtx* c, U32 idx, F t,
bb = gather<F>(c->bs[2], idx);
ba = gather<F>(c->bs[3], idx);
}
*r = round_F_to_U16(mad(t, fr, br));
*g = round_F_to_U16(mad(t, fg, bg));
*b = round_F_to_U16(mad(t, fb, bb));
*a = round_F_to_U16(mad(t, fa, ba));
round_F_to_U16(mad(t, fr, br),
mad(t, fg, bg),
mad(t, fb, bb),
mad(t, fa, ba),
c->interpolatedInPremul,
r,g,b,a);
}
STAGE_GP(gradient, const SkJumper_GradientCtx* c) {
@ -3162,16 +3173,14 @@ STAGE_GP(evenly_spaced_gradient, const SkJumper_GradientCtx* c) {
gradient_lookup(c, idx, t, &r, &g, &b, &a);
}
STAGE_GP(evenly_spaced_2_stop_gradient, const void* ctx) {
// TODO: Rename Ctx SkJumper_EvenlySpaced2StopGradientCtx.
struct Ctx { float f[4], b[4]; };
auto c = (const Ctx*)ctx;
STAGE_GP(evenly_spaced_2_stop_gradient, const SkJumper_EvenlySpaced2StopGradientCtx* c) {
auto t = x;
r = round_F_to_U16(mad(t, c->f[0], c->b[0]));
g = round_F_to_U16(mad(t, c->f[1], c->b[1]));
b = round_F_to_U16(mad(t, c->f[2], c->b[2]));
a = round_F_to_U16(mad(t, c->f[3], c->b[3]));
round_F_to_U16(mad(t, c->f[0], c->b[0]),
mad(t, c->f[1], c->b[1]),
mad(t, c->f[2], c->b[2]),
mad(t, c->f[3], c->b[3]),
c->interpolatedInPremul,
&r,&g,&b,&a);
}
STAGE_GG(xy_to_unit_angle, Ctx::None) {

View File

@ -328,13 +328,15 @@ bool SkGradientShaderBase::onAppendStages(const StageRec& rec) const {
c_r = prepareColor(1);
// See F and B below.
auto* f_and_b = alloc->makeArrayDefault<SkPM4f>(2);
f_and_b[0] = SkPM4f::From4f(c_r.to4f() - c_l.to4f());
f_and_b[1] = c_l;
auto ctx = alloc->make<SkJumper_EvenlySpaced2StopGradientCtx>();
(c_r.to4f() - c_l.to4f()).store(ctx->f);
( c_l.to4f()).store(ctx->b);
ctx->interpolatedInPremul = premulGrad;
p->append(SkRasterPipeline::evenly_spaced_2_stop_gradient, f_and_b);
p->append(SkRasterPipeline::evenly_spaced_2_stop_gradient, ctx);
} else {
auto* ctx = alloc->make<SkJumper_GradientCtx>();
ctx->interpolatedInPremul = premulGrad;
// Note: In order to handle clamps in search, the search assumes a stop conceptully placed
// at -inf. Therefore, the max number of stops is fColorCount+1.