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