spin off: always clamp linear gradients
While we're refactoring how gradients work it's going to be easier to centralized how and when we tile. - PS2 changed linear and radial in place to alwys clamp. - PS3 moved tiling to the base class, where it's even harder to screw up. Sweeps don't need but don't mind tiling. - PS4 clamps when iff evenly spaced PS4 has image diffs for only a few GMs that I'm not familiar with. If its logic reads as correct to you, they may be bug fixes? Change-Id: I5e37d6e88aaea898356d4c57db0cd5bf414c0295 Reviewed-on: https://skia-review.googlesource.com/16501 Commit-Queue: Mike Klein <mtklein@chromium.org> Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
b6deea8f0e
commit
e75985393e
@ -347,30 +347,44 @@ void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst,
|
|||||||
memcpy(colorDst, colorsTemp.get(), count * sizeof(SkColor));
|
memcpy(colorDst, colorsTemp.get(), count * sizeof(SkColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkGradientShaderBase::onAppendStages(
|
bool SkGradientShaderBase::onAppendStages(SkRasterPipeline* p,
|
||||||
SkRasterPipeline* pipeline, SkColorSpace* dstCS, SkArenaAlloc* alloc,
|
SkColorSpace* dstCS,
|
||||||
const SkMatrix& ctm, const SkPaint& paint,
|
SkArenaAlloc* alloc,
|
||||||
const SkMatrix* localM) const
|
const SkMatrix& ctm,
|
||||||
{
|
const SkPaint& paint,
|
||||||
|
const SkMatrix* localM) const {
|
||||||
SkMatrix matrix;
|
SkMatrix matrix;
|
||||||
if (!this->computeTotalInverse(ctm, localM, &matrix)) {
|
if (!this->computeTotalInverse(ctm, localM, &matrix)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkRasterPipeline p;
|
SkRasterPipeline subclass;
|
||||||
if (!this->adjustMatrixAndAppendStages(alloc, &matrix, &p)) {
|
if (!this->adjustMatrixAndAppendStages(alloc, &matrix, &subclass)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* m = alloc->makeArrayDefault<float>(9);
|
auto* m = alloc->makeArrayDefault<float>(9);
|
||||||
if (matrix.asAffine(m)) {
|
if (matrix.asAffine(m)) {
|
||||||
pipeline->append(SkRasterPipeline::matrix_2x3, m);
|
p->append(SkRasterPipeline::matrix_2x3, m);
|
||||||
} else {
|
} else {
|
||||||
matrix.get9(m);
|
matrix.get9(m);
|
||||||
pipeline->append(SkRasterPipeline::matrix_perspective, m);
|
p->append(SkRasterPipeline::matrix_perspective, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline->extend(p);
|
p->extend(subclass);
|
||||||
|
|
||||||
|
switch(fTileMode) {
|
||||||
|
case kMirror_TileMode: p->append(SkRasterPipeline::mirror_x, alloc->make<float>(1)); break;
|
||||||
|
case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_x, alloc->make<float>(1)); break;
|
||||||
|
case kClamp_TileMode:
|
||||||
|
if (!fOrigPos) {
|
||||||
|
// We clamp only when the stops are evenly spaced.
|
||||||
|
// If not, there may be hard stops, and clamping ruins hard stops at 0 and/or 1.
|
||||||
|
// In that case, we must make sure we're using the general linear_gradient stage,
|
||||||
|
// which is the only stage that will correctly handle unclamped t.
|
||||||
|
p->append(SkRasterPipeline::clamp_x, alloc->make<float>(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const bool premulGrad = fGradFlags & SkGradientShader::kInterpolateColorsInPremul_Flag;
|
const bool premulGrad = fGradFlags & SkGradientShader::kInterpolateColorsInPremul_Flag;
|
||||||
auto prepareColor = [premulGrad, dstCS, this](int i) {
|
auto prepareColor = [premulGrad, dstCS, this](int i) {
|
||||||
@ -390,7 +404,7 @@ bool SkGradientShaderBase::onAppendStages(
|
|||||||
f_and_b[0] = SkPM4f::From4f(c_r.to4f() - c_l.to4f());
|
f_and_b[0] = SkPM4f::From4f(c_r.to4f() - c_l.to4f());
|
||||||
f_and_b[1] = c_l;
|
f_and_b[1] = c_l;
|
||||||
|
|
||||||
pipeline->append(SkRasterPipeline::linear_gradient_2stops, f_and_b);
|
p->append(SkRasterPipeline::linear_gradient_2stops, f_and_b);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
struct Stop { float t; SkPM4f f, b; };
|
struct Stop { float t; SkPM4f f, b; };
|
||||||
@ -479,11 +493,11 @@ bool SkGradientShaderBase::onAppendStages(
|
|||||||
ctx->stops = stopsArray;
|
ctx->stops = stopsArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline->append(SkRasterPipeline::linear_gradient, ctx);
|
p->append(SkRasterPipeline::linear_gradient, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!premulGrad && !this->colorsAreOpaque()) {
|
if (!premulGrad && !this->colorsAreOpaque()) {
|
||||||
pipeline->append(SkRasterPipeline::premul);
|
p->append(SkRasterPipeline::premul);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -90,17 +90,8 @@ bool SkLinearGradient::adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
|
|||||||
// If the gradient is less than a quarter of a pixel, this falls into the
|
// If the gradient is less than a quarter of a pixel, this falls into the
|
||||||
// subpixel gradient code handled on a different path.
|
// subpixel gradient code handled on a different path.
|
||||||
SkVector dx = matrix->mapVector(1, 0);
|
SkVector dx = matrix->mapVector(1, 0);
|
||||||
if (dx.fX >= 4) { return false; }
|
if (dx.fX >= 4) {
|
||||||
|
return false;
|
||||||
switch(fTileMode) {
|
|
||||||
case kMirror_TileMode: p->append(SkRasterPipeline::mirror_x, alloc->make<float>(1)); break;
|
|
||||||
case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_x, alloc->make<float>(1)); break;
|
|
||||||
case kClamp_TileMode:
|
|
||||||
if (fColorCount == 2 && fOrigPos == nullptr) {
|
|
||||||
// The general strategy does not need clamping due to implicit hard stops at 0 and 1,
|
|
||||||
// but the 2-point specialization must be clamped.
|
|
||||||
p->append(SkRasterPipeline::clamp_x, alloc->make<float>(1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -383,18 +383,6 @@ bool SkRadialGradient::adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
|
|||||||
matrix->postScale(1/fRadius, 1/fRadius);
|
matrix->postScale(1/fRadius, 1/fRadius);
|
||||||
|
|
||||||
p->append(SkRasterPipeline::xy_to_radius);
|
p->append(SkRasterPipeline::xy_to_radius);
|
||||||
|
|
||||||
switch(fTileMode) {
|
|
||||||
case kMirror_TileMode: p->append(SkRasterPipeline::mirror_x, alloc->make<float>(1)); break;
|
|
||||||
case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_x, alloc->make<float>(1)); break;
|
|
||||||
case kClamp_TileMode:
|
|
||||||
if (fColorCount == 2 && fOrigPos == nullptr) {
|
|
||||||
// The general strategy does not need clamping due to implicit hard stops at 0 and 1,
|
|
||||||
// but the 2-point specialization must be clamped.
|
|
||||||
p->append(SkRasterPipeline::clamp_x, alloc->make<float>(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user