aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/shaders/gradients/SkGradientShaderPriv.h
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2017-11-08 15:46:42 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-11-09 15:15:54 +0000
commit14a8dd7255494c982673b2926e56a60e36a1a8a6 (patch)
tree70bda26bcd7b750855f1db9fe53e72a7e6313134 /src/shaders/gradients/SkGradientShaderPriv.h
parent5be933f01bf18e0869422d96840f6906ff42bfbb (diff)
Simplify analytical GPU gradient impls
1) reformulate the gradient data as a series of interpolation intervals, defined as tuples of (color_scale, color_bias) such that color(t) = t * color_scale + color_bias (this allows us to skip the relative_t computation and simply feed tiled_t into a fast MAD) 2) then, the existing specializations can be generalized as a) select an interpolation interval (possibly based on a threshold) b) compute the interpolated color using the method in #1 3) simplify the hard-edge cases by using clamp intervals (color_scale == 0) and relaxing the clamping step (allowing tiled_t < 0 or tiled_t > 1, in order to hit the clamping intervals during the selection step) The existing specializations are converted as follows: * kTwo_ColorType -> single interpolation interval, normal clamping * kThree_ColorType -> two interpolation intervals, normal clamping, threshold == pos[1] * kSingleHardStop_ColorType -> two interpolation intervals, normal clamping, threshold == pos[1/2] * kHardStopLeftEdged_ColorType -> two interpolation intervals, clamping (-inf, 1], threshold == 0 * kHardStopRightEdged_ColorType -> two interpolation intervals, clamping [0, +inf), threshold == 1 This reduces the SkSL overhead in a couple of ways: * the clamp stage is sometimes reduced to min/max vs. full clamp() * the color interpolation stage is just a MAD vs. full mix() Change-Id: I65be84d131d56136ec5e946c2b3dba149a4473cf Reviewed-on: https://skia-review.googlesource.com/68218 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'src/shaders/gradients/SkGradientShaderPriv.h')
-rw-r--r--src/shaders/gradients/SkGradientShaderPriv.h91
1 files changed, 28 insertions, 63 deletions
diff --git a/src/shaders/gradients/SkGradientShaderPriv.h b/src/shaders/gradients/SkGradientShaderPriv.h
index 93c07094dc..9d82e82ef8 100644
--- a/src/shaders/gradients/SkGradientShaderPriv.h
+++ b/src/shaders/gradients/SkGradientShaderPriv.h
@@ -14,7 +14,7 @@
#include "SkAutoMalloc.h"
#include "SkMatrix.h"
#include "SkShaderBase.h"
-#include "SkTDArray.h"
+#include "SkTArray.h"
#include "SkTemplates.h"
class SkColorSpace;
@@ -194,7 +194,7 @@ public:
const SkGradientShaderBase* shader,
const SkMatrix* matrix,
SkShader::TileMode tileMode,
- const SkColorSpace* dstColorSpace)
+ SkColorSpace* dstColorSpace)
: fContext(context)
, fShader(shader)
, fMatrix(matrix)
@@ -216,7 +216,7 @@ public:
const SkGradientShaderBase* shader,
const SkMatrix* matrix,
GrSamplerState::WrapMode wrapMode,
- const SkColorSpace* dstColorSpace)
+ SkColorSpace* dstColorSpace)
: fContext(context)
, fShader(shader)
, fMatrix(matrix)
@@ -227,7 +227,7 @@ public:
const SkGradientShaderBase* fShader;
const SkMatrix* fMatrix;
GrSamplerState::WrapMode fWrapMode;
- const SkColorSpace* fDstColorSpace;
+ SkColorSpace* fDstColorSpace;
};
class GLSLProcessor;
@@ -235,41 +235,22 @@ public:
~GrGradientEffect() override;
bool useAtlas() const { return SkToBool(-1 != fRow); }
- SkScalar getYCoord() const { return fYCoord; }
-
- enum ColorType {
- kTwo_ColorType,
- kThree_ColorType, // 0, t, 1
- kTexture_ColorType,
- kSingleHardStop_ColorType, // 0, t, t, 1
- kHardStopLeftEdged_ColorType, // 0, 0, 1
- kHardStopRightEdged_ColorType, // 0, 1, 1
- };
-
- ColorType getColorType() const { return fColorType; }
- // Determines the type of gradient, one of:
- // - Two-color
- // - Symmetric three-color
- // - Texture
- // - Centered hard stop
- // - Left-edged hard stop
- // - Right-edged hard stop
- ColorType determineColorType(const SkGradientShaderBase& shader);
+ // 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,
};
- PremulType getPremulType() const { return fPremulType; }
-
- const GrColor4f* getColors4f(int pos) const {
- SkASSERT(fColorType != kTexture_ColorType);
- SkASSERT(pos < fColors4f.count());
- return &fColors4f[pos];
- }
-
protected:
GrGradientEffect(ClassID classID, const CreateArgs&, bool isOpaque);
explicit GrGradientEffect(const GrGradientEffect&); // facilitates clone() implementations
@@ -287,7 +268,7 @@ protected:
// With analytic gradients, we pre-convert the stops to the destination color space, so no
// xform is needed. With texture-based gradients, we leave the data in the source color
// space (to avoid clamping if we can't use F16)... Add an extra FP to do the xform.
- if (kTexture_ColorType == gradientFP->getColorType()) {
+ if (gradientFP->fStrategy == InterpolationStrategy::kTexture) {
// Our texture is always either F16 or sRGB, so the data is "linear" in the shader.
// Create our xform assuming float inputs, which will suppress any extra sRGB work.
// We do support having a transfer function on the color space of the stops, so
@@ -331,15 +312,18 @@ protected:
/** Checks whether the constructor failed to fully initialize the processor. */
bool isValid() const {
- return fColorType != kTexture_ColorType || fTextureSampler.isInitialized();
+ return fStrategy != InterpolationStrategy::kTexture || fTextureSampler.isInitialized();
}
private:
+ void addInterval(const SkGradientShaderBase&, size_t idx0, size_t idx1, SkColorSpace*);
+
static OptimizationFlags OptFlags(bool isOpaque);
- SkTDArray<GrColor4f> fColors4f;
+ // Interpolation intervals, encoded as 4f tuples of (scale, bias)
+ // such that color(t) = t * scale + bias.
+ SkSTArray<4, GrColor4f, true> fIntervals;
- SkTDArray<SkScalar> fPositions;
GrSamplerState::WrapMode fWrapMode;
GrCoordTransform fCoordTransform;
@@ -348,9 +332,12 @@ private:
GrTextureStripAtlas* fAtlas;
int fRow;
bool fIsOpaque;
- ColorType fColorType;
- PremulType fPremulType; // This is already baked into the table for texture gradients, and
- // only changes behavior for gradients that don't use a texture.
+
+ 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;
};
@@ -395,31 +382,9 @@ private:
const char* outputColor,
const char* inputColor);
- enum {
- // First bit for premul before/after interpolation
- kPremulBeforeInterpKey = 1,
-
- // Next three bits for 2/3 color type or different special
- // hard stop cases ('none' means using texture atlas)
- kTwoColorKey = 2,
- kThreeColorKey = 4,
-
- kHardStopCenteredKey = 6,
- kHardStopZeroZeroOneKey = 8,
- kHardStopZeroOneOneKey = 10,
-
- // Next two bits for tile mode
- kClampTileMode = 16,
- kRepeatTileMode = 32,
- kMirrorTileMode = 48,
-
- // Lower six bits for premul, 2/3 color type, and tile mode
- kReservedBits = 6,
- };
-
SkScalar fCachedYCoord;
- GrGLSLProgramDataManager::UniformHandle fColorsUni;
- GrGLSLProgramDataManager::UniformHandle fExtraStopT;
+ GrGLSLProgramDataManager::UniformHandle fIntervalsUni;
+ GrGLSLProgramDataManager::UniformHandle fThresholdUni;
GrGLSLProgramDataManager::UniformHandle fFSYUni;
typedef GrGLSLFragmentProcessor INHERITED;