| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrDrawPathOp_DEFINED |
| #define GrDrawPathOp_DEFINED |
| |
| #include "GrDrawOp.h" |
| #include "GrOpFlushState.h" |
| #include "GrPath.h" |
| #include "GrPathProcessor.h" |
| #include "GrPathRendering.h" |
| #include "GrProcessorSet.h" |
| #include "GrStencilSettings.h" |
| |
| #include "SkTLList.h" |
| |
| class GrPaint; |
| |
| class GrDrawPathOpBase : public GrDrawOp { |
| protected: |
| GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&&, |
| GrPathRendering::FillType, GrAAType); |
| |
| FixedFunctionFlags fixedFunctionFlags() const override { |
| if (GrAATypeIsHW(fAAType)) { |
| return FixedFunctionFlags::kUsesHWAA | FixedFunctionFlags::kUsesStencil; |
| } |
| return FixedFunctionFlags::kUsesStencil; |
| } |
| RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip, |
| GrPixelConfigIsClamped dstIsClamped) override { |
| return this->doProcessorAnalysis(caps, clip, dstIsClamped).requiresDstTexture() |
| ? RequiresDstTexture::kYes : RequiresDstTexture::kNo; |
| } |
| |
| void visitProxies(const VisitProxyFunc& func) const override { |
| fProcessorSet.visitProxies(func); |
| } |
| |
| protected: |
| const SkMatrix& viewMatrix() const { return fViewMatrix; } |
| GrColor color() const { return fInputColor; } |
| GrPathRendering::FillType fillType() const { return fFillType; } |
| const GrProcessorSet& processors() const { return fProcessorSet; } |
| GrProcessorSet detachProcessors() { return std::move(fProcessorSet); } |
| uint32_t pipelineSRGBFlags() const { return fPipelineSRGBFlags; } |
| inline GrPipeline::InitArgs pipelineInitArgs(const GrOpFlushState&); |
| const GrProcessorSet::Analysis& doProcessorAnalysis(const GrCaps& caps, |
| const GrAppliedClip* clip, |
| GrPixelConfigIsClamped dstIsClamped) { |
| bool isMixedSamples = GrAAType::kMixedSamples == fAAType; |
| fAnalysis = fProcessorSet.finalize(fInputColor, GrProcessorAnalysisCoverage::kNone, clip, |
| isMixedSamples, caps, dstIsClamped, &fInputColor); |
| return fAnalysis; |
| } |
| const GrProcessorSet::Analysis& processorAnalysis() const { |
| SkASSERT(fAnalysis.isInitialized()); |
| return fAnalysis; |
| } |
| |
| private: |
| void onPrepare(GrOpFlushState*) final {} |
| |
| SkMatrix fViewMatrix; |
| GrColor fInputColor; |
| GrProcessorSet::Analysis fAnalysis; |
| GrPathRendering::FillType fFillType; |
| GrAAType fAAType; |
| uint32_t fPipelineSRGBFlags; |
| GrProcessorSet fProcessorSet; |
| |
| typedef GrDrawOp INHERITED; |
| }; |
| |
| class GrDrawPathOp final : public GrDrawPathOpBase { |
| public: |
| DEFINE_OP_CLASS_ID |
| |
| static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, GrPaint&& paint, |
| GrAAType aaType, GrPath* path) { |
| return std::unique_ptr<GrDrawOp>( |
| new GrDrawPathOp(viewMatrix, std::move(paint), aaType, path)); |
| } |
| |
| const char* name() const override { return "DrawPath"; } |
| |
| SkString dumpInfo() const override; |
| |
| private: |
| GrDrawPathOp(const SkMatrix& viewMatrix, GrPaint&& paint, GrAAType aaType, const GrPath* path) |
| : GrDrawPathOpBase(ClassID(), viewMatrix, std::move(paint), path->getFillType(), aaType) |
| , fPath(path) { |
| this->setTransformedBounds(path->getBounds(), viewMatrix, HasAABloat::kNo, IsZeroArea::kNo); |
| } |
| |
| bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { return false; } |
| |
| void onExecute(GrOpFlushState* state) override; |
| |
| GrPendingIOResource<const GrPath, kRead_GrIOType> fPath; |
| |
| typedef GrDrawPathOpBase INHERITED; |
| }; |
| |
| // Template this if we decide to support index types other than 16bit |
| class GrDrawPathRangeOp final : public GrDrawPathOpBase { |
| public: |
| typedef GrPathRendering::PathTransformType TransformType; |
| |
| DEFINE_OP_CLASS_ID |
| |
| struct InstanceData : private ::SkNoncopyable { |
| public: |
| static InstanceData* Alloc(TransformType transformType, int reserveCnt) { |
| int transformSize = GrPathRendering::PathTransformSize(transformType); |
| uint8_t* ptr = (uint8_t*)sk_malloc_throw(Align32(sizeof(InstanceData)) + |
| Align32(reserveCnt * sizeof(uint16_t)) + |
| reserveCnt * transformSize * sizeof(float)); |
| InstanceData* instanceData = (InstanceData*)ptr; |
| instanceData->fIndices = (uint16_t*)&ptr[Align32(sizeof(InstanceData))]; |
| instanceData->fTransformValues = (float*)&ptr[Align32(sizeof(InstanceData)) + |
| Align32(reserveCnt * sizeof(uint16_t))]; |
| instanceData->fTransformType = transformType; |
| instanceData->fInstanceCount = 0; |
| instanceData->fRefCnt = 1; |
| SkDEBUGCODE(instanceData->fReserveCnt = reserveCnt); |
| return instanceData; |
| } |
| |
| // Overload this method if we start using other transform types. |
| void append(uint16_t index, float x, float y) { |
| SkASSERT(GrPathRendering::kTranslate_PathTransformType == fTransformType); |
| SkASSERT(fInstanceCount < fReserveCnt); |
| fIndices[fInstanceCount] = index; |
| fTransformValues[2 * fInstanceCount] = x; |
| fTransformValues[2 * fInstanceCount + 1] = y; |
| ++fInstanceCount; |
| } |
| |
| TransformType transformType() const { return fTransformType; } |
| int count() const { return fInstanceCount; } |
| |
| const uint16_t* indices() const { return fIndices; } |
| uint16_t* indices() { return fIndices; } |
| |
| const float* transformValues() const { return fTransformValues; } |
| float* transformValues() { return fTransformValues; } |
| |
| void ref() const { ++fRefCnt; } |
| |
| void unref() const { |
| if (0 == --fRefCnt) { |
| sk_free(const_cast<InstanceData*>(this)); |
| } |
| } |
| |
| private: |
| static int Align32(int sizeInBytes) { return (sizeInBytes + 3) & ~3; } |
| |
| InstanceData() {} |
| ~InstanceData() {} |
| |
| uint16_t* fIndices; |
| float* fTransformValues; |
| TransformType fTransformType; |
| int fInstanceCount; |
| mutable int fRefCnt; |
| SkDEBUGCODE(int fReserveCnt;) |
| }; |
| |
| static std::unique_ptr<GrDrawOp> Make(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, |
| SkScalar y, GrPaint&& paint, |
| GrPathRendering::FillType fill, GrAAType aaType, |
| GrPathRange* range, const InstanceData* instanceData, |
| const SkRect& bounds) { |
| return std::unique_ptr<GrDrawOp>(new GrDrawPathRangeOp(viewMatrix, scale, x, y, |
| std::move(paint), fill, aaType, |
| range, instanceData, bounds)); |
| } |
| |
| const char* name() const override { return "DrawPathRange"; } |
| |
| SkString dumpInfo() const override; |
| |
| private: |
| GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, SkScalar y, |
| GrPaint&& paint, GrPathRendering::FillType fill, GrAAType aaType, |
| GrPathRange* range, const InstanceData* instanceData, const SkRect& bounds); |
| |
| TransformType transformType() const { return fDraws.head()->fInstanceData->transformType(); } |
| |
| bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override; |
| |
| void onExecute(GrOpFlushState* state) override; |
| |
| struct Draw { |
| void set(const InstanceData* instanceData, SkScalar x, SkScalar y) { |
| fInstanceData.reset(SkRef(instanceData)); |
| fX = x; |
| fY = y; |
| } |
| |
| sk_sp<const InstanceData> fInstanceData; |
| SkScalar fX, fY; |
| }; |
| |
| typedef GrPendingIOResource<const GrPathRange, kRead_GrIOType> PendingPathRange; |
| typedef SkTLList<Draw, 4> DrawList; |
| |
| PendingPathRange fPathRange; |
| DrawList fDraws; |
| int fTotalPathCount; |
| SkScalar fScale; |
| |
| typedef GrDrawPathOpBase INHERITED; |
| }; |
| |
| #endif |