1 /*
2 * Copyright 2020 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 GrSurfaceFillContext_DEFINED
9 #define GrSurfaceFillContext_DEFINED
10
11 #include "include/core/SkSize.h"
12 #include "include/private/GrTypesPriv.h"
13 #include "src/gpu/GrImageInfo.h"
14 #include "src/gpu/GrOpsTask.h"
15 #include "src/gpu/GrSurfaceContext.h"
16 #include "src/gpu/GrSwizzle.h"
17 #include "src/gpu/effects/GrMatrixEffect.h"
18
19 #include <array>
20 #include <tuple>
21
22 class GrFragmentProcessor;
23 class GrImageContext;
24 class GrOp;
25 class GrBackendFormat;
26 class GrRecordingContext;
27 class GrSurfaceProxyView;
28 class SkColorSpace;
29
30 class GrSurfaceFillContext : public GrSurfaceContext {
31 public:
32 /**
33 * Checks whether the passed color type is renderable with the passed context. If so, the
34 * same color type is passed back along with the default format used for the color type. If
35 * not, provides an alternative (perhaps lower bit depth and/or unorm instead of float) color
36 * type that is supported along with it's default format or kUnknown if there no renderable
37 * fallback format.
38 */
39 static std::tuple<GrColorType, GrBackendFormat> GetFallbackColorTypeAndFormat(GrImageContext*,
40 GrColorType,
41 int sampleCount);
42
43 GrSurfaceFillContext(GrRecordingContext*,
44 GrSurfaceProxyView readView,
45 GrSurfaceProxyView writeView,
46 const GrColorInfo&,
47 bool flushTimeOpsTask = false);
48
49 /**
50 * Uses GrImageInfo's color type to pick the default texture format. Will return a
51 * GrSurfaceDrawContext if possible.
52 */
53 static std::unique_ptr<GrSurfaceFillContext> Make(GrRecordingContext*,
54 GrImageInfo,
55 SkBackingFit = SkBackingFit::kExact,
56 int sampleCount = 1,
57 GrMipmapped = GrMipmapped::kNo,
58 GrProtected = GrProtected::kNo,
59 GrSurfaceOrigin = kTopLeft_GrSurfaceOrigin,
60 SkBudgeted = SkBudgeted::kYes);
61
62 /**
63 * Like the above but uses GetFallbackColorTypeAndFormat to find a fallback color type (and
64 * compatible format) if the passed GrImageInfo's color type is not renderable.
65 */
66 static std::unique_ptr<GrSurfaceFillContext> MakeWithFallback(
67 GrRecordingContext*,
68 GrImageInfo,
69 SkBackingFit = SkBackingFit::kExact,
70 int sampleCount = 1,
71 GrMipmapped = GrMipmapped::kNo,
72 GrProtected = GrProtected::kNo,
73 GrSurfaceOrigin = kTopLeft_GrSurfaceOrigin,
74 SkBudgeted = SkBudgeted::kYes);
75
76 /**
77 * Makes a custom configured GrSurfaceFillContext where the caller specifies the specific
78 * texture format and swizzles. The color type will be kUnknown. Returns a GrSurfaceDrawContext
79 * if possible.
80 */
81 static std::unique_ptr<GrSurfaceFillContext> Make(GrRecordingContext*,
82 SkAlphaType,
83 sk_sp<SkColorSpace>,
84 SkISize dimensions,
85 SkBackingFit,
86 const GrBackendFormat&,
87 int sampleCount,
88 GrMipmapped,
89 GrProtected,
90 GrSwizzle readSwizzle,
91 GrSwizzle writeSwizzle,
92 GrSurfaceOrigin,
93 SkBudgeted);
94
95 /**
96 * Creates a GrSurfaceFillContext from an existing GrBackendTexture. The GrColorInfo's color
97 * type must be compatible with backend texture's format or this will fail. All formats are
98 * considered compatible with kUnknown. Returns a GrSurfaceDrawContext if possible.
99 */
100 static std::unique_ptr<GrSurfaceFillContext> MakeFromBackendTexture(
101 GrRecordingContext*,
102 GrColorInfo,
103 const GrBackendTexture&,
104 int sampleCount,
105 GrSurfaceOrigin,
106 sk_sp<GrRefCntedCallback> releaseHelper);
107
asFillContext()108 GrSurfaceFillContext* asFillContext() override { return this; }
109
110 /**
111 * Provides a performance hint that the render target's contents are allowed
112 * to become undefined.
113 */
114 void discard();
115
116 /**
117 * Clear the rect of the render target to the given color.
118 * @param rect the rect to clear to
119 * @param color the color to clear to.
120 */
121 template <SkAlphaType AlphaType>
clear(const SkIRect & rect,const SkRGBA4f<AlphaType> & color)122 void clear(const SkIRect& rect, const SkRGBA4f<AlphaType>& color) {
123 this->internalClear(&rect, this->adjustColorAlphaType(color));
124 }
125
126 /** Clears the entire render target to the color. */
clear(const SkRGBA4f<AlphaType> & color)127 template <SkAlphaType AlphaType> void clear(const SkRGBA4f<AlphaType>& color) {
128 this->internalClear(nullptr, this->adjustColorAlphaType(color));
129 }
130
131 /**
132 * Clear at minimum the pixels within 'scissor', but is allowed to clear the full render target
133 * if that is the more performant option.
134 */
135 template <SkAlphaType AlphaType>
clearAtLeast(const SkIRect & scissor,const SkRGBA4f<AlphaType> & color)136 void clearAtLeast(const SkIRect& scissor, const SkRGBA4f<AlphaType>& color) {
137 this->internalClear(&scissor,
138 this->adjustColorAlphaType(color),
139 /* upgrade to full */ true);
140 }
141
142 /** Fills 'dstRect' with 'fp' */
143 void fillRectWithFP(const SkIRect& dstRect, std::unique_ptr<GrFragmentProcessor> fp);
144
145 /**
146 * A convenience version of fillRectWithFP that applies a coordinate transformation via
147 * GrMatrixEffect.
148 */
fillRectWithFP(const SkIRect & dstRect,const SkMatrix & localMatrix,std::unique_ptr<GrFragmentProcessor> fp)149 void fillRectWithFP(const SkIRect& dstRect,
150 const SkMatrix& localMatrix,
151 std::unique_ptr<GrFragmentProcessor> fp) {
152 fp = GrMatrixEffect::Make(localMatrix, std::move(fp));
153 this->fillRectWithFP(dstRect, std::move(fp));
154 }
155
156 /** 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)157 void fillRectToRectWithFP(const SkRect& srcRect,
158 const SkIRect& dstRect,
159 std::unique_ptr<GrFragmentProcessor> fp) {
160 SkMatrix lm = SkMatrix::RectToRect(SkRect::Make(dstRect), srcRect);
161 this->fillRectWithFP(dstRect, lm, std::move(fp));
162 }
163
164 /** 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)165 void fillRectToRectWithFP(const SkIRect& srcRect,
166 const SkIRect& dstRect,
167 std::unique_ptr<GrFragmentProcessor> fp) {
168 this->fillRectToRectWithFP(SkRect::Make(srcRect), dstRect, std::move(fp));
169 }
170
171 /** Fills the entire render target with the passed FP. */
fillWithFP(std::unique_ptr<GrFragmentProcessor> fp)172 void fillWithFP(std::unique_ptr<GrFragmentProcessor> fp) {
173 this->fillRectWithFP(SkIRect::MakeSize(fWriteView.proxy()->dimensions()), std::move(fp));
174 }
175
176 /**
177 * A convenience version of fillWithFP that applies a coordinate transformation via
178 * GrMatrixEffect and fills the entire render target.
179 */
fillWithFP(const SkMatrix & localMatrix,std::unique_ptr<GrFragmentProcessor> fp)180 void fillWithFP(const SkMatrix& localMatrix, std::unique_ptr<GrFragmentProcessor> fp) {
181 this->fillRectWithFP(
182 SkIRect::MakeSize(fWriteView.proxy()->dimensions()), localMatrix, std::move(fp));
183 }
184
185 /**
186 * Draws the src texture with no matrix. The dstRect is the dstPoint with the width and height
187 * of the srcRect. The srcRect and dstRect are clipped to the bounds of the src and dst surfaces
188 * respectively.
189 */
190 bool blitTexture(GrSurfaceProxyView view, const SkIRect& srcRect, const SkIPoint& dstPoint);
191
192 GrOpsTask* getOpsTask();
193
numSamples()194 int numSamples() const { return this->asRenderTargetProxy()->numSamples(); }
wrapsVkSecondaryCB()195 bool wrapsVkSecondaryCB() const { return this->asRenderTargetProxy()->wrapsVkSecondaryCB(); }
196 GrMipmapped mipmapped() const;
197
arenaAlloc()198 SkArenaAlloc* arenaAlloc() { return this->arenas()->arenaAlloc(); }
subRunAlloc()199 GrSubRunAllocator* subRunAlloc() { return this->arenas()->subRunAlloc(); }
200
201 #if GR_TEST_UTILS
testingOnly_PeekLastOpsTask()202 GrOpsTask* testingOnly_PeekLastOpsTask() { return fOpsTask.get(); }
203 #endif
204
writeSurfaceView()205 const GrSurfaceProxyView& writeSurfaceView() const { return fWriteView; }
206
207 protected:
208 /**
209 * Creates a constant color paint for a clear, using src-over if possible to improve batching.
210 */
211 static void ClearToGrPaint(std::array<float, 4> color, GrPaint* paint);
212
213 void addOp(GrOp::Owner);
214
215 private:
arenas()216 sk_sp<GrArenas> arenas() { return fWriteView.proxy()->asRenderTargetProxy()->arenas(); }
217
218 template <SkAlphaType AlphaType>
219 static std::array<float, 4> ConvertColor(SkRGBA4f<AlphaType> color);
220
221 template <SkAlphaType AlphaType>
222 std::array<float, 4> adjustColorAlphaType(SkRGBA4f<AlphaType> color) const;
223
224 /** Override to be notified in subclass before the current ops task is replaced. */
willReplaceOpsTask(GrOpsTask * prevTask,GrOpsTask * nextTask)225 virtual void willReplaceOpsTask(GrOpsTask* prevTask, GrOpsTask* nextTask) {}
226
227 /**
228 * Override to be called to participate in the decision to discard all previous ops if a
229 * fullscreen clear occurs.
230 */
canDiscardPreviousOpsOnFullClear()231 virtual GrOpsTask::CanDiscardPreviousOps canDiscardPreviousOpsOnFullClear() const {
232 return GrOpsTask::CanDiscardPreviousOps::kYes;
233 }
234
235 void internalClear(const SkIRect* scissor,
236 std::array<float, 4> color,
237 bool upgradePartialToFull = false);
238
239 void addDrawOp(GrOp::Owner);
240
241 SkDEBUGCODE(void onValidate() const override;)
242
243 GrSurfaceProxyView fWriteView;
244
245 // The GrOpsTask can be closed by some other surface context that has picked it up. For this
246 // reason, the GrOpsTask should only ever be accessed via 'getOpsTask'.
247 sk_sp<GrOpsTask> fOpsTask;
248
249 bool fFlushTimeOpsTask;
250
251 using INHERITED = GrSurfaceContext;
252 };
253
254 template<>
255 inline std::array<float, 4> GrSurfaceFillContext::ConvertColor<kPremul_SkAlphaType>(
256 SkPMColor4f color) {
257 return color.unpremul().array();
258 }
259
260 template<>
261 inline std::array<float, 4> GrSurfaceFillContext::ConvertColor<kUnpremul_SkAlphaType>(
262 SkColor4f color) {
263 return color.premul().array();
264 }
265
266 template <SkAlphaType AlphaType>
adjustColorAlphaType(SkRGBA4f<AlphaType> color)267 std::array<float, 4> GrSurfaceFillContext::adjustColorAlphaType(SkRGBA4f<AlphaType> color) const {
268 if (AlphaType == kUnknown_SkAlphaType ||
269 this->colorInfo().alphaType() == kUnknown_SkAlphaType) {
270 return color.array();
271 }
272 return (AlphaType == this->colorInfo().alphaType()) ? color.array() : ConvertColor(color);
273 }
274
275 #endif
276