Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2010 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 GrRenderTargetOpList_DEFINED
      9 #define GrRenderTargetOpList_DEFINED
     10 
     11 #include "GrAppliedClip.h"
     12 #include "GrOpList.h"
     13 #include "GrPathRendering.h"
     14 #include "GrPrimitiveProcessor.h"
     15 #include "ops/GrOp.h"
     16 #include "ops/GrDrawOp.h"
     17 #include "SkArenaAlloc.h"
     18 #include "SkClipStack.h"
     19 #include "SkMatrix.h"
     20 #include "SkStringUtils.h"
     21 #include "SkStrokeRec.h"
     22 #include "SkTArray.h"
     23 #include "SkTLazy.h"
     24 #include "SkTypes.h"
     25 
     26 class GrAuditTrail;
     27 class GrClearOp;
     28 class GrCaps;
     29 class GrRenderTargetProxy;
     30 
     31 class GrRenderTargetOpList final : public GrOpList {
     32 private:
     33     using DstProxy = GrXferProcessor::DstProxy;
     34 
     35 public:
     36     GrRenderTargetOpList(GrResourceProvider*, sk_sp<GrOpMemoryPool>,
     37                          GrRenderTargetProxy*, GrAuditTrail*);
     38 
     39     ~GrRenderTargetOpList() override;
     40 
     41     void makeClosed(const GrCaps& caps) override {
     42         if (this->isClosed()) {
     43             return;
     44         }
     45 
     46         this->forwardCombine(caps);
     47 
     48         INHERITED::makeClosed(caps);
     49     }
     50 
     51     bool isEmpty() const { return fOpChains.empty(); }
     52 
     53     /**
     54      * Empties the draw buffer of any queued up draws.
     55      */
     56     void endFlush() override;
     57 
     58     /**
     59      * Together these two functions flush all queued up draws to GrCommandBuffer. The return value
     60      * of executeOps() indicates whether any commands were actually issued to the GPU.
     61      */
     62     void onPrepare(GrOpFlushState* flushState) override;
     63     bool onExecute(GrOpFlushState* flushState) override;
     64 
     65     void addOp(std::unique_ptr<GrOp> op, const GrCaps& caps) {
     66         auto addDependency = [ &caps, this ] (GrSurfaceProxy* p) {
     67             this->addDependency(p, caps);
     68         };
     69 
     70         op->visitProxies(addDependency);
     71 
     72         this->recordOp(std::move(op), GrProcessorSet::EmptySetAnalysis(), nullptr, nullptr, caps);
     73     }
     74 
     75     void addDrawOp(std::unique_ptr<GrDrawOp> op, const GrProcessorSet::Analysis& processorAnalysis,
     76                    GrAppliedClip&& clip, const DstProxy& dstProxy, const GrCaps& caps) {
     77         auto addDependency = [ &caps, this ] (GrSurfaceProxy* p) {
     78             this->addDependency(p, caps);
     79         };
     80 
     81         op->visitProxies(addDependency);
     82         clip.visitProxies(addDependency);
     83         if (dstProxy.proxy()) {
     84             addDependency(dstProxy.proxy());
     85         }
     86 
     87         this->recordOp(std::move(op), processorAnalysis, clip.doesClip() ? &clip : nullptr,
     88                        &dstProxy, caps);
     89     }
     90 
     91     void discard();
     92 
     93     /**
     94      * Copies a pixel rectangle from one surface to another. This call may finalize
     95      * reserved vertex/index data (as though a draw call was made). The src pixels
     96      * copied are specified by srcRect. They are copied to a rect of the same
     97      * size in dst with top left at dstPoint. If the src rect is clipped by the
     98      * src bounds then  pixel values in the dst rect corresponding to area clipped
     99      * by the src rect are not overwritten. This method is not guaranteed to succeed
    100      * depending on the type of surface, configs, etc, and the backend-specific
    101      * limitations.
    102      */
    103     bool copySurface(GrContext*,
    104                      GrSurfaceProxy* dst,
    105                      GrSurfaceProxy* src,
    106                      const SkIRect& srcRect,
    107                      const SkIPoint& dstPoint) override;
    108 
    109     GrRenderTargetOpList* asRenderTargetOpList() override { return this; }
    110 
    111     SkDEBUGCODE(void dump(bool printDependencies) const override;)
    112     SkDEBUGCODE(int numClips() const override { return fNumClips; })
    113     SkDEBUGCODE(void visitProxies_debugOnly(const GrOp::VisitProxyFunc&) const;)
    114 
    115 private:
    116     friend class GrRenderTargetContextPriv; // for stencil clip state. TODO: this is invasive
    117 
    118     // The RTC and RTOpList have to work together to handle buffer clears. In most cases, buffer
    119     // clearing can be done natively, in which case the op list's load ops are sufficient. In other
    120     // cases, draw ops must be used, which makes the RTC the best place for those decisions. This,
    121     // however, requires that the RTC be able to coordinate with the op list to achieve similar ends
    122     friend class GrRenderTargetContext;
    123 
    124     // Must only be called if native stencil buffer clearing is enabled
    125     void setStencilLoadOp(GrLoadOp op);
    126     // Must only be called if native color buffer clearing is enabled.
    127     void setColorLoadOp(GrLoadOp op, const SkPMColor4f& color);
    128     // Sets the clear color to transparent black
    129     void setColorLoadOp(GrLoadOp op) {
    130         static const SkPMColor4f kDefaultClearColor = {0.f, 0.f, 0.f, 0.f};
    131         this->setColorLoadOp(op, kDefaultClearColor);
    132     }
    133 
    134     // Perform book-keeping for a fullscreen clear, regardless of how the clear is implemented later
    135     // (i.e. setColorLoadOp(), adding a ClearOp, or adding a GrFillRectOp that covers the device).
    136     // Returns true if the clear can be converted into a load op (barring device caps).
    137     bool resetForFullscreenClear();
    138 
    139     void deleteOps();
    140 
    141     class OpChain {
    142     public:
    143         OpChain(const OpChain&) = delete;
    144         OpChain& operator=(const OpChain&) = delete;
    145         OpChain(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxy*);
    146 
    147         ~OpChain() {
    148             // The ops are stored in a GrMemoryPool and must be explicitly deleted via the pool.
    149             SkASSERT(fList.empty());
    150         }
    151 
    152         void visitProxies(const GrOp::VisitProxyFunc&, GrOp::VisitorType) const;
    153 
    154         GrOp* head() const { return fList.head(); }
    155 
    156         GrAppliedClip* appliedClip() const { return fAppliedClip; }
    157         const DstProxy& dstProxy() const { return fDstProxy; }
    158         const SkRect& bounds() const { return fBounds; }
    159 
    160         // Deletes all the ops in the chain via the pool.
    161         void deleteOps(GrOpMemoryPool* pool);
    162 
    163         // Attempts to move the ops from the passed chain to this chain at the head. Also attempts
    164         // to merge ops between the chains. Upon success the passed chain is empty.
    165         // Fails when the chains aren't of the same op type, have different clips or dst proxies.
    166         bool prependChain(OpChain*, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
    167 
    168         // Attempts to add 'op' to this chain either by merging or adding to the tail. Returns
    169         // 'op' to the caller upon failure, otherwise null. Fails when the op and chain aren't of
    170         // the same op type, have different clips or dst proxies.
    171         std::unique_ptr<GrOp> appendOp(std::unique_ptr<GrOp> op, GrProcessorSet::Analysis,
    172                                        const DstProxy*, const GrAppliedClip*, const GrCaps&,
    173                                        GrOpMemoryPool*, GrAuditTrail*);
    174 
    175     private:
    176         class List {
    177         public:
    178             List() = default;
    179             List(std::unique_ptr<GrOp>);
    180             List(List&&);
    181             List& operator=(List&& that);
    182 
    183             bool empty() const { return !SkToBool(fHead); }
    184             GrOp* head() const { return fHead.get(); }
    185             GrOp* tail() const { return fTail; }
    186 
    187             std::unique_ptr<GrOp> popHead();
    188             std::unique_ptr<GrOp> removeOp(GrOp* op);
    189             void pushHead(std::unique_ptr<GrOp> op);
    190             void pushTail(std::unique_ptr<GrOp>);
    191 
    192             void validate() const;
    193 
    194         private:
    195             std::unique_ptr<GrOp> fHead;
    196             GrOp* fTail = nullptr;
    197         };
    198 
    199         void validate() const;
    200 
    201         bool tryConcat(List*, GrProcessorSet::Analysis, const DstProxy&, const GrAppliedClip*,
    202                        const SkRect& bounds, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
    203         static List DoConcat(List, List, const GrCaps&, GrOpMemoryPool*, GrAuditTrail*);
    204 
    205         List fList;
    206         GrProcessorSet::Analysis fProcessorAnalysis;
    207         DstProxy fDstProxy;
    208         GrAppliedClip* fAppliedClip;
    209         SkRect fBounds;
    210     };
    211 
    212     void purgeOpsWithUninstantiatedProxies() override;
    213 
    214     void gatherProxyIntervals(GrResourceAllocator*) const override;
    215 
    216     void recordOp(std::unique_ptr<GrOp>, GrProcessorSet::Analysis, GrAppliedClip*, const DstProxy*,
    217                   const GrCaps& caps);
    218 
    219     void forwardCombine(const GrCaps&);
    220 
    221     uint32_t                       fLastClipStackGenID;
    222     SkIRect                        fLastDevClipBounds;
    223     int                            fLastClipNumAnalyticFPs;
    224 
    225     // For ops/opList we have mean: 5 stdDev: 28
    226     SkSTArray<25, OpChain, true> fOpChains;
    227 
    228     // MDB TODO: 4096 for the first allocation of the clip space will be huge overkill.
    229     // Gather statistics to determine the correct size.
    230     SkArenaAlloc                   fClipAllocator{4096};
    231     SkDEBUGCODE(int                fNumClips;)
    232 
    233     typedef GrOpList INHERITED;
    234 };
    235 
    236 #endif
    237