blob: cb416895f7e0a104aa8b5b88a1b54037c82de402 [file] [log] [blame]
rileya@google.com1c6d64b2012-07-27 15:49:05 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkGradientShaderPriv_DEFINED
9#define SkGradientShaderPriv_DEFINED
10
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/effects/SkGradientShader.h"
Hal Canary95e3c052017-01-11 12:44:43 -050012
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkMatrix.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/private/SkTArray.h"
15#include "include/private/SkTemplates.h"
Ben Wagner729a23f2019-05-17 16:29:34 -040016#include "src/core/SkArenaAlloc.h"
Mike Kleinba9da462020-01-28 14:25:09 -060017#include "src/core/SkVM.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/shaders/SkShaderBase.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000019
Florin Malitad4e9ec82017-10-25 18:00:26 -040020class SkColorSpace;
21class SkRasterPipeline;
22class SkReadBuffer;
23class SkWriteBuffer;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000024
Florin Malita4aed1382017-05-25 10:38:07 -040025class SkGradientShaderBase : public SkShaderBase {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000026public:
reed@google.com437d6eb2013-05-23 19:03:05 +000027 struct Descriptor {
28 Descriptor() {
29 sk_bzero(this, sizeof(*this));
Mike Reedfae8fce2019-04-03 10:27:45 -040030 fTileMode = SkTileMode::kClamp;
reed@google.com437d6eb2013-05-23 19:03:05 +000031 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000032
reedaddf2ed2014-08-11 08:28:24 -070033 const SkMatrix* fLocalMatrix;
brianosmane25d71c2016-09-28 11:27:28 -070034 const SkColor4f* fColors;
brianosmanb9c51372016-09-15 11:09:45 -070035 sk_sp<SkColorSpace> fColorSpace;
reed@google.com437d6eb2013-05-23 19:03:05 +000036 const SkScalar* fPos;
37 int fCount;
Mike Reedfae8fce2019-04-03 10:27:45 -040038 SkTileMode fTileMode;
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +000039 uint32_t fGradFlags;
reed9fa60da2014-08-21 07:59:51 -070040
41 void flatten(SkWriteBuffer&) const;
42 };
43
44 class DescriptorScope : public Descriptor {
45 public:
46 DescriptorScope() {}
mtklein88fd0fb2014-12-01 06:56:38 -080047
reed9fa60da2014-08-21 07:59:51 -070048 bool unflatten(SkReadBuffer&);
49
50 // fColors and fPos always point into local memory, so they can be safely mutated
51 //
brianosmane25d71c2016-09-28 11:27:28 -070052 SkColor4f* mutableColors() { return const_cast<SkColor4f*>(fColors); }
reed9fa60da2014-08-21 07:59:51 -070053 SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
54
55 private:
Florin Malitaf77db112018-05-10 09:52:27 -040056 SkSTArray<16, SkColor4f, true> fColorStorage;
57 SkSTArray<16, SkScalar , true> fPosStorage;
58 SkMatrix fLocalMatrixStorage;
reed@google.com437d6eb2013-05-23 19:03:05 +000059 };
60
mtkleincc695fe2014-12-10 10:29:19 -080061 SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
Brian Salomond3b65972017-03-22 12:05:03 -040062 ~SkGradientShaderBase() override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000063
mtklein36352bf2015-03-25 18:17:31 -070064 bool isOpaque() const override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000065
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +000066 uint32_t getGradFlags() const { return fGradFlags; }
commit-bot@chromium.org53783b02014-04-17 21:09:49 +000067
Michael Ludwig4f94ef62018-09-12 15:22:16 -040068 const SkMatrix& getGradientMatrix() const { return fPtsToUnit; }
69
rileya@google.com1c6d64b2012-07-27 15:49:05 +000070protected:
fmalitabc590c02016-02-22 09:12:33 -080071 class GradientShaderBase4fContext;
72
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000073 SkGradientShaderBase(SkReadBuffer& );
mtklein36352bf2015-03-25 18:17:31 -070074 void flatten(SkWriteBuffer&) const override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000075
Florin Malita5f379a82017-10-18 16:22:35 -040076 void commonAsAGradient(GradientInfo*) const;
skia.committer@gmail.comd3b28e82014-04-22 03:05:17 +000077
mtklein36352bf2015-03-25 18:17:31 -070078 bool onAsLuminanceColor(SkColor*) const override;
reed8367b8c2014-08-22 08:30:20 -070079
Mike Reed1386b2d2019-03-13 21:15:05 -040080 bool onAppendStages(const SkStageRec&) const override;
Mike Kleina3771842017-05-04 19:38:48 -040081
Mike Klein85754d52020-01-22 10:04:11 -060082 bool onProgram(skvm::Builder* p,
83 const SkMatrix& ctm, const SkMatrix* localM,
84 SkFilterQuality quality, SkColorSpace* dstCS,
85 skvm::Uniforms* uniforms, SkArenaAlloc* alloc,
86 skvm::F32 x, skvm::F32 y,
87 skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override;
88
Florin Malita50b20842017-07-29 19:08:28 -040089 virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
90 SkRasterPipeline* postPipeline) const = 0;
Mike Kleina3771842017-05-04 19:38:48 -040091
Mike Kleincaf5ee42020-01-28 16:11:34 -060092 enum class MaskNeeded { None, NaNs, Degens, NotYetImplemented };
93 virtual MaskNeeded transformT(skvm::Builder*, skvm::Uniforms*,
94 skvm::F32 x, skvm::F32 y, skvm::F32* t) const = 0;
Mike Klein85754d52020-01-22 10:04:11 -060095
fmalita088e21b2016-10-05 09:28:42 -070096 template <typename T, typename... Args>
Herb Derby83e939b2017-02-07 14:25:11 -050097 static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
98 auto* ctx = alloc->make<T>(std::forward<Args>(args)...);
fmalita088e21b2016-10-05 09:28:42 -070099 if (!ctx->isValid()) {
fmalita088e21b2016-10-05 09:28:42 -0700100 return nullptr;
101 }
102 return ctx;
103 }
104
Mike Kleina3771842017-05-04 19:38:48 -0400105 const SkMatrix fPtsToUnit;
Mike Reedfae8fce2019-04-03 10:27:45 -0400106 SkTileMode fTileMode;
Mike Kleina3771842017-05-04 19:38:48 -0400107 uint8_t fGradFlags;
Mike Kleina3771842017-05-04 19:38:48 -0400108
reedf3182eb2015-11-17 08:12:19 -0800109public:
Florin Malitaed6ae562017-10-28 11:06:48 -0400110 SkScalar getPos(int i) const {
111 SkASSERT(i < fColorCount);
112 return fOrigPos ? fOrigPos[i] : SkIntToScalar(i) / (fColorCount - 1);
113 }
114
Florin Malita39d71de2017-10-31 11:33:49 -0400115 SkColor getLegacyColor(int i) const {
116 SkASSERT(i < fColorCount);
Brian Osman9ba9d7d2018-10-26 13:31:32 -0400117 return fOrigColors4f[i].toSkColor();
Florin Malita39d71de2017-10-31 11:33:49 -0400118 }
119
Mike Reed011d1662019-02-28 17:19:25 -0500120 bool colorsCanConvertToSkColor() const {
121 bool canConvert = true;
122 for (int i = 0; i < fColorCount; ++i) {
123 canConvert &= fOrigColors4f[i].fitsInBytes();
124 }
125 return canConvert;
126 }
127
128 SkColor4f* fOrigColors4f; // original colors, as floats
brianosmanb9c51372016-09-15 11:09:45 -0700129 SkScalar* fOrigPos; // original positions
130 int fColorCount;
Florin Malita39d71de2017-10-31 11:33:49 -0400131 sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops
reedf3182eb2015-11-17 08:12:19 -0800132
133 bool colorsAreOpaque() const { return fColorsAreOpaque; }
134
Mike Reedfae8fce2019-04-03 10:27:45 -0400135 SkTileMode getTileMode() const { return fTileMode; }
fmenozzicd9a1d02016-08-15 07:03:47 -0700136
reedf3182eb2015-11-17 08:12:19 -0800137private:
Florin Malita89ab2402017-11-01 10:14:57 -0400138 // Reserve inline space for up to 4 stops.
139 static constexpr size_t kInlineStopCount = 4;
140 static constexpr size_t kInlineStorageSize = (sizeof(SkColor4f) + sizeof(SkScalar))
141 * kInlineStopCount;
142 SkAutoSTMalloc<kInlineStorageSize, uint8_t> fStorage;
143
144 bool fColorsAreOpaque;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000145
Florin Malita4aed1382017-05-25 10:38:07 -0400146 typedef SkShaderBase INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000147};
148
149///////////////////////////////////////////////////////////////////////////////
150
Brian Osman6667fb12018-07-03 16:44:02 -0400151struct SkColor4fXformer {
152 SkColor4fXformer(const SkColor4f* colors, int colorCount, SkColorSpace* src, SkColorSpace* dst);
153
154 const SkColor4f* fColors;
155 SkSTArray<4, SkColor4f, true> fStorage;
156};
157
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000158#endif