Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/gpu/v1/SurfaceFillContext_v1.cpp
Line
Count
Source (jump to first uncovered line)
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
#include "src/gpu/v1/SurfaceFillContext_v1.h"
9
10
#include "include/private/GrImageContext.h"
11
#include "src/gpu/GrDstProxyView.h"
12
#include "src/gpu/GrImageContextPriv.h"
13
#include "src/gpu/GrProxyProvider.h"
14
#include "src/gpu/effects/GrTextureEffect.h"
15
#include "src/gpu/geometry/GrRect.h"
16
#include "src/gpu/ops/GrClearOp.h"
17
#include "src/gpu/ops/GrFillRectOp.h"
18
#include "src/gpu/v1/SurfaceDrawContext_v1.h"
19
20
60.7k
#define ASSERT_SINGLE_OWNER        GR_ASSERT_SINGLE_OWNER(this->singleOwner())
21
121k
#define RETURN_IF_ABANDONED        if (fContext->abandoned()) { return; }
22
23
class AutoCheckFlush {
24
public:
25
35.5k
    AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
26
35.5k
        SkASSERT(fDrawingManager);
27
35.5k
    }
28
35.5k
    ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
29
30
private:
31
    GrDrawingManager* fDrawingManager;
32
};
33
34
namespace skgpu::v1 {
35
36
// In MDB mode the reffing of the 'getLastOpsTask' call's result allows in-progress
37
// GrOpsTask to be picked up and added to by SurfaceFillContext lower in the call
38
// stack. When this occurs with a closed GrOpsTask, a new one will be allocated
39
// when the SurfaceFillContext attempts to use it (via getOpsTask).
40
SurfaceFillContext::SurfaceFillContext(GrRecordingContext* rContext,
41
                                       GrSurfaceProxyView readView,
42
                                       GrSurfaceProxyView writeView,
43
                                       const GrColorInfo& colorInfo,
44
                                       bool flushTimeOpsTask)
45
        : skgpu::SurfaceFillContext(rContext,
46
                                    std::move(readView),
47
                                    std::move(writeView),
48
                                    std::move(colorInfo))
49
134k
        , fFlushTimeOpsTask(flushTimeOpsTask) {
50
134k
    fOpsTask = sk_ref_sp(rContext->priv().drawingManager()->getLastOpsTask(this->asSurfaceProxy()));
51
52
67.3k
    SkDEBUGCODE(this->validate();)
53
134k
}
skgpu::v1::SurfaceFillContext::SurfaceFillContext(GrRecordingContext*, GrSurfaceProxyView, GrSurfaceProxyView, GrColorInfo const&, bool)
Line
Count
Source
49
67.3k
        , fFlushTimeOpsTask(flushTimeOpsTask) {
50
67.3k
    fOpsTask = sk_ref_sp(rContext->priv().drawingManager()->getLastOpsTask(this->asSurfaceProxy()));
51
52
67.3k
    SkDEBUGCODE(this->validate();)
53
67.3k
}
skgpu::v1::SurfaceFillContext::SurfaceFillContext(GrRecordingContext*, GrSurfaceProxyView, GrSurfaceProxyView, GrColorInfo const&, bool)
Line
Count
Source
49
67.3k
        , fFlushTimeOpsTask(flushTimeOpsTask) {
50
67.3k
    fOpsTask = sk_ref_sp(rContext->priv().drawingManager()->getLastOpsTask(this->asSurfaceProxy()));
51
52
67.3k
    SkDEBUGCODE(this->validate();)
53
67.3k
}
54
55
void SurfaceFillContext::fillRectWithFP(const SkIRect& dstRect,
56
71.1k
                                        std::unique_ptr<GrFragmentProcessor> fp) {
57
35.5k
    ASSERT_SINGLE_OWNER
58
71.1k
    RETURN_IF_ABANDONED
59
35.5k
    SkDEBUGCODE(this->validate();)
60
71.1k
    GR_CREATE_TRACE_MARKER_CONTEXT("v1::SurfaceFillContext", "fillRectWithFP", fContext);
61
62
35.5k
    AutoCheckFlush acf(this->drawingManager());
63
64
35.5k
    GrPaint paint;
65
35.5k
    paint.setColorFragmentProcessor(std::move(fp));
66
35.5k
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
67
35.5k
    auto op = GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
68
35.5k
                                          SkRect::Make(dstRect));
69
35.5k
    this->addDrawOp(std::move(op));
70
35.5k
}
skgpu::v1::SurfaceFillContext::fillRectWithFP(SkIRect const&, std::__1::unique_ptr<GrFragmentProcessor, std::__1::default_delete<GrFragmentProcessor> >)
Line
Count
Source
56
35.5k
                                        std::unique_ptr<GrFragmentProcessor> fp) {
57
35.5k
    ASSERT_SINGLE_OWNER
58
35.5k
    RETURN_IF_ABANDONED
59
35.5k
    SkDEBUGCODE(this->validate();)
60
35.5k
    GR_CREATE_TRACE_MARKER_CONTEXT("v1::SurfaceFillContext", "fillRectWithFP", fContext);
61
62
35.5k
    AutoCheckFlush acf(this->drawingManager());
63
64
35.5k
    GrPaint paint;
65
35.5k
    paint.setColorFragmentProcessor(std::move(fp));
66
35.5k
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
67
35.5k
    auto op = GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
68
35.5k
                                          SkRect::Make(dstRect));
69
35.5k
    this->addDrawOp(std::move(op));
70
35.5k
}
skgpu::v1::SurfaceFillContext::fillRectWithFP(SkIRect const&, std::__1::unique_ptr<GrFragmentProcessor, std::__1::default_delete<GrFragmentProcessor> >)
Line
Count
Source
56
35.5k
                                        std::unique_ptr<GrFragmentProcessor> fp) {
57
35.5k
    ASSERT_SINGLE_OWNER
58
35.5k
    RETURN_IF_ABANDONED
59
35.5k
    SkDEBUGCODE(this->validate();)
60
35.5k
    GR_CREATE_TRACE_MARKER_CONTEXT("v1::SurfaceFillContext", "fillRectWithFP", fContext);
61
62
35.5k
    AutoCheckFlush acf(this->drawingManager());
63
64
35.5k
    GrPaint paint;
65
35.5k
    paint.setColorFragmentProcessor(std::move(fp));
66
35.5k
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
67
35.5k
    auto op = GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
68
35.5k
                                          SkRect::Make(dstRect));
69
35.5k
    this->addDrawOp(std::move(op));
70
35.5k
}
71
72
35.5k
void SurfaceFillContext::addDrawOp(GrOp::Owner owner) {
73
35.5k
    GrDrawOp* op = static_cast<GrDrawOp*>(owner.get());
74
35.5k
    GrClampType clampType = GrColorTypeClampType(this->colorInfo().colorType());
75
35.5k
    auto clip = GrAppliedClip::Disabled();
76
35.5k
    const GrCaps& caps = *this->caps();
77
35.5k
    GrProcessorSet::Analysis analysis = op->finalize(caps, &clip, clampType);
78
35.5k
    SkASSERT(!op->usesStencil());
79
35.5k
    SkASSERT(!analysis.requiresDstTexture());
80
35.5k
    SkRect bounds = owner->bounds();
81
    // We shouldn't have coverage AA or hairline draws in fill contexts.
82
35.5k
    SkASSERT(!op->hasAABloat() && !op->hasZeroArea());
83
35.5k
    if (!bounds.intersect(this->asSurfaceProxy()->getBoundsRect())) {
84
0
        return;
85
0
    }
86
35.5k
    op->setClippedBounds(op->bounds());
87
35.5k
    SkDEBUGCODE(op->fAddDrawOpCalled = true;)
88
89
35.5k
    GrDstProxyView dstProxyView;
90
35.5k
    this->getOpsTask()->addDrawOp(fContext->priv().drawingManager(),
91
35.5k
                                  std::move(owner),
92
35.5k
                                  op->usesMSAA(),
93
35.5k
                                  analysis,
94
35.5k
                                  std::move(clip),
95
35.5k
                                  dstProxyView,
96
35.5k
                                  GrTextureResolveManager(this->drawingManager()),
97
35.5k
                                  caps);
98
35.5k
}
99
100
0
void SurfaceFillContext::ClearToGrPaint(std::array<float, 4> color, GrPaint* paint) {
101
0
    paint->setColor4f({color[0], color[1], color[2], color[3]});
102
0
    if (color[3] == 1.f) {
103
        // Can just rely on the src-over blend mode to do the right thing.
104
        // This may improve batching.
105
0
        paint->setPorterDuffXPFactory(SkBlendMode::kSrcOver);
106
0
    } else {
107
        // A clear overwrites the prior color, so even if it's transparent, it behaves as if it
108
        // were src blended
109
0
        paint->setPorterDuffXPFactory(SkBlendMode::kSrc);
110
0
    }
111
0
}
112
113
1.84k
void SurfaceFillContext::addOp(GrOp::Owner op) {
114
1.84k
    GrDrawingManager* drawingMgr = this->drawingManager();
115
1.84k
    this->getOpsTask()->addOp(drawingMgr,
116
1.84k
                              std::move(op),
117
1.84k
                              GrTextureResolveManager(drawingMgr),
118
1.84k
                              *this->caps());
119
1.84k
}
120
121
188k
GrOpsTask* SurfaceFillContext::getOpsTask() {
122
188k
    ASSERT_SINGLE_OWNER
123
188k
    SkDEBUGCODE(this->validate();)
124
125
188k
    if (!fOpsTask || fOpsTask->isClosed()) {
126
89.6k
        this->replaceOpsTask();
127
89.6k
    }
128
188k
    SkASSERT(!fOpsTask->isClosed());
129
188k
    return fOpsTask.get();
130
188k
}
131
132
0
sk_sp<GrRenderTask> SurfaceFillContext::refRenderTask() {
133
0
    return sk_ref_sp(this->getOpsTask());
134
0
}
135
136
89.6k
GrOpsTask* SurfaceFillContext::replaceOpsTask() {
137
89.6k
    sk_sp<GrOpsTask> newOpsTask = this->drawingManager()->newOpsTask(
138
89.6k
            this->writeSurfaceView(), this->arenas(), fFlushTimeOpsTask);
139
89.6k
    this->willReplaceOpsTask(fOpsTask.get(), newOpsTask.get());
140
89.6k
    fOpsTask = std::move(newOpsTask);
141
89.6k
    return fOpsTask.get();
142
89.6k
}
143
144
#ifdef SK_DEBUG
145
0
void SurfaceFillContext::onValidate() const {
146
0
    if (fOpsTask && !fOpsTask->isClosed()) {
147
0
        SkASSERT(this->drawingManager()->getLastRenderTask(fWriteView.proxy()) == fOpsTask.get());
148
0
    }
149
0
}
150
#endif
151
152
0
void SurfaceFillContext::discard() {
153
0
    ASSERT_SINGLE_OWNER
154
0
    RETURN_IF_ABANDONED
155
0
    SkDEBUGCODE(this->validate();)
156
0
    GR_CREATE_TRACE_MARKER_CONTEXT("v1::SurfaceFillContext", "discard", fContext);
157
158
0
    AutoCheckFlush acf(this->drawingManager());
159
160
0
    this->getOpsTask()->discard();
161
0
}
Unexecuted instantiation: skgpu::v1::SurfaceFillContext::discard()
Unexecuted instantiation: skgpu::v1::SurfaceFillContext::discard()
162
163
void SurfaceFillContext::internalClear(const SkIRect* scissor,
164
                                       std::array<float, 4> color,
165
50.2k
                                       bool upgradePartialToFull) {
166
25.1k
    ASSERT_SINGLE_OWNER
167
50.2k
    RETURN_IF_ABANDONED
168
25.1k
    SkDEBUGCODE(this->validate();)
169
50.2k
    GR_CREATE_TRACE_MARKER_CONTEXT("v1::SurfaceFillContext", "clear", fContext);
170
171
    // There are three ways clears are handled: load ops, native clears, and draws. Load ops are
172
    // only for fullscreen clears; native clears can be fullscreen or with scissors if the backend
173
    // supports then. Drawing an axis-aligned rect is the fallback path.
174
25.1k
    GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions());
175
50.2k
    if (scissor && !scissorState.set(*scissor)) {
176
        // The clear is offscreen, so skip it (normally this would be handled by addDrawOp,
177
        // except clear ops are not draw ops).
178
0
        return;
179
0
    }
180
181
    // If we have a scissor but it's okay to clear beyond it for performance reasons, then disable
182
    // the test. We only do this when the clear would be handled by a load op or natively.
183
50.2k
    if (scissorState.enabled() && !this->caps()->performColorClearsAsDraws()) {
184
4.06k
        if (upgradePartialToFull && (this->caps()->preferFullscreenClears() ||
185
4.03k
                                     this->caps()->shouldInitializeTextures())) {
186
            // TODO: wrt the shouldInitializeTextures path, it would be more performant to
187
            // only clear the entire target if we knew it had not been cleared before. As
188
            // is this could end up doing a lot of redundant clears.
189
0
            scissorState.setDisabled();
190
4.06k
        } else {
191
            // Unlike with stencil clears, we also allow clears up to the logical dimensions of the
192
            // render target to overflow into any approx-fit padding of the backing store dimensions
193
4.06k
            scissorState.relaxTest(this->dimensions());
194
4.06k
        }
195
4.06k
    }
196
197
50.2k
    if (!scissorState.enabled()) {
198
        // This is a fullscreen clear, so could be handled as a load op. Regardless, we can also
199
        // discard all prior ops in the current task since the color buffer will be overwritten.
200
50.2k
        GrOpsTask* opsTask = this->getOpsTask();
201
50.2k
        if (opsTask->resetForFullscreenClear(this->canDiscardPreviousOpsOnFullClear()) &&
202
50.2k
            !this->caps()->performColorClearsAsDraws()) {
203
50.2k
            color = this->writeSurfaceView().swizzle().applyTo(color);
204
            // The op list was emptied and native clears are allowed, so just use the load op
205
50.2k
            opsTask->setColorLoadOp(GrLoadOp::kClear, color);
206
50.2k
            return;
207
0
        } else {
208
            // Will use an op for the clear, reset the load op to discard since the op will
209
            // blow away the color buffer contents
210
0
            opsTask->setColorLoadOp(GrLoadOp::kDiscard);
211
0
        }
212
50.2k
    }
213
214
    // At this point we are either a partial clear or a fullscreen clear that couldn't be applied
215
    // as a load op.
216
26
    bool clearAsDraw = this->caps()->performColorClearsAsDraws() ||
217
26
                       (scissorState.enabled() && this->caps()->performPartialClearsAsDraws());
218
26
    if (clearAsDraw) {
219
0
        GrPaint paint;
220
0
        ClearToGrPaint(color, &paint);
221
0
        auto op = GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
222
0
                                              SkRect::Make(scissorState.rect()));
223
0
        this->addDrawOp(std::move(op));
224
26
    } else {
225
26
        color = this->writeSurfaceView().swizzle().applyTo(color);
226
26
        this->addOp(GrClearOp::MakeColor(fContext, scissorState, color));
227
26
    }
228
26
}
skgpu::v1::SurfaceFillContext::internalClear(SkIRect const*, std::__1::array<float, 4ul>, bool)
Line
Count
Source
165
25.1k
                                       bool upgradePartialToFull) {
166
25.1k
    ASSERT_SINGLE_OWNER
167
25.1k
    RETURN_IF_ABANDONED
168
25.1k
    SkDEBUGCODE(this->validate();)
169
25.1k
    GR_CREATE_TRACE_MARKER_CONTEXT("v1::SurfaceFillContext", "clear", fContext);
170
171
    // There are three ways clears are handled: load ops, native clears, and draws. Load ops are
172
    // only for fullscreen clears; native clears can be fullscreen or with scissors if the backend
173
    // supports then. Drawing an axis-aligned rect is the fallback path.
174
25.1k
    GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions());
175
25.1k
    if (scissor && !scissorState.set(*scissor)) {
176
        // The clear is offscreen, so skip it (normally this would be handled by addDrawOp,
177
        // except clear ops are not draw ops).
178
0
        return;
179
0
    }
180
181
    // If we have a scissor but it's okay to clear beyond it for performance reasons, then disable
182
    // the test. We only do this when the clear would be handled by a load op or natively.
183
25.1k
    if (scissorState.enabled() && !this->caps()->performColorClearsAsDraws()) {
184
2.03k
        if (upgradePartialToFull && (this->caps()->preferFullscreenClears() ||
185
2.01k
                                     this->caps()->shouldInitializeTextures())) {
186
            // TODO: wrt the shouldInitializeTextures path, it would be more performant to
187
            // only clear the entire target if we knew it had not been cleared before. As
188
            // is this could end up doing a lot of redundant clears.
189
0
            scissorState.setDisabled();
190
2.03k
        } else {
191
            // Unlike with stencil clears, we also allow clears up to the logical dimensions of the
192
            // render target to overflow into any approx-fit padding of the backing store dimensions
193
2.03k
            scissorState.relaxTest(this->dimensions());
194
2.03k
        }
195
2.03k
    }
196
197
25.1k
    if (!scissorState.enabled()) {
198
        // This is a fullscreen clear, so could be handled as a load op. Regardless, we can also
199
        // discard all prior ops in the current task since the color buffer will be overwritten.
200
25.1k
        GrOpsTask* opsTask = this->getOpsTask();
201
25.1k
        if (opsTask->resetForFullscreenClear(this->canDiscardPreviousOpsOnFullClear()) &&
202
25.1k
            !this->caps()->performColorClearsAsDraws()) {
203
25.1k
            color = this->writeSurfaceView().swizzle().applyTo(color);
204
            // The op list was emptied and native clears are allowed, so just use the load op
205
25.1k
            opsTask->setColorLoadOp(GrLoadOp::kClear, color);
206
25.1k
            return;
207
0
        } else {
208
            // Will use an op for the clear, reset the load op to discard since the op will
209
            // blow away the color buffer contents
210
0
            opsTask->setColorLoadOp(GrLoadOp::kDiscard);
211
0
        }
212
25.1k
    }
213
214
    // At this point we are either a partial clear or a fullscreen clear that couldn't be applied
215
    // as a load op.
216
13
    bool clearAsDraw = this->caps()->performColorClearsAsDraws() ||
217
13
                       (scissorState.enabled() && this->caps()->performPartialClearsAsDraws());
218
13
    if (clearAsDraw) {
219
0
        GrPaint paint;
220
0
        ClearToGrPaint(color, &paint);
221
0
        auto op = GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
222
0
                                              SkRect::Make(scissorState.rect()));
223
0
        this->addDrawOp(std::move(op));
224
13
    } else {
225
13
        color = this->writeSurfaceView().swizzle().applyTo(color);
226
13
        this->addOp(GrClearOp::MakeColor(fContext, scissorState, color));
227
13
    }
228
13
}
skgpu::v1::SurfaceFillContext::internalClear(SkIRect const*, std::__1::array<float, 4ul>, bool)
Line
Count
Source
165
25.1k
                                       bool upgradePartialToFull) {
166
25.1k
    ASSERT_SINGLE_OWNER
167
25.1k
    RETURN_IF_ABANDONED
168
25.1k
    SkDEBUGCODE(this->validate();)
169
25.1k
    GR_CREATE_TRACE_MARKER_CONTEXT("v1::SurfaceFillContext", "clear", fContext);
170
171
    // There are three ways clears are handled: load ops, native clears, and draws. Load ops are
172
    // only for fullscreen clears; native clears can be fullscreen or with scissors if the backend
173
    // supports then. Drawing an axis-aligned rect is the fallback path.
174
25.1k
    GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions());
175
25.1k
    if (scissor && !scissorState.set(*scissor)) {
176
        // The clear is offscreen, so skip it (normally this would be handled by addDrawOp,
177
        // except clear ops are not draw ops).
178
0
        return;
179
0
    }
180
181
    // If we have a scissor but it's okay to clear beyond it for performance reasons, then disable
182
    // the test. We only do this when the clear would be handled by a load op or natively.
183
25.1k
    if (scissorState.enabled() && !this->caps()->performColorClearsAsDraws()) {
184
2.03k
        if (upgradePartialToFull && (this->caps()->preferFullscreenClears() ||
185
2.01k
                                     this->caps()->shouldInitializeTextures())) {
186
            // TODO: wrt the shouldInitializeTextures path, it would be more performant to
187
            // only clear the entire target if we knew it had not been cleared before. As
188
            // is this could end up doing a lot of redundant clears.
189
0
            scissorState.setDisabled();
190
2.03k
        } else {
191
            // Unlike with stencil clears, we also allow clears up to the logical dimensions of the
192
            // render target to overflow into any approx-fit padding of the backing store dimensions
193
2.03k
            scissorState.relaxTest(this->dimensions());
194
2.03k
        }
195
2.03k
    }
196
197
25.1k
    if (!scissorState.enabled()) {
198
        // This is a fullscreen clear, so could be handled as a load op. Regardless, we can also
199
        // discard all prior ops in the current task since the color buffer will be overwritten.
200
25.1k
        GrOpsTask* opsTask = this->getOpsTask();
201
25.1k
        if (opsTask->resetForFullscreenClear(this->canDiscardPreviousOpsOnFullClear()) &&
202
25.1k
            !this->caps()->performColorClearsAsDraws()) {
203
25.1k
            color = this->writeSurfaceView().swizzle().applyTo(color);
204
            // The op list was emptied and native clears are allowed, so just use the load op
205
25.1k
            opsTask->setColorLoadOp(GrLoadOp::kClear, color);
206
25.1k
            return;
207
0
        } else {
208
            // Will use an op for the clear, reset the load op to discard since the op will
209
            // blow away the color buffer contents
210
0
            opsTask->setColorLoadOp(GrLoadOp::kDiscard);
211
0
        }
212
25.1k
    }
213
214
    // At this point we are either a partial clear or a fullscreen clear that couldn't be applied
215
    // as a load op.
216
13
    bool clearAsDraw = this->caps()->performColorClearsAsDraws() ||
217
13
                       (scissorState.enabled() && this->caps()->performPartialClearsAsDraws());
218
13
    if (clearAsDraw) {
219
0
        GrPaint paint;
220
0
        ClearToGrPaint(color, &paint);
221
0
        auto op = GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
222
0
                                              SkRect::Make(scissorState.rect()));
223
0
        this->addDrawOp(std::move(op));
224
13
    } else {
225
13
        color = this->writeSurfaceView().swizzle().applyTo(color);
226
13
        this->addOp(GrClearOp::MakeColor(fContext, scissorState, color));
227
13
    }
228
13
}
229
230
bool SurfaceFillContext::blitTexture(GrSurfaceProxyView view,
231
                                     const SkIRect& srcRect,
232
0
                                     const SkIPoint& dstPoint) {
233
0
    SkASSERT(view.asTextureProxy());
234
0
    SkIRect clippedSrcRect;
235
0
    SkIPoint clippedDstPoint;
236
0
    if (!GrClipSrcRectAndDstPoint(this->dimensions(),
237
0
                                  view.dimensions(),
238
0
                                  srcRect,
239
0
                                  dstPoint,
240
0
                                  &clippedSrcRect,
241
0
                                  &clippedDstPoint)) {
242
0
        return false;
243
0
    }
244
245
0
    auto fp = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
246
0
    auto dstRect = SkIRect::MakePtSize(clippedDstPoint, clippedSrcRect.size());
247
0
    auto srcRectF = SkRect::Make(clippedSrcRect);
248
0
    this->fillRectToRectWithFP(srcRectF, dstRect, std::move(fp));
249
0
    return true;
250
0
}
Unexecuted instantiation: skgpu::v1::SurfaceFillContext::blitTexture(GrSurfaceProxyView, SkIRect const&, SkIPoint const&)
Unexecuted instantiation: skgpu::v1::SurfaceFillContext::blitTexture(GrSurfaceProxyView, SkIRect const&, SkIPoint const&)
251
252
} // namespace skgpu::v1