1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#ifndef OpsTask_DEFINED
9cb93a386Sopenharmony_ci#define OpsTask_DEFINED
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h"
12cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h"
13cb93a386Sopenharmony_ci#include "include/core/SkSpan.h"
14cb93a386Sopenharmony_ci#include "include/core/SkStrokeRec.h"
15cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
16cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h"
17cb93a386Sopenharmony_ci#include "include/private/SkTArray.h"
18cb93a386Sopenharmony_ci#include "include/private/SkTDArray.h"
19cb93a386Sopenharmony_ci#include "src/core/SkArenaAlloc.h"
20cb93a386Sopenharmony_ci#include "src/core/SkClipStack.h"
21cb93a386Sopenharmony_ci#include "src/core/SkStringUtils.h"
22cb93a386Sopenharmony_ci#include "src/core/SkTLazy.h"
23cb93a386Sopenharmony_ci#include "src/gpu/GrAppliedClip.h"
24cb93a386Sopenharmony_ci#include "src/gpu/GrDstProxyView.h"
25cb93a386Sopenharmony_ci#include "src/gpu/GrGeometryProcessor.h"
26cb93a386Sopenharmony_ci#include "src/gpu/GrProcessorSet.h"
27cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTask.h"
28cb93a386Sopenharmony_ci#include "src/gpu/ops/GrOp.h"
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ciclass GrAuditTrail;
31cb93a386Sopenharmony_ciclass GrCaps;
32cb93a386Sopenharmony_ciclass GrClearOp;
33cb93a386Sopenharmony_ciclass GrGpuBuffer;
34cb93a386Sopenharmony_ciclass GrRenderTargetProxy;
35cb93a386Sopenharmony_ciclass OpsTaskTestingAccess;
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_cinamespace skgpu::v1 {
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ciclass SurfaceDrawContext;
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ciclass OpsTask : public GrRenderTask {
42cb93a386Sopenharmony_cipublic:
43cb93a386Sopenharmony_ci    // Manage the arenas life time by maintaining are reference to it.
44cb93a386Sopenharmony_ci    OpsTask(GrDrawingManager*, GrSurfaceProxyView, GrAuditTrail*, sk_sp<GrArenas>);
45cb93a386Sopenharmony_ci    ~OpsTask() override;
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci    OpsTask* asOpsTask() override { return this; }
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    bool isEmpty() const { return fOpChains.empty(); }
50cb93a386Sopenharmony_ci    bool usesMSAASurface() const { return fUsesMSAASurface; }
51cb93a386Sopenharmony_ci    GrXferBarrierFlags renderPassXferBarriers() const { return fRenderPassXferBarriers; }
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci    /**
54cb93a386Sopenharmony_ci     * Empties the draw buffer of any queued up draws.
55cb93a386Sopenharmony_ci     */
56cb93a386Sopenharmony_ci    void endFlush(GrDrawingManager*) override;
57cb93a386Sopenharmony_ci
58cb93a386Sopenharmony_ci    void onPrePrepare(GrRecordingContext*) override;
59cb93a386Sopenharmony_ci    /**
60cb93a386Sopenharmony_ci     * Together these two functions flush all queued up draws to GrCommandBuffer. The return value
61cb93a386Sopenharmony_ci     * of onExecute() indicates whether any commands were actually issued to the GPU.
62cb93a386Sopenharmony_ci     */
63cb93a386Sopenharmony_ci    void onPrepare(GrOpFlushState* flushState) override;
64cb93a386Sopenharmony_ci    bool onExecute(GrOpFlushState* flushState) override;
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci    void addSampledTexture(GrSurfaceProxy* proxy) {
67cb93a386Sopenharmony_ci        // This function takes a GrSurfaceProxy because all subsequent uses of the proxy do not
68cb93a386Sopenharmony_ci        // require the specifics of GrTextureProxy, so this avoids a number of unnecessary virtual
69cb93a386Sopenharmony_ci        // asTextureProxy() calls. However, sampling the proxy implicitly requires that the proxy
70cb93a386Sopenharmony_ci        // be a texture. Eventually, when proxies are a unified type with flags, this can just
71cb93a386Sopenharmony_ci        // assert that capability.
72cb93a386Sopenharmony_ci        SkASSERT(proxy->asTextureProxy());
73cb93a386Sopenharmony_ci        fSampledProxies.push_back(proxy);
74cb93a386Sopenharmony_ci    }
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_ci    void addOp(GrDrawingManager*, GrOp::Owner, GrTextureResolveManager, const GrCaps&);
77cb93a386Sopenharmony_ci
78cb93a386Sopenharmony_ci    void addDrawOp(GrDrawingManager*, GrOp::Owner, bool usesMSAA, const GrProcessorSet::Analysis&,
79cb93a386Sopenharmony_ci                   GrAppliedClip&&, const GrDstProxyView&, GrTextureResolveManager, const GrCaps&);
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci    void discard();
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_ci    enum class CanDiscardPreviousOps : bool {
84cb93a386Sopenharmony_ci        kYes = true,
85cb93a386Sopenharmony_ci        kNo = false
86cb93a386Sopenharmony_ci    };
87cb93a386Sopenharmony_ci
88cb93a386Sopenharmony_ci    // Perform book-keeping for a fullscreen clear, regardless of how the clear is implemented later
89cb93a386Sopenharmony_ci    // (i.e. setColorLoadOp(), adding a ClearOp, or adding a FillRectOp that covers the device).
90cb93a386Sopenharmony_ci    // Returns true if the clear can be converted into a load op (barring device caps).
91cb93a386Sopenharmony_ci    bool resetForFullscreenClear(CanDiscardPreviousOps);
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    // Must only be called if native color buffer clearing is enabled.
94cb93a386Sopenharmony_ci    void setColorLoadOp(GrLoadOp op, std::array<float, 4> color = {0, 0, 0, 0});
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_ci    // Returns whether the given opsTask can be appended at the end of this one.
97cb93a386Sopenharmony_ci    bool canMerge(const OpsTask*) const;
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_ci    // Merge as many opsTasks as possible from the head of 'tasks'. They should all be
100cb93a386Sopenharmony_ci    // renderPass compatible. Return the number of tasks merged into 'this'.
101cb93a386Sopenharmony_ci    int mergeFrom(SkSpan<const sk_sp<GrRenderTask>> tasks);
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci#ifdef SK_DEBUG
104cb93a386Sopenharmony_ci    int numClips() const override { return fNumClips; }
105cb93a386Sopenharmony_ci    void visitProxies_debugOnly(const GrVisitProxyFunc&) const override;
106cb93a386Sopenharmony_ci#endif
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ci#if GR_TEST_UTILS
109cb93a386Sopenharmony_ci    void dump(const SkString& label,
110cb93a386Sopenharmony_ci              SkString indent,
111cb93a386Sopenharmony_ci              bool printDependencies,
112cb93a386Sopenharmony_ci              bool close) const override;
113cb93a386Sopenharmony_ci    const char* name() const final { return "Ops"; }
114cb93a386Sopenharmony_ci    int numOpChains() const { return fOpChains.count(); }
115cb93a386Sopenharmony_ci    const GrOp* getChain(int index) const { return fOpChains[index].head(); }
116cb93a386Sopenharmony_ci#endif
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ciprotected:
119cb93a386Sopenharmony_ci    enum class StencilContent {
120cb93a386Sopenharmony_ci        kDontCare,
121cb93a386Sopenharmony_ci        kUserBitsCleared,  // User bits: cleared
122cb93a386Sopenharmony_ci                           // Clip bit: don't care (Ganesh always pre-clears the clip bit.)
123cb93a386Sopenharmony_ci        kPreserved
124cb93a386Sopenharmony_ci    };
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci    // Lets the caller specify what the content of the stencil buffer should be at the beginning
127cb93a386Sopenharmony_ci    // of the render pass.
128cb93a386Sopenharmony_ci    //
129cb93a386Sopenharmony_ci    // When requesting kClear: Tilers will load the stencil buffer with a "clear" op; non-tilers
130cb93a386Sopenharmony_ci    // will clear the stencil on first load, and then preserve it on subsequent loads. (Preserving
131cb93a386Sopenharmony_ci    // works because SurfaceDrawContexts are required to leave the user bits in a cleared state
132cb93a386Sopenharmony_ci    // once finished.)
133cb93a386Sopenharmony_ci    //
134cb93a386Sopenharmony_ci    // NOTE: initialContent must not be kClear if caps.performStencilClearsAsDraws() is true.
135cb93a386Sopenharmony_ci    void setInitialStencilContent(StencilContent initialContent) {
136cb93a386Sopenharmony_ci        fInitialStencilContent = initialContent;
137cb93a386Sopenharmony_ci    }
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci    void recordOp(GrOp::Owner, bool usesMSAA, GrProcessorSet::Analysis, GrAppliedClip*,
140cb93a386Sopenharmony_ci                  const GrDstProxyView*, const GrCaps&);
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci    ExpectedOutcome onMakeClosed(GrRecordingContext*, SkIRect* targetUpdateBounds) override;
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ciprivate:
145cb93a386Sopenharmony_ci    bool isColorNoOp() const {
146cb93a386Sopenharmony_ci        // TODO: GrLoadOp::kDiscard (i.e., storing a discard) should also be grounds for skipping
147cb93a386Sopenharmony_ci        // execution. We currently don't because of Vulkan. See http://skbug.com/9373.
148cb93a386Sopenharmony_ci        return fOpChains.empty() && GrLoadOp::kLoad == fColorLoadOp;
149cb93a386Sopenharmony_ci    }
150cb93a386Sopenharmony_ci
151cb93a386Sopenharmony_ci    void deleteOps();
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci    // If a surfaceDrawContext splits its opsTask, it uses this method to guarantee stencil values
154cb93a386Sopenharmony_ci    // get preserved across its split tasks.
155cb93a386Sopenharmony_ci    void setMustPreserveStencil() { fMustPreserveStencil = true; }
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ci    // Prevents this opsTask from merging backward. This is used by DMSAA when a non-multisampled
158cb93a386Sopenharmony_ci    // opsTask cannot be promoted to MSAA, or when we split a multisampled opsTask in order to
159cb93a386Sopenharmony_ci    // resolve its texture.
160cb93a386Sopenharmony_ci    void setCannotMergeBackward() { fCannotMergeBackward = true; }
161cb93a386Sopenharmony_ci
162cb93a386Sopenharmony_ci    class OpChain {
163cb93a386Sopenharmony_ci    public:
164cb93a386Sopenharmony_ci        OpChain(GrOp::Owner, GrProcessorSet::Analysis, GrAppliedClip*, const GrDstProxyView*);
165cb93a386Sopenharmony_ci        ~OpChain() {
166cb93a386Sopenharmony_ci            // The ops are stored in a GrMemoryPool and must be explicitly deleted via the pool.
167cb93a386Sopenharmony_ci            SkASSERT(fList.empty());
168cb93a386Sopenharmony_ci        }
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ci        OpChain(const OpChain&) = delete;
171cb93a386Sopenharmony_ci        OpChain& operator=(const OpChain&) = delete;
172cb93a386Sopenharmony_ci        OpChain(OpChain&&) = default;
173cb93a386Sopenharmony_ci        OpChain& operator=(OpChain&&) = default;
174cb93a386Sopenharmony_ci
175cb93a386Sopenharmony_ci        void visitProxies(const GrVisitProxyFunc&) const;
176cb93a386Sopenharmony_ci
177cb93a386Sopenharmony_ci        GrOp* head() const { return fList.head(); }
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_ci        GrAppliedClip* appliedClip() const { return fAppliedClip; }
180cb93a386Sopenharmony_ci        const GrDstProxyView& dstProxyView() const { return fDstProxyView; }
181cb93a386Sopenharmony_ci        const SkRect& bounds() const { return fBounds; }
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_ci        // Deletes all the ops in the chain.
184cb93a386Sopenharmony_ci        void deleteOps();
185cb93a386Sopenharmony_ci
186cb93a386Sopenharmony_ci        // Attempts to move the ops from the passed chain to this chain at the head. Also attempts
187cb93a386Sopenharmony_ci        // to merge ops between the chains. Upon success the passed chain is empty.
188cb93a386Sopenharmony_ci        // Fails when the chains aren't of the same op type, have different clips or dst proxies.
189cb93a386Sopenharmony_ci        bool prependChain(OpChain*, const GrCaps&, SkArenaAlloc* opsTaskArena, GrAuditTrail*);
190cb93a386Sopenharmony_ci
191cb93a386Sopenharmony_ci        // Attempts to add 'op' to this chain either by merging or adding to the tail. Returns
192cb93a386Sopenharmony_ci        // 'op' to the caller upon failure, otherwise null. Fails when the op and chain aren't of
193cb93a386Sopenharmony_ci        // the same op type, have different clips or dst proxies.
194cb93a386Sopenharmony_ci        GrOp::Owner appendOp(GrOp::Owner op, GrProcessorSet::Analysis, const GrDstProxyView*,
195cb93a386Sopenharmony_ci                             const GrAppliedClip*, const GrCaps&, SkArenaAlloc* opsTaskArena,
196cb93a386Sopenharmony_ci                             GrAuditTrail*);
197cb93a386Sopenharmony_ci
198cb93a386Sopenharmony_ci        bool shouldExecute() const {
199cb93a386Sopenharmony_ci            return SkToBool(this->head());
200cb93a386Sopenharmony_ci        }
201cb93a386Sopenharmony_ci
202cb93a386Sopenharmony_ci    private:
203cb93a386Sopenharmony_ci        class List {
204cb93a386Sopenharmony_ci        public:
205cb93a386Sopenharmony_ci            List() = default;
206cb93a386Sopenharmony_ci            List(GrOp::Owner);
207cb93a386Sopenharmony_ci            List(List&&);
208cb93a386Sopenharmony_ci            List& operator=(List&& that);
209cb93a386Sopenharmony_ci
210cb93a386Sopenharmony_ci            bool empty() const { return !SkToBool(fHead); }
211cb93a386Sopenharmony_ci            GrOp* head() const { return fHead.get(); }
212cb93a386Sopenharmony_ci            GrOp* tail() const { return fTail; }
213cb93a386Sopenharmony_ci
214cb93a386Sopenharmony_ci            GrOp::Owner popHead();
215cb93a386Sopenharmony_ci            GrOp::Owner removeOp(GrOp* op);
216cb93a386Sopenharmony_ci            void pushHead(GrOp::Owner op);
217cb93a386Sopenharmony_ci            void pushTail(GrOp::Owner);
218cb93a386Sopenharmony_ci
219cb93a386Sopenharmony_ci            void validate() const;
220cb93a386Sopenharmony_ci
221cb93a386Sopenharmony_ci        private:
222cb93a386Sopenharmony_ci            GrOp::Owner fHead{nullptr};
223cb93a386Sopenharmony_ci            GrOp* fTail{nullptr};
224cb93a386Sopenharmony_ci        };
225cb93a386Sopenharmony_ci
226cb93a386Sopenharmony_ci        void validate() const;
227cb93a386Sopenharmony_ci
228cb93a386Sopenharmony_ci        bool tryConcat(List*, GrProcessorSet::Analysis, const GrDstProxyView&, const GrAppliedClip*,
229cb93a386Sopenharmony_ci                       const SkRect& bounds, const GrCaps&, SkArenaAlloc* opsTaskArena,
230cb93a386Sopenharmony_ci                       GrAuditTrail*);
231cb93a386Sopenharmony_ci        static List DoConcat(List, List, const GrCaps&, SkArenaAlloc* opsTaskArena, GrAuditTrail*);
232cb93a386Sopenharmony_ci
233cb93a386Sopenharmony_ci        List fList;
234cb93a386Sopenharmony_ci        GrProcessorSet::Analysis fProcessorAnalysis;
235cb93a386Sopenharmony_ci        GrDstProxyView fDstProxyView;
236cb93a386Sopenharmony_ci        GrAppliedClip* fAppliedClip;
237cb93a386Sopenharmony_ci        SkRect fBounds;
238cb93a386Sopenharmony_ci    };
239cb93a386Sopenharmony_ci
240cb93a386Sopenharmony_ci    void onMakeSkippable() override;
241cb93a386Sopenharmony_ci
242cb93a386Sopenharmony_ci    bool onIsUsed(GrSurfaceProxy*) const override;
243cb93a386Sopenharmony_ci
244cb93a386Sopenharmony_ci    void gatherProxyIntervals(GrResourceAllocator*) const override;
245cb93a386Sopenharmony_ci
246cb93a386Sopenharmony_ci    void forwardCombine(const GrCaps&);
247cb93a386Sopenharmony_ci
248cb93a386Sopenharmony_ci    // Remove all ops, proxies, etc. Used in the merging algorithm when tasks can be skipped.
249cb93a386Sopenharmony_ci    void reset();
250cb93a386Sopenharmony_ci
251cb93a386Sopenharmony_ci    friend class ::OpsTaskTestingAccess;
252cb93a386Sopenharmony_ci
253cb93a386Sopenharmony_ci    // The SDC and OpsTask have to work together to handle buffer clears. In most cases, buffer
254cb93a386Sopenharmony_ci    // clearing can be done natively, in which case the op list's load ops are sufficient. In other
255cb93a386Sopenharmony_ci    // cases, draw ops must be used, which makes the SDC the best place for those decisions. This,
256cb93a386Sopenharmony_ci    // however, requires that the SDC be able to coordinate with the op list to achieve similar ends
257cb93a386Sopenharmony_ci    friend class skgpu::v1::SurfaceDrawContext;
258cb93a386Sopenharmony_ci
259cb93a386Sopenharmony_ci    GrAuditTrail* fAuditTrail;
260cb93a386Sopenharmony_ci
261cb93a386Sopenharmony_ci    bool fUsesMSAASurface;
262cb93a386Sopenharmony_ci    GrSwizzle fTargetSwizzle;
263cb93a386Sopenharmony_ci    GrSurfaceOrigin fTargetOrigin;
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_ci    GrLoadOp fColorLoadOp = GrLoadOp::kLoad;
266cb93a386Sopenharmony_ci    std::array<float, 4> fLoadClearColor = {0, 0, 0, 0};
267cb93a386Sopenharmony_ci    StencilContent fInitialStencilContent = StencilContent::kDontCare;
268cb93a386Sopenharmony_ci    bool fMustPreserveStencil = false;
269cb93a386Sopenharmony_ci    bool fCannotMergeBackward = false;
270cb93a386Sopenharmony_ci
271cb93a386Sopenharmony_ci    uint32_t fLastClipStackGenID = SK_InvalidUniqueID;
272cb93a386Sopenharmony_ci    SkIRect fLastDevClipBounds;
273cb93a386Sopenharmony_ci    int fLastClipNumAnalyticElements;
274cb93a386Sopenharmony_ci
275cb93a386Sopenharmony_ci    GrXferBarrierFlags fRenderPassXferBarriers = GrXferBarrierFlags::kNone;
276cb93a386Sopenharmony_ci
277cb93a386Sopenharmony_ci    // For ops/opsTask we have mean: 5 stdDev: 28
278cb93a386Sopenharmony_ci    SkSTArray<25, OpChain> fOpChains;
279cb93a386Sopenharmony_ci
280cb93a386Sopenharmony_ci    sk_sp<GrArenas> fArenas;
281cb93a386Sopenharmony_ci    SkDEBUGCODE(int fNumClips;)
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_ci    // TODO: We could look into this being a set if we find we're adding a lot of duplicates that is
284cb93a386Sopenharmony_ci    // causing slow downs.
285cb93a386Sopenharmony_ci    SkTArray<GrSurfaceProxy*, true> fSampledProxies;
286cb93a386Sopenharmony_ci
287cb93a386Sopenharmony_ci    SkRect fTotalBounds = SkRect::MakeEmpty();
288cb93a386Sopenharmony_ci    SkIRect fClippedContentBounds = SkIRect::MakeEmpty();
289cb93a386Sopenharmony_ci};
290cb93a386Sopenharmony_ci
291cb93a386Sopenharmony_ci} // namespace skgpu::v1
292cb93a386Sopenharmony_ci
293cb93a386Sopenharmony_ci#endif // OpsTask_DEFINED
294