diff options
author | Mike Reed <reed@google.com> | 2018-02-16 12:40:18 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-02-16 23:19:47 +0000 |
commit | dfc0e910dfdf7ad11995d357e44c029d839f2e73 (patch) | |
tree | 59710dc00e01ceeddfe79ed920d308b12761d31a /src/shaders/gradients | |
parent | 1701ecea23b05d66476de4358d4ff74fd19c3a67 (diff) |
add decal tilemode to shaders
Plenty more to follow-up:
- gradients
- gpu impl
Bug: skia:7638
Change-Id: I8e54fd0e24921f040f178c793b36c7fb855b136e
Reviewed-on: https://skia-review.googlesource.com/107420
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src/shaders/gradients')
-rw-r--r-- | src/shaders/gradients/Sk4fLinearGradient.cpp | 3 | ||||
-rw-r--r-- | src/shaders/gradients/SkGradientShader.cpp | 74 | ||||
-rw-r--r-- | src/shaders/gradients/SkGradientShaderPriv.h | 5 | ||||
-rw-r--r-- | src/shaders/gradients/SkLinearGradient.cpp | 4 |
4 files changed, 76 insertions, 10 deletions
diff --git a/src/shaders/gradients/Sk4fLinearGradient.cpp b/src/shaders/gradients/Sk4fLinearGradient.cpp index 528a6baa7e..1a0dbd2042 100644 --- a/src/shaders/gradients/Sk4fLinearGradient.cpp +++ b/src/shaders/gradients/Sk4fLinearGradient.cpp @@ -202,6 +202,9 @@ LinearGradient4fContext::shadePremulSpan(int x, int y, dstType dst[], int count, float bias0, float bias1) const { const SkLinearGradient& shader = static_cast<const SkLinearGradient&>(fShader); switch (shader.fTileMode) { + case kDecal_TileMode: + SkASSERT(false); // decal only supported via stages + // fall-through case kClamp_TileMode: this->shadeSpanInternal<dstType, premul, kClamp_TileMode >(x, y, dst, count, bias0, bias1); break; diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp index 871c7ba55e..05ba798fe9 100644 --- a/src/shaders/gradients/SkGradientShader.cpp +++ b/src/shaders/gradients/SkGradientShader.cpp @@ -149,24 +149,40 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri fColorCount += dummyFirst + dummyLast; } - size_t storageSize = fColorCount * (sizeof(SkColor4f) + (desc.fPos ? sizeof(SkScalar) : 0)); + 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)); fOrigColors4f = reinterpret_cast<SkColor4f*>(fStorage.reset(storageSize)); - fOrigPos = desc.fPos ? reinterpret_cast<SkScalar*>(fOrigColors4f + fColorCount) - : nullptr; + fOrigPos = need_pos ? 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[i] = desc.fColors[i]; + *origColors++ = desc.fColors[i]; fColorsAreOpaque = fColorsAreOpaque && (desc.fColors[i].fA == 1); } if (dummyLast) { - origColors += desc.fCount; - *origColors = desc.fColors[desc.fCount - 1]; + *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 @@ -178,9 +194,13 @@ 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; @@ -197,9 +217,33 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri } // If the stops are uniform, treat them as implicit. - if (uniformStops) { + if (uniformStops && !decal_mode) { 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; } } @@ -292,9 +336,12 @@ 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 case kClamp_TileMode: if (!fOrigPos) { // We clamp only when the stops are evenly spaced. @@ -512,6 +559,13 @@ 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); @@ -640,7 +694,7 @@ void SkGradientShaderBase::toString(SkString* str) const { } static const char* gTileModeName[SkShader::kTileModeCount] = { - "clamp", "repeat", "mirror" + "clamp", "repeat", "mirror", "decal", }; str->append(" "); diff --git a/src/shaders/gradients/SkGradientShaderPriv.h b/src/shaders/gradients/SkGradientShaderPriv.h index d71ba0295d..c015a73bf7 100644 --- a/src/shaders/gradients/SkGradientShaderPriv.h +++ b/src/shaders/gradients/SkGradientShaderPriv.h @@ -94,6 +94,7 @@ protected: void initLinearBitmap(SkBitmap* bitmap, GradientBitmapType) const; bool onAppendStages(const StageRec&) const override; + bool onIsRasterPipelineOnly(const SkMatrix& ctm) const override; virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline, SkRasterPipeline* postPipeline) const = 0; @@ -209,6 +210,10 @@ public: case SkShader::kMirror_TileMode: fWrapMode = GrSamplerState::WrapMode::kMirrorRepeat; break; + case SkShader::kDecal_TileMode: + // TODO: actually support decal + fWrapMode = GrSamplerState::WrapMode::kClamp; + break; } } diff --git a/src/shaders/gradients/SkLinearGradient.cpp b/src/shaders/gradients/SkLinearGradient.cpp index 86e8179daa..739822157c 100644 --- a/src/shaders/gradients/SkLinearGradient.cpp +++ b/src/shaders/gradients/SkLinearGradient.cpp @@ -61,6 +61,10 @@ SkShaderBase::Context* SkLinearGradient::onMakeContext( SkShaderBase::Context* SkLinearGradient::onMakeBurstPipelineContext( const ContextRec& rec, SkArenaAlloc* alloc) const { + if (fTileMode == SkShader::kDecal_TileMode) { + // we only support decal w/ stages + return nullptr; + } // Raster pipeline has a 2-stop specialization faster than our burst. return fColorCount > 2 ? CheckedMakeContext<LinearGradient4fContext>(alloc, *this, rec) : nullptr; |