aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ops/GrMeshDrawOp.h
blob: 4cf7c52672a64a3490306e29291900dc24e5de9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * 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 GrMeshDrawOp_DEFINED
#define GrMeshDrawOp_DEFINED

#include "GrDrawOp.h"
#include "GrGeometryProcessor.h"
#include "GrMesh.h"
#include "GrPendingProgramElement.h"

#include "SkTLList.h"

class GrCaps;
class GrOpFlushState;

/**
 * Base class for mesh-drawing GrDrawOps.
 */
class GrMeshDrawOp : public GrDrawOp {
public:
    class Target;

    /**
     * Performs analysis of the fragment processors in GrProcessorSet and GrAppliedClip using the
     * initial color and coverage from this op's geometry processor.
     */
    void analyzeProcessors(GrProcessorSet::FragmentProcessorAnalysis* analysis,
                           const GrProcessorSet& processors,
                           const GrAppliedClip* appliedClip,
                           const GrCaps& caps) const {
        FragmentProcessorAnalysisInputs input;
        this->getFragmentProcessorAnalysisInputs(&input);
        analysis->init(*input.colorInput(), *input.coverageInput(), processors, appliedClip, caps);
    }

    void initPipeline(const GrPipeline::InitArgs& args) {
        this->applyPipelineOptimizations(fPipeline.init(args));
    }

    /**
     * Mesh draw ops use a legacy system in GrRenderTargetContext where the pipeline is created when
     * the op is recorded. These methods are unnecessary as this information is in the pipeline.
     */
    FixedFunctionFlags fixedFunctionFlags() const override {
        SkFAIL("This should never be called for mesh draw ops.");
        return FixedFunctionFlags::kNone;
    }
    bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) override {
        SkFAIL("Should never be called for mesh draw ops.");
        return false;
    }

protected:
    GrMeshDrawOp(uint32_t classID);

    /** Helper for rendering instances using an instanced index index buffer. This class creates the
        space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
    class InstancedHelper {
    public:
        InstancedHelper() {}
        /** Returns the allocated storage for the vertices. The caller should populate the vertices
            before calling recordDraws(). */
        void* init(Target*, GrPrimitiveType, size_t vertexStride, const GrBuffer*,
                   int verticesPerInstance, int indicesPerInstance, int instancesToDraw);

        /** Call after init() to issue draws to the GrMeshDrawOp::Target.*/
        void recordDraw(Target*, const GrGeometryProcessor*);

    private:
        GrMesh fMesh;
    };

    static const int kVerticesPerQuad = 4;
    static const int kIndicesPerQuad = 6;

    /** A specialization of InstanceHelper for quad rendering. */
    class QuadHelper : private InstancedHelper {
    public:
        QuadHelper() : INHERITED() {}
        /** Finds the cached quad index buffer and reserves vertex space. Returns nullptr on failure
            and on success a pointer to the vertex data that the caller should populate before
            calling recordDraws(). */
        void* init(Target*, size_t vertexStride, int quadsToDraw);

        using InstancedHelper::recordDraw;

    private:
        typedef InstancedHelper INHERITED;
    };

    const GrPipeline* pipeline() const {
        SkASSERT(fPipeline.isInitialized());
        return &fPipeline;
    }

    /**
     * This describes aspects of the GrPrimitiveProcessor produced by a GrDrawOp that are used in
     * pipeline analysis.
     */
    class FragmentProcessorAnalysisInputs {
    public:
        FragmentProcessorAnalysisInputs() = default;
        GrPipelineInput* colorInput() { return &fColorInput; }
        GrPipelineInput* coverageInput() { return &fCoverageInput; }

    private:
        GrPipelineInput fColorInput;
        GrPipelineInput fCoverageInput;
    };

private:
    /**
     * Provides information about the GrPrimitiveProccesor color and coverage outputs which become
     * inputs to the first color and coverage fragment processors.
     */
    virtual void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs*) const = 0;

    /**
     * After GrPipeline analysis is complete this is called so that the op can use the analysis
     * results when constructing its GrPrimitiveProcessor.
     */
    virtual void applyPipelineOptimizations(const GrPipelineOptimizations&) = 0;

    void onPrepare(GrOpFlushState* state) final;
    void onExecute(GrOpFlushState* state) final;

    virtual void onPrepareDraws(Target*) const = 0;

    // A set of contiguous draws that share a draw token and primitive processor. The draws all use
    // the op's pipeline. The meshes for the draw are stored in the fMeshes array and each
    // Queued draw uses fMeshCnt meshes from the fMeshes array. The reason for coallescing meshes
    // that share a primitive processor into a QueuedDraw is that it allows the Gpu object to setup
    // the shared state once and then issue draws for each mesh.
    struct QueuedDraw {
        int fMeshCnt = 0;
        GrPendingProgramElement<const GrGeometryProcessor> fGeometryProcessor;
    };

    // All draws in all the GrMeshDrawOps have implicit tokens based on the order they are enqueued
    // globally across all ops. This is the offset of the first entry in fQueuedDraws.
    // fQueuedDraws[i]'s token is fBaseDrawToken + i.
    GrDrawOpUploadToken fBaseDrawToken;
    GrPipeline fPipeline;
    SkSTArray<4, GrMesh> fMeshes;
    SkSTArray<4, QueuedDraw, true> fQueuedDraws;

    typedef GrDrawOp INHERITED;
};

#endif