diff options
Diffstat (limited to 'gfx/skia/skia/src/shaders/gradients/SkGradientShaderBase.h')
-rw-r--r-- | gfx/skia/skia/src/shaders/gradients/SkGradientShaderBase.h | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/shaders/gradients/SkGradientShaderBase.h b/gfx/skia/skia/src/shaders/gradients/SkGradientShaderBase.h new file mode 100644 index 0000000000..fc677cfaed --- /dev/null +++ b/gfx/skia/skia/src/shaders/gradients/SkGradientShaderBase.h @@ -0,0 +1,192 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkGradientShaderPriv_DEFINED +#define SkGradientShaderPriv_DEFINED + +#include "include/effects/SkGradientShader.h" + +#include "include/core/SkMatrix.h" +#include "include/private/base/SkTArray.h" +#include "include/private/base/SkTemplates.h" +#include "src/core/SkVM.h" +#include "src/shaders/SkShaderBase.h" + +#if defined(SK_GRAPHITE) +#include "src/gpu/graphite/KeyHelpers.h" +#endif + +class SkArenaAlloc; +class SkColorSpace; +class SkRasterPipeline; +class SkReadBuffer; +class SkWriteBuffer; + +class SkGradientShaderBase : public SkShaderBase { +public: + using Interpolation = SkGradientShader::Interpolation; + + struct Descriptor { + Descriptor(); + ~Descriptor(); + + Descriptor(const SkColor4f colors[], + sk_sp<SkColorSpace> colorSpace, + const SkScalar positions[], + int colorCount, + SkTileMode mode, + const Interpolation& interpolation); + + const SkColor4f* fColors; + sk_sp<SkColorSpace> fColorSpace; + const SkScalar* fPositions; + int fColorCount; // length of fColors (and fPositions, if not nullptr) + SkTileMode fTileMode; + Interpolation fInterpolation; + }; + + class DescriptorScope : public Descriptor { + public: + DescriptorScope() {} + + bool unflatten(SkReadBuffer&, SkMatrix* legacyLocalMatrix); + + private: + SkSTArray<16, SkColor4f, true> fColorStorage; + SkSTArray<16, SkScalar , true> fPositionStorage; + }; + + SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit); + ~SkGradientShaderBase() override; + + bool isOpaque() const override; + + bool interpolateInPremul() const { + return fInterpolation.fInPremul == SkGradientShader::Interpolation::InPremul::kYes; + } + + const SkMatrix& getGradientMatrix() const { return fPtsToUnit; } + + static bool ValidGradient(const SkColor4f colors[], int count, SkTileMode tileMode, + const Interpolation& interpolation); + + static sk_sp<SkShader> MakeDegenerateGradient(const SkColor4f colors[], const SkScalar pos[], + int colorCount, sk_sp<SkColorSpace> colorSpace, + SkTileMode mode); + + struct ColorStopOptimizer { + ColorStopOptimizer(const SkColor4f* colors, const SkScalar* pos, int count, + SkTileMode mode); + + const SkColor4f* fColors; + const SkScalar* fPos; + int fCount; + }; + + // The default SkScalarNearlyZero threshold of .0024 is too big and causes regressions for svg + // gradients defined in the wild. + static constexpr SkScalar kDegenerateThreshold = SK_Scalar1 / (1 << 15); + +protected: + void flatten(SkWriteBuffer&) const override; + + void commonAsAGradient(GradientInfo*) const; + + bool onAsLuminanceColor(SkColor*) const override; + + bool appendStages(const SkStageRec&, const MatrixRec&) const override; + + skvm::Color program(skvm::Builder*, + skvm::Coord device, + skvm::Coord local, + skvm::Color paint, + const MatrixRec&, + const SkColorInfo& dstCS, + skvm::Uniforms* uniforms, + SkArenaAlloc* alloc) const override; + + virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline, + SkRasterPipeline* postPipeline) const = 0; + + // Produce t from (x,y), modifying mask if it should be anything other than ~0. + virtual skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*, + skvm::Coord coord, skvm::I32* mask) const = 0; + + const SkMatrix fPtsToUnit; + SkTileMode fTileMode; + +#if defined(SK_GRAPHITE) + static void MakeInterpolatedToDst(const skgpu::graphite::KeyContext&, + skgpu::graphite::PaintParamsKeyBuilder*, + skgpu::graphite::PipelineDataGatherer*, + const skgpu::graphite::GradientShaderBlocks::GradientData&, + const SkGradientShaderBase::Interpolation&, + SkColorSpace* intermediateCS); +#endif + +public: + static void AppendGradientFillStages(SkRasterPipeline* p, + SkArenaAlloc* alloc, + const SkPMColor4f* colors, + const SkScalar* positions, + int count); + + SkScalar getPos(int i) const { + SkASSERT(i < fColorCount); + return fPositions ? fPositions[i] : SkIntToScalar(i) / (fColorCount - 1); + } + + SkColor getLegacyColor(int i) const { + SkASSERT(i < fColorCount); + return fColors[i].toSkColor(); + } + + SkColor4f* fColors; // points into fStorage + SkScalar* fPositions; // points into fStorage, or nullptr + int fColorCount; // length of fColors (and fPositions, if not nullptr) + sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops + Interpolation fInterpolation; + bool fFirstStopIsImplicit; + bool fLastStopIsImplicit; + + bool colorsAreOpaque() const { return fColorsAreOpaque; } + + SkTileMode getTileMode() const { return fTileMode; } + +private: + // Reserve inline space for up to 4 stops. + inline static constexpr size_t kInlineStopCount = 4; + inline static constexpr size_t kInlineStorageSize = (sizeof(SkColor4f) + sizeof(SkScalar)) + * kInlineStopCount; + skia_private::AutoSTMalloc<kInlineStorageSize, uint8_t> fStorage; + + bool fColorsAreOpaque; + + using INHERITED = SkShaderBase; +}; + +/////////////////////////////////////////////////////////////////////////////// + +struct SkColor4fXformer { + SkColor4fXformer(const SkGradientShaderBase* shader, SkColorSpace* dst); + + SkSTArray<4, SkPMColor4f, true> fColors; + sk_sp<SkColorSpace> fIntermediateColorSpace; +}; + +struct SkColorConverter { + SkColorConverter(const SkColor* colors, int count); + + SkSTArray<2, SkColor4f, true> fColors4f; +}; + +void SkRegisterLinearGradientShaderFlattenable(); +void SkRegisterRadialGradientShaderFlattenable(); +void SkRegisterSweepGradientShaderFlattenable(); +void SkRegisterTwoPointConicalGradientShaderFlattenable(); + +#endif |