Simplify decal for gradients

Previous change extended the stored array of colors/positions, and lost the
information that the intent was decal. This variant just uses custom stages
already developed for imageshader, keeping the intent of decal.

Bug: skia:7638
Change-Id: Ie3f30b42f4c1793487f08039cd3cea8e31aafc40
Reviewed-on: https://skia-review.googlesource.com/108280
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2018-02-19 14:20:15 -05:00 committed by Skia Commit-Bot
parent 19d7bd6504
commit 62ce2ca069

View File

@ -149,40 +149,24 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri
fColorCount += dummyFirst + dummyLast;
}
bool decal_mode = (desc.fTileMode == SkShader::kDecal_TileMode);
bool need_pos = (desc.fPos != nullptr);
if (decal_mode) {
fColorCount += 2; // extra first and last stops
need_pos = true;
}
size_t storageSize = fColorCount * (sizeof(SkColor4f) + (need_pos ? sizeof(SkScalar) : 0));
size_t storageSize = fColorCount * (sizeof(SkColor4f) + (desc.fPos ? sizeof(SkScalar) : 0));
fOrigColors4f = reinterpret_cast<SkColor4f*>(fStorage.reset(storageSize));
fOrigPos = need_pos ? reinterpret_cast<SkScalar*>(fOrigColors4f + fColorCount)
fOrigPos = desc.fPos ? reinterpret_cast<SkScalar*>(fOrigColors4f + fColorCount)
: nullptr;
SkASSERT(need_pos == (fOrigPos != nullptr));
// Now copy over the colors, adding the dummies as needed
SkColor4f* origColors = fOrigColors4f;
if (decal_mode) {
*origColors++ = { 0, 0, 0, 0 };
}
if (dummyFirst) {
*origColors++ = desc.fColors[0];
}
for (int i = 0; i < desc.fCount; ++i) {
*origColors++ = desc.fColors[i];
origColors[i] = desc.fColors[i];
fColorsAreOpaque = fColorsAreOpaque && (desc.fColors[i].fA == 1);
}
if (dummyLast) {
*origColors++ = desc.fColors[desc.fCount - 1];
origColors += desc.fCount;
*origColors = desc.fColors[desc.fCount - 1];
}
if (decal_mode) {
*origColors++ = { 0, 0, 0, 0 };
fColorsAreOpaque = false;
}
SkASSERT(fColorCount == (origColors - fOrigColors4f));
if (!desc.fColorSpace) {
// This happens if we were constructed from SkColors, so our colors are really sRGB
@ -194,13 +178,9 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri
fColorSpace = desc.fColorSpace;
}
SkScalar* origPosPtr = fOrigPos;
if (decal_mode) {
*origPosPtr++ = 0;
}
if (desc.fPos) {
SkScalar prev = 0;
SkScalar* origPosPtr = fOrigPos;
*origPosPtr++ = prev; // force the first pos to 0
int startIndex = dummyFirst ? 0 : 1;
@ -217,33 +197,9 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri
}
// If the stops are uniform, treat them as implicit.
if (uniformStops && !decal_mode) {
if (uniformStops) {
fOrigPos = nullptr;
}
} else if (decal_mode) {
// we need to create evenly spaced positions, since decal has forced extra start/ends
int n = fColorCount - 2; // subtract off the extra 2 decal added
float dt = 1.0f / (n - 1);
float t = 0;
for (int i = 0; i < n - 1; ++i) {
*origPosPtr++ = t;
t += dt;
}
*origPosPtr++ = 1.0f; // store the last explicitly, so we always hit 1.0 exactly
}
if (decal_mode) {
SkASSERT(origPosPtr[-1] == 1.0f);
*origPosPtr++ = SkBits2Float(SkFloat2Bits(1.0f) + 1);
}
if (fOrigPos) {
SkASSERT(fColorCount == (origPosPtr - fOrigPos));
}
// Now that we've munged the stops, pretend we're clamp
// (so we don't do this again via serialization)
if (decal_mode) {
fTileMode = SkShader::kClamp_TileMode;
}
}
@ -323,6 +279,7 @@ bool SkGradientShaderBase::onAppendStages(const StageRec& rec) const {
SkRasterPipeline* p = rec.fPipeline;
SkArenaAlloc* alloc = rec.fAlloc;
SkColorSpace* dstCS = rec.fDstCS;
SkJumper_DecalTileCtx* decal_ctx = nullptr;
SkMatrix matrix;
if (!this->computeTotalInverse(rec.fCTM, rec.fLocalM, &matrix)) {
@ -336,12 +293,15 @@ bool SkGradientShaderBase::onAppendStages(const StageRec& rec) const {
p->append_matrix(alloc, matrix);
this->appendGradientStages(alloc, p, &postPipeline);
switch (fTileMode) {
switch(fTileMode) {
case kMirror_TileMode: p->append(SkRasterPipeline::mirror_x_1); break;
case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_x_1); break;
case kDecal_TileMode:
// TODO: need decal stages
// fall-through for now
decal_ctx = alloc->make<SkJumper_DecalTileCtx>();
decal_ctx->limit_x = SkBits2Float(SkFloat2Bits(1.0f) + 1);
// reuse mask + limit_x stage, or create a custom decal_1 that just stores the mask
p->append(SkRasterPipeline::decal_x, decal_ctx);
// fall-through to clamp
case kClamp_TileMode:
if (!fOrigPos) {
// We clamp only when the stops are evenly spaced.
@ -350,6 +310,7 @@ bool SkGradientShaderBase::onAppendStages(const StageRec& rec) const {
// which is the only stage that will correctly handle unclamped t.
p->append(SkRasterPipeline::clamp_x_1);
}
break;
}
const bool premulGrad = fGradFlags & SkGradientShader::kInterpolateColorsInPremul_Flag;
@ -440,6 +401,10 @@ bool SkGradientShaderBase::onAppendStages(const StageRec& rec) const {
}
}
if (decal_ctx) {
p->append(SkRasterPipeline::check_decal_mask, decal_ctx);
}
if (!premulGrad && !this->colorsAreOpaque()) {
p->append(SkRasterPipeline::premul);
}
@ -451,7 +416,14 @@ bool SkGradientShaderBase::onAppendStages(const StageRec& rec) const {
bool SkGradientShaderBase::isOpaque() const {
return fColorsAreOpaque;
return fColorsAreOpaque && (this->getTileMode() != SkShader::kDecal_TileMode);
}
bool SkGradientShaderBase::onIsRasterPipelineOnly(const SkMatrix& ctm) const {
if (this->getTileMode() == SkShader::kDecal_TileMode) {
return true;
}
return this->INHERITED::onIsRasterPipelineOnly(ctm);
}
static unsigned rounded_divide(unsigned numer, unsigned denom) {
@ -559,13 +531,6 @@ void SkGradientShaderBase::initLinearBitmap(SkBitmap* bitmap, GradientBitmapType
SkASSERT(prevIndex == kGradientTextureSize - 1);
}
bool SkGradientShaderBase::onIsRasterPipelineOnly(const SkMatrix& ctm) const {
if (this->getTileMode() == SkShader::kDecal_TileMode) {
return true;
}
return this->INHERITED::onIsRasterPipelineOnly(ctm);
}
SkColor4f SkGradientShaderBase::getXformedColor(size_t i, SkColorSpace* dstCS) const {
if (dstCS) {
return to_colorspace(fOrigColors4f[i], fColorSpace.get(), dstCS);