aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/shaders/gradients
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2018-02-16 12:40:18 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-16 23:19:47 +0000
commitdfc0e910dfdf7ad11995d357e44c029d839f2e73 (patch)
tree59710dc00e01ceeddfe79ed920d308b12761d31a /src/shaders/gradients
parent1701ecea23b05d66476de4358d4ff74fd19c3a67 (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.cpp3
-rw-r--r--src/shaders/gradients/SkGradientShader.cpp74
-rw-r--r--src/shaders/gradients/SkGradientShaderPriv.h5
-rw-r--r--src/shaders/gradients/SkLinearGradient.cpp4
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;