1 /*
2 * Copyright 2021 Google LLC
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 #ifndef SurfaceFillContext_DEFINED
8 #define SurfaceFillContext_DEFINED
9
10 #include "include/core/SkAlphaType.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkMatrix.h"
13 #include "include/core/SkRect.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/private/SkColorData.h"
16 #include "include/private/base/SkDebug.h"
17 #include "src/gpu/ganesh/GrColorInfo.h"
18 #include "src/gpu/ganesh/GrFragmentProcessor.h"
19 #include "src/gpu/ganesh/GrRenderTargetProxy.h"
20 #include "src/gpu/ganesh/GrSurfaceProxy.h"
21 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
22 #include "src/gpu/ganesh/SurfaceContext.h"
23 #include "src/gpu/ganesh/ops/GrOp.h"
24 #include "src/gpu/ganesh/ops/OpsTask.h"
25
26 #include <array>
27 #include <memory>
28 #include <utility>
29
30 class GrPaint;
31 class GrRecordingContext;
32 class GrRenderTask;
33 class SkArenaAlloc;
34 struct SkIPoint;
35
36 namespace sktext::gpu {
37 class SubRunAllocator;
38 }
39
40 namespace skgpu::ganesh {
41
42 class SurfaceFillContext : public SurfaceContext {
43 public:
44 SurfaceFillContext(GrRecordingContext* rContext,
45 GrSurfaceProxyView readView,
46 GrSurfaceProxyView writeView,
47 const GrColorInfo& colorInfo);
48
asFillContext()49 SurfaceFillContext* asFillContext() override { return this; }
50
51 OpsTask* getOpsTask();
52
53 #if defined(GPU_TEST_UTILS)
testingOnly_PeekLastOpsTask()54 OpsTask* testingOnly_PeekLastOpsTask() { return fOpsTask.get(); }
55 #endif
56
57 /**
58 * Provides a performance hint that the render target's contents are allowed
59 * to become undefined.
60 */
61 void discard();
62
63 void resolveMSAA();
64
65 /**
66 * Clear the rect of the render target to the given color.
67 * @param rect the rect to clear to
68 * @param color the color to clear to.
69 */
70 template <SkAlphaType AlphaType>
clear(const SkIRect & rect,const SkRGBA4f<AlphaType> & color)71 void clear(const SkIRect& rect, const SkRGBA4f<AlphaType>& color) {
72 this->internalClear(&rect, this->adjustColorAlphaType(color));
73 }
74
75 /** Clears the entire render target to the color. */
clear(const SkRGBA4f<AlphaType> & color)76 template <SkAlphaType AlphaType> void clear(const SkRGBA4f<AlphaType>& color) {
77 this->internalClear(nullptr, this->adjustColorAlphaType(color));
78 }
79
80 /**
81 * Clear at minimum the pixels within 'scissor', but is allowed to clear the full render target
82 * if that is the more performant option.
83 */
84 template <SkAlphaType AlphaType>
clearAtLeast(const SkIRect & scissor,const SkRGBA4f<AlphaType> & color)85 void clearAtLeast(const SkIRect& scissor, const SkRGBA4f<AlphaType>& color) {
86 this->internalClear(&scissor,
87 this->adjustColorAlphaType(color),
88 /* upgrade to full */ true);
89 }
90
91 /** Fills 'dstRect' with 'fp' */
92 void fillRectWithFP(const SkIRect& dstRect, std::unique_ptr<GrFragmentProcessor>);
93
94 /**
95 * A convenience version of fillRectWithFP that applies a coordinate transformation via
96 * GrMatrixEffect.
97 */
98 void fillRectWithFP(const SkIRect& dstRect,
99 const SkMatrix& localMatrix,
100 std::unique_ptr<GrFragmentProcessor>);
101
102 /** Fills 'dstRect' with 'fp' using a local matrix that maps 'srcRect' to 'dstRect' */
fillRectToRectWithFP(const SkRect & srcRect,const SkIRect & dstRect,std::unique_ptr<GrFragmentProcessor> fp)103 void fillRectToRectWithFP(const SkRect& srcRect,
104 const SkIRect& dstRect,
105 std::unique_ptr<GrFragmentProcessor> fp) {
106 SkMatrix lm = SkMatrix::RectToRect(SkRect::Make(dstRect), srcRect);
107 this->fillRectWithFP(dstRect, lm, std::move(fp));
108 }
109
110 /** Fills 'dstRect' with 'fp' using a local matrix that maps 'srcRect' to 'dstRect' */
fillRectToRectWithFP(const SkIRect & srcRect,const SkIRect & dstRect,std::unique_ptr<GrFragmentProcessor> fp)111 void fillRectToRectWithFP(const SkIRect& srcRect,
112 const SkIRect& dstRect,
113 std::unique_ptr<GrFragmentProcessor> fp) {
114 this->fillRectToRectWithFP(SkRect::Make(srcRect), dstRect, std::move(fp));
115 }
116
117 /** Fills the entire render target with the passed FP. */
fillWithFP(std::unique_ptr<GrFragmentProcessor> fp)118 void fillWithFP(std::unique_ptr<GrFragmentProcessor> fp) {
119 this->fillRectWithFP(SkIRect::MakeSize(fWriteView.proxy()->dimensions()), std::move(fp));
120 }
121
122 /**
123 * Draws the src texture with no matrix. The dstRect is the dstPoint with the width and height
124 * of the srcRect. The srcRect and dstRect are clipped to the bounds of the src and dst surfaces
125 * respectively.
126 */
127 bool blitTexture(GrSurfaceProxyView,
128 const SkIRect& srcRect,
129 const SkIPoint& dstPoint);
130
131 sk_sp<GrRenderTask> refRenderTask();
132
numSamples()133 int numSamples() const { return this->asRenderTargetProxy()->numSamples(); }
wrapsVkSecondaryCB()134 bool wrapsVkSecondaryCB() const { return this->asRenderTargetProxy()->wrapsVkSecondaryCB(); }
135
arenaAlloc()136 SkArenaAlloc* arenaAlloc() { return this->arenas()->arenaAlloc(); }
subRunAlloc()137 sktext::gpu::SubRunAllocator* subRunAlloc() { return this->arenas()->subRunAlloc(); }
138
writeSurfaceView()139 const GrSurfaceProxyView& writeSurfaceView() const { return fWriteView; }
140
141 protected:
142 OpsTask* replaceOpsTask();
143
144 /**
145 * Creates a constant color paint for a clear, using src-over if possible to improve batching.
146 */
147 static void ClearToGrPaint(std::array<float, 4> color, GrPaint* paint);
148
149 void addOp(GrOp::Owner);
150
151 template <SkAlphaType AlphaType>
152 static std::array<float, 4> ConvertColor(SkRGBA4f<AlphaType> color);
153
154 template <SkAlphaType AlphaType>
155 std::array<float, 4> adjustColorAlphaType(SkRGBA4f<AlphaType> color) const;
156
157 GrSurfaceProxyView fWriteView;
158
159 private:
arenas()160 sk_sp<GrArenas> arenas() { return fWriteView.proxy()->asRenderTargetProxy()->arenas(); }
161
162 void addDrawOp(GrOp::Owner);
163
164 /** Override to be notified in subclass before the current ops task is replaced. */
willReplaceOpsTask(OpsTask * prevTask,OpsTask * nextTask)165 virtual void willReplaceOpsTask(OpsTask* prevTask, OpsTask* nextTask) {}
166
167 /**
168 * Override to be called to participate in the decision to discard all previous ops if a
169 * fullscreen clear occurs.
170 */
canDiscardPreviousOpsOnFullClear()171 virtual OpsTask::CanDiscardPreviousOps canDiscardPreviousOpsOnFullClear() const {
172 return OpsTask::CanDiscardPreviousOps::kYes;
173 }
174
175 void internalClear(const SkIRect* scissor,
176 std::array<float, 4> color,
177 bool upgradePartialToFull = false);
178
179 SkDEBUGCODE(void onValidate() const override;)
180
181 // The OpsTask can be closed by some other surface context that has picked it up. For this
182 // reason, the OpsTask should only ever be accessed via 'getOpsTask'.
183 sk_sp<OpsTask> fOpsTask;
184
185 using INHERITED = SurfaceContext;
186 };
187
188 template<>
189 inline std::array<float, 4> SurfaceFillContext::ConvertColor<kPremul_SkAlphaType>(
190 SkPMColor4f color) {
191 return color.unpremul().array();
192 }
193
194 template<>
195 inline std::array<float, 4> SurfaceFillContext::ConvertColor<kUnpremul_SkAlphaType>(
196 SkColor4f color) {
197 return color.premul().array();
198 }
199
200 template <SkAlphaType AlphaType>
adjustColorAlphaType(SkRGBA4f<AlphaType> color)201 std::array<float, 4> SurfaceFillContext::adjustColorAlphaType(SkRGBA4f<AlphaType> color) const {
202 if (AlphaType == kUnknown_SkAlphaType ||
203 this->colorInfo().alphaType() == kUnknown_SkAlphaType) {
204 return color.array();
205 }
206 return (AlphaType == this->colorInfo().alphaType()) ? color.array() : ConvertColor(color);
207 }
208
209 } // namespace skgpu::ganesh
210
211 #endif // SurfaceFillContext_DEFINED
212