diff options
author | Mike Klein <mtklein@chromium.org> | 2016-12-06 11:31:25 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2016-12-06 17:10:47 +0000 |
commit | 886cf53447a7f78a80476742d50424a5d45c3108 (patch) | |
tree | d425ae8e59747f2ff65994f5fc62a2c28d47f354 | |
parent | 0ce4f230eb2e95523557bf6c6a195f51bc88163f (diff) |
Refactor bilerp a little.
1) rename to bilerp_xy, for x,y in {n[egative], p[ositive};
2) pull out a save_xy stage to save off the original x,y;
3) also calculate the fractional x,y fx,fy once instead of 4 times.
1) is a pure refactor;
2) adds a stage but otherwise is nothing different;
3) changes images a little bit (fractional parts can vary a bit around powers of two).
This extends naturally to naive bicubic using 16 bicubic_xy stages.
CQ_INCLUDE_TRYBOTS=skia.primary:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD
Change-Id: I666de5c21e978abb4feb6e3225e5b5920ba6c5b9
Reviewed-on: https://skia-review.googlesource.com/5550
Commit-Queue: Mike Klein <mtklein@chromium.org>
Reviewed-by: Herb Derby <herb@google.com>
-rw-r--r-- | src/core/SkRasterPipeline.h | 4 | ||||
-rw-r--r-- | src/image/SkImageShader.cpp | 26 | ||||
-rw-r--r-- | src/image/SkImageShaderContext.h | 2 | ||||
-rw-r--r-- | src/opts/SkRasterPipeline_opts.h | 55 |
4 files changed, 36 insertions, 51 deletions
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h index 179bfb531d..3ecf80f79b 100644 --- a/src/core/SkRasterPipeline.h +++ b/src/core/SkRasterPipeline.h @@ -86,8 +86,8 @@ M(clamp_y) M(mirror_y) M(repeat_y) \ M(gather_a8) M(gather_g8) M(gather_i8) \ M(gather_565) M(gather_4444) M(gather_8888) M(gather_f16) \ - M(top_left) M(top_right) M(bottom_left) M(bottom_right) \ - M(accumulate) + M(bilinear_nn) M(bilinear_pn) M(bilinear_np) M(bilinear_pp) \ + M(save_xy) M(accumulate) class SkRasterPipeline { public: diff --git a/src/image/SkImageShader.cpp b/src/image/SkImageShader.cpp index d2ddc95744..719bced4f5 100644 --- a/src/image/SkImageShader.cpp +++ b/src/image/SkImageShader.cpp @@ -358,26 +358,20 @@ bool SkImageShader::onAppendStages(SkRasterPipeline* p, SkColorSpace* dst, SkFal } }; - if (quality == kNone_SkFilterQuality) { - append_tiling_and_gather(); - - } else { - p->append(SkRasterPipeline::top_left, ctx); - append_tiling_and_gather(); - p->append(SkRasterPipeline::accumulate, ctx); - - p->append(SkRasterPipeline::top_right, ctx); - append_tiling_and_gather(); - p->append(SkRasterPipeline::accumulate, ctx); - - p->append(SkRasterPipeline::bottom_left, ctx); + auto sample = [&](SkRasterPipeline::StockStage sampler) { + p->append(sampler, ctx); append_tiling_and_gather(); p->append(SkRasterPipeline::accumulate, ctx); + }; - p->append(SkRasterPipeline::bottom_right, ctx); + if (quality == kNone_SkFilterQuality) { append_tiling_and_gather(); - p->append(SkRasterPipeline::accumulate, ctx); - + } else { + p->append(SkRasterPipeline::save_xy, ctx); + sample(SkRasterPipeline::bilinear_nn); + sample(SkRasterPipeline::bilinear_np); + sample(SkRasterPipeline::bilinear_pn); + sample(SkRasterPipeline::bilinear_pp); p->append(SkRasterPipeline::move_dst_src); } diff --git a/src/image/SkImageShaderContext.h b/src/image/SkImageShaderContext.h index 7e50286072..b0652900dd 100644 --- a/src/image/SkImageShaderContext.h +++ b/src/image/SkImageShaderContext.h @@ -28,6 +28,8 @@ struct SkImageShaderContext { float matrix[9]; float x[8]; float y[8]; + float fx[8]; + float fy[8]; float scale[8]; }; diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h index e73d56cc8b..d0a57e4a11 100644 --- a/src/opts/SkRasterPipeline_opts.h +++ b/src/opts/SkRasterPipeline_opts.h @@ -801,49 +801,38 @@ STAGE( clamp_y) { g = clamp (g, *(const int*)ctx); } STAGE(repeat_y) { g = repeat(g, *(const int*)ctx); } STAGE(mirror_y) { g = mirror(g, *(const int*)ctx); } -STAGE(top_left) { +STAGE(save_xy) { auto sc = (SkImageShaderContext*)ctx; r.store(sc->x); g.store(sc->y); - r -= 0.5f; - g -= 0.5f; - - auto fx = r - r.floor(), - fy = g - g.floor(); - ((1.0f - fx) * (1.0f - fy)).store(sc->scale); -}; -STAGE(top_right) { - auto sc = (SkImageShaderContext*)ctx; - - r = SkNf::Load(sc->x) + 0.5f; - g = SkNf::Load(sc->y) - 0.5f; + auto fract = [](const SkNf& v) { return v - v.floor(); }; + fract(r + 0.5f).store(sc->fx); + fract(g + 0.5f).store(sc->fy); +} - auto fx = r - r.floor(), - fy = g - g.floor(); - (fx * (1.0f - fy)).store(sc->scale); -}; -STAGE(bottom_left) { +template <int X, int Y> +SI void bilinear(void* ctx, SkNf* x, SkNf* y) { auto sc = (SkImageShaderContext*)ctx; - r = SkNf::Load(sc->x) - 0.5f; - g = SkNf::Load(sc->y) + 0.5f; + // Bilinear interpolation considers the 4 physical pixels at + // each corner of a logical pixel centered at (sc->x, sc->y). + *x = SkNf::Load(sc->x) + X*0.5f; + *y = SkNf::Load(sc->y) + Y*0.5f; - auto fx = r - r.floor(), - fy = g - g.floor(); - ((1.0f - fx) * fy).store(sc->scale); -}; -STAGE(bottom_right) { - auto sc = (SkImageShaderContext*)ctx; - - r = SkNf::Load(sc->x) + 0.5f; - g = SkNf::Load(sc->y) + 0.5f; + // Each corner pixel contributes color in direct proportion to its overlap. + auto fx = SkNf::Load(sc->fx), + fy = SkNf::Load(sc->fy); + auto overlap = (X > 0 ? fx : (1.0f - fx)) + * (Y > 0 ? fy : (1.0f - fy)); + overlap.store(sc->scale); +} +STAGE(bilinear_nn) { bilinear<-1,-1>(ctx, &r, &g); } +STAGE(bilinear_pn) { bilinear<+1,-1>(ctx, &r, &g); } +STAGE(bilinear_np) { bilinear<-1,+1>(ctx, &r, &g); } +STAGE(bilinear_pp) { bilinear<+1,+1>(ctx, &r, &g); } - auto fx = r - r.floor(), - fy = g - g.floor(); - (fx * fy).store(sc->scale); -}; STAGE(accumulate) { auto sc = (const SkImageShaderContext*)ctx; |