diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h index 45576a3631..3269a16109 100644 --- a/src/core/SkRasterPipeline.h +++ b/src/core/SkRasterPipeline.h @@ -72,6 +72,8 @@ M(exclusion) M(hardlight) M(lighten) M(overlay) M(softlight) \ M(luminance_to_alpha) M(matrix_3x4) M(matrix_4x5) \ M(fn_1_r) M(fn_1_g) M(fn_1_b) \ + M(parametric_r) M(parametric_g) M(parametric_b) \ + M(table_r) M(table_g) M(table_b) \ M(color_lookup_table) M(lab_to_xyz) M(swap_rb) class SkRasterPipeline { diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h index 4584f3d6d7..b90faf85b2 100644 --- a/src/opts/SkRasterPipeline_opts.h +++ b/src/opts/SkRasterPipeline_opts.h @@ -543,6 +543,46 @@ STAGE(matrix_4x5, true) { a = A; } +SI SkNf parametric(const SkNf& v, const SkColorSpaceTransferFn& p) { + float result[N]; // Unconstrained powf() doesn't vectorize well... + for (int i = 0; i < N; i++) { + float s = v[i]; + result[i] = (s <= p.fD) ? p.fE * s + p.fF + : powf(s * p.fA + p.fB, p.fG) + p.fC; + } + return SkNf::Load(result); +} + +STAGE(parametric_r, true) { + r = parametric(r, *(const SkColorSpaceTransferFn*)ctx); +} +STAGE(parametric_g, true) { + g = parametric(g, *(const SkColorSpaceTransferFn*)ctx); +} +STAGE(parametric_b, true) { + b = parametric(b, *(const SkColorSpaceTransferFn*)ctx); +} + +SI SkNf table(const SkNf& v, const float t[1024]) { + SkNi ix = SkNx_cast(SkNf::Max(0, SkNf::Min(v, 1)) * 1023 + 0.5); + + float result[N]; // TODO: vgatherdps? + for (int i = 0; i < N; i++) { + result[i] = t[ix[i]]; + } + return SkNf::Load(result); +} + +STAGE(table_r, true) { + r = table(r, (const float*)ctx); +} +STAGE(table_g, true) { + g = table(g, (const float*)ctx); +} +STAGE(table_b, true) { + b = table(b, (const float*)ctx); +} + STAGE(fn_1_r, true) { auto fn = (const std::function*)ctx; float result[N];