From 24de648346000e724f63e21cb2fcfad085d46c93 Mon Sep 17 00:00:00 2001 From: Mike Klein Date: Fri, 7 Sep 2018 12:05:29 -0400 Subject: [PATCH] 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 Reviewed-by: Brian Osman --- src/jumper/SkJumper.h | 7 ++++ src/opts/SkRasterPipeline_opts.h | 37 ++++++++++++++-------- src/shaders/gradients/SkGradientShader.cpp | 10 +++--- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/jumper/SkJumper.h b/src/jumper/SkJumper.h index a826c5a412..d2a9058ffc 100644 --- a/src/jumper/SkJumper.h +++ b/src/jumper/SkJumper.h @@ -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 { diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h index 98c2c356bb..0144becf83 100644 --- a/src/opts/SkRasterPipeline_opts.h +++ b/src/opts/SkRasterPipeline_opts.h @@ -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(x * 255.0f + 0.5f); }; -SI U16 round_F_to_U16(F x) { return cast(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(c->bs[2], idx); ba = gather(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) { diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp index 50c19d67a1..bfce551039 100644 --- a/src/shaders/gradients/SkGradientShader.cpp +++ b/src/shaders/gradients/SkGradientShader.cpp @@ -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(2); - f_and_b[0] = SkPM4f::From4f(c_r.to4f() - c_l.to4f()); - f_and_b[1] = c_l; + auto ctx = alloc->make(); + (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(); + 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.