blob: 66a3f1ad09b70ac05bf968e48854b27844a8011e [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 Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/shaders/SkShaderBase.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000018
Florin Malitad4e9ec82017-10-25 18:00:26 -040019class SkColorSpace;
20class SkRasterPipeline;
21class SkReadBuffer;
22class SkWriteBuffer;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000023
Florin Malita4aed1382017-05-25 10:38:07 -040024class SkGradientShaderBase : public SkShaderBase {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000025public:
reed@google.com437d6eb2013-05-23 19:03:05 +000026 struct Descriptor {
27 Descriptor() {
28 sk_bzero(this, sizeof(*this));
Mike Reedfae8fce2019-04-03 10:27:45 -040029 fTileMode = SkTileMode::kClamp;
reed@google.com437d6eb2013-05-23 19:03:05 +000030 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000031
reedaddf2ed2014-08-11 08:28:24 -070032 const SkMatrix* fLocalMatrix;
brianosmane25d71c2016-09-28 11:27:28 -070033 const SkColor4f* fColors;
brianosmanb9c51372016-09-15 11:09:45 -070034 sk_sp<SkColorSpace> fColorSpace;
reed@google.com437d6eb2013-05-23 19:03:05 +000035 const SkScalar* fPos;
36 int fCount;
Mike Reedfae8fce2019-04-03 10:27:45 -040037 SkTileMode fTileMode;
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +000038 uint32_t fGradFlags;
reed9fa60da2014-08-21 07:59:51 -070039
40 void flatten(SkWriteBuffer&) const;
41 };
42
43 class DescriptorScope : public Descriptor {
44 public:
45 DescriptorScope() {}
mtklein88fd0fb2014-12-01 06:56:38 -080046
reed9fa60da2014-08-21 07:59:51 -070047 bool unflatten(SkReadBuffer&);
48
49 // fColors and fPos always point into local memory, so they can be safely mutated
50 //
brianosmane25d71c2016-09-28 11:27:28 -070051 SkColor4f* mutableColors() { return const_cast<SkColor4f*>(fColors); }
reed9fa60da2014-08-21 07:59:51 -070052 SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
53
54 private:
Florin Malitaf77db112018-05-10 09:52:27 -040055 SkSTArray<16, SkColor4f, true> fColorStorage;
56 SkSTArray<16, SkScalar , true> fPosStorage;
57 SkMatrix fLocalMatrixStorage;
reed@google.com437d6eb2013-05-23 19:03:05 +000058 };
59
mtkleincc695fe2014-12-10 10:29:19 -080060 SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
Brian Salomond3b65972017-03-22 12:05:03 -040061 ~SkGradientShaderBase() override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000062
mtklein36352bf2015-03-25 18:17:31 -070063 bool isOpaque() const override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000064
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +000065 uint32_t getGradFlags() const { return fGradFlags; }
commit-bot@chromium.org53783b02014-04-17 21:09:49 +000066
Michael Ludwig4f94ef62018-09-12 15:22:16 -040067 const SkMatrix& getGradientMatrix() const { return fPtsToUnit; }
68
rileya@google.com1c6d64b2012-07-27 15:49:05 +000069protected:
fmalitabc590c02016-02-22 09:12:33 -080070 class GradientShaderBase4fContext;
71
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000072 SkGradientShaderBase(SkReadBuffer& );
mtklein36352bf2015-03-25 18:17:31 -070073 void flatten(SkWriteBuffer&) const override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000074
Florin Malita5f379a82017-10-18 16:22:35 -040075 void commonAsAGradient(GradientInfo*) const;
skia.committer@gmail.comd3b28e82014-04-22 03:05:17 +000076
mtklein36352bf2015-03-25 18:17:31 -070077 bool onAsLuminanceColor(SkColor*) const override;
reed8367b8c2014-08-22 08:30:20 -070078
Mike Reed1386b2d2019-03-13 21:15:05 -040079 bool onAppendStages(const SkStageRec&) const override;
Mike Kleina3771842017-05-04 19:38:48 -040080
Mike Klein85754d52020-01-22 10:04:11 -060081 bool onProgram(skvm::Builder* p,
82 const SkMatrix& ctm, const SkMatrix* localM,
83 SkFilterQuality quality, SkColorSpace* dstCS,
84 skvm::Uniforms* uniforms, SkArenaAlloc* alloc,
85 skvm::F32 x, skvm::F32 y,
86 skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override;
87
Florin Malita50b20842017-07-29 19:08:28 -040088 virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
89 SkRasterPipeline* postPipeline) const = 0;
Mike Kleina3771842017-05-04 19:38:48 -040090
Mike Klein85754d52020-01-22 10:04:11 -060091 virtual bool transformT(skvm::Builder*, skvm::F32* t) const { return false; }
92
fmalita088e21b2016-10-05 09:28:42 -070093 template <typename T, typename... Args>
Herb Derby83e939b2017-02-07 14:25:11 -050094 static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
95 auto* ctx = alloc->make<T>(std::forward<Args>(args)...);
fmalita088e21b2016-10-05 09:28:42 -070096 if (!ctx->isValid()) {
fmalita088e21b2016-10-05 09:28:42 -070097 return nullptr;
98 }
99 return ctx;
100 }
101
Mike Kleina3771842017-05-04 19:38:48 -0400102 const SkMatrix fPtsToUnit;
Mike Reedfae8fce2019-04-03 10:27:45 -0400103 SkTileMode fTileMode;
Mike Kleina3771842017-05-04 19:38:48 -0400104 uint8_t fGradFlags;
Mike Kleina3771842017-05-04 19:38:48 -0400105
reedf3182eb2015-11-17 08:12:19 -0800106public:
Florin Malitaed6ae562017-10-28 11:06:48 -0400107 SkScalar getPos(int i) const {
108 SkASSERT(i < fColorCount);
109 return fOrigPos ? fOrigPos[i] : SkIntToScalar(i) / (fColorCount - 1);
110 }
111
Florin Malita39d71de2017-10-31 11:33:49 -0400112 SkColor getLegacyColor(int i) const {
113 SkASSERT(i < fColorCount);
Brian Osman9ba9d7d2018-10-26 13:31:32 -0400114 return fOrigColors4f[i].toSkColor();
Florin Malita39d71de2017-10-31 11:33:49 -0400115 }
116
Mike Reed011d1662019-02-28 17:19:25 -0500117 bool colorsCanConvertToSkColor() const {
118 bool canConvert = true;
119 for (int i = 0; i < fColorCount; ++i) {
120 canConvert &= fOrigColors4f[i].fitsInBytes();
121 }
122 return canConvert;
123 }
124
125 SkColor4f* fOrigColors4f; // original colors, as floats
brianosmanb9c51372016-09-15 11:09:45 -0700126 SkScalar* fOrigPos; // original positions
127 int fColorCount;
Florin Malita39d71de2017-10-31 11:33:49 -0400128 sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops
reedf3182eb2015-11-17 08:12:19 -0800129
130 bool colorsAreOpaque() const { return fColorsAreOpaque; }
131
Mike Reedfae8fce2019-04-03 10:27:45 -0400132 SkTileMode getTileMode() const { return fTileMode; }
fmenozzicd9a1d02016-08-15 07:03:47 -0700133
reedf3182eb2015-11-17 08:12:19 -0800134private:
Florin Malita89ab2402017-11-01 10:14:57 -0400135 // Reserve inline space for up to 4 stops.
136 static constexpr size_t kInlineStopCount = 4;
137 static constexpr size_t kInlineStorageSize = (sizeof(SkColor4f) + sizeof(SkScalar))
138 * kInlineStopCount;
139 SkAutoSTMalloc<kInlineStorageSize, uint8_t> fStorage;
140
141 bool fColorsAreOpaque;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000142
Florin Malita4aed1382017-05-25 10:38:07 -0400143 typedef SkShaderBase INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000144};
145
146///////////////////////////////////////////////////////////////////////////////
147
Brian Osman6667fb12018-07-03 16:44:02 -0400148struct SkColor4fXformer {
149 SkColor4fXformer(const SkColor4f* colors, int colorCount, SkColorSpace* src, SkColorSpace* dst);
150
151 const SkColor4f* fColors;
152 SkSTArray<4, SkColor4f, true> fStorage;
153};
154
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000155#endif