/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 |