Remove all old gpu gradient code
At this point, all gradient configurations should be handled by the new
FP gradient code path so this removes all of the dead code.
Bug: skia:
Change-Id: If6041edcd8417d8f345e17000ccb27d9efea0bb3
Reviewed-on: https://skia-review.googlesource.com/152383
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 17bed51..aafe1d8 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -57,7 +57,7 @@
* we verify the count is as expected. If a new factory is added, then these numbers must be
* manually adjusted.
*/
-static const int kFPFactoryCount = 40;
+static const int kFPFactoryCount = 36;
static const int kGPFactoryCount = 14;
static const int kXPFactoryCount = 4;
diff --git a/src/gpu/gradients/GrGradientShader.h b/src/gpu/gradients/GrGradientShader.h
index 28a0d4a..97f620c 100644
--- a/src/gpu/gradients/GrGradientShader.h
+++ b/src/gpu/gradients/GrGradientShader.h
@@ -9,12 +9,17 @@
#define GrGradientShader_DEFINE
#include "GrFPArgs.h"
+#include "GrFragmentProcessor.h"
#include "SkGradientShaderPriv.h"
#include "SkLinearGradient.h"
#include "SkRadialGradient.h"
#include "SkSweepGradient.h"
#include "SkTwoPointConicalGradient.h"
+#if GR_TEST_UTILS
+#include "SkRandom.h"
+#endif
+
namespace GrGradientShader {
std::unique_ptr<GrFragmentProcessor> MakeLinear(const SkLinearGradient& shader,
const GrFPArgs& args);
diff --git a/src/shaders/gradients/SkGradientBitmapCache.cpp b/src/shaders/gradients/SkGradientBitmapCache.cpp
deleted file mode 100644
index 06b2d8c..0000000
--- a/src/shaders/gradients/SkGradientBitmapCache.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkGradientBitmapCache.h"
-
-#include "SkMalloc.h"
-
-struct SkGradientBitmapCache::Entry {
- Entry* fPrev;
- Entry* fNext;
-
- void* fBuffer;
- size_t fSize;
- SkBitmap fBitmap;
-
- Entry(const void* buffer, size_t size, const SkBitmap& bm)
- : fPrev(nullptr),
- fNext(nullptr),
- fBitmap(bm) {
- fBuffer = sk_malloc_throw(size);
- fSize = size;
- memcpy(fBuffer, buffer, size);
- }
-
- ~Entry() { sk_free(fBuffer); }
-
- bool equals(const void* buffer, size_t size) const {
- return (fSize == size) && !memcmp(fBuffer, buffer, size);
- }
-};
-
-SkGradientBitmapCache::SkGradientBitmapCache(int max) : fMaxEntries(max) {
- fEntryCount = 0;
- fHead = fTail = nullptr;
-
- this->validate();
-}
-
-SkGradientBitmapCache::~SkGradientBitmapCache() {
- this->validate();
-
- Entry* entry = fHead;
- while (entry) {
- Entry* next = entry->fNext;
- delete entry;
- entry = next;
- }
-}
-
-SkGradientBitmapCache::Entry* SkGradientBitmapCache::release(Entry* entry) const {
- if (entry->fPrev) {
- SkASSERT(fHead != entry);
- entry->fPrev->fNext = entry->fNext;
- } else {
- SkASSERT(fHead == entry);
- fHead = entry->fNext;
- }
- if (entry->fNext) {
- SkASSERT(fTail != entry);
- entry->fNext->fPrev = entry->fPrev;
- } else {
- SkASSERT(fTail == entry);
- fTail = entry->fPrev;
- }
- return entry;
-}
-
-void SkGradientBitmapCache::attachToHead(Entry* entry) const {
- entry->fPrev = nullptr;
- entry->fNext = fHead;
- if (fHead) {
- fHead->fPrev = entry;
- } else {
- fTail = entry;
- }
- fHead = entry;
-}
-
-bool SkGradientBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
- AutoValidate av(this);
-
- Entry* entry = fHead;
- while (entry) {
- if (entry->equals(buffer, size)) {
- if (bm) {
- *bm = entry->fBitmap;
- }
- // move to the head of our list, so we purge it last
- this->release(entry);
- this->attachToHead(entry);
- return true;
- }
- entry = entry->fNext;
- }
- return false;
-}
-
-void SkGradientBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
- AutoValidate av(this);
-
- if (fEntryCount == fMaxEntries) {
- SkASSERT(fTail);
- delete this->release(fTail);
- fEntryCount -= 1;
- }
-
- Entry* entry = new Entry(buffer, len, bm);
- this->attachToHead(entry);
- fEntryCount += 1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_DEBUG
-
-void SkGradientBitmapCache::validate() const {
- SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
-
- if (fEntryCount > 0) {
- SkASSERT(nullptr == fHead->fPrev);
- SkASSERT(nullptr == fTail->fNext);
-
- if (fEntryCount == 1) {
- SkASSERT(fHead == fTail);
- } else {
- SkASSERT(fHead != fTail);
- }
-
- Entry* entry = fHead;
- int count = 0;
- while (entry) {
- count += 1;
- entry = entry->fNext;
- }
- SkASSERT(count == fEntryCount);
-
- entry = fTail;
- while (entry) {
- count -= 1;
- entry = entry->fPrev;
- }
- SkASSERT(0 == count);
- } else {
- SkASSERT(nullptr == fHead);
- SkASSERT(nullptr == fTail);
- }
-}
-
-#endif
diff --git a/src/shaders/gradients/SkGradientBitmapCache.h b/src/shaders/gradients/SkGradientBitmapCache.h
deleted file mode 100644
index 22ab31f..0000000
--- a/src/shaders/gradients/SkGradientBitmapCache.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#ifndef SkGradientBitmapCache_DEFINED
-#define SkGradientBitmapCache_DEFINED
-
-#include "SkBitmap.h"
-#include "SkNoncopyable.h"
-
-class SkGradientBitmapCache : SkNoncopyable {
-public:
- SkGradientBitmapCache(int maxEntries);
- ~SkGradientBitmapCache();
-
- bool find(const void* buffer, size_t len, SkBitmap*) const;
- void add(const void* buffer, size_t len, const SkBitmap&);
-
-private:
- int fEntryCount;
- const int fMaxEntries;
-
- struct Entry;
- mutable Entry* fHead;
- mutable Entry* fTail;
-
- inline Entry* release(Entry*) const;
- inline void attachToHead(Entry*) const;
-
-#ifdef SK_DEBUG
- void validate() const;
-#else
- void validate() const {}
-#endif
-
- class AutoValidate : SkNoncopyable {
- public:
- AutoValidate(const SkGradientBitmapCache* bc) : fBC(bc) { bc->validate(); }
- ~AutoValidate() { fBC->validate(); }
- private:
- const SkGradientBitmapCache* fBC;
- };
-};
-
-#endif
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index bfce551..721ecf9 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -11,7 +11,6 @@
#include "SkColorSpaceXformer.h"
#include "SkFlattenablePriv.h"
#include "SkFloatBits.h"
-#include "SkGradientBitmapCache.h"
#include "SkGradientShaderPriv.h"
#include "SkHalf.h"
#include "SkLinearGradient.h"
@@ -488,121 +487,6 @@
}
}
-static constexpr int kGradientTextureSize = 256;
-
-void SkGradientShaderBase::initLinearBitmap(const SkColor4f* colors, SkBitmap* bitmap,
- SkColorType colorType) const {
- const bool interpInPremul = SkToBool(fGradFlags &
- SkGradientShader::kInterpolateColorsInPremul_Flag);
- SkHalf* pixelsF16 = reinterpret_cast<SkHalf*>(bitmap->getPixels());
- uint32_t* pixels32 = reinterpret_cast<uint32_t*>(bitmap->getPixels());
-
- typedef std::function<void(const Sk4f&, int)> pixelWriteFn_t;
-
- pixelWriteFn_t writeF16Pixel = [&](const Sk4f& x, int index) {
- Sk4h c = SkFloatToHalf_finite_ftz(x);
- pixelsF16[4*index+0] = c[0];
- pixelsF16[4*index+1] = c[1];
- pixelsF16[4*index+2] = c[2];
- pixelsF16[4*index+3] = c[3];
- };
- pixelWriteFn_t write8888Pixel = [&](const Sk4f& c, int index) {
- pixels32[index] = Sk4f_toL32(c);
- };
-
- pixelWriteFn_t writeSizedPixel =
- (colorType == kRGBA_F16_SkColorType) ? writeF16Pixel : write8888Pixel;
- pixelWriteFn_t writeUnpremulPixel = [&](const Sk4f& c, int index) {
- writeSizedPixel(c * Sk4f(c[3], c[3], c[3], 1.0f), index);
- };
-
- pixelWriteFn_t writePixel = interpInPremul ? writeSizedPixel : writeUnpremulPixel;
-
- int prevIndex = 0;
- for (int i = 1; i < fColorCount; i++) {
- // Historically, stops have been mapped to [0, 256], with 256 then nudged to the
- // next smaller value, then truncate for the texture index. This seems to produce
- // the best results for some common distributions, so we preserve the behavior.
- int nextIndex = SkTMin(this->getPos(i) * kGradientTextureSize,
- SkIntToScalar(kGradientTextureSize - 1));
-
- if (nextIndex > prevIndex) {
- Sk4f c0 = Sk4f::Load(colors[i - 1].vec()),
- c1 = Sk4f::Load(colors[i ].vec());
-
- if (interpInPremul) {
- c0 = c0 * Sk4f(c0[3], c0[3], c0[3], 1.0f);
- c1 = c1 * Sk4f(c1[3], c1[3], c1[3], 1.0f);
- }
-
- Sk4f step = Sk4f(1.0f / static_cast<float>(nextIndex - prevIndex));
- Sk4f delta = (c1 - c0) * step;
-
- for (int curIndex = prevIndex; curIndex <= nextIndex; ++curIndex) {
- writePixel(c0, curIndex);
- c0 += delta;
- }
- }
- prevIndex = nextIndex;
- }
- SkASSERT(prevIndex == kGradientTextureSize - 1);
-}
-
-SK_DECLARE_STATIC_MUTEX(gGradientCacheMutex);
-/*
- * Because our caller might rebuild the same (logically the same) gradient
- * over and over, we'd like to return exactly the same "bitmap" if possible,
- * allowing the client to utilize a cache of our bitmap (e.g. with a GPU).
- * To do that, we maintain a private cache of built-bitmaps, based on our
- * colors and positions.
- */
-void SkGradientShaderBase::getGradientTableBitmap(const SkColor4f* colors, SkBitmap* bitmap,
- SkColorType colorType) const {
- // build our key: [numColors + colors[] + {positions[]} + flags + colorType ]
- static_assert(sizeof(SkColor4f) % sizeof(int32_t) == 0, "");
- const int colorsAsIntCount = fColorCount * sizeof(SkColor4f) / sizeof(int32_t);
- int count = 1 + colorsAsIntCount + 1 + 1;
- if (fColorCount > 2) {
- count += fColorCount - 1;
- }
-
- SkAutoSTMalloc<64, int32_t> storage(count);
- int32_t* buffer = storage.get();
-
- *buffer++ = fColorCount;
- memcpy(buffer, colors, fColorCount * sizeof(SkColor4f));
- buffer += colorsAsIntCount;
- if (fColorCount > 2) {
- for (int i = 1; i < fColorCount; i++) {
- *buffer++ = SkFloat2Bits(this->getPos(i));
- }
- }
- *buffer++ = fGradFlags;
- *buffer++ = static_cast<int32_t>(colorType);
- SkASSERT(buffer - storage.get() == count);
-
- ///////////////////////////////////
-
- static SkGradientBitmapCache* gCache;
- // Each cache entry costs 1K or 2K of RAM. Each bitmap will be 1x256 at either 32bpp or 64bpp.
- static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32;
- SkAutoMutexAcquire ama(gGradientCacheMutex);
-
- if (nullptr == gCache) {
- gCache = new SkGradientBitmapCache(MAX_NUM_CACHED_GRADIENT_BITMAPS);
- }
- size_t size = count * sizeof(int32_t);
-
- if (!gCache->find(storage.get(), size, bitmap)) {
- SkImageInfo info = SkImageInfo::Make(kGradientTextureSize, 1, colorType,
- kPremul_SkAlphaType);
- bitmap->allocPixels(info);
- this->initLinearBitmap(colors, bitmap, colorType);
- bitmap->setImmutable();
- gCache->add(storage.get(), size, *bitmap);
- }
-}
-
void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
if (info) {
if (info->fColorCount >= fColorCount) {
@@ -911,446 +795,3 @@
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSweepGradient)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointConicalGradient)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
-
-///////////////////////////////////////////////////////////////////////////////
-
-#if SK_SUPPORT_GPU
-
-#include "GrColorSpaceXform.h"
-#include "GrContext.h"
-#include "GrContextPriv.h"
-#include "GrShaderCaps.h"
-#include "GrTexture.h"
-#include "gl/GrGLContext.h"
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-#include "glsl/GrGLSLProgramDataManager.h"
-#include "glsl/GrGLSLUniformHandler.h"
-#include "SkGr.h"
-
-void GrGradientEffect::GLSLProcessor::emitUniforms(GrGLSLUniformHandler* uniformHandler,
- const GrGradientEffect& ge) {
- switch (ge.fStrategy) {
- case GrGradientEffect::InterpolationStrategy::kThreshold:
- case GrGradientEffect::InterpolationStrategy::kThresholdClamp0:
- case GrGradientEffect::InterpolationStrategy::kThresholdClamp1:
- fThresholdUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
- kFloat_GrSLType,
- kHigh_GrSLPrecision,
- "Threshold");
- // fall through
- case GrGradientEffect::InterpolationStrategy::kSingle:
- fIntervalsUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag,
- kHalf4_GrSLType,
- "Intervals",
- ge.fIntervals.count());
- break;
- case GrGradientEffect::InterpolationStrategy::kTexture:
- // No extra uniforms
- break;
- }
-}
-
-void GrGradientEffect::GLSLProcessor::onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& processor) {
- const GrGradientEffect& e = processor.cast<GrGradientEffect>();
-
- switch (e.fStrategy) {
- case GrGradientEffect::InterpolationStrategy::kThreshold:
- case GrGradientEffect::InterpolationStrategy::kThresholdClamp0:
- case GrGradientEffect::InterpolationStrategy::kThresholdClamp1:
- pdman.set1f(fThresholdUni, e.fThreshold);
- // fall through
- case GrGradientEffect::InterpolationStrategy::kSingle:
- pdman.set4fv(fIntervalsUni, e.fIntervals.count(),
- reinterpret_cast<const float*>(e.fIntervals.begin()));
- break;
- case GrGradientEffect::InterpolationStrategy::kTexture:
- // No additional uniform data beyond what is already managed by the samplers
- break;
- }
-}
-
-void GrGradientEffect::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
- b->add32(GLSLProcessor::GenBaseGradientKey(*this));
-}
-
-uint32_t GrGradientEffect::GLSLProcessor::GenBaseGradientKey(const GrProcessor& processor) {
- const GrGradientEffect& e = processor.cast<GrGradientEffect>();
-
- // Build a key using the following bit allocation:
- static constexpr uint32_t kStrategyBits = 3;
- static constexpr uint32_t kPremulBits = 1;
- SkDEBUGCODE(static constexpr uint32_t kWrapModeBits = 2;)
-
- uint32_t key = static_cast<uint32_t>(e.fStrategy);
- SkASSERT(key < (1 << kStrategyBits));
-
- // This is already baked into the table for texture gradients,
- // and only changes behavior for analytical gradients.
- if (e.fStrategy != InterpolationStrategy::kTexture &&
- e.fPremulType == GrGradientEffect::kBeforeInterp_PremulType) {
- key |= 1 << kStrategyBits;
- SkASSERT(key < (1 << (kStrategyBits + kPremulBits)));
- }
-
- key |= static_cast<uint32_t>(e.fWrapMode) << (kStrategyBits + kPremulBits);
- SkASSERT(key < (1 << (kStrategyBits + kPremulBits + kWrapModeBits)));
-
- return key;
-}
-
-void GrGradientEffect::GLSLProcessor::emitAnalyticalColor(GrGLSLFPFragmentBuilder* fragBuilder,
- GrGLSLUniformHandler* uniformHandler,
- const GrShaderCaps* shaderCaps,
- const GrGradientEffect& ge,
- const char* t,
- const char* outputColor,
- const char* inputColor) {
- // First, apply tiling rules.
- switch (ge.fWrapMode) {
- case GrSamplerState::WrapMode::kClamp:
- switch (ge.fStrategy) {
- case GrGradientEffect::InterpolationStrategy::kThresholdClamp0:
- // allow t > 1, in order to hit the clamp interval (1, inf)
- fragBuilder->codeAppendf("half tiled_t = max(%s, 0.0);", t);
- break;
- case GrGradientEffect::InterpolationStrategy::kThresholdClamp1:
- // allow t < 0, in order to hit the clamp interval (-inf, 0)
- fragBuilder->codeAppendf("half tiled_t = min(%s, 1.0);", t);
- break;
- default:
- // regular [0, 1] clamping
- fragBuilder->codeAppendf("half tiled_t = saturate(%s);", t);
- }
- break;
- case GrSamplerState::WrapMode::kRepeat:
- fragBuilder->codeAppendf("half tiled_t = fract(%s);", t);
- break;
- case GrSamplerState::WrapMode::kMirrorRepeat:
- fragBuilder->codeAppendf("half t_1 = %s - 1.0;", t);
- fragBuilder->codeAppendf("half tiled_t = t_1 - 2.0 * floor(t_1 * 0.5) - 1.0;");
- if (shaderCaps->mustDoOpBetweenFloorAndAbs()) {
- // At this point the expected value of tiled_t should between -1 and 1, so this
- // clamp has no effect other than to break up the floor and abs calls and make sure
- // the compiler doesn't merge them back together.
- fragBuilder->codeAppendf("tiled_t = clamp(tiled_t, -1.0, 1.0);");
- }
- fragBuilder->codeAppendf("tiled_t = abs(tiled_t);");
- break;
- }
-
- // Calculate the color.
- const char* intervals = uniformHandler->getUniformCStr(fIntervalsUni);
-
- switch (ge.fStrategy) {
- case GrGradientEffect::InterpolationStrategy::kSingle:
- SkASSERT(ge.fIntervals.count() == 2);
- fragBuilder->codeAppendf(
- "half4 color_scale = %s[0],"
- " color_bias = %s[1];"
- , intervals, intervals
- );
- break;
- case GrGradientEffect::InterpolationStrategy::kThreshold:
- case GrGradientEffect::InterpolationStrategy::kThresholdClamp0:
- case GrGradientEffect::InterpolationStrategy::kThresholdClamp1:
- {
- SkASSERT(ge.fIntervals.count() == 4);
- const char* threshold = uniformHandler->getUniformCStr(fThresholdUni);
- fragBuilder->codeAppendf(
- "half4 color_scale, color_bias;"
- "if (tiled_t < %s) {"
- " color_scale = %s[0];"
- " color_bias = %s[1];"
- "} else {"
- " color_scale = %s[2];"
- " color_bias = %s[3];"
- "}"
- , threshold, intervals, intervals, intervals, intervals
- );
- } break;
- default:
- SkASSERT(false);
- break;
- }
-
- fragBuilder->codeAppend("half4 colorTemp = tiled_t * color_scale + color_bias;");
-
- // We could skip this step if all colors are known to be opaque. Two considerations:
- // The gradient SkShader reporting opaque is more restrictive than necessary in the two
- // pt case. Make sure the key reflects this optimization (and note that it can use the
- // same shader as the kBeforeInterp case).
- if (ge.fPremulType == GrGradientEffect::kAfterInterp_PremulType) {
- fragBuilder->codeAppend("colorTemp.rgb *= colorTemp.a;");
- }
-
- // If the input colors were floats, or there was a color space xform, we may end up out of
- // range. The simplest solution is to always clamp our (premul) value here. We only need to
- // clamp RGB, but that causes hangs on the Tegra3 Nexus7. Clamping RGBA avoids the problem.
- fragBuilder->codeAppend("colorTemp = clamp(colorTemp, 0, colorTemp.a);");
-
- fragBuilder->codeAppendf("%s = %s * colorTemp;", outputColor, inputColor);
-}
-
-void GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
- GrGLSLUniformHandler* uniformHandler,
- const GrShaderCaps* shaderCaps,
- const GrGradientEffect& ge,
- const char* gradientTValue,
- const char* outputColor,
- const char* inputColor,
- const TextureSamplers& texSamplers) {
- if (ge.fStrategy != InterpolationStrategy::kTexture) {
- this->emitAnalyticalColor(fragBuilder, uniformHandler, shaderCaps, ge, gradientTValue,
- outputColor, inputColor);
- return;
- }
-
- fragBuilder->codeAppendf("half2 coord = half2(%s, 0.5);", gradientTValue);
- fragBuilder->codeAppendf("%s = ", outputColor);
- fragBuilder->appendTextureLookupAndModulate(inputColor, texSamplers[0], "coord",
- kFloat2_GrSLType);
- fragBuilder->codeAppend(";");
-}
-
-/////////////////////////////////////////////////////////////////////
-
-inline GrFragmentProcessor::OptimizationFlags GrGradientEffect::OptFlags(bool isOpaque) {
- return isOpaque
- ? kPreservesOpaqueInput_OptimizationFlag |
- kCompatibleWithCoverageAsAlpha_OptimizationFlag
- : kCompatibleWithCoverageAsAlpha_OptimizationFlag;
-}
-
-void GrGradientEffect::addInterval(const SkGradientShaderBase& shader, const SkColor4f* colors,
- size_t idx0, size_t idx1) {
- SkASSERT(idx0 <= idx1);
- const auto c4f0 = colors[idx0],
- c4f1 = colors[idx1];
- const auto c0 = (fPremulType == kBeforeInterp_PremulType)
- ? c4f0.premul().to4f() : Sk4f::Load(c4f0.vec()),
- c1 = (fPremulType == kBeforeInterp_PremulType)
- ? c4f1.premul().to4f() : Sk4f::Load(c4f1.vec());
- const auto t0 = shader.getPos(idx0),
- t1 = shader.getPos(idx1),
- dt = t1 - t0;
- SkASSERT(dt >= 0);
- // dt can be 0 for clamp intervals => in this case we want a scale == 0
- const auto scale = SkScalarNearlyZero(dt) ? 0 : (c1 - c0) / dt,
- bias = c0 - t0 * scale;
-
- // Intervals are stored as (scale, bias) tuples.
- SkASSERT(!(fIntervals.count() & 1));
- fIntervals.emplace_back(scale[0], scale[1], scale[2], scale[3]);
- fIntervals.emplace_back( bias[0], bias[1], bias[2], bias[3]);
-}
-
-GrGradientEffect::GrGradientEffect(ClassID classID, const CreateArgs& args, bool isOpaque)
- : INHERITED(classID, OptFlags(isOpaque))
- , fWrapMode(args.fWrapMode)
- , fIsOpaque(args.fShader->isOpaque())
- , fStrategy(InterpolationStrategy::kTexture)
- , fThreshold(0) {
-
- const SkGradientShaderBase& shader(*args.fShader);
-
- fPremulType = (args.fShader->getGradFlags() & SkGradientShader::kInterpolateColorsInPremul_Flag)
- ? kBeforeInterp_PremulType : kAfterInterp_PremulType;
-
- // Transform all of the colors to destination color space
- SkColor4fXformer xformedColors(shader.fOrigColors4f, shader.fColorCount,
- shader.fColorSpace.get(), args.fDstColorSpaceInfo->colorSpace());
-
- // First, determine the interpolation strategy and params.
- switch (shader.fColorCount) {
- case 2:
- SkASSERT(!shader.fOrigPos);
- fStrategy = InterpolationStrategy::kSingle;
- this->addInterval(shader, xformedColors.fColors, 0, 1);
- break;
- case 3:
- fThreshold = shader.getPos(1);
-
- if (shader.fOrigPos) {
- SkASSERT(SkScalarNearlyEqual(shader.fOrigPos[0], 0));
- SkASSERT(SkScalarNearlyEqual(shader.fOrigPos[2], 1));
- if (SkScalarNearlyEqual(shader.fOrigPos[1], 0)) {
- // hard stop on the left edge.
- if (fWrapMode == GrSamplerState::WrapMode::kClamp) {
- fStrategy = InterpolationStrategy::kThresholdClamp1;
- // Clamp interval (scale == 0, bias == colors[0]).
- this->addInterval(shader, xformedColors.fColors, 0, 0);
- } else {
- // We can ignore the hard stop when not clamping.
- fStrategy = InterpolationStrategy::kSingle;
- }
- this->addInterval(shader, xformedColors.fColors, 1, 2);
- break;
- }
-
- if (SkScalarNearlyEqual(shader.fOrigPos[1], 1)) {
- // hard stop on the right edge.
- this->addInterval(shader, xformedColors.fColors, 0, 1);
- if (fWrapMode == GrSamplerState::WrapMode::kClamp) {
- fStrategy = InterpolationStrategy::kThresholdClamp0;
- // Clamp interval (scale == 0, bias == colors[2]).
- this->addInterval(shader, xformedColors.fColors, 2, 2);
- } else {
- // We can ignore the hard stop when not clamping.
- fStrategy = InterpolationStrategy::kSingle;
- }
- break;
- }
- }
-
- // Two arbitrary interpolation intervals.
- fStrategy = InterpolationStrategy::kThreshold;
- this->addInterval(shader, xformedColors.fColors, 0, 1);
- this->addInterval(shader, xformedColors.fColors, 1, 2);
- break;
- case 4:
- if (shader.fOrigPos && SkScalarNearlyEqual(shader.fOrigPos[1], shader.fOrigPos[2])) {
- SkASSERT(SkScalarNearlyEqual(shader.fOrigPos[0], 0));
- SkASSERT(SkScalarNearlyEqual(shader.fOrigPos[3], 1));
-
- // Single hard stop => two arbitrary interpolation intervals.
- fStrategy = InterpolationStrategy::kThreshold;
- fThreshold = shader.getPos(1);
- this->addInterval(shader, xformedColors.fColors, 0, 1);
- this->addInterval(shader, xformedColors.fColors, 2, 3);
- }
- break;
- default:
- break;
- }
-
- // Now that we've locked down a strategy, adjust any dependent params.
- if (fStrategy != InterpolationStrategy::kTexture) {
- // Analytical cases.
- fCoordTransform.reset(*args.fMatrix);
- } else {
- // Use 8888 or F16, depending on the destination config.
- // TODO: Use 1010102 for opaque gradients, at least if destination is 1010102?
- SkColorType colorType = kRGBA_8888_SkColorType;
- if (kLow_GrSLPrecision != GrSLSamplerPrecision(args.fDstColorSpaceInfo->config()) &&
- args.fContext->contextPriv().caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
- colorType = kRGBA_F16_SkColorType;
- }
-
- SkBitmap bitmap;
- shader.getGradientTableBitmap(xformedColors.fColors, &bitmap, colorType);
- SkASSERT(1 == bitmap.height() && SkIsPow2(bitmap.width()));
- SkASSERT(kPremul_SkAlphaType == bitmap.alphaType());
- SkASSERT(bitmap.isImmutable());
-
- // We always filter the gradient table. Each table is one row of a texture, always
- // y-clamp.
- GrSamplerState samplerState(args.fWrapMode, GrSamplerState::Filter::kBilerp);
-
- // We know the samplerState state is:
- // clampY, bilerp
- // and the proxy is:
- // exact fit, power of two in both dimensions
- // Only the x-tileMode is unknown. However, given all the other knowns we know
- // that GrMakeCachedImageProxy is sufficient (i.e., it won't need to be
- // extracted to a subset or mipmapped).
-
- sk_sp<SkImage> srcImage = SkImage::MakeFromBitmap(bitmap);
- if (!srcImage) {
- return;
- }
-
- sk_sp<GrTextureProxy> proxy = GrMakeCachedImageProxy(
- args.fContext->contextPriv().proxyProvider(),
- std::move(srcImage));
- if (!proxy) {
- SkDebugf("Gradient won't draw. Could not create texture.");
- return;
- }
- // Auto-normalization is disabled because the gradient T is 0..1
- fCoordTransform.reset(*args.fMatrix, proxy.get(), false);
- fTextureSampler.reset(std::move(proxy), samplerState);
- SkASSERT(1 == bitmap.height());
-
- this->setTextureSamplerCnt(1);
- }
-
- this->addCoordTransform(&fCoordTransform);
-}
-
-GrGradientEffect::GrGradientEffect(const GrGradientEffect& that)
- : INHERITED(that.classID(), OptFlags(that.fIsOpaque))
- , fIntervals(that.fIntervals)
- , fWrapMode(that.fWrapMode)
- , fCoordTransform(that.fCoordTransform)
- , fTextureSampler(that.fTextureSampler)
- , fIsOpaque(that.fIsOpaque)
- , fStrategy(that.fStrategy)
- , fThreshold(that.fThreshold)
- , fPremulType(that.fPremulType) {
- this->addCoordTransform(&fCoordTransform);
- if (fStrategy == InterpolationStrategy::kTexture) {
- this->setTextureSamplerCnt(1);
- }
-}
-
-bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
- const GrGradientEffect& ge = processor.cast<GrGradientEffect>();
-
- if (fWrapMode != ge.fWrapMode || fStrategy != ge.fStrategy) {
- return false;
- }
-
- if (fStrategy == InterpolationStrategy::kTexture) {
- if (fTextureSampler != ge.fTextureSampler) {
- return false;
- }
- } else {
- if (fThreshold != ge.fThreshold ||
- fIntervals != ge.fIntervals ||
- fPremulType != ge.fPremulType) {
- return false;
- }
- }
- return true;
-}
-
-#if GR_TEST_UTILS
-GrGradientEffect::RandomGradientParams::RandomGradientParams(SkRandom* random) {
- // Set color count to min of 2 so that we don't trigger the const color optimization and make
- // a non-gradient processor.
- fColorCount = random->nextRangeU(2, kMaxRandomGradientColors);
- fUseColors4f = random->nextBool();
-
- // if one color, omit stops, otherwise randomly decide whether or not to
- if (fColorCount == 1 || (fColorCount >= 2 && random->nextBool())) {
- fStops = nullptr;
- } else {
- fStops = fStopStorage;
- }
-
- // if using SkColor4f, attach a random (possibly null) color space (with linear gamma)
- if (fUseColors4f) {
- fColorSpace = GrTest::TestColorSpace(random);
- }
-
- SkScalar stop = 0.f;
- for (int i = 0; i < fColorCount; ++i) {
- if (fUseColors4f) {
- fColors4f[i].fR = random->nextUScalar1();
- fColors4f[i].fG = random->nextUScalar1();
- fColors4f[i].fB = random->nextUScalar1();
- fColors4f[i].fA = random->nextUScalar1();
- } else {
- fColors[i] = random->nextU();
- }
- if (fStops) {
- fStops[i] = stop;
- stop = i < fColorCount - 1 ? stop + random->nextUScalar1() * (1.f - stop) : 1.f;
- }
- }
- fTileMode = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileModeCount));
-}
-#endif
-
-#endif
diff --git a/src/shaders/gradients/SkGradientShaderPriv.h b/src/shaders/gradients/SkGradientShaderPriv.h
index bd31190..c9efe50 100644
--- a/src/shaders/gradients/SkGradientShaderPriv.h
+++ b/src/shaders/gradients/SkGradientShaderPriv.h
@@ -64,8 +64,6 @@
bool isOpaque() const override;
- void getGradientTableBitmap(const SkColor4f* colors, SkBitmap*, SkColorType) const;
-
uint32_t getGradFlags() const { return fGradFlags; }
const SkMatrix& getGradientMatrix() const { return fPtsToUnit; }
@@ -80,8 +78,6 @@
bool onAsLuminanceColor(SkColor*) const override;
- void initLinearBitmap(const SkColor4f* colors, SkBitmap* bitmap, SkColorType colorType) const;
-
bool onAppendStages(const StageRec&) const override;
virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
@@ -147,224 +143,4 @@
SkSTArray<4, SkColor4f, true> fStorage;
};
-///////////////////////////////////////////////////////////////////////////////
-
-#if SK_SUPPORT_GPU
-
-#include "GrColorSpaceInfo.h"
-#include "GrCoordTransform.h"
-#include "GrFragmentProcessor.h"
-#include "glsl/GrGLSLFragmentProcessor.h"
-#include "glsl/GrGLSLProgramDataManager.h"
-
-class GrInvariantOutput;
-class GrTextureStripAtlas;
-
-/*
- * The interpretation of the texture matrix depends on the sample mode. The
- * texture matrix is applied both when the texture coordinates are explicit
- * and when vertex positions are used as texture coordinates. In the latter
- * case the texture matrix is applied to the pre-view-matrix position
- * values.
- *
- * Normal SampleMode
- * The post-matrix texture coordinates are in normalize space with (0,0) at
- * the top-left and (1,1) at the bottom right.
- * RadialGradient
- * The matrix specifies the radial gradient parameters.
- * (0,0) in the post-matrix space is center of the radial gradient.
- * Radial2Gradient
- * Matrix transforms to space where first circle is centered at the
- * origin. The second circle will be centered (x, 0) where x may be
- * 0 and is provided by setRadial2Params. The post-matrix space is
- * normalized such that 1 is the second radius - first radius.
- * SweepGradient
- * The angle from the origin of texture coordinates in post-matrix space
- * determines the gradient value.
- */
-
-// Base class for Gr gradient effects
-class GrGradientEffect : public GrFragmentProcessor {
-public:
- struct CreateArgs {
- CreateArgs(GrContext* context,
- const SkGradientShaderBase* shader,
- const SkMatrix* matrix,
- SkShader::TileMode tileMode,
- const GrColorSpaceInfo* dstColorSpaceInfo)
- : fContext(context)
- , fShader(shader)
- , fMatrix(matrix)
- , fDstColorSpaceInfo(dstColorSpaceInfo) {
- switch (tileMode) {
- case SkShader::kClamp_TileMode:
- fWrapMode = GrSamplerState::WrapMode::kClamp;
- break;
- case SkShader::kRepeat_TileMode:
- fWrapMode = GrSamplerState::WrapMode::kRepeat;
- break;
- case SkShader::kMirror_TileMode:
- fWrapMode = GrSamplerState::WrapMode::kMirrorRepeat;
- break;
- case SkShader::kDecal_TileMode:
- // TODO: actually support decal
- fWrapMode = GrSamplerState::WrapMode::kClamp;
- break;
- }
- }
-
- CreateArgs(GrContext* context,
- const SkGradientShaderBase* shader,
- const SkMatrix* matrix,
- GrSamplerState::WrapMode wrapMode,
- const GrColorSpaceInfo* dstColorSpaceInfo)
- : fContext(context)
- , fShader(shader)
- , fMatrix(matrix)
- , fWrapMode(wrapMode)
- , fDstColorSpaceInfo(dstColorSpaceInfo) {}
-
- GrContext* fContext;
- const SkGradientShaderBase* fShader;
- const SkMatrix* fMatrix;
- GrSamplerState::WrapMode fWrapMode;
- const GrColorSpaceInfo* fDstColorSpaceInfo;
- };
-
- class GLSLProcessor;
-
- // Controls the implementation strategy for this effect.
- // NB: all entries need to be reflected in the key.
- enum class InterpolationStrategy : uint8_t {
- kSingle, // interpolation in a single domain [0,1]
- kThreshold, // interpolation in two domains [0,T) [T,1], with normal clamping
- kThresholdClamp0, // same as kThreshold, but clamped only on the left edge
- kThresholdClamp1, // same as kThreshold, but clamped only on the right edge
- kTexture, // texture-based fallback
- };
-
- enum PremulType {
- kBeforeInterp_PremulType,
- kAfterInterp_PremulType,
- };
-
-protected:
- GrGradientEffect(ClassID classID, const CreateArgs&, bool isOpaque);
- explicit GrGradientEffect(const GrGradientEffect&); // facilitates clone() implementations
-
- void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
-
- // Helper function used by derived class factories to handle modulation by input alpha.
- static std::unique_ptr<GrFragmentProcessor> AdjustFP(
- std::unique_ptr<GrGradientEffect> gradientFP, const CreateArgs& args) {
- if (!gradientFP->isValid()) {
- return nullptr;
- }
- return GrFragmentProcessor::MulChildByInputAlpha(std::move(gradientFP));
- }
-
-#if GR_TEST_UTILS
- /** Helper struct that stores (and populates) parameters to construct a random gradient.
- If fUseColors4f is true, then the SkColor4f factory should be called, with fColors4f and
- fColorSpace. Otherwise, the SkColor factory should be called, with fColors. fColorCount
- will be the number of color stops in either case, and fColors and fStops can be passed to
- the gradient factory. (The constructor may decide not to use stops, in which case fStops
- will be nullptr). */
- struct RandomGradientParams {
- static constexpr int kMaxRandomGradientColors = 5;
-
- RandomGradientParams(SkRandom* r);
-
- bool fUseColors4f;
- SkColor fColors[kMaxRandomGradientColors];
- SkColor4f fColors4f[kMaxRandomGradientColors];
- sk_sp<SkColorSpace> fColorSpace;
- SkScalar fStopStorage[kMaxRandomGradientColors];
- SkShader::TileMode fTileMode;
- int fColorCount;
- SkScalar* fStops;
- };
- #endif
-
- bool onIsEqual(const GrFragmentProcessor&) const override;
-
- const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
-
- /** Checks whether the constructor failed to fully initialize the processor. */
- bool isValid() const {
- return fStrategy != InterpolationStrategy::kTexture || fTextureSampler.isInitialized();
- }
-
-private:
- void addInterval(const SkGradientShaderBase&, const SkColor4f* colors,
- size_t idx0, size_t idx1);
-
- const TextureSampler& onTextureSampler(int i) const override { return fTextureSampler; }
-
- static OptimizationFlags OptFlags(bool isOpaque);
-
- // Interpolation intervals, encoded as 4f tuples of (scale, bias)
- // such that color(t) = t * scale + bias.
- SkSTArray<4, GrColor4f, true> fIntervals;
-
- GrSamplerState::WrapMode fWrapMode;
-
- GrCoordTransform fCoordTransform;
- TextureSampler fTextureSampler;
- bool fIsOpaque;
-
- InterpolationStrategy fStrategy;
- SkScalar fThreshold; // used for InterpolationStrategy::kThreshold
- PremulType fPremulType; // This is already baked into the table for texture
- // gradients, and only changes behavior for gradients
- // that don't use a texture.
-
- typedef GrFragmentProcessor INHERITED;
-
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Base class for GL gradient effects
-class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor {
-public:
- static uint32_t GenBaseGradientKey(const GrProcessor&);
-
-protected:
- void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
-
- // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
- // should call this method from their emitCode().
- void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&);
-
- // Emit code that gets a fragment's color from an expression for t; has branches for
- // several control flows inside -- 2-color gradients, 3-color symmetric gradients, 4+
- // color gradients that use the traditional texture lookup, as well as several varieties
- // of hard stop gradients
- void emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
- GrGLSLUniformHandler* uniformHandler,
- const GrShaderCaps* shaderCaps,
- const GrGradientEffect&,
- const char* gradientTValue,
- const char* outputColor,
- const char* inputColor,
- const TextureSamplers&);
-
-private:
- void emitAnalyticalColor(GrGLSLFPFragmentBuilder* fragBuilder,
- GrGLSLUniformHandler* uniformHandler,
- const GrShaderCaps* shaderCaps,
- const GrGradientEffect&,
- const char* gradientTValue,
- const char* outputColor,
- const char* inputColor);
-
- GrGLSLProgramDataManager::UniformHandle fIntervalsUni;
- GrGLSLProgramDataManager::UniformHandle fThresholdUni;
-
- typedef GrGLSLFragmentProcessor INHERITED;
-};
-
-#endif
-
#endif
diff --git a/src/shaders/gradients/SkLinearGradient.cpp b/src/shaders/gradients/SkLinearGradient.cpp
index 57ad3c5..d41f375 100644
--- a/src/shaders/gradients/SkLinearGradient.cpp
+++ b/src/shaders/gradients/SkLinearGradient.cpp
@@ -93,126 +93,15 @@
return kLinear_GradientType;
}
-#if SK_SUPPORT_GPU
+/////////////////////////////////////////////////////////////////////
-#include "GrShaderCaps.h"
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-#include "SkGr.h"
+#if SK_SUPPORT_GPU
#include "gradients/GrGradientShader.h"
-/////////////////////////////////////////////////////////////////////
-
-class GrLinearGradient : public GrGradientEffect {
-public:
- class GLSLLinearProcessor;
-
- static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args) {
- return GrGradientEffect::AdjustFP(std::unique_ptr<GrLinearGradient>(
- new GrLinearGradient(args)),
- args);
- }
-
- const char* name() const override { return "Linear Gradient"; }
-
- std::unique_ptr<GrFragmentProcessor> clone() const override {
- return std::unique_ptr<GrFragmentProcessor>(new GrLinearGradient(*this));
- }
-
-private:
- explicit GrLinearGradient(const CreateArgs& args)
- : INHERITED(kGrLinearGradient_ClassID, args, args.fShader->colorsAreOpaque()) {
- }
-
- explicit GrLinearGradient(const GrLinearGradient& that) : INHERITED(that) {}
-
- GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
-
- GR_DECLARE_FRAGMENT_PROCESSOR_TEST
-
- typedef GrGradientEffect INHERITED;
-};
-
-/////////////////////////////////////////////////////////////////////
-
-class GrLinearGradient::GLSLLinearProcessor : public GrGradientEffect::GLSLProcessor {
-public:
- GLSLLinearProcessor(const GrProcessor&) {}
-
- virtual void emitCode(EmitArgs&) override;
-
-private:
- typedef GrGradientEffect::GLSLProcessor INHERITED;
-};
-
-/////////////////////////////////////////////////////////////////////
-
-GrGLSLFragmentProcessor* GrLinearGradient::onCreateGLSLInstance() const {
- return new GrLinearGradient::GLSLLinearProcessor(*this);
-}
-
-/////////////////////////////////////////////////////////////////////
-
-GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrLinearGradient);
-
-#if GR_TEST_UTILS
-std::unique_ptr<GrFragmentProcessor> GrLinearGradient::TestCreate(GrProcessorTestData* d) {
- SkPoint points[] = {{d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()},
- {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()}};
-
- RandomGradientParams params(d->fRandom);
- auto shader = params.fUseColors4f ?
- SkGradientShader::MakeLinear(points, params.fColors4f, params.fColorSpace, params.fStops,
- params.fColorCount, params.fTileMode) :
- SkGradientShader::MakeLinear(points, params.fColors, params.fStops,
- params.fColorCount, params.fTileMode);
- GrTest::TestAsFPArgs asFPArgs(d);
- std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
- GrAlwaysAssert(fp);
- return fp;
-}
-#endif
-
-/////////////////////////////////////////////////////////////////////
-
-void GrLinearGradient::GLSLLinearProcessor::emitCode(EmitArgs& args) {
- const GrLinearGradient& ge = args.fFp.cast<GrLinearGradient>();
- this->emitUniforms(args.fUniformHandler, ge);
- SkString t = args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
- t.append(".x");
- this->emitColor(args.fFragBuilder,
- args.fUniformHandler,
- args.fShaderCaps,
- ge,
- t.c_str(),
- args.fOutputColor,
- args.fInputColor,
- args.fTexSamplers);
-}
-
-/////////////////////////////////////////////////////////////////////
-
std::unique_ptr<GrFragmentProcessor> SkLinearGradient::asFragmentProcessor(
const GrFPArgs& args) const {
- SkASSERT(args.fContext);
-
- // Try to use new gradient system first
- std::unique_ptr<GrFragmentProcessor> gradient = GrGradientShader::MakeLinear(*this, args);
- if (gradient) {
- return gradient;
- }
-
- SkMatrix matrix;
- if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
- return nullptr;
- }
- matrix.postConcat(fPtsToUnit);
-
- return GrLinearGradient::Make(GrGradientEffect::CreateArgs(
- args.fContext, this, &matrix, fTileMode, args.fDstColorSpaceInfo));
+ return GrGradientShader::MakeLinear(*this, args);
}
-
#endif
-
-
diff --git a/src/shaders/gradients/SkRadialGradient.cpp b/src/shaders/gradients/SkRadialGradient.cpp
index 9d86162..7209486 100644
--- a/src/shaders/gradients/SkRadialGradient.cpp
+++ b/src/shaders/gradients/SkRadialGradient.cpp
@@ -59,129 +59,6 @@
buffer.writeScalar(fRadius);
}
-/////////////////////////////////////////////////////////////////////
-
-#if SK_SUPPORT_GPU
-
-#include "SkGr.h"
-#include "GrShaderCaps.h"
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-
-#include "gradients/GrGradientShader.h"
-
-class GrRadialGradient : public GrGradientEffect {
-public:
- class GLSLRadialProcessor;
-
- static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args) {
- return GrGradientEffect::AdjustFP(std::unique_ptr<GrRadialGradient>(
- new GrRadialGradient(args)),
- args);
- }
-
- const char* name() const override { return "Radial Gradient"; }
-
- std::unique_ptr<GrFragmentProcessor> clone() const override {
- return std::unique_ptr<GrFragmentProcessor>(new GrRadialGradient(*this));
- }
-
-private:
- explicit GrRadialGradient(const CreateArgs& args)
- : INHERITED(kGrRadialGradient_ClassID, args, args.fShader->colorsAreOpaque()) {}
-
- explicit GrRadialGradient(const GrRadialGradient& that) : INHERITED(that) {}
-
- GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
-
- GR_DECLARE_FRAGMENT_PROCESSOR_TEST
-
- typedef GrGradientEffect INHERITED;
-};
-
-/////////////////////////////////////////////////////////////////////
-
-class GrRadialGradient::GLSLRadialProcessor : public GrGradientEffect::GLSLProcessor {
-public:
- GLSLRadialProcessor(const GrProcessor&) {}
-
- virtual void emitCode(EmitArgs&) override;
-
-private:
- typedef GrGradientEffect::GLSLProcessor INHERITED;
-
-};
-
-/////////////////////////////////////////////////////////////////////
-
-GrGLSLFragmentProcessor* GrRadialGradient::onCreateGLSLInstance() const {
- return new GrRadialGradient::GLSLRadialProcessor(*this);
-}
-
-/////////////////////////////////////////////////////////////////////
-
-GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRadialGradient);
-
-#if GR_TEST_UTILS
-std::unique_ptr<GrFragmentProcessor> GrRadialGradient::TestCreate(GrProcessorTestData* d) {
- sk_sp<SkShader> shader;
- do {
- RandomGradientParams params(d->fRandom);
- SkPoint center = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
- SkScalar radius = d->fRandom->nextUScalar1();
- shader = params.fUseColors4f
- ? SkGradientShader::MakeRadial(center, radius, params.fColors4f,
- params.fColorSpace, params.fStops,
- params.fColorCount, params.fTileMode)
- : SkGradientShader::MakeRadial(center, radius, params.fColors,
- params.fStops, params.fColorCount,
- params.fTileMode);
- } while (!shader);
- GrTest::TestAsFPArgs asFPArgs(d);
- std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
- GrAlwaysAssert(fp);
- return fp;
-}
-#endif
-
-/////////////////////////////////////////////////////////////////////
-
-void GrRadialGradient::GLSLRadialProcessor::emitCode(EmitArgs& args) {
- const GrRadialGradient& ge = args.fFp.cast<GrRadialGradient>();
- this->emitUniforms(args.fUniformHandler, ge);
- SkString t("length(");
- t.append(args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]));
- t.append(")");
- this->emitColor(args.fFragBuilder,
- args.fUniformHandler,
- args.fShaderCaps,
- ge, t.c_str(),
- args.fOutputColor,
- args.fInputColor,
- args.fTexSamplers);
-}
-
-/////////////////////////////////////////////////////////////////////
-
-std::unique_ptr<GrFragmentProcessor> SkRadialGradient::asFragmentProcessor(
- const GrFPArgs& args) const {
- // Try to use new gradient system first
- std::unique_ptr<GrFragmentProcessor> gradient = GrGradientShader::MakeRadial(*this, args);
- if (gradient) {
- return gradient;
- }
-
- SkMatrix matrix;
- if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
- return nullptr;
- }
- matrix.postConcat(fPtsToUnit);
-
- return GrRadialGradient::Make(GrGradientEffect::CreateArgs(
- args.fContext, this, &matrix, fTileMode, args.fDstColorSpaceInfo));
-}
-
-#endif
-
sk_sp<SkShader> SkRadialGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
const AutoXformColors xformedColors(*this, xformer);
return SkGradientShader::MakeRadial(fCenter, fRadius, xformedColors.fColors.get(), fOrigPos,
@@ -193,3 +70,16 @@
SkRasterPipeline*) const {
p->append(SkRasterPipeline::xy_to_radius);
}
+
+/////////////////////////////////////////////////////////////////////
+
+#if SK_SUPPORT_GPU
+
+#include "gradients/GrGradientShader.h"
+
+std::unique_ptr<GrFragmentProcessor> SkRadialGradient::asFragmentProcessor(
+ const GrFPArgs& args) const {
+ return GrGradientShader::MakeRadial(*this, args);
+}
+
+#endif
diff --git a/src/shaders/gradients/SkSweepGradient.cpp b/src/shaders/gradients/SkSweepGradient.cpp
index a37dc8f..d36c5ba 100644
--- a/src/shaders/gradients/SkSweepGradient.cpp
+++ b/src/shaders/gradients/SkSweepGradient.cpp
@@ -63,182 +63,6 @@
buffer.writeScalar(fTScale);
}
-/////////////////////////////////////////////////////////////////////
-
-#if SK_SUPPORT_GPU
-
-#include "SkGr.h"
-#include "GrShaderCaps.h"
-#include "gl/GrGLContext.h"
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-
-#include "gradients/GrGradientShader.h"
-
-class GrSweepGradient : public GrGradientEffect {
-public:
- class GLSLSweepProcessor;
-
- static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar tBias,
- SkScalar tScale) {
- return GrGradientEffect::AdjustFP(std::unique_ptr<GrSweepGradient>(
- new GrSweepGradient(args, tBias, tScale)),
- args);
- }
-
- const char* name() const override { return "Sweep Gradient"; }
-
- std::unique_ptr<GrFragmentProcessor> clone() const override {
- return std::unique_ptr<GrFragmentProcessor>(new GrSweepGradient(*this));
- }
-
-private:
- explicit GrSweepGradient(const CreateArgs& args, SkScalar tBias, SkScalar tScale)
- : INHERITED(kGrSweepGradient_ClassID, args, args.fShader->colorsAreOpaque())
- , fTBias(tBias)
- , fTScale(tScale) {}
-
- explicit GrSweepGradient(const GrSweepGradient& that)
- : INHERITED(that)
- , fTBias(that.fTBias)
- , fTScale(that.fTScale) {}
-
- GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
-
- bool onIsEqual(const GrFragmentProcessor& base) const override {
- const GrSweepGradient& fp = base.cast<GrSweepGradient>();
- return INHERITED::onIsEqual(base)
- && fTBias == fp.fTBias
- && fTScale == fp.fTScale;
- }
-
- GR_DECLARE_FRAGMENT_PROCESSOR_TEST
-
- SkScalar fTBias;
- SkScalar fTScale;
-
- typedef GrGradientEffect INHERITED;
-};
-
-/////////////////////////////////////////////////////////////////////
-
-class GrSweepGradient::GLSLSweepProcessor : public GrGradientEffect::GLSLProcessor {
-public:
- GLSLSweepProcessor(const GrProcessor&)
- : fCachedTBias(SK_FloatNaN)
- , fCachedTScale(SK_FloatNaN) {}
-
- void emitCode(EmitArgs&) override;
-
-protected:
- void onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& processor) override {
- INHERITED::onSetData(pdman, processor);
- const GrSweepGradient& data = processor.cast<GrSweepGradient>();
-
- if (fCachedTBias != data.fTBias || fCachedTScale != data.fTScale) {
- fCachedTBias = data.fTBias;
- fCachedTScale = data.fTScale;
- pdman.set2f(fTBiasScaleUni, fCachedTBias, fCachedTScale);
- }
- }
-
-private:
- UniformHandle fTBiasScaleUni;
-
- // Uploaded uniform values.
- float fCachedTBias,
- fCachedTScale;
-
- typedef GrGradientEffect::GLSLProcessor INHERITED;
-};
-
-/////////////////////////////////////////////////////////////////////
-
-GrGLSLFragmentProcessor* GrSweepGradient::onCreateGLSLInstance() const {
- return new GrSweepGradient::GLSLSweepProcessor(*this);
-}
-
-/////////////////////////////////////////////////////////////////////
-
-GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSweepGradient);
-
-#if GR_TEST_UTILS
-std::unique_ptr<GrFragmentProcessor> GrSweepGradient::TestCreate(GrProcessorTestData* d) {
- SkPoint center = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
-
- RandomGradientParams params(d->fRandom);
- auto shader = params.fUseColors4f ?
- SkGradientShader::MakeSweep(center.fX, center.fY, params.fColors4f, params.fColorSpace,
- params.fStops, params.fColorCount) :
- SkGradientShader::MakeSweep(center.fX, center.fY, params.fColors,
- params.fStops, params.fColorCount);
- GrTest::TestAsFPArgs asFPArgs(d);
- std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
- GrAlwaysAssert(fp);
- return fp;
-}
-#endif
-
-/////////////////////////////////////////////////////////////////////
-
-void GrSweepGradient::GLSLSweepProcessor::emitCode(EmitArgs& args) {
- const GrSweepGradient& ge = args.fFp.cast<GrSweepGradient>();
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
- this->emitUniforms(uniformHandler, ge);
- fTBiasScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
- "SweepFSParams");
- const char* tBiasScaleV = uniformHandler->getUniformCStr(fTBiasScaleUni);
-
- const SkString coords2D = args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
-
- // On some devices they incorrectly implement atan2(y,x) as atan(y/x). In actuality it is
- // atan2(y,x) = 2 * atan(y / (sqrt(x^2 + y^2) + x)). So to work around this we pass in
- // (sqrt(x^2 + y^2) + x) as the second parameter to atan2 in these cases. We let the device
- // handle the undefined behavior of the second paramenter being 0 instead of doing the
- // divide ourselves and using atan instead.
- const SkString atan = args.fShaderCaps->atan2ImplementedAsAtanYOverX()
- ? SkStringPrintf("2.0 * atan(- %s.y, length(%s) - %s.x)",
- coords2D.c_str(), coords2D.c_str(), coords2D.c_str())
- : SkStringPrintf("atan(- %s.y, - %s.x)", coords2D.c_str(), coords2D.c_str());
-
- // 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi]
- const SkString t = SkStringPrintf("((%s * 0.1591549430918 + 0.5 + %s[0]) * %s[1])",
- atan.c_str(), tBiasScaleV, tBiasScaleV);
-
- this->emitColor(args.fFragBuilder,
- args.fUniformHandler,
- args.fShaderCaps,
- ge, t.c_str(),
- args.fOutputColor,
- args.fInputColor,
- args.fTexSamplers);
-}
-
-/////////////////////////////////////////////////////////////////////
-
-std::unique_ptr<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor(
- const GrFPArgs& args) const {
-
- // Try to use new gradient system first
- std::unique_ptr<GrFragmentProcessor> gradient = GrGradientShader::MakeSweep(*this, args);
- if (gradient) {
- return gradient;
- }
-
- SkMatrix matrix;
- if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
- return nullptr;
- }
- matrix.postConcat(fPtsToUnit);
-
- return GrSweepGradient::Make(
- GrGradientEffect::CreateArgs(args.fContext, this, &matrix, fTileMode,
- args.fDstColorSpaceInfo),
- fTBias, fTScale);
-}
-
-#endif
-
sk_sp<SkShader> SkSweepGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
const AutoXformColors xformedColors(*this, xformer);
@@ -257,3 +81,15 @@
SkMatrix::MakeTrans(fTBias , 0)));
}
+/////////////////////////////////////////////////////////////////////
+
+#if SK_SUPPORT_GPU
+
+#include "gradients/GrGradientShader.h"
+
+std::unique_ptr<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor(
+ const GrFPArgs& args) const {
+ return GrGradientShader::MakeSweep(*this, args);
+}
+
+#endif
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.cpp b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
index 41b89a8..b605af3 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
@@ -176,33 +176,6 @@
buffer.writeScalar(fRadius2);
}
-#if SK_SUPPORT_GPU
-
-#include "SkGr.h"
-#include "SkTwoPointConicalGradient_gpu.h"
-
-#include "gradients/GrGradientShader.h"
-
-std::unique_ptr<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProcessor(
- const GrFPArgs& args) const {
- // Try to use new gradient system first
- std::unique_ptr<GrFragmentProcessor> gradient = GrGradientShader::MakeConical(*this, args);
- if (gradient) {
- return gradient;
- }
-
- SkMatrix matrix;
- if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
- return nullptr;
- }
-
- return Gr2PtConicalGradientEffect::Make(
- GrGradientEffect::CreateArgs(args.fContext, this, &matrix, fTileMode,
- args.fDstColorSpaceInfo));
-}
-
-#endif
-
sk_sp<SkShader> SkTwoPointConicalGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
const AutoXformColors xformedColors(*this, xformer);
return SkGradientShader::MakeTwoPointConical(fCenter1, fRadius1, fCenter2, fRadius2,
@@ -266,3 +239,16 @@
postPipeline->append(SkRasterPipeline::apply_vector_mask, &ctx->fMask);
}
}
+
+/////////////////////////////////////////////////////////////////////
+
+#if SK_SUPPORT_GPU
+
+#include "gradients/GrGradientShader.h"
+
+std::unique_ptr<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProcessor(
+ const GrFPArgs& args) const {
+ return GrGradientShader::MakeConical(*this, args);
+}
+
+#endif
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
deleted file mode 100644
index c346f35..0000000
--- a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkTwoPointConicalGradient.h"
-
-#if SK_SUPPORT_GPU
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-#include "glsl/GrGLSLProgramDataManager.h"
-#include "glsl/GrGLSLUniformHandler.h"
-#include "SkTwoPointConicalGradient_gpu.h"
-
-// For brevity
-typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
-
-// Please see https://skia.org/dev/design/conical for how our shader works.
-class TwoPointConicalEffect : public GrGradientEffect {
-public:
- using Type = SkTwoPointConicalGradient::Type;
- class DegeneratedGLSLProcessor; // radial (center0 == center1) or strip (r0 == r1) case
- class FocalGLSLProcessor; // all other cases where we can derive a focal point
-
- struct Data {
- Type fType;
- SkScalar fRadius0;
- SkScalar fDiffRadius;
- SkTwoPointConicalGradient::FocalData fFocalData;
-
- // Construct from the shader, and set the matrix accordingly
- Data(const SkTwoPointConicalGradient& shader, SkMatrix& matrix);
-
- bool operator== (const Data& d) const {
- if (fType != d.fType) {
- return false;
- }
- switch (fType) {
- case Type::kRadial:
- case Type::kStrip:
- return fRadius0 == d.fRadius0 && fDiffRadius == d.fDiffRadius;
- case Type::kFocal:
- return fFocalData.fR1 == d.fFocalData.fR1 &&
- fFocalData.fFocalX == d.fFocalData.fFocalX &&
- fFocalData.fIsSwapped == d.fFocalData.fIsSwapped;
- }
- SkDEBUGFAIL("This return should be unreachable; it's here just for compile warning");
- return false;
- }
- };
-
- static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args, const Data& data);
-
- SkScalar diffRadius() const {
- SkASSERT(!this->isFocal()); // fDiffRadius is uninitialized for focal cases
- return fData.fDiffRadius;
- }
- SkScalar r0() const {
- SkASSERT(!this->isFocal()); // fRadius0 is uninitialized for focal cases
- return fData.fRadius0;
- }
-
- SkScalar r1() const {
- SkASSERT(this->isFocal()); // fFocalData is uninitialized for non-focal cases
- return fData.fFocalData.fR1;
- }
- SkScalar focalX() const {
- SkASSERT(this->isFocal()); // fFocalData is uninitialized for non-focal cases
- return fData.fFocalData.fFocalX;
- }
-
- const char* name() const override { return "Two-Point Conical Gradient"; }
-
- // Whether the focal point (0, 0) is on the end circle with center (1, 0) and radius r1. If this
- // is true, it's as if an aircraft is flying at Mach 1 and all circles (soundwaves) will go
- // through the focal point (aircraft). In our previous implementations, this was known as the
- // edge case where the inside circle touches the outside circle (on the focal point). If we were
- // to solve for t bruteforcely using a quadratic equation, this case implies that the quadratic
- // equation degenerates to a linear equation.
- bool isFocalOnCircle() const { return this->isFocal() && fData.fFocalData.isFocalOnCircle(); }
- bool isSwapped() const { return this->isFocal() && fData.fFocalData.isSwapped(); }
-
- Type getType() const { return fData.fType; }
- bool isFocal() const { return fData.fType == Type::kFocal; }
-
- // Whether the t we solved is always valid (so we don't need to check r(t) > 0).
- bool isWellBehaved() const { return this->isFocal() && fData.fFocalData.isWellBehaved(); }
-
- // Whether r0 == 0 so it's focal without any transformation
- bool isNativelyFocal() const { return this->isFocal() && fData.fFocalData.isNativelyFocal(); }
-
- // Note that focalX = f = r0 / (r0 - r1), so 1 - focalX > 0 == r0 < r1
- bool isRadiusIncreasing() const {
- return this->isFocal() ? 1 - fData.fFocalData.fFocalX > 0 : this->diffRadius() > 0;
- }
-
-protected:
- void onGetGLSLProcessorKey(const GrShaderCaps& c, GrProcessorKeyBuilder* b) const override {
- INHERITED::onGetGLSLProcessorKey(c, b);
- uint32_t key = 0;
- key |= static_cast<int>(fData.fType);
- SkASSERT(key < (1 << 2));
- key |= (this->isFocalOnCircle() << 2);
- key |= (this->isWellBehaved() << 3);
- key |= (this->isRadiusIncreasing() << 4);
- key |= (this->isNativelyFocal() << 5);
- key |= (this->isSwapped() << 6);
- SkASSERT(key < (1 << 7));
- b->add32(key);
- }
-
-
- GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
-
- std::unique_ptr<GrFragmentProcessor> clone() const override {
- return std::unique_ptr<GrFragmentProcessor>(new TwoPointConicalEffect(*this));
- }
-
- bool onIsEqual(const GrFragmentProcessor& sBase) const override {
- const TwoPointConicalEffect& s = sBase.cast<TwoPointConicalEffect>();
- return (INHERITED::onIsEqual(sBase) && fData == s.fData);
- }
-
- explicit TwoPointConicalEffect(const CreateArgs& args, const Data data)
- : INHERITED(kTwoPointConicalEffect_ClassID, args,
- false /* opaque: draws transparent black outside of the cone. */)
- , fData(data) {}
-
- explicit TwoPointConicalEffect(const TwoPointConicalEffect& that)
- : INHERITED(that)
- , fData(that.fData) {}
-
- GR_DECLARE_FRAGMENT_PROCESSOR_TEST
-
- Data fData;
-
- typedef GrGradientEffect INHERITED;
-};
-
-GR_DEFINE_FRAGMENT_PROCESSOR_TEST(TwoPointConicalEffect);
-
-#if GR_TEST_UTILS
-
-std::unique_ptr<GrFragmentProcessor> TwoPointConicalEffect::TestCreate(
- GrProcessorTestData* d) {
- SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
- SkPoint center2 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
- SkScalar radius1 = d->fRandom->nextUScalar1();
- SkScalar radius2 = d->fRandom->nextUScalar1();
-
- constexpr int kTestTypeMask = (1 << 2) - 1,
- kTestNativelyFocalBit = (1 << 2),
- kTestFocalOnCircleBit = (1 << 3),
- kTestSwappedBit = (1 << 4);
- // We won't treat isWellDefined and isRadiusIncreasing specially beacuse they
- // should have high probability to be turned on and off as we're getting random
- // radii and centers.
-
- int mask = d->fRandom->nextU();
- int type = mask & kTestTypeMask;
- if (type == static_cast<int>(TwoPointConicalEffect::Type::kRadial)) {
- center2 = center1;
- // Make sure that the radii are different
- if (SkScalarNearlyZero(radius1 - radius2)) {
- radius2 += .1f;
- }
- } else if (type == static_cast<int>(TwoPointConicalEffect::Type::kStrip)) {
- radius1 = SkTMax(radius1, .1f); // Make sure that the radius is non-zero
- radius2 = radius1;
- // Make sure that the centers are different
- if (SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
- center2.fX += .1f;
- }
- } else { // kFocal_Type
- // Make sure that the centers are different
- if (SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
- center2.fX += .1f;
- }
-
- if (kTestNativelyFocalBit & mask) {
- radius1 = 0;
- }
- if (kTestFocalOnCircleBit & mask) {
- radius2 = radius1 + SkPoint::Distance(center1, center2);
- }
- if (kTestSwappedBit & mask) {
- std::swap(radius1, radius2);
- radius2 = 0;
- }
-
- // Make sure that the radii are different
- if (SkScalarNearlyZero(radius1 - radius2)) {
- radius2 += .1f;
- }
- }
-
- if (SkScalarNearlyZero(radius1 - radius2) &&
- SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
- radius2 += .1f; // make sure that we're not degenerated
- }
-
- RandomGradientParams params(d->fRandom);
- auto shader = params.fUseColors4f ?
- SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
- params.fColors4f, params.fColorSpace, params.fStops,
- params.fColorCount, params.fTileMode) :
- SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
- params.fColors, params.fStops,
- params.fColorCount, params.fTileMode);
- GrTest::TestAsFPArgs asFPArgs(d);
- std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
-
- GrAlwaysAssert(fp);
- return fp;
-}
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-// DegeneratedGLSLProcessor
-//////////////////////////////////////////////////////////////////////////////
-
-class TwoPointConicalEffect::DegeneratedGLSLProcessor : public GrGradientEffect::GLSLProcessor {
-protected:
- void emitCode(EmitArgs& args) override {
- const TwoPointConicalEffect& effect = args.fFp.cast<TwoPointConicalEffect>();
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
- this->emitUniforms(uniformHandler, effect);
- fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
- "Conical2FSParams");
-
- SkString p0; // r0 for radial case, r0^2 for strip case
- p0.appendf("%s", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
- const char* tName = "t"; // the gradient
-
- GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
- SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
- const char* p = coords2D.c_str();
-
- if (effect.getType() == Type::kRadial) {
- char sign = effect.isRadiusIncreasing() ? '+' : '-';
- fragBuilder->codeAppendf("half %s = %clength(%s) - %s;", tName, sign, p, p0.c_str());
- } else {
- // output will default to transparent black (we simply won't write anything
- // else to it if invalid, instead of discarding or returning prematurely)
- fragBuilder->codeAppendf("%s = half4(0.0,0.0,0.0,0.0);", args.fOutputColor);
- fragBuilder->codeAppendf("half temp = %s - %s.y * %s.y;", p0.c_str(), p, p);
- fragBuilder->codeAppendf("if (temp >= 0) {");
- fragBuilder->codeAppendf("half %s = %s.x + sqrt(temp);", tName, p);
- }
- this->emitColor(fragBuilder,
- uniformHandler,
- args.fShaderCaps,
- effect,
- tName,
- args.fOutputColor,
- args.fInputColor,
- args.fTexSamplers);
-
- if (effect.getType() != Type::kRadial) {
- fragBuilder->codeAppendf("}");
- }
- }
-
- void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& p) override {
- INHERITED::onSetData(pdman, p);
- const TwoPointConicalEffect& effect = p.cast<TwoPointConicalEffect>();
- // kRadialType should imply |r1 - r0| = 1 (after our transformation)
- SkASSERT(effect.getType() == Type::kStrip ||
- SkScalarNearlyZero(SkTAbs(effect.diffRadius()) - 1));
- pdman.set1f(fParamUni, effect.getType() == Type::kRadial ? effect.r0()
- : effect.r0() * effect.r0());
- }
-
- UniformHandle fParamUni;
-
-private:
- typedef GrGradientEffect::GLSLProcessor INHERITED;
-};
-
-//////////////////////////////////////////////////////////////////////////////
-// FocalGLSLProcessor
-//////////////////////////////////////////////////////////////////////////////
-
-// Please see https://skia.org/dev/design/conical for how our shader works.
-class TwoPointConicalEffect::FocalGLSLProcessor : public GrGradientEffect::GLSLProcessor {
-protected:
- void emitCode(EmitArgs& args) override {
- const TwoPointConicalEffect& effect = args.fFp.cast<TwoPointConicalEffect>();
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
- this->emitUniforms(uniformHandler, effect);
- fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
- "Conical2FSParams");
-
- SkString p0; // 1 / r1
- SkString p1; // f = focalX = r0 / (r0 - r1)
- p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
- p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
- const char* tName = "t"; // the gradient
-
- GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
- SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
- const char* p = coords2D.c_str();
-
- if (effect.isFocalOnCircle()) {
- fragBuilder->codeAppendf("half x_t = dot(%s, %s) / %s.x;", p, p, p);
- } else if (effect.isWellBehaved()) {
- fragBuilder->codeAppendf("half x_t = length(%s) - %s.x * %s;", p, p, p0.c_str());
- } else {
- char sign = (effect.isSwapped() || !effect.isRadiusIncreasing()) ? '-' : ' ';
- fragBuilder->codeAppendf("half temp = %s.x * %s.x - %s.y * %s.y;", p, p, p, p);
- // Initialize x_t to illegal state
- fragBuilder->codeAppendf("half x_t = -1;");
-
- // Only do sqrt if temp >= 0; this is significantly slower than checking temp >= 0 in
- // the if statement that checks r(t) >= 0. But GPU may break if we sqrt a negative
- // float. (Although I havevn't observed that on any devices so far, and the old approach
- // also does sqrt negative value without a check.) If the performance is really
- // critical, maybe we should just compute the area where temp and x_t are always
- // valid and drop all these ifs.
- fragBuilder->codeAppendf("if (temp >= 0) {");
- fragBuilder->codeAppendf("x_t = (%csqrt(temp) - %s.x * %s);", sign, p, p0.c_str());
- fragBuilder->codeAppendf("}");
- }
-
- // empty sign is positive
- char sign = effect.isRadiusIncreasing() ? ' ' : '-';
-
- // "+ 0" is much faster than "+ p1" so we specialize the natively focal case where p1 = 0.
- fragBuilder->codeAppendf("half %s = %cx_t + %s;", tName, sign,
- effect.isNativelyFocal() ? "0" : p1.c_str());
-
- if (!effect.isWellBehaved()) {
- // output will default to transparent black (we simply won't write anything
- // else to it if invalid, instead of discarding or returning prematurely)
- fragBuilder->codeAppendf("%s = half4(0.0,0.0,0.0,0.0);", args.fOutputColor);
- fragBuilder->codeAppendf("if (x_t > 0.0) {");
- }
-
- if (effect.isSwapped()) {
- fragBuilder->codeAppendf("%s = 1 - %s;", tName, tName);
- }
-
- this->emitColor(fragBuilder,
- uniformHandler,
- args.fShaderCaps,
- effect,
- tName,
- args.fOutputColor,
- args.fInputColor,
- args.fTexSamplers);
- if (!effect.isWellBehaved()) {
- fragBuilder->codeAppend("};");
- }
- }
-
- void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& p) override {
- INHERITED::onSetData(pdman, p);
- const TwoPointConicalEffect& effect = p.cast<TwoPointConicalEffect>();
- pdman.set2f(fParamUni, 1 / effect.r1(), effect.focalX());
- }
-
- UniformHandle fParamUni;
-
-private:
- typedef GrGradientEffect::GLSLProcessor INHERITED;
-};
-
-//////////////////////////////////////////////////////////////////////////////
-
-GrGLSLFragmentProcessor* TwoPointConicalEffect::onCreateGLSLInstance() const {
- if (fData.fType == Type::kRadial || fData.fType == Type::kStrip) {
- return new DegeneratedGLSLProcessor;
- }
- return new FocalGLSLProcessor;
-}
-
-std::unique_ptr<GrFragmentProcessor> TwoPointConicalEffect::Make(
- const GrGradientEffect::CreateArgs& args, const Data& data) {
- return GrGradientEffect::AdjustFP(
- std::unique_ptr<TwoPointConicalEffect>(new TwoPointConicalEffect(args, data)),
- args);
-}
-
-std::unique_ptr<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
- const GrGradientEffect::CreateArgs& args) {
- const SkTwoPointConicalGradient& shader =
- *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
-
- SkMatrix matrix = *args.fMatrix;
- GrGradientEffect::CreateArgs newArgs(args.fContext, args.fShader, &matrix, args.fWrapMode,
- args.fDstColorSpaceInfo);
- // Data and matrix has to be prepared before constructing TwoPointConicalEffect so its parent
- // class can have the right matrix to work with during construction.
- TwoPointConicalEffect::Data data(shader, matrix);
- return TwoPointConicalEffect::Make(newArgs, data);
-}
-
-TwoPointConicalEffect::Data::Data(const SkTwoPointConicalGradient& shader, SkMatrix& matrix) {
- fType = shader.getType();
- if (fType == Type::kRadial) {
- // Map center to (0, 0)
- matrix.postTranslate(-shader.getStartCenter().fX, -shader.getStartCenter().fY);
-
- // scale |fDiffRadius| to 1
- SkScalar dr = shader.getDiffRadius();
- matrix.postScale(1 / dr, 1 / dr);
- fRadius0 = shader.getStartRadius() / dr;
- fDiffRadius = dr < 0 ? -1 : 1;
- } else if (fType == Type::kStrip) {
- fRadius0 = shader.getStartRadius() / shader.getCenterX1();
- fDiffRadius = 0;
- matrix.postConcat(shader.getGradientMatrix());
- } else if (fType == Type::kFocal) {
- fFocalData = shader.getFocalData();
- matrix.postConcat(shader.getGradientMatrix());
- }
-}
-
-#endif
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.h b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.h
deleted file mode 100644
index e7eac07..0000000
--- a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkTwoPointConicalGradient_gpu_DEFINED
-#define SkTwoPointConicalGradient_gpu_DEFINED
-
-#include "SkGradientShaderPriv.h"
-
-class GrProcessor;
-class SkTwoPointConicalGradient;
-
-namespace Gr2PtConicalGradientEffect {
-
-/**
- * Creates an effect that produces a two point conical gradient based on the shader passed in.
- */
-std::unique_ptr<GrFragmentProcessor> Make(const GrGradientEffect::CreateArgs& args);
-
-};
-
-#endif