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:
parent
b681a0f1b0
commit
a07e4302cf
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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:
|
||||
|
@ -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 &&
|
||||
|
@ -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
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user