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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2015 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 "GrDrawPathOp.h"
       9             : #include "GrAppliedClip.h"
      10             : #include "GrRenderTargetContext.h"
      11             : #include "GrRenderTargetPriv.h"
      12             : #include "SkTemplates.h"
      13             : 
      14           0 : GrDrawPathOpBase::GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
      15           0 :                                    GrPathRendering::FillType fill, GrAAType aaType)
      16             :         : INHERITED(classID)
      17             :         , fViewMatrix(viewMatrix)
      18           0 :         , fInputColor(paint.getColor())
      19           0 :         , fProcessorSet(std::move(paint))
      20             :         , fFillType(fill)
      21           0 :         , fAAType(aaType) {
      22           0 :     SkASSERT(fAAType != GrAAType::kCoverage);
      23           0 : }
      24             : 
      25           0 : SkString GrDrawPathOp::dumpInfo() const {
      26           0 :     SkString string;
      27           0 :     string.printf("PATH: 0x%p", fPath.get());
      28           0 :     string.append(INHERITED::dumpInfo());
      29           0 :     return string;
      30             : }
      31             : 
      32           0 : void GrDrawPathOpBase::initPipeline(const GrOpFlushState& state, GrPipeline* pipeline) {
      33             :     static constexpr GrUserStencilSettings kCoverPass{
      34             :             GrUserStencilSettings::StaticInit<
      35             :                     0x0000,
      36             :                     GrUserStencilTest::kNotEqual,
      37             :                     0xffff,
      38             :                     GrUserStencilOp::kZero,
      39             :                     GrUserStencilOp::kKeep,
      40             :                     0xffff>()
      41             :     };
      42           0 :     GrPipeline::InitArgs args;
      43           0 :     args.fProcessors = &this->processors();
      44           0 :     args.fFlags = GrAATypeIsHW(fAAType) ? GrPipeline::kHWAntialias_Flag : 0;
      45           0 :     args.fUserStencil = &kCoverPass;
      46           0 :     args.fAppliedClip = state.drawOpArgs().fAppliedClip;
      47           0 :     args.fRenderTarget = state.drawOpArgs().fRenderTarget;
      48           0 :     args.fCaps = &state.caps();
      49           0 :     args.fDstTexture = state.drawOpArgs().fDstTexture;
      50             : 
      51           0 :     return pipeline->init(args);
      52             : }
      53             : 
      54             : //////////////////////////////////////////////////////////////////////////////
      55             : 
      56           0 : void init_stencil_pass_settings(const GrOpFlushState& flushState,
      57             :                                 GrPathRendering::FillType fillType, GrStencilSettings* stencil) {
      58           0 :     const GrAppliedClip* appliedClip = flushState.drawOpArgs().fAppliedClip;
      59           0 :     bool stencilClip = appliedClip && appliedClip->hasStencilClip();
      60           0 :     stencil->reset(GrPathRendering::GetStencilPassSettings(fillType), stencilClip,
      61           0 :                    flushState.drawOpArgs().fRenderTarget->renderTargetPriv().numStencilBits());
      62           0 : }
      63             : 
      64             : //////////////////////////////////////////////////////////////////////////////
      65             : 
      66           0 : void GrDrawPathOp::onExecute(GrOpFlushState* state) {
      67           0 :     GrPipeline pipeline;
      68           0 :     this->initPipeline(*state, &pipeline);
      69           0 :     sk_sp<GrPathProcessor> pathProc(GrPathProcessor::Create(this->color(), this->viewMatrix()));
      70             : 
      71           0 :     GrStencilSettings stencil;
      72           0 :     init_stencil_pass_settings(*state, this->fillType(), &stencil);
      73           0 :     state->gpu()->pathRendering()->drawPath(pipeline, *pathProc, stencil, fPath.get());
      74           0 : }
      75             : 
      76             : //////////////////////////////////////////////////////////////////////////////
      77             : 
      78           0 : SkString GrDrawPathRangeOp::dumpInfo() const {
      79           0 :     SkString string;
      80           0 :     string.printf("RANGE: 0x%p COUNTS: [", fPathRange.get());
      81           0 :     for (DrawList::Iter iter(fDraws); iter.get(); iter.next()) {
      82           0 :         string.appendf("%d, ", iter.get()->fInstanceData->count());
      83             :     }
      84           0 :     string.remove(string.size() - 2, 2);
      85           0 :     string.append("]");
      86           0 :     string.append(INHERITED::dumpInfo());
      87           0 :     return string;
      88             : }
      89             : 
      90           0 : GrDrawPathRangeOp::GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x,
      91             :                                      SkScalar y, GrPaint&& paint, GrPathRendering::FillType fill,
      92             :                                      GrAAType aaType, GrPathRange* range,
      93           0 :                                      const InstanceData* instanceData, const SkRect& bounds)
      94           0 :         : INHERITED(ClassID(), viewMatrix, std::move(paint), fill, aaType)
      95             :         , fPathRange(range)
      96           0 :         , fTotalPathCount(instanceData->count())
      97           0 :         , fScale(scale) {
      98           0 :     fDraws.addToHead()->set(instanceData, x, y);
      99           0 :     this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
     100           0 : }
     101             : 
     102             : static void pre_translate_transform_values(const float* xforms,
     103             :                                            GrPathRendering::PathTransformType type, int count,
     104             :                                            SkScalar x, SkScalar y, float* dst);
     105             : 
     106           0 : bool GrDrawPathRangeOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
     107           0 :     GrDrawPathRangeOp* that = t->cast<GrDrawPathRangeOp>();
     108           0 :     if (this->fPathRange.get() != that->fPathRange.get() ||
     109           0 :         this->transformType() != that->transformType() || this->fScale != that->fScale ||
     110           0 :         this->color() != that->color() || !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
     111           0 :         return false;
     112             :     }
     113           0 :     if (this->processors() != that->processors()) {
     114           0 :         return false;
     115             :     }
     116           0 :     switch (fDraws.head()->fInstanceData->transformType()) {
     117             :         case GrPathRendering::kNone_PathTransformType:
     118           0 :             if (this->fDraws.head()->fX != that->fDraws.head()->fX ||
     119           0 :                 this->fDraws.head()->fY != that->fDraws.head()->fY) {
     120           0 :                 return false;
     121             :             }
     122           0 :             break;
     123             :         case GrPathRendering::kTranslateX_PathTransformType:
     124           0 :             if (this->fDraws.head()->fY != that->fDraws.head()->fY) {
     125           0 :                 return false;
     126             :             }
     127           0 :             break;
     128             :         case GrPathRendering::kTranslateY_PathTransformType:
     129           0 :             if (this->fDraws.head()->fX != that->fDraws.head()->fX) {
     130           0 :                 return false;
     131             :             }
     132           0 :             break;
     133             :         default:
     134           0 :             break;
     135             :     }
     136             :     // TODO: Check some other things here. (winding, opaque, pathProc color, vm, ...)
     137             :     // Try to combine this call with the previous DrawPaths. We do this by stenciling all the
     138             :     // paths together and then covering them in a single pass. This is not equivalent to two
     139             :     // separate draw calls, so we can only do it if there is no blending (no overlap would also
     140             :     // work). Note that it's also possible for overlapping paths to cancel each other's winding
     141             :     // numbers, and we only partially account for this by not allowing even/odd paths to be
     142             :     // combined. (Glyphs in the same font tend to wind the same direction so it works out OK.)
     143             : 
     144           0 :     if (GrPathRendering::kWinding_FillType != this->fillType() ||
     145           0 :         GrPathRendering::kWinding_FillType != that->fillType()) {
     146           0 :         return false;
     147             :     }
     148           0 :     if (!this->processorAnalysis().canCombineOverlappedStencilAndCover()) {
     149           0 :         return false;
     150             :     }
     151           0 :     fTotalPathCount += that->fTotalPathCount;
     152           0 :     while (Draw* head = that->fDraws.head()) {
     153           0 :         Draw* draw = fDraws.addToTail();
     154           0 :         draw->fInstanceData.reset(head->fInstanceData.release());
     155           0 :         draw->fX = head->fX;
     156           0 :         draw->fY = head->fY;
     157           0 :         that->fDraws.popHead();
     158           0 :     }
     159           0 :     this->joinBounds(*that);
     160           0 :     return true;
     161             : }
     162             : 
     163           0 : void GrDrawPathRangeOp::onExecute(GrOpFlushState* state) {
     164           0 :     const Draw& head = *fDraws.head();
     165             : 
     166           0 :     SkMatrix drawMatrix(this->viewMatrix());
     167           0 :     drawMatrix.preScale(fScale, fScale);
     168           0 :     drawMatrix.preTranslate(head.fX, head.fY);
     169             : 
     170             :     SkMatrix localMatrix;
     171           0 :     localMatrix.setScale(fScale, fScale);
     172           0 :     localMatrix.preTranslate(head.fX, head.fY);
     173             : 
     174             :     sk_sp<GrPathProcessor> pathProc(
     175           0 :             GrPathProcessor::Create(this->color(), drawMatrix, localMatrix));
     176             : 
     177           0 :     GrPipeline pipeline;
     178           0 :     this->initPipeline(*state, &pipeline);
     179           0 :     GrStencilSettings stencil;
     180           0 :     init_stencil_pass_settings(*state, this->fillType(), &stencil);
     181           0 :     if (fDraws.count() == 1) {
     182           0 :         const InstanceData& instances = *head.fInstanceData;
     183           0 :         state->gpu()->pathRendering()->drawPaths(pipeline,
     184           0 :                                                  *pathProc,
     185             :                                                  stencil,
     186             :                                                  fPathRange.get(),
     187           0 :                                                  instances.indices(),
     188             :                                                  GrPathRange::kU16_PathIndexType,
     189             :                                                  instances.transformValues(),
     190             :                                                  instances.transformType(),
     191           0 :                                                  instances.count());
     192             :     } else {
     193           0 :         int floatsPerTransform = GrPathRendering::PathTransformSize(this->transformType());
     194           0 :         SkAutoSTMalloc<4096, float> transformStorage(floatsPerTransform * fTotalPathCount);
     195           0 :         SkAutoSTMalloc<2048, uint16_t> indexStorage(fTotalPathCount);
     196           0 :         int idx = 0;
     197           0 :         for (DrawList::Iter iter(fDraws); iter.get(); iter.next()) {
     198           0 :             const Draw& draw = *iter.get();
     199           0 :             const InstanceData& instances = *draw.fInstanceData;
     200           0 :             memcpy(&indexStorage[idx], instances.indices(), instances.count() * sizeof(uint16_t));
     201           0 :             pre_translate_transform_values(instances.transformValues(), this->transformType(),
     202           0 :                                            instances.count(), draw.fX - head.fX, draw.fY - head.fY,
     203           0 :                                            &transformStorage[floatsPerTransform * idx]);
     204           0 :             idx += instances.count();
     205             : 
     206             :             // TODO: Support mismatched transform types if we start using more types other than 2D.
     207           0 :             SkASSERT(instances.transformType() == this->transformType());
     208             :         }
     209           0 :         SkASSERT(idx == fTotalPathCount);
     210             : 
     211           0 :         state->gpu()->pathRendering()->drawPaths(pipeline,
     212           0 :                                                  *pathProc,
     213             :                                                  stencil,
     214             :                                                  fPathRange.get(),
     215             :                                                  indexStorage,
     216             :                                                  GrPathRange::kU16_PathIndexType,
     217             :                                                  transformStorage,
     218             :                                                  this->transformType(),
     219           0 :                                                  fTotalPathCount);
     220             :     }
     221           0 : }
     222             : 
     223           0 : inline void pre_translate_transform_values(const float* xforms,
     224             :                                            GrPathRendering::PathTransformType type, int count,
     225             :                                            SkScalar x, SkScalar y, float* dst) {
     226           0 :     if (0 == x && 0 == y) {
     227           0 :         memcpy(dst, xforms, count * GrPathRendering::PathTransformSize(type) * sizeof(float));
     228           0 :         return;
     229             :     }
     230           0 :     switch (type) {
     231             :         case GrPathRendering::kNone_PathTransformType:
     232           0 :             SkFAIL("Cannot pre-translate kNone_PathTransformType.");
     233           0 :             break;
     234             :         case GrPathRendering::kTranslateX_PathTransformType:
     235           0 :             SkASSERT(0 == y);
     236           0 :             for (int i = 0; i < count; i++) {
     237           0 :                 dst[i] = xforms[i] + x;
     238             :             }
     239           0 :             break;
     240             :         case GrPathRendering::kTranslateY_PathTransformType:
     241           0 :             SkASSERT(0 == x);
     242           0 :             for (int i = 0; i < count; i++) {
     243           0 :                 dst[i] = xforms[i] + y;
     244             :             }
     245           0 :             break;
     246             :         case GrPathRendering::kTranslate_PathTransformType:
     247           0 :             for (int i = 0; i < 2 * count; i += 2) {
     248           0 :                 dst[i] = xforms[i] + x;
     249           0 :                 dst[i + 1] = xforms[i + 1] + y;
     250             :             }
     251           0 :             break;
     252             :         case GrPathRendering::kAffine_PathTransformType:
     253           0 :             for (int i = 0; i < 6 * count; i += 6) {
     254           0 :                 dst[i] = xforms[i];
     255           0 :                 dst[i + 1] = xforms[i + 1];
     256           0 :                 dst[i + 2] = xforms[i] * x + xforms[i + 1] * y + xforms[i + 2];
     257           0 :                 dst[i + 3] = xforms[i + 3];
     258           0 :                 dst[i + 4] = xforms[i + 4];
     259           0 :                 dst[i + 5] = xforms[i + 3] * x + xforms[i + 4] * y + xforms[i + 5];
     260             :             }
     261           0 :             break;
     262             :         default:
     263           0 :             SkFAIL("Unknown transform type.");
     264           0 :             break;
     265             :     }
     266             : }

Generated by: LCOV version 1.13