Line data Source code
1 : /*
2 : * Copyright 2016 Google Inc.
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 "InstancedRendering.h"
9 : #include "GrAppliedClip.h"
10 : #include "GrCaps.h"
11 : #include "GrOpFlushState.h"
12 : #include "GrPipeline.h"
13 : #include "GrResourceProvider.h"
14 : #include "instanced/InstanceProcessor.h"
15 :
16 : namespace gr_instanced {
17 :
18 0 : InstancedRendering::InstancedRendering(GrGpu* gpu)
19 : : fGpu(SkRef(gpu)),
20 : fState(State::kRecordingDraws),
21 0 : fDrawPool(1024, 1024) {
22 0 : }
23 :
24 0 : std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
25 : const SkMatrix& viewMatrix,
26 : GrPaint&& paint, GrAA aa,
27 : const GrInstancedPipelineInfo& info) {
28 0 : return this->recordShape(ShapeType::kRect, rect, viewMatrix, std::move(paint), rect, aa, info);
29 : }
30 :
31 0 : std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
32 : const SkMatrix& viewMatrix,
33 : GrPaint&& paint, const SkRect& localRect,
34 : GrAA aa,
35 : const GrInstancedPipelineInfo& info) {
36 0 : return this->recordShape(ShapeType::kRect, rect, viewMatrix, std::move(paint), localRect, aa,
37 0 : info);
38 : }
39 :
40 0 : std::unique_ptr<GrDrawOp> InstancedRendering::recordRect(const SkRect& rect,
41 : const SkMatrix& viewMatrix,
42 : GrPaint&& paint,
43 : const SkMatrix& localMatrix, GrAA aa,
44 : const GrInstancedPipelineInfo& info) {
45 0 : if (localMatrix.hasPerspective()) {
46 0 : return nullptr; // Perspective is not yet supported in the local matrix.
47 : }
48 0 : if (std::unique_ptr<Op> op = this->recordShape(ShapeType::kRect, rect, viewMatrix,
49 0 : std::move(paint), rect, aa, info)) {
50 0 : op->getSingleInstance().fInfo |= kLocalMatrix_InfoFlag;
51 0 : op->appendParamsTexel(localMatrix.getScaleX(), localMatrix.getSkewX(),
52 0 : localMatrix.getTranslateX());
53 0 : op->appendParamsTexel(localMatrix.getSkewY(), localMatrix.getScaleY(),
54 0 : localMatrix.getTranslateY());
55 0 : op->fInfo.fHasLocalMatrix = true;
56 0 : return std::move(op);
57 : }
58 0 : return nullptr;
59 : }
60 :
61 0 : std::unique_ptr<GrDrawOp> InstancedRendering::recordOval(const SkRect& oval,
62 : const SkMatrix& viewMatrix,
63 : GrPaint&& paint, GrAA aa,
64 : const GrInstancedPipelineInfo& info) {
65 0 : return this->recordShape(ShapeType::kOval, oval, viewMatrix, std::move(paint), oval, aa, info);
66 : }
67 :
68 0 : std::unique_ptr<GrDrawOp> InstancedRendering::recordRRect(const SkRRect& rrect,
69 : const SkMatrix& viewMatrix,
70 : GrPaint&& paint, GrAA aa,
71 : const GrInstancedPipelineInfo& info) {
72 0 : if (std::unique_ptr<Op> op =
73 : this->recordShape(GetRRectShapeType(rrect), rrect.rect(), viewMatrix,
74 0 : std::move(paint), rrect.rect(), aa, info)) {
75 0 : op->appendRRectParams(rrect);
76 0 : return std::move(op);
77 : }
78 0 : return nullptr;
79 : }
80 :
81 0 : std::unique_ptr<GrDrawOp> InstancedRendering::recordDRRect(const SkRRect& outer,
82 : const SkRRect& inner,
83 : const SkMatrix& viewMatrix,
84 : GrPaint&& paint, GrAA aa,
85 : const GrInstancedPipelineInfo& info) {
86 0 : if (inner.getType() > SkRRect::kSimple_Type) {
87 0 : return nullptr; // Complex inner round rects are not yet supported.
88 : }
89 0 : if (SkRRect::kEmpty_Type == inner.getType()) {
90 0 : return this->recordRRect(outer, viewMatrix, std::move(paint), aa, info);
91 : }
92 0 : if (std::unique_ptr<Op> op =
93 : this->recordShape(GetRRectShapeType(outer), outer.rect(), viewMatrix,
94 0 : std::move(paint), outer.rect(), aa, info)) {
95 0 : op->appendRRectParams(outer);
96 0 : ShapeType innerShapeType = GetRRectShapeType(inner);
97 0 : op->fInfo.fInnerShapeTypes |= GetShapeFlag(innerShapeType);
98 0 : op->getSingleInstance().fInfo |= ((int)innerShapeType << kInnerShapeType_InfoBit);
99 0 : op->appendParamsTexel(inner.rect().asScalars(), 4);
100 0 : op->appendRRectParams(inner);
101 0 : return std::move(op);
102 : }
103 0 : return nullptr;
104 : }
105 :
106 0 : std::unique_ptr<InstancedRendering::Op> InstancedRendering::recordShape(
107 : ShapeType type, const SkRect& bounds, const SkMatrix& viewMatrix, GrPaint&& paint,
108 : const SkRect& localRect, GrAA aa, const GrInstancedPipelineInfo& info) {
109 0 : SkASSERT(State::kRecordingDraws == fState);
110 :
111 0 : if (info.fIsRenderingToFloat && fGpu->caps()->avoidInstancedDrawsToFPTargets()) {
112 0 : return nullptr;
113 : }
114 :
115 : GrAAType aaType;
116 0 : if (!this->selectAntialiasMode(viewMatrix, aa, info, &aaType)) {
117 0 : return nullptr;
118 : }
119 :
120 0 : GrColor color = paint.getColor();
121 0 : std::unique_ptr<Op> op = this->makeOp(std::move(paint));
122 0 : op->fInfo.setAAType(aaType);
123 0 : op->fInfo.fShapeTypes = GetShapeFlag(type);
124 0 : op->fInfo.fCannotDiscard = true;
125 0 : Instance& instance = op->getSingleInstance();
126 0 : instance.fInfo = (int)type << kShapeType_InfoBit;
127 :
128 : Op::HasAABloat aaBloat =
129 0 : (aaType == GrAAType::kCoverage) ? Op::HasAABloat::kYes : Op::HasAABloat::kNo;
130 0 : Op::IsZeroArea zeroArea = (bounds.isEmpty()) ? Op::IsZeroArea::kYes : Op::IsZeroArea::kNo;
131 :
132 : // The instanced shape renderer draws rectangles of [-1, -1, +1, +1], so we find the matrix that
133 : // will map this rectangle to the same device coordinates as "viewMatrix * bounds".
134 0 : float sx = 0.5f * bounds.width();
135 0 : float sy = 0.5f * bounds.height();
136 0 : float tx = sx + bounds.fLeft;
137 0 : float ty = sy + bounds.fTop;
138 0 : if (!viewMatrix.hasPerspective()) {
139 0 : float* m = instance.fShapeMatrix2x3;
140 0 : m[0] = viewMatrix.getScaleX() * sx;
141 0 : m[1] = viewMatrix.getSkewX() * sy;
142 0 : m[2] = viewMatrix.getTranslateX() +
143 0 : viewMatrix.getScaleX() * tx + viewMatrix.getSkewX() * ty;
144 :
145 0 : m[3] = viewMatrix.getSkewY() * sx;
146 0 : m[4] = viewMatrix.getScaleY() * sy;
147 0 : m[5] = viewMatrix.getTranslateY() +
148 0 : viewMatrix.getSkewY() * tx + viewMatrix.getScaleY() * ty;
149 :
150 : // Since 'm' is a 2x3 matrix that maps the rect [-1, +1] into the shape's device-space quad,
151 : // it's quite simple to find the bounding rectangle:
152 0 : float devBoundsHalfWidth = fabsf(m[0]) + fabsf(m[1]);
153 0 : float devBoundsHalfHeight = fabsf(m[3]) + fabsf(m[4]);
154 : SkRect opBounds;
155 0 : opBounds.fLeft = m[2] - devBoundsHalfWidth;
156 0 : opBounds.fRight = m[2] + devBoundsHalfWidth;
157 0 : opBounds.fTop = m[5] - devBoundsHalfHeight;
158 0 : opBounds.fBottom = m[5] + devBoundsHalfHeight;
159 0 : op->setBounds(opBounds, aaBloat, zeroArea);
160 :
161 : // TODO: Is this worth the CPU overhead?
162 0 : op->fInfo.fNonSquare =
163 0 : fabsf(devBoundsHalfHeight - devBoundsHalfWidth) > 0.5f || // Early out.
164 0 : fabs(m[0] * m[3] + m[1] * m[4]) > 1e-3f || // Skew?
165 0 : fabs(m[0] * m[0] + m[1] * m[1] - m[3] * m[3] - m[4] * m[4]) >
166 : 1e-2f; // Diff. lengths?
167 : } else {
168 0 : SkMatrix shapeMatrix(viewMatrix);
169 0 : shapeMatrix.preTranslate(tx, ty);
170 0 : shapeMatrix.preScale(sx, sy);
171 0 : instance.fInfo |= kPerspective_InfoFlag;
172 :
173 0 : float* m = instance.fShapeMatrix2x3;
174 0 : m[0] = SkScalarToFloat(shapeMatrix.getScaleX());
175 0 : m[1] = SkScalarToFloat(shapeMatrix.getSkewX());
176 0 : m[2] = SkScalarToFloat(shapeMatrix.getTranslateX());
177 0 : m[3] = SkScalarToFloat(shapeMatrix.getSkewY());
178 0 : m[4] = SkScalarToFloat(shapeMatrix.getScaleY());
179 0 : m[5] = SkScalarToFloat(shapeMatrix.getTranslateY());
180 :
181 : // Send the perspective column as a param.
182 0 : op->appendParamsTexel(shapeMatrix[SkMatrix::kMPersp0], shapeMatrix[SkMatrix::kMPersp1],
183 0 : shapeMatrix[SkMatrix::kMPersp2]);
184 0 : op->fInfo.fHasPerspective = true;
185 :
186 0 : op->setBounds(bounds, aaBloat, zeroArea);
187 0 : op->fInfo.fNonSquare = true;
188 : }
189 :
190 0 : instance.fColor = color;
191 :
192 0 : const float* rectAsFloats = localRect.asScalars(); // Ensure SkScalar == float.
193 0 : memcpy(&instance.fLocalRect, rectAsFloats, 4 * sizeof(float));
194 :
195 0 : op->fPixelLoad = op->bounds().height() * op->bounds().width();
196 0 : return op;
197 : }
198 :
199 0 : inline bool InstancedRendering::selectAntialiasMode(const SkMatrix& viewMatrix, GrAA aa,
200 : const GrInstancedPipelineInfo& info,
201 : GrAAType* aaType) {
202 0 : SkASSERT(!info.fIsMixedSampled || info.fIsMultisampled);
203 0 : SkASSERT(GrCaps::InstancedSupport::kNone != fGpu->caps()->instancedSupport());
204 :
205 0 : if (!info.fIsMultisampled || fGpu->caps()->multisampleDisableSupport()) {
206 0 : if (GrAA::kNo == aa) {
207 0 : *aaType = GrAAType::kNone;
208 0 : return true;
209 : }
210 :
211 0 : if (info.canUseCoverageAA() && viewMatrix.preservesRightAngles()) {
212 0 : *aaType = GrAAType::kCoverage;
213 0 : return true;
214 : }
215 : }
216 :
217 0 : if (info.fIsMultisampled &&
218 0 : fGpu->caps()->instancedSupport() >= GrCaps::InstancedSupport::kMultisampled) {
219 0 : if (!info.fIsMixedSampled) {
220 0 : *aaType = GrAAType::kMSAA;
221 0 : return true;
222 : }
223 0 : if (fGpu->caps()->instancedSupport() >= GrCaps::InstancedSupport::kMixedSampled) {
224 0 : *aaType = GrAAType::kMixedSamples;
225 0 : return true;
226 : }
227 : }
228 :
229 0 : return false;
230 : }
231 :
232 0 : InstancedRendering::Op::Op(uint32_t classID, GrPaint&& paint, InstancedRendering* ir)
233 : : INHERITED(classID)
234 : , fInstancedRendering(ir)
235 0 : , fProcessors(std::move(paint))
236 : , fIsTracked(false)
237 : , fRequiresBarrierOnOverlap(false)
238 : , fNumDraws(1)
239 0 : , fNumChangesInGeometry(0) {
240 0 : fHeadDraw = fTailDraw = fInstancedRendering->fDrawPool.allocate();
241 : #ifdef SK_DEBUG
242 0 : fHeadDraw->fGeometry = {-1, 0};
243 : #endif
244 0 : fHeadDraw->fNext = nullptr;
245 0 : }
246 :
247 0 : InstancedRendering::Op::~Op() {
248 0 : if (fIsTracked) {
249 0 : fInstancedRendering->fTrackedOps.remove(this);
250 : }
251 :
252 0 : Draw* draw = fHeadDraw;
253 0 : while (draw) {
254 0 : Draw* next = draw->fNext;
255 0 : fInstancedRendering->fDrawPool.release(draw);
256 0 : draw = next;
257 : }
258 0 : }
259 :
260 0 : void InstancedRendering::Op::appendRRectParams(const SkRRect& rrect) {
261 0 : SkASSERT(!fIsTracked);
262 0 : switch (rrect.getType()) {
263 : case SkRRect::kSimple_Type: {
264 0 : const SkVector& radii = rrect.getSimpleRadii();
265 0 : this->appendParamsTexel(radii.x(), radii.y(), rrect.width(), rrect.height());
266 0 : return;
267 : }
268 : case SkRRect::kNinePatch_Type: {
269 0 : float twoOverW = 2 / rrect.width();
270 0 : float twoOverH = 2 / rrect.height();
271 0 : const SkVector& radiiTL = rrect.radii(SkRRect::kUpperLeft_Corner);
272 0 : const SkVector& radiiBR = rrect.radii(SkRRect::kLowerRight_Corner);
273 0 : this->appendParamsTexel(radiiTL.x() * twoOverW, radiiBR.x() * twoOverW,
274 0 : radiiTL.y() * twoOverH, radiiBR.y() * twoOverH);
275 0 : return;
276 : }
277 : case SkRRect::kComplex_Type: {
278 : /**
279 : * The x and y radii of each arc are stored in separate vectors,
280 : * in the following order:
281 : *
282 : * __x1 _ _ _ x3__
283 : * y1 | | y2
284 : *
285 : * | |
286 : *
287 : * y3 |__ _ _ _ __| y4
288 : * x2 x4
289 : *
290 : */
291 0 : float twoOverW = 2 / rrect.width();
292 0 : float twoOverH = 2 / rrect.height();
293 0 : const SkVector& radiiTL = rrect.radii(SkRRect::kUpperLeft_Corner);
294 0 : const SkVector& radiiTR = rrect.radii(SkRRect::kUpperRight_Corner);
295 0 : const SkVector& radiiBR = rrect.radii(SkRRect::kLowerRight_Corner);
296 0 : const SkVector& radiiBL = rrect.radii(SkRRect::kLowerLeft_Corner);
297 0 : this->appendParamsTexel(radiiTL.x() * twoOverW, radiiBL.x() * twoOverW,
298 0 : radiiTR.x() * twoOverW, radiiBR.x() * twoOverW);
299 0 : this->appendParamsTexel(radiiTL.y() * twoOverH, radiiTR.y() * twoOverH,
300 0 : radiiBL.y() * twoOverH, radiiBR.y() * twoOverH);
301 0 : return;
302 : }
303 0 : default: return;
304 : }
305 : }
306 :
307 0 : void InstancedRendering::Op::appendParamsTexel(const SkScalar* vals, int count) {
308 0 : SkASSERT(!fIsTracked);
309 0 : SkASSERT(count <= 4 && count >= 0);
310 0 : const float* valsAsFloats = vals; // Ensure SkScalar == float.
311 0 : memcpy(&fParams.push_back(), valsAsFloats, count * sizeof(float));
312 0 : fInfo.fHasParams = true;
313 0 : }
314 :
315 0 : void InstancedRendering::Op::appendParamsTexel(SkScalar x, SkScalar y, SkScalar z, SkScalar w) {
316 0 : SkASSERT(!fIsTracked);
317 0 : ParamsTexel& texel = fParams.push_back();
318 0 : texel.fX = SkScalarToFloat(x);
319 0 : texel.fY = SkScalarToFloat(y);
320 0 : texel.fZ = SkScalarToFloat(z);
321 0 : texel.fW = SkScalarToFloat(w);
322 0 : fInfo.fHasParams = true;
323 0 : }
324 :
325 0 : void InstancedRendering::Op::appendParamsTexel(SkScalar x, SkScalar y, SkScalar z) {
326 0 : SkASSERT(!fIsTracked);
327 0 : ParamsTexel& texel = fParams.push_back();
328 0 : texel.fX = SkScalarToFloat(x);
329 0 : texel.fY = SkScalarToFloat(y);
330 0 : texel.fZ = SkScalarToFloat(z);
331 0 : fInfo.fHasParams = true;
332 0 : }
333 :
334 0 : bool InstancedRendering::Op::xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) {
335 0 : SkASSERT(State::kRecordingDraws == fInstancedRendering->fState);
336 : GrProcessorAnalysisCoverage coverageInput;
337 0 : bool isMixedSamples = false;
338 0 : if (GrAAType::kCoverage == fInfo.aaType() ||
339 0 : (GrAAType::kNone == fInfo.aaType() && !fInfo.isSimpleRects() && fInfo.fCannotDiscard)) {
340 0 : coverageInput = GrProcessorAnalysisCoverage::kSingleChannel;
341 : } else {
342 0 : coverageInput = GrProcessorAnalysisCoverage::kNone;
343 0 : isMixedSamples = GrAAType::kMixedSamples == fInfo.aaType();
344 : }
345 : GrProcessorSet::Analysis analysis =
346 0 : fProcessors.finalize(this->getSingleInstance().fColor, coverageInput, clip,
347 0 : isMixedSamples, caps, &this->getSingleDraw().fInstance.fColor);
348 :
349 0 : Draw& draw = this->getSingleDraw(); // This will assert if we have > 1 command.
350 0 : SkASSERT(draw.fGeometry.isEmpty());
351 0 : SkASSERT(SkIsPow2(fInfo.fShapeTypes));
352 0 : SkASSERT(!fIsTracked);
353 :
354 0 : if (kRect_ShapeFlag == fInfo.fShapeTypes) {
355 0 : draw.fGeometry = InstanceProcessor::GetIndexRangeForRect(fInfo.aaType());
356 0 : } else if (kOval_ShapeFlag == fInfo.fShapeTypes) {
357 0 : draw.fGeometry = InstanceProcessor::GetIndexRangeForOval(fInfo.aaType(), this->bounds());
358 : } else {
359 0 : draw.fGeometry = InstanceProcessor::GetIndexRangeForRRect(fInfo.aaType());
360 : }
361 :
362 0 : if (!fParams.empty()) {
363 0 : SkASSERT(fInstancedRendering->fParams.count() < (int)kParamsIdx_InfoMask); // TODO: cleaner.
364 0 : this->getSingleInstance().fInfo |= fInstancedRendering->fParams.count();
365 0 : fInstancedRendering->fParams.push_back_n(fParams.count(), fParams.begin());
366 : }
367 :
368 0 : fInfo.fCannotTweakAlphaForCoverage = !analysis.isCompatibleWithCoverageAsAlpha();
369 :
370 0 : fInfo.fUsesLocalCoords = analysis.usesLocalCoords();
371 0 : fRequiresBarrierOnOverlap = analysis.requiresBarrierBetweenOverlappingDraws();
372 0 : return analysis.requiresDstTexture();
373 : }
374 :
375 0 : void InstancedRendering::Op::wasRecorded() {
376 0 : SkASSERT(!fIsTracked);
377 0 : fInstancedRendering->fTrackedOps.addToTail(this);
378 0 : fIsTracked = true;
379 0 : }
380 :
381 0 : bool InstancedRendering::Op::onCombineIfPossible(GrOp* other, const GrCaps& caps) {
382 0 : Op* that = static_cast<Op*>(other);
383 0 : SkASSERT(fInstancedRendering == that->fInstancedRendering);
384 0 : SkASSERT(fTailDraw);
385 0 : SkASSERT(that->fTailDraw);
386 :
387 0 : if (!OpInfo::CanCombine(fInfo, that->fInfo) || fProcessors != that->fProcessors) {
388 0 : return false;
389 : }
390 :
391 0 : SkASSERT(fRequiresBarrierOnOverlap == that->fRequiresBarrierOnOverlap);
392 0 : if (fRequiresBarrierOnOverlap && this->bounds().intersects(that->bounds())) {
393 0 : return false;
394 : }
395 0 : OpInfo combinedInfo = fInfo | that->fInfo;
396 0 : if (!combinedInfo.isSimpleRects()) {
397 : // This threshold was chosen with the "shapes_mixed" bench on a MacBook with Intel graphics.
398 : // There seems to be a wide range where it doesn't matter if we combine or not. What matters
399 : // is that the itty bitty rects combine with other shapes and the giant ones don't.
400 0 : constexpr SkScalar kMaxPixelsToGeneralizeRects = 256 * 256;
401 0 : if (fInfo.isSimpleRects() && fPixelLoad > kMaxPixelsToGeneralizeRects) {
402 0 : return false;
403 : }
404 0 : if (that->fInfo.isSimpleRects() && that->fPixelLoad > kMaxPixelsToGeneralizeRects) {
405 0 : return false;
406 : }
407 : }
408 :
409 0 : this->joinBounds(*that);
410 0 : fInfo = combinedInfo;
411 0 : fPixelLoad += that->fPixelLoad;
412 : // Adopt the other op's draws.
413 0 : fNumDraws += that->fNumDraws;
414 0 : fNumChangesInGeometry += that->fNumChangesInGeometry;
415 0 : if (fTailDraw->fGeometry != that->fHeadDraw->fGeometry) {
416 0 : ++fNumChangesInGeometry;
417 : }
418 0 : fTailDraw->fNext = that->fHeadDraw;
419 0 : fTailDraw = that->fTailDraw;
420 :
421 0 : that->fHeadDraw = that->fTailDraw = nullptr;
422 :
423 0 : return true;
424 : }
425 :
426 0 : void InstancedRendering::beginFlush(GrResourceProvider* rp) {
427 0 : SkASSERT(State::kRecordingDraws == fState);
428 0 : fState = State::kFlushing;
429 :
430 0 : if (fTrackedOps.isEmpty()) {
431 0 : return;
432 : }
433 :
434 0 : if (!fVertexBuffer) {
435 0 : fVertexBuffer.reset(InstanceProcessor::FindOrCreateVertexBuffer(fGpu.get()));
436 0 : if (!fVertexBuffer) {
437 0 : return;
438 : }
439 : }
440 :
441 0 : if (!fIndexBuffer) {
442 0 : fIndexBuffer.reset(InstanceProcessor::FindOrCreateIndex8Buffer(fGpu.get()));
443 0 : if (!fIndexBuffer) {
444 0 : return;
445 : }
446 : }
447 :
448 0 : if (!fParams.empty()) {
449 0 : fParamsBuffer.reset(rp->createBuffer(fParams.count() * sizeof(ParamsTexel),
450 : kTexel_GrBufferType, kDynamic_GrAccessPattern,
451 : GrResourceProvider::kNoPendingIO_Flag |
452 : GrResourceProvider::kRequireGpuMemory_Flag,
453 0 : fParams.begin()));
454 0 : if (!fParamsBuffer) {
455 0 : return;
456 : }
457 : }
458 :
459 0 : this->onBeginFlush(rp);
460 : }
461 :
462 0 : void InstancedRendering::Op::onExecute(GrOpFlushState* state) {
463 0 : SkASSERT(State::kFlushing == fInstancedRendering->fState);
464 0 : SkASSERT(state->gpu() == fInstancedRendering->gpu());
465 :
466 0 : state->gpu()->handleDirtyContext();
467 :
468 0 : GrPipeline pipeline;
469 0 : GrPipeline::InitArgs args;
470 0 : args.fAppliedClip = state->drawOpArgs().fAppliedClip;
471 0 : args.fCaps = &state->caps();
472 0 : args.fProcessors = &fProcessors;
473 0 : args.fFlags = GrAATypeIsHW(fInfo.aaType()) ? GrPipeline::kHWAntialias_Flag : 0;
474 0 : args.fRenderTarget = state->drawOpArgs().fRenderTarget;
475 0 : args.fDstTexture = state->drawOpArgs().fDstTexture;
476 0 : pipeline.init(args);
477 :
478 0 : if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*state->gpu()->caps())) {
479 0 : state->gpu()->xferBarrier(pipeline.getRenderTarget(), barrierType);
480 : }
481 0 : InstanceProcessor instProc(fInfo, fInstancedRendering->fParamsBuffer.get());
482 0 : fInstancedRendering->onDraw(pipeline, instProc, this);
483 0 : }
484 :
485 0 : void InstancedRendering::endFlush() {
486 : // The caller is expected to delete all tracked ops (i.e. ops whose applyPipelineOptimizations
487 : // method has been called) before ending the flush.
488 0 : SkASSERT(fTrackedOps.isEmpty());
489 0 : fParams.reset();
490 0 : fParamsBuffer.reset();
491 0 : this->onEndFlush();
492 0 : fState = State::kRecordingDraws;
493 : // Hold on to the shape coords and index buffers.
494 0 : }
495 :
496 0 : void InstancedRendering::resetGpuResources(ResetType resetType) {
497 0 : fVertexBuffer.reset();
498 0 : fIndexBuffer.reset();
499 0 : fParamsBuffer.reset();
500 0 : this->onResetGpuResources(resetType);
501 0 : }
502 :
503 : }
|