Flutter Engine
The Flutter Engine
SurfaceFillContext.cpp
Go to the documentation of this file.
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
9
16
17#define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(this->singleOwner())
18#define RETURN_IF_ABANDONED if (fContext->abandoned()) { return; }
19
21public:
22 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
23 SkASSERT(fDrawingManager);
24 }
25 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
26
27private:
28 GrDrawingManager* fDrawingManager;
29};
30
31namespace skgpu::ganesh {
32
33// In MDB mode the reffing of the 'getLastOpsTask' call's result allows in-progress
34// OpsTask to be picked up and added to by SurfaceFillContext lower in the call
35// stack. When this occurs with a closed OpsTask, a new one will be allocated
36// when the SurfaceFillContext attempts to use it (via getOpsTask).
38 GrSurfaceProxyView readView,
39 GrSurfaceProxyView writeView,
40 const GrColorInfo& colorInfo)
41 : SurfaceContext(rContext, std::move(readView), colorInfo)
42 , fWriteView(std::move(writeView)) {
44 SkASSERT(this->origin() == fWriteView.origin());
45
46 fOpsTask = sk_ref_sp(rContext->priv().drawingManager()->getLastOpsTask(this->asSurfaceProxy()));
47
48 SkDEBUGCODE(this->validate();)
49}
50
53 SkDEBUGCODE(this->validate();)
54
55 if (!fOpsTask || fOpsTask->isClosed()) {
56 this->replaceOpsTask();
57 }
58 SkASSERT(!fOpsTask->isClosed());
59 return fOpsTask.get();
60}
61
65 SkDEBUGCODE(this->validate();)
66 GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceFillContext", "discard", fContext);
67
68 AutoCheckFlush acf(this->drawingManager());
69
70 this->getOpsTask()->discard();
71}
72
76 SkDEBUGCODE(this->validate();)
77 GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceFillContext", "resolveMSAA", fContext);
78
79 AutoCheckFlush acf(this->drawingManager());
80
83 *this->caps());
84}
85
87 std::unique_ptr<GrFragmentProcessor> fp) {
90 SkDEBUGCODE(this->validate();)
91 GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceFillContext", "fillRectWithFP", fContext);
92
93 AutoCheckFlush acf(this->drawingManager());
94
96 paint.setColorFragmentProcessor(std::move(fp));
97 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
98 auto op = FillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
99 SkRect::Make(dstRect));
100 this->addDrawOp(std::move(op));
101}
102
104 const SkMatrix& localMatrix,
105 std::unique_ptr<GrFragmentProcessor> fp) {
106 fp = GrMatrixEffect::Make(localMatrix, std::move(fp));
107 this->fillRectWithFP(dstRect, std::move(fp));
108}
109
111 const SkIRect& srcRect,
112 const SkIPoint& dstPoint) {
113 SkASSERT(view.asTextureProxy());
114
115 SkIPoint clippedDstPoint = dstPoint;
116 SkIRect clippedSrcRect = srcRect;
118 &clippedDstPoint,
119 view.dimensions(),
120 &clippedSrcRect)) {
121 return false;
122 }
123
124 SkIRect clippedDstRect = SkIRect::MakePtSize(clippedDstPoint, clippedSrcRect.size());
125
126 auto fp = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
127 this->fillRectToRectWithFP(SkRect::Make(clippedSrcRect), clippedDstRect, std::move(fp));
128 return true;
129}
130
132 return sk_ref_sp(this->getOpsTask());
133}
134
136 sk_sp<OpsTask> newOpsTask = this->drawingManager()->newOpsTask(this->writeSurfaceView(),
137 this->arenas());
138 this->willReplaceOpsTask(fOpsTask.get(), newOpsTask.get());
139 fOpsTask = std::move(newOpsTask);
140 return fOpsTask.get();
141}
142
144 paint->setColor4f({color[0], color[1], color[2], color[3]});
145 if (color[3] == 1.f) {
146 // Can just rely on the src-over blend mode to do the right thing.
147 // This may improve batching.
148 paint->setPorterDuffXPFactory(SkBlendMode::kSrcOver);
149 } else {
150 // A clear overwrites the prior color, so even if it's transparent, it behaves as if it
151 // were src blended
152 paint->setPorterDuffXPFactory(SkBlendMode::kSrc);
153 }
154}
155
157 GrDrawingManager* drawingMgr = this->drawingManager();
158 this->getOpsTask()->addOp(drawingMgr,
159 std::move(op),
160 GrTextureResolveManager(drawingMgr),
161 *this->caps());
162}
163
164
165void SurfaceFillContext::addDrawOp(GrOp::Owner owner) {
166 GrDrawOp* op = static_cast<GrDrawOp*>(owner.get());
169 const GrCaps& caps = *this->caps();
170 GrProcessorSet::Analysis analysis = op->finalize(caps, &clip, clampType);
171 SkASSERT(!op->usesStencil());
172 SkASSERT(!analysis.requiresDstTexture());
173 SkRect bounds = owner->bounds();
174 // We shouldn't have coverage AA or hairline draws in fill contexts.
175 SkASSERT(!op->hasAABloat() && !op->hasZeroArea());
176 if (!bounds.intersect(this->asSurfaceProxy()->getBoundsRect())) {
177 return;
178 }
179 op->setClippedBounds(op->bounds());
180 SkDEBUGCODE(op->fAddDrawOpCalled = true;)
181
182 GrDstProxyView dstProxyView;
183 this->getOpsTask()->addDrawOp(fContext->priv().drawingManager(),
184 std::move(owner),
185 op->usesMSAA(),
186 analysis,
187 std::move(clip),
188 dstProxyView,
190 caps);
191}
192
193void SurfaceFillContext::internalClear(const SkIRect* scissor,
194 std::array<float, 4> color,
195 bool upgradePartialToFull) {
198 SkDEBUGCODE(this->validate();)
199 GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceFillContext", "clear", fContext);
200
201 // There are three ways clears are handled: load ops, native clears, and draws. Load ops are
202 // only for fullscreen clears; native clears can be fullscreen or with scissors if the backend
203 // supports then. Drawing an axis-aligned rect is the fallback path.
204 GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions());
205 if (scissor && !scissorState.set(*scissor)) {
206 // The clear is offscreen, so skip it (normally this would be handled by addDrawOp,
207 // except clear ops are not draw ops).
208 return;
209 }
210
211 // If we have a scissor but it's okay to clear beyond it for performance reasons, then disable
212 // the test. We only do this when the clear would be handled by a load op or natively.
213 if (scissorState.enabled() && !this->caps()->performColorClearsAsDraws()) {
214 if (upgradePartialToFull && (this->caps()->preferFullscreenClears() ||
215 this->caps()->shouldInitializeTextures())) {
216 // TODO: wrt the shouldInitializeTextures path, it would be more performant to
217 // only clear the entire target if we knew it had not been cleared before. As
218 // is this could end up doing a lot of redundant clears.
219 scissorState.setDisabled();
220 } else {
221 // Unlike with stencil clears, we also allow clears up to the logical dimensions of the
222 // render target to overflow into any approx-fit padding of the backing store dimensions
223 scissorState.relaxTest(this->dimensions());
224 }
225 }
226
227 if (!scissorState.enabled()) {
228 // This is a fullscreen clear, so could be handled as a load op. Regardless, we can also
229 // discard all prior ops in the current task since the color buffer will be overwritten.
230 auto opsTask = this->getOpsTask();
231 if (opsTask->resetForFullscreenClear(this->canDiscardPreviousOpsOnFullClear()) &&
232 !this->caps()->performColorClearsAsDraws()) {
233 color = this->writeSurfaceView().swizzle().applyTo(color);
234 // The op list was emptied and native clears are allowed, so just use the load op
235 opsTask->setColorLoadOp(GrLoadOp::kClear, color);
236 return;
237 } else {
238 // Will use an op for the clear, reset the load op to discard since the op will
239 // blow away the color buffer contents
240 opsTask->setColorLoadOp(GrLoadOp::kDiscard);
241 }
242 }
243
244 // At this point we are either a partial clear or a fullscreen clear that couldn't be applied
245 // as a load op.
246 bool clearAsDraw = this->caps()->performColorClearsAsDraws() ||
247 (scissorState.enabled() && this->caps()->performPartialClearsAsDraws());
248 if (clearAsDraw) {
251 auto op = FillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
252 SkRect::Make(scissorState.rect()));
253 this->addDrawOp(std::move(op));
254 } else {
255 color = this->writeSurfaceView().swizzle().applyTo(color);
256 this->addOp(ClearOp::MakeColor(fContext, scissorState, color));
257 }
258}
259
260#ifdef SK_DEBUG
261void SurfaceFillContext::onValidate() const {
262 if (fOpsTask && !fOpsTask->isClosed()) {
263 SkASSERT(this->drawingManager()->getLastRenderTask(fWriteView.proxy()) == fOpsTask.get());
264 }
265}
266#endif
267
268} // namespace skgpu::ganesh
static bool GrClipSrcRectAndDstPoint(const SkISize &dstSize, SkIPoint *dstPoint, const SkISize &srcSize, SkIRect *srcRect)
Definition: GrRect.h:48
#define GR_CREATE_TRACE_MARKER_CONTEXT(classname, op, context)
Definition: GrTracing.h:18
GrClampType
Definition: GrTypesPriv.h:228
static constexpr GrClampType GrColorTypeClampType(GrColorType colorType)
Definition: GrTypesPriv.h:868
@ kUnknown_SkAlphaType
uninitialized
Definition: SkAlphaType.h:27
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kSrcOver
r = s + (1-sa)*d
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
#define RETURN_IF_ABANDONED
#define ASSERT_SINGLE_OWNER
AutoCheckFlush(GrDrawingManager *drawingManager)
static GrAppliedClip Disabled()
Definition: GrAppliedClip.h:96
Definition: GrCaps.h:57
bool performPartialClearsAsDraws() const
Definition: GrCaps.h:426
bool performColorClearsAsDraws() const
Definition: GrCaps.h:431
virtual GrProcessorSet::Analysis finalize(const GrCaps &, const GrAppliedClip *, GrClampType)=0
virtual bool usesStencil() const
Definition: GrDrawOp.h:82
skgpu::ganesh::OpsTask * getLastOpsTask(const GrSurfaceProxy *) const
sk_sp< skgpu::ganesh::OpsTask > newOpsTask(GrSurfaceProxyView, sk_sp< GrArenas > arenas)
void newTextureResolveRenderTask(sk_sp< GrSurfaceProxy > proxy, GrSurfaceProxy::ResolveFlags, const GrCaps &)
static std::unique_ptr< GrFragmentProcessor > Make(const SkMatrix &matrix, std::unique_ptr< GrFragmentProcessor > child)
std::unique_ptr< GrOp > Owner
Definition: GrOp.h:72
void setClippedBounds(const SkRect &clippedBounds)
Definition: GrOp.h:127
const SkRect & bounds() const
Definition: GrOp.h:122
bool hasAABloat() const
Definition: GrOp.h:133
bool hasZeroArea() const
Definition: GrOp.h:138
bool requiresDstTexture() const
GrDrawingManager * drawingManager()
GrRecordingContextPriv priv()
skgpu::Swizzle swizzle() const
GrTextureProxy * asTextureProxy() const
SkISize dimensions() const
GrSurfaceOrigin origin() const
GrSurfaceProxy * proxy() const
static std::unique_ptr< GrFragmentProcessor > Make(GrSurfaceProxyView, SkAlphaType, const SkMatrix &=SkMatrix::I(), GrSamplerState::Filter=GrSamplerState::Filter::kNearest, GrSamplerState::MipmapMode mipmapMode=GrSamplerState::MipmapMode::kNone)
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
T * get() const
Definition: SkRefCnt.h:303
constexpr std::array< float, 4 > applyTo(std::array< float, 4 > color) const
Definition: Swizzle.h:101
static DEFINE_OP_CLASS_ID GrOp::Owner MakeColor(GrRecordingContext *context, const GrScissorState &scissor, std::array< float, 4 > color)
Definition: ClearOp.cpp:27
static GrOp::Owner MakeNonAARect(GrRecordingContext *, GrPaint &&, const SkMatrix &view, const SkRect &, const GrUserStencilSettings *=nullptr)
Definition: FillRectOp.cpp:480
void addOp(GrDrawingManager *, GrOp::Owner, GrTextureResolveManager, const GrCaps &)
Definition: OpsTask.cpp:417
GrSurfaceProxy * asSurfaceProxy()
GrDrawingManager * drawingManager()
SkDEBUGCODE(void validate() const ;) SkDEBUGCODE(skgpu GrRecordingContext * fContext
const GrCaps * caps() const
const GrColorInfo & colorInfo() const
sk_sp< GrSurfaceProxy > asSurfaceProxyRef()
GrSurfaceOrigin origin() const
static void ClearToGrPaint(std::array< float, 4 > color, GrPaint *paint)
void fillRectToRectWithFP(const SkRect &srcRect, const SkIRect &dstRect, std::unique_ptr< GrFragmentProcessor > fp)
void fillRectWithFP(const SkIRect &dstRect, std::unique_ptr< GrFragmentProcessor >)
bool blitTexture(GrSurfaceProxyView, const SkIRect &srcRect, const SkIPoint &dstPoint)
const GrSurfaceProxyView & writeSurfaceView() const
virtual void willReplaceOpsTask(OpsTask *prevTask, OpsTask *nextTask)
SurfaceFillContext(GrRecordingContext *rContext, GrSurfaceProxyView readView, GrSurfaceProxyView writeView, const GrColorInfo &colorInfo)
const Paint & paint
Definition: color_source.cc:38
DlColor color
FlPixelBufferTexturePrivate * priv
Optional< SkRect > bounds
Definition: SkRecords.h:189
const uint32_t fp
Definition: ref_ptr.h:256
Definition: SkRect.h:32
constexpr SkISize size() const
Definition: SkRect.h:172
static constexpr SkIRect MakePtSize(SkIPoint pt, SkISize size)
Definition: SkRect.h:78
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669