add gamma stage

Until now we've been using 3 separate parametric stages to apply
gamma to r,g,b.  That works fine, but is kind of unnecessarily
slow, and again less clear in a stack trace than seeing "gamma".

The new bench runs in about 60% of the time the old one does
on my Trashcan.

BUG=skia:6939

Change-Id: I079698d3009b081f1c23a2e27fc26e373b439610
Reviewed-on: https://skia-review.googlesource.com/32721
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
This commit is contained in:
Mike Klein 2017-08-09 13:51:35 -04:00 committed by Skia Commit-Bot
parent b681a0f1b0
commit a07e4302cf
9 changed files with 8305 additions and 6280 deletions

View File

@ -113,9 +113,12 @@ static SkColorSpaceTransferFn gamma(float g) {
class SkRasterPipeline_2dot2 : public Benchmark {
public:
SkRasterPipeline_2dot2(bool parametric) : fParametric(parametric) {}
bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
const char* onGetName() override {
return "SkRasterPipeline_2dot2";
return fParametric ? "SkRasterPipeline_2dot2_parametric"
: "SkRasterPipeline_2dot2_gamma";
}
void onDraw(int loops, SkCanvas*) override {
@ -126,19 +129,27 @@ public:
SkSTArenaAlloc<256> alloc;
SkRasterPipeline p(&alloc);
p.append_constant_color(&alloc, c);
p.append(SkRasterPipeline::parametric_r, &from_2dot2);
p.append(SkRasterPipeline::parametric_g, &from_2dot2);
p.append(SkRasterPipeline::parametric_b, &from_2dot2);
p.append(SkRasterPipeline::parametric_r, & to_2dot2);
p.append(SkRasterPipeline::parametric_g, & to_2dot2);
p.append(SkRasterPipeline::parametric_b, & to_2dot2);
if (fParametric) {
p.append(SkRasterPipeline::parametric_r, &from_2dot2);
p.append(SkRasterPipeline::parametric_g, &from_2dot2);
p.append(SkRasterPipeline::parametric_b, &from_2dot2);
p.append(SkRasterPipeline::parametric_r, & to_2dot2);
p.append(SkRasterPipeline::parametric_g, & to_2dot2);
p.append(SkRasterPipeline::parametric_b, & to_2dot2);
} else {
p.append(SkRasterPipeline::gamma, &from_2dot2.fG);
p.append(SkRasterPipeline::gamma, & to_2dot2.fG);
}
while (loops --> 0) {
p.run(0,0,N,1);
}
}
private:
bool fParametric;
};
DEF_BENCH( return (new SkRasterPipeline_2dot2); )
DEF_BENCH( return (new SkRasterPipeline_2dot2( true)); )
DEF_BENCH( return (new SkRasterPipeline_2dot2(false)); )
class SkRasterPipelineToSRGB : public Benchmark {
public:

View File

@ -170,6 +170,16 @@ static inline bool is_almost_linear(const SkColorSpaceTransferFn& coeffs) {
return linearExp || linearFn;
}
static inline bool is_just_gamma(const SkColorSpaceTransferFn& coeffs) {
return transfer_fn_almost_equal(coeffs.fA, 1.0f)
&& transfer_fn_almost_equal(coeffs.fB, 0.0f)
&& transfer_fn_almost_equal(coeffs.fC, 0.0f)
&& transfer_fn_almost_equal(coeffs.fD, 0.0f)
&& transfer_fn_almost_equal(coeffs.fE, 0.0f)
&& transfer_fn_almost_equal(coeffs.fF, 0.0f);
}
static inline void value_to_parametric(SkColorSpaceTransferFn* coeffs, float exponent) {
coeffs->fA = 1.0f;
coeffs->fB = 0.0f;

View File

@ -588,17 +588,13 @@ bool SkColorSpaceXform_XYZ<kCSM>
}
TablesContext tables;
SkColorSpaceTransferFn to_2dot2 = {0,0,0,0,0,0,0};
to_2dot2.fG = 1/2.2f;
to_2dot2.fA = 1;
float to_2dot2 = 1/2.2f;
switch (fDstGamma) {
case kSRGB_DstGamma:
pipeline.append(SkRasterPipeline::to_srgb);
break;
case k2Dot2_DstGamma:
pipeline.append(SkRasterPipeline::parametric_r, &to_2dot2);
pipeline.append(SkRasterPipeline::parametric_g, &to_2dot2);
pipeline.append(SkRasterPipeline::parametric_b, &to_2dot2);
pipeline.append(SkRasterPipeline::gamma, &to_2dot2);
break;
case kTable_DstGamma:
tables.fR = fDstGammaTables[0];

View File

@ -149,9 +149,13 @@ SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
auto fn = fAlloc.make<SkColorSpaceTransferFn>();
SkAssertResult(named_to_parametric(fn, e.gammaNamed()));
fElementsPipeline.append(SkRasterPipeline::parametric_r, fn);
fElementsPipeline.append(SkRasterPipeline::parametric_g, fn);
fElementsPipeline.append(SkRasterPipeline::parametric_b, fn);
if (is_just_gamma(*fn)) {
fElementsPipeline.append(SkRasterPipeline::gamma, &fn->fG);
} else {
fElementsPipeline.append(SkRasterPipeline::parametric_r, fn);
fElementsPipeline.append(SkRasterPipeline::parametric_g, fn);
fElementsPipeline.append(SkRasterPipeline::parametric_b, fn);
}
break;
}
case SkColorSpace_A2B::Element::Type::kGammas: {
@ -236,13 +240,7 @@ SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
// do nothing
break;
case k2Dot2Curve_SkGammaNamed: {
SkColorSpaceTransferFn fn = {0,0,0,0,0,0,0};
fn.fG = 1/2.2f;
fn.fA = 1;
auto to_2dot2 = this->copy(fn);
fElementsPipeline.append(SkRasterPipeline::parametric_r, to_2dot2);
fElementsPipeline.append(SkRasterPipeline::parametric_g, to_2dot2);
fElementsPipeline.append(SkRasterPipeline::parametric_b, to_2dot2);
fElementsPipeline.append(SkRasterPipeline::gamma, this->copy(1/2.2f));
break;
}
case kSRGB_SkGammaNamed:

View File

@ -7,6 +7,7 @@
#include "SkColorSpaceXform_Base.h"
#include "SkColorSpaceXformPriv.h"
#include "SkColorSpacePriv.h"
#include "SkColorTable.h"
#include "SkConvertPixels.h"
#include "SkHalf.h"
@ -255,9 +256,13 @@ static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size
pipeline.append_from_srgb(premulState);
} else if (isColorAware && !srcInfo.colorSpace()->gammaIsLinear()) {
SkAssertResult(srcInfo.colorSpace()->isNumericalTransferFn(&srcFn));
pipeline.append(SkRasterPipeline::parametric_r, &srcFn);
pipeline.append(SkRasterPipeline::parametric_g, &srcFn);
pipeline.append(SkRasterPipeline::parametric_b, &srcFn);
if (is_just_gamma(srcFn)) {
pipeline.append(SkRasterPipeline::gamma, &srcFn.fG);
} else {
pipeline.append(SkRasterPipeline::parametric_r, &srcFn);
pipeline.append(SkRasterPipeline::parametric_g, &srcFn);
pipeline.append(SkRasterPipeline::parametric_b, &srcFn);
}
}
float matrix[12];
@ -283,9 +288,13 @@ static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size
} else if (isColorAware && !dstInfo.colorSpace()->gammaIsLinear()) {
SkAssertResult(dstInfo.colorSpace()->isNumericalTransferFn(&dstFn));
dstFn = dstFn.invert();
pipeline.append(SkRasterPipeline::parametric_r, &dstFn);
pipeline.append(SkRasterPipeline::parametric_g, &dstFn);
pipeline.append(SkRasterPipeline::parametric_b, &dstFn);
if (is_just_gamma(dstFn)) {
pipeline.append(SkRasterPipeline::gamma, &dstFn.fG);
} else {
pipeline.append(SkRasterPipeline::parametric_r, &dstFn);
pipeline.append(SkRasterPipeline::parametric_g, &dstFn);
pipeline.append(SkRasterPipeline::parametric_b, &dstFn);
}
}
if (kUnpremul_SkAlphaType == premulState && kPremul_SkAlphaType == dat &&

View File

@ -71,7 +71,7 @@ struct SkJumper_Engine;
M(matrix_2x3) M(matrix_3x4) M(matrix_4x5) M(matrix_4x3) \
M(matrix_perspective) \
M(parametric_r) M(parametric_g) M(parametric_b) \
M(parametric_a) \
M(parametric_a) M(gamma) \
M(table_r) M(table_g) M(table_b) M(table_a) \
M(lab_to_xyz) \
M(clamp_x) M(mirror_x) M(repeat_x) \

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -836,6 +836,13 @@ STAGE(parametric_g) { g = parametric(g, ctx); }
STAGE(parametric_b) { b = parametric(b, ctx); }
STAGE(parametric_a) { a = parametric(a, ctx); }
STAGE(gamma) {
float G = *(const float*)ctx;
r = approx_powf(r,G);
g = approx_powf(g,G);
b = approx_powf(b,G);
}
STAGE(lab_to_xyz) {
F L = r * 100.0f,
A = g * 255.0f - 128.0f,