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#ifndef GrDrawPathOp_DEFINED 9#define GrDrawPathOp_DEFINED 10 11#include "GrDrawOp.h" 12#include "GrGpu.h" 13#include "GrOpFlushState.h" 14#include "GrPath.h" 15#include "GrPathProcessor.h" 16#include "GrPathRendering.h" 17#include "GrProcessorSet.h" 18#include "GrStencilSettings.h" 19 20#include "SkTLList.h" 21 22class GrPaint; 23 24class GrDrawPathOpBase : public GrDrawOp { 25protected: 26 GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint, 27 GrPathRendering::FillType fill, GrAA aa); 28 FixedFunctionFlags fixedFunctionFlags() const override { 29 return FixedFunctionFlags::kUsesHWAA | FixedFunctionFlags::kUsesStencil; 30 } 31 bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override { 32 return GrXPFactory::WillNeedDstTexture(fProcessorSet.xpFactory(), caps, 33 this->doFragmentProcessorAnalysis(caps, clip)); 34 } 35 36 void wasRecorded() override { fProcessorSet.makePendingExecution(); } 37 38protected: 39 const SkMatrix& viewMatrix() const { return fViewMatrix; } 40 GrColor color() const { return fAnalysis.inputColor(); } 41 GrPathRendering::FillType fillType() const { return fFillType; } 42 const GrProcessorSet& processors() const { return fProcessorSet; } 43 GrPipelineOptimizations initPipeline(const GrOpFlushState&, GrPipeline*); 44 const GrProcessorSet::FragmentProcessorAnalysis& doFragmentProcessorAnalysis( 45 const GrCaps& caps, const GrAppliedClip* clip) { 46 fProcessorSet.analyzeAndEliminateFragmentProcessors( 47 &fAnalysis, fAnalysis.inputColor(), GrPipelineAnalysisCoverage::kNone, clip, caps); 48 return fAnalysis; 49 } 50 const GrProcessorSet::FragmentProcessorAnalysis& fragmentProcessorAnalysis() const { 51 SkASSERT(fAnalysis.isInitializedWithProcessorSet()); 52 return fAnalysis; 53 } 54 55private: 56 void onPrepare(GrOpFlushState*) final {} 57 58 SkMatrix fViewMatrix; 59 GrProcessorSet fProcessorSet; 60 GrProcessorSet::FragmentProcessorAnalysis fAnalysis; 61 GrPathRendering::FillType fFillType; 62 GrAA fAA; 63 64 typedef GrDrawOp INHERITED; 65}; 66 67class GrDrawPathOp final : public GrDrawPathOpBase { 68public: 69 DEFINE_OP_CLASS_ID 70 71 static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa, 72 GrPath* path) { 73 return std::unique_ptr<GrDrawOp>(new GrDrawPathOp(viewMatrix, std::move(paint), aa, path)); 74 } 75 76 const char* name() const override { return "DrawPath"; } 77 78 SkString dumpInfo() const override; 79 80private: 81 GrDrawPathOp(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa, const GrPath* path) 82 : GrDrawPathOpBase(ClassID(), viewMatrix, std::move(paint), path->getFillType(), aa) 83 , fPath(path) { 84 this->setTransformedBounds(path->getBounds(), viewMatrix, HasAABloat::kNo, IsZeroArea::kNo); 85 } 86 87 bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { return false; } 88 89 void onExecute(GrOpFlushState* state) override; 90 91 GrPendingIOResource<const GrPath, kRead_GrIOType> fPath; 92 93 typedef GrDrawPathOpBase INHERITED; 94}; 95 96// Template this if we decide to support index types other than 16bit 97class GrDrawPathRangeOp final : public GrDrawPathOpBase { 98public: 99 typedef GrPathRendering::PathTransformType TransformType; 100 101 DEFINE_OP_CLASS_ID 102 103 struct InstanceData : private ::SkNoncopyable { 104 public: 105 static InstanceData* Alloc(TransformType transformType, int reserveCnt) { 106 int transformSize = GrPathRendering::PathTransformSize(transformType); 107 uint8_t* ptr = (uint8_t*)sk_malloc_throw(Align32(sizeof(InstanceData)) + 108 Align32(reserveCnt * sizeof(uint16_t)) + 109 reserveCnt * transformSize * sizeof(float)); 110 InstanceData* instanceData = (InstanceData*)ptr; 111 instanceData->fIndices = (uint16_t*)&ptr[Align32(sizeof(InstanceData))]; 112 instanceData->fTransformValues = (float*)&ptr[Align32(sizeof(InstanceData)) + 113 Align32(reserveCnt * sizeof(uint16_t))]; 114 instanceData->fTransformType = transformType; 115 instanceData->fInstanceCount = 0; 116 instanceData->fRefCnt = 1; 117 SkDEBUGCODE(instanceData->fReserveCnt = reserveCnt); 118 return instanceData; 119 } 120 121 // Overload this method if we start using other transform types. 122 void append(uint16_t index, float x, float y) { 123 SkASSERT(GrPathRendering::kTranslate_PathTransformType == fTransformType); 124 SkASSERT(fInstanceCount < fReserveCnt); 125 fIndices[fInstanceCount] = index; 126 fTransformValues[2 * fInstanceCount] = x; 127 fTransformValues[2 * fInstanceCount + 1] = y; 128 ++fInstanceCount; 129 } 130 131 TransformType transformType() const { return fTransformType; } 132 int count() const { return fInstanceCount; } 133 134 const uint16_t* indices() const { return fIndices; } 135 uint16_t* indices() { return fIndices; } 136 137 const float* transformValues() const { return fTransformValues; } 138 float* transformValues() { return fTransformValues; } 139 140 void ref() const { ++fRefCnt; } 141 142 void unref() const { 143 if (0 == --fRefCnt) { 144 sk_free(const_cast<InstanceData*>(this)); 145 } 146 } 147 148 private: 149 static int Align32(int sizeInBytes) { return (sizeInBytes + 3) & ~3; } 150 151 InstanceData() {} 152 ~InstanceData() {} 153 154 uint16_t* fIndices; 155 float* fTransformValues; 156 TransformType fTransformType; 157 int fInstanceCount; 158 mutable int fRefCnt; 159 SkDEBUGCODE(int fReserveCnt;) 160 }; 161 162 static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, 163 SkScalar y, GrPaint&& paint, 164 GrPathRendering::FillType fill, GrAA aa, 165 GrPathRange* range, const InstanceData* instanceData, 166 const SkRect& bounds) { 167 return std::unique_ptr<GrDrawOp>(new GrDrawPathRangeOp( 168 viewMatrix, scale, x, y, std::move(paint), fill, aa, range, instanceData, bounds)); 169 } 170 171 const char* name() const override { return "DrawPathRange"; } 172 173 SkString dumpInfo() const override; 174 175private: 176 GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, SkScalar y, 177 GrPaint&& paint, GrPathRendering::FillType fill, GrAA aa, GrPathRange* range, 178 const InstanceData* instanceData, const SkRect& bounds); 179 180 TransformType transformType() const { return fDraws.head()->fInstanceData->transformType(); } 181 182 bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override; 183 184 void onExecute(GrOpFlushState* state) override; 185 186 struct Draw { 187 void set(const InstanceData* instanceData, SkScalar x, SkScalar y) { 188 fInstanceData.reset(SkRef(instanceData)); 189 fX = x; 190 fY = y; 191 } 192 193 sk_sp<const InstanceData> fInstanceData; 194 SkScalar fX, fY; 195 }; 196 197 typedef GrPendingIOResource<const GrPathRange, kRead_GrIOType> PendingPathRange; 198 typedef SkTLList<Draw, 4> DrawList; 199 200 PendingPathRange fPathRange; 201 DrawList fDraws; 202 int fTotalPathCount; 203 SkScalar fScale; 204 205 typedef GrDrawPathOpBase INHERITED; 206}; 207 208#endif 209