tzh
2024-08-22 c7d0944258c7d0943aa7b2211498fd612971ce27
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
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
 
#ifndef GrProgramDesc_DEFINED
#define GrProgramDesc_DEFINED
 
#include "GrColor.h"
#include "GrTypesPriv.h"
#include "SkOpts.h"
#include "SkTArray.h"
#include "SkTo.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
 
class GrShaderCaps;
class GrPipeline;
class GrPrimitiveProcessor;
 
/** This class describes a program to generate. It also serves as a program cache key */
class GrProgramDesc {
public:
    // Creates an uninitialized key that must be populated by GrGpu::buildProgramDesc()
    GrProgramDesc() {}
 
    /**
    * Builds a program descriptor. Before the descriptor can be used, the client must call finalize
    * on the returned GrProgramDesc.
    *
    * @param GrPrimitiveProcessor The geometry
    * @param hasPointSize Controls whether the shader will output a point size.
    * @param GrPipeline  The optimized drawstate.  The descriptor will represent a program
    *                        which this optstate can use to draw with.  The optstate contains
    *                        general draw information, as well as the specific color, geometry,
    *                        and coverage stages which will be used to generate the GL Program for
    *                        this optstate.
    * @param GrGpu          Ptr to the GrGpu object the program will be used with.
    * @param GrProgramDesc  The built and finalized descriptor
    **/
    static bool Build(GrProgramDesc*,
                      GrPixelConfig,
                      const GrPrimitiveProcessor&,
                      bool hasPointSize,
                      const GrPipeline&,
                      GrGpu*);
 
    // Returns this as a uint32_t array to be used as a key in the program cache.
    const uint32_t* asKey() const {
        return reinterpret_cast<const uint32_t*>(fKey.begin());
    }
 
    // Gets the number of bytes in asKey(). It will be a 4-byte aligned value.
    uint32_t keyLength() const {
        SkASSERT(0 == (fKey.count() % 4));
        return fKey.count();
    }
 
    GrProgramDesc& operator= (const GrProgramDesc& other) {
        uint32_t keyLength = other.keyLength();
        fKey.reset(SkToInt(keyLength));
        memcpy(fKey.begin(), other.fKey.begin(), keyLength);
        return *this;
    }
 
    bool operator== (const GrProgramDesc& that) const {
        if (this->keyLength() != that.keyLength()) {
            return false;
        }
 
        SkASSERT(SkIsAlign4(this->keyLength()));
        int l = this->keyLength() >> 2;
        const uint32_t* aKey = this->asKey();
        const uint32_t* bKey = that.asKey();
        for (int i = 0; i < l; ++i) {
            if (aKey[i] != bKey[i]) {
                return false;
            }
        }
        return true;
    }
 
    bool operator!= (const GrProgramDesc& other) const {
        return !(*this == other);
    }
 
    void setSurfaceOriginKey(int key) {
        KeyHeader* header = this->atOffset<KeyHeader, kHeaderOffset>();
        header->fSurfaceOriginKey = key;
    }
 
    struct KeyHeader {
        // Set to uniquely idenitify any swizzling of the shader's output color(s).
        uint8_t fOutputSwizzle;
        uint8_t fColorFragmentProcessorCnt; // Can be packed into 4 bits if required.
        uint8_t fCoverageFragmentProcessorCnt;
        // Set to uniquely identify the rt's origin, or 0 if the shader does not require this info.
        uint8_t fSurfaceOriginKey : 2;
        bool fSnapVerticesToPixelCenters : 1;
        bool fHasPointSize : 1;
        uint8_t fPad : 4;
    };
    GR_STATIC_ASSERT(sizeof(KeyHeader) == 4);
 
    // This should really only be used internally, base classes should return their own headers
    const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
 
protected:
    template<typename T, size_t OFFSET> T* atOffset() {
        return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
    }
 
    template<typename T, size_t OFFSET> const T* atOffset() const {
        return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
    }
 
    // The key, stored in fKey, is composed of two parts:
    // 1. Header struct defined above.
    // 2. A Backend specific payload which includes the per-processor keys.
    enum KeyOffsets {
        kHeaderOffset = 0,
        kHeaderSize = SkAlign4(sizeof(KeyHeader)),
        // Part 4.
        // This is the offset into the backenend specific part of the key, which includes
        // per-processor keys.
        kProcessorKeysOffset = kHeaderOffset + kHeaderSize,
    };
 
    enum {
        kMaxPreallocProcessors = 8,
        kIntsPerProcessor      = 4,    // This is an overestimate of the average effect key size.
        kPreAllocSize = kHeaderOffset + kHeaderSize +
                        kMaxPreallocProcessors * sizeof(uint32_t) * kIntsPerProcessor,
    };
 
    SkSTArray<kPreAllocSize, uint8_t, true>& key() { return fKey; }
    const SkSTArray<kPreAllocSize, uint8_t, true>& key() const { return fKey; }
 
private:
    SkSTArray<kPreAllocSize, uint8_t, true> fKey;
};
 
#endif