Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2017 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 GrCoverageCountingPathRenderer_DEFINED |
| 9 | #define GrCoverageCountingPathRenderer_DEFINED |
| 10 | |
| 11 | #include "GrAllocator.h" |
| 12 | #include "GrOnFlushResourceProvider.h" |
| 13 | #include "GrPathRenderer.h" |
| 14 | #include "SkTInternalLList.h" |
| 15 | #include "ccpr/GrCCPRAtlas.h" |
| 16 | #include "ccpr/GrCCPRCoverageOpsBuilder.h" |
| 17 | #include "ops/GrDrawOp.h" |
| 18 | #include <map> |
| 19 | |
| 20 | /** |
| 21 | * This is a path renderer that draws antialiased paths by counting coverage in an offscreen |
| 22 | * buffer. (See GrCCPRCoverageProcessor, GrCCPRPathProcessor) |
| 23 | * |
| 24 | * It also serves as the per-render-target tracker for pending path draws, and at the start of |
| 25 | * flush, it compiles GPU buffers and renders a "coverage count atlas" for the upcoming paths. |
| 26 | */ |
| 27 | class GrCoverageCountingPathRenderer |
| 28 | : public GrPathRenderer |
| 29 | , public GrOnFlushCallbackObject { |
| 30 | |
| 31 | struct RTPendingOps; |
| 32 | |
| 33 | public: |
| 34 | static bool IsSupported(const GrCaps&); |
| 35 | static sk_sp<GrCoverageCountingPathRenderer> CreateIfSupported(const GrCaps&); |
| 36 | |
| 37 | // GrPathRenderer overrides. |
| 38 | StencilSupport onGetStencilSupport(const GrShape&) const override { |
| 39 | return GrPathRenderer::kNoSupport_StencilSupport; |
| 40 | } |
| 41 | bool onCanDrawPath(const CanDrawPathArgs& args) const override; |
| 42 | bool onDrawPath(const DrawPathArgs&) final; |
| 43 | |
| 44 | // GrOnFlushCallbackObject overrides. |
| 45 | void preFlush(GrOnFlushResourceProvider*, const uint32_t* opListIDs, int numOpListIDs, |
| 46 | SkTArray<sk_sp<GrRenderTargetContext>>* results) override; |
| 47 | void postFlush() override; |
| 48 | |
| 49 | // This is the Op that ultimately draws a path into its final destination, using the atlas we |
| 50 | // generate at flush time. |
| 51 | class DrawPathsOp : public GrDrawOp { |
| 52 | public: |
| 53 | DEFINE_OP_CLASS_ID |
| 54 | SK_DECLARE_INTERNAL_LLIST_INTERFACE(DrawPathsOp); |
| 55 | |
| 56 | DrawPathsOp(GrCoverageCountingPathRenderer*, const DrawPathArgs&, GrColor); |
| 57 | |
| 58 | // GrDrawOp overrides. |
| 59 | const char* name() const override { return "GrCoverageCountingPathRenderer::DrawPathsOp"; } |
| 60 | FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; } |
| 61 | RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*) override; |
| 62 | void wasRecorded(GrRenderTargetOpList*) override; |
| 63 | bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override; |
| 64 | void onPrepare(GrOpFlushState*) override {} |
| 65 | void onExecute(GrOpFlushState*) override; |
| 66 | |
| 67 | private: |
| 68 | SkPath::FillType getFillType() const { |
| 69 | SkASSERT(fDebugInstanceCount >= 1); |
| 70 | return fHeadDraw.fPath.getFillType(); |
| 71 | } |
| 72 | |
| 73 | struct SingleDraw { |
| 74 | using ScissorMode = GrCCPRCoverageOpsBuilder::ScissorMode; |
| 75 | SkIRect fClipBounds; |
| 76 | ScissorMode fScissorMode; |
| 77 | SkMatrix fMatrix; |
| 78 | SkPath fPath; |
| 79 | GrColor fColor; |
| 80 | SingleDraw* fNext = nullptr; |
| 81 | }; |
| 82 | |
| 83 | SingleDraw& getOnlyPathDraw() { |
| 84 | SkASSERT(&fHeadDraw == fTailDraw); |
| 85 | SkASSERT(1 == fDebugInstanceCount); |
| 86 | return fHeadDraw; |
| 87 | } |
| 88 | |
| 89 | struct AtlasBatch { |
| 90 | const GrCCPRAtlas* fAtlas; |
| 91 | int fEndInstanceIdx; |
| 92 | }; |
| 93 | |
| 94 | void addAtlasBatch(const GrCCPRAtlas* atlas, int endInstanceIdx) { |
| 95 | SkASSERT(endInstanceIdx > fBaseInstance); |
| 96 | SkASSERT(fAtlasBatches.empty() || |
| 97 | endInstanceIdx > fAtlasBatches.back().fEndInstanceIdx); |
| 98 | fAtlasBatches.push_back() = {atlas, endInstanceIdx}; |
| 99 | } |
| 100 | |
| 101 | GrCoverageCountingPathRenderer* const fCCPR; |
| 102 | const uint32_t fSRGBFlags; |
| 103 | GrProcessorSet fProcessors; |
| 104 | SingleDraw fHeadDraw; |
| 105 | SingleDraw* fTailDraw; |
| 106 | RTPendingOps* fOwningRTPendingOps; |
| 107 | int fBaseInstance; |
| 108 | SkDEBUGCODE(int fDebugInstanceCount;) |
| 109 | SkSTArray<1, AtlasBatch, true> fAtlasBatches; |
| 110 | |
| 111 | friend class GrCoverageCountingPathRenderer; |
| 112 | |
| 113 | typedef GrDrawOp INHERITED; |
| 114 | }; |
| 115 | |
| 116 | private: |
| 117 | GrCoverageCountingPathRenderer() = default; |
| 118 | |
| 119 | struct RTPendingOps { |
| 120 | SkTInternalLList<DrawPathsOp> fOpList; |
| 121 | GrCCPRCoverageOpsBuilder::MaxBufferItems fMaxBufferItems; |
| 122 | GrSTAllocator<256, DrawPathsOp::SingleDraw> fDrawsAllocator; |
| 123 | }; |
| 124 | |
| 125 | // Map from render target ID to the individual render target's pending path ops. |
| 126 | std::map<uint32_t, RTPendingOps> fRTPendingOpsMap; |
| 127 | |
| 128 | sk_sp<GrBuffer> fPerFlushIndexBuffer; |
| 129 | sk_sp<GrBuffer> fPerFlushVertexBuffer; |
| 130 | sk_sp<GrBuffer> fPerFlushInstanceBuffer; |
| 131 | GrSTAllocator<4, GrCCPRAtlas> fPerFlushAtlases; |
| 132 | SkDEBUGCODE(bool fFlushing = false;) |
| 133 | }; |
| 134 | |
| 135 | #endif |