aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/gpu/GrBackendProcessorFactory.h
blob: 3e4f13314756734cfb5c7957a1db0f969e9da2e9 (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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrBackendProcessorFactory_DEFINED
#define GrBackendProcessorFactory_DEFINED

#include "GrTypes.h"
#include "SkTemplates.h"
#include "SkThread.h"
#include "SkTypes.h"
#include "SkTArray.h"

class GrGLProcessor;
class GrGLCaps;
class GrProcessor;

/**
 * Used by processors to build their keys. It incorporates each per-processor key into a larger shader
 * key.
 */
class GrProcessorKeyBuilder {
public:
    GrProcessorKeyBuilder(SkTArray<unsigned char, true>* data) : fData(data), fCount(0) {
        SkASSERT(0 == fData->count() % sizeof(uint32_t));
    }

    void add32(uint32_t v) {
        ++fCount;
        fData->push_back_n(4, reinterpret_cast<uint8_t*>(&v));
    }

    /** Inserts count uint32_ts into the key. The returned pointer is only valid until the next
        add*() call. */
    uint32_t* SK_WARN_UNUSED_RESULT add32n(int count) {
        SkASSERT(count > 0);
        fCount += count;
        return reinterpret_cast<uint32_t*>(fData->push_back_n(4 * count));
    }

    size_t size() const { return sizeof(uint32_t) * fCount; }

private:
    SkTArray<uint8_t, true>* fData; // unowned ptr to the larger key.
    int fCount;                     // number of uint32_ts added to fData by the processor.
};

/**
 * This class is used to pass the key that was created for a GrGLProcessor back to it
 * when it emits code. It may allow the emit step to skip calculations that were
 * performed when computing the key.
 */
class GrProcessorKey {
public:
    GrProcessorKey(const uint32_t* key, int count) : fKey(key), fCount(count) {
        SkASSERT(0 == reinterpret_cast<intptr_t>(key) % sizeof(uint32_t));
    }

    /** Gets the uint32_t values that the processor inserted into the key. */
    uint32_t get32(int index) const {
        SkASSERT(index >=0 && index < fCount);
        return fKey[index];
    }

    /** Gets the number of uint32_t values that the processor inserted into the key. */
    int count32() const { return fCount; }

private:
    const uint32_t* fKey;           // unowned ptr into the larger key.
    int             fCount;         // number of uint32_ts inserted by the processor into its key.
};

/**
 * Given a GrProcessor of a particular type, creates the corresponding graphics-backend-specific
 * processor object. It also tracks equivalence of shaders generated via a key. The factory for an
 * processor is accessed via GrProcessor::getFactory(). Each factory instance is assigned an ID at
 * construction. The ID of GrProcessor::getFactory() is used as a type identifier. Thus, a
 * GrProcessor subclass must always return the same object from getFactory() and that factory object
 * must be unique to the GrProcessor subclass (and unique from any further derived subclasses).
 *
 * Rather than subclassing this class themselves, it is recommended that GrProcessor authors use 
 * the templated subclass GrTBackendProcessorFactory by writing their getFactory() method as:
 *
 * const GrBackendProcessorFactory& MyProcessor::getFactory() const {
 *     return GrTBackendProcessorFactory<MyProcessor>::getInstance();
 * }
 *
 * Using GrTBackendProcessorFactory places a few constraints on the processor. See that class's
 * comments.
 */
class GrBackendProcessorFactory : SkNoncopyable {
public:
    /** 
     * Generates an processor's key. The key is based on the aspects of the GrProcessor object's
     * configuration that affect GLSL code generation. Two GrProcessor instances that would cause
     * this->createGLInstance()->emitCode() to produce different code must produce different keys.
     */
    virtual void getGLProcessorKey(const GrProcessor&, const GrGLCaps&,
                                   GrProcessorKeyBuilder*) const = 0;

    /**
     * Produces a human-reable name for the v.
     */
    virtual const char* name() const = 0;

    /**
     * A unique value for every instance of this factory. It is automatically incorporated into the
     * processor's key. This allows keys generated by getGLProcessorKey() to only be unique within a
     * GrProcessor subclass and not necessarily across subclasses.
     */
    uint32_t classID() const { return fProcessorClassID; }

protected:
    GrBackendProcessorFactory() : fProcessorClassID(GenClassID()) {}
    virtual ~GrBackendProcessorFactory() {}

private:
    enum {
        kIllegalProcessorClassID = 0,
    };

    static uint32_t GenClassID() {
        // fCurrProcessorClassID has been initialized to kIllegalProcessorClassID. The
        // atomic inc returns the old value not the incremented value. So we add
        // 1 to the returned value.
        uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&fCurrProcessorClassID)) + 1;
        if (!id) {
            SkFAIL("This should never wrap as it should only be called once for each GrProcessor "
                   "subclass.");
        }
        return id;
    }

    const uint32_t fProcessorClassID;
    static int32_t fCurrProcessorClassID;
};

class GrFragmentProcessor;
class GrGeometryProcessor;
class GrGLFragmentProcessor;
class GrGLGeometryProcessor;

/**
 * Backend processor factory cannot actually create anything, it is up to subclasses to implement
 * a create binding which matches Gr to GL in a type safe way
 */

class GrBackendFragmentProcessorFactory : public GrBackendProcessorFactory {
public:
    /**
     * Creates a GrGLProcessor instance that is used both to generate code for the GrProcessor in a
     * GLSL program and to manage updating uniforms for the program when it is used.
     */
    virtual GrGLFragmentProcessor* createGLInstance(const GrFragmentProcessor&) const = 0;
};

class GrBackendGeometryProcessorFactory : public GrBackendProcessorFactory {
public:
    /**
     * Creates a GrGLProcessor instance that is used both to generate code for the GrProcessor in a
     * GLSL program and to manage updating uniforms for the program when it is used.
     */
    virtual GrGLGeometryProcessor* createGLInstance(const GrGeometryProcessor&) const = 0;
};

#endif