LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/instanced - InstancedRendering.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 299 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.13