1/*
2 * Copyright (C) 2011-2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_RSD_SHADER_CACHE_H
18#define ANDROID_RSD_SHADER_CACHE_H
19
20#include <string>
21#include <vector>
22
23namespace android {
24namespace renderscript {
25
26class Context;
27
28} // namespace renderscript
29} // namespace android
30
31class RsdShader;
32
33// ---------------------------------------------------------------------------
34
35// An element is a group of Components that occupies one cell in a structure.
36class RsdShaderCache {
37public:
38    RsdShaderCache();
39    virtual ~RsdShaderCache();
40
41    void setActiveVertex(RsdShader *pv) {
42        mVertexDirty = true;
43        mVertex = pv;
44    }
45
46    void setActiveFragment(RsdShader *pf) {
47        mFragmentDirty = true;
48        mFragment = pf;
49    }
50
51    bool setup(const android::renderscript::Context *rsc);
52
53    void cleanupVertex(RsdShader *s);
54    void cleanupFragment(RsdShader *s);
55
56    void cleanupAll();
57
58    int32_t vtxAttribSlot(const std::string &attrName) const;
59    int32_t vtxUniformSlot(uint32_t a) const {return mCurrent->vtxUniforms[a].slot;}
60    uint32_t vtxUniformSize(uint32_t a) const {return mCurrent->vtxUniforms[a].arraySize;}
61    int32_t fragUniformSlot(uint32_t a) const {return mCurrent->fragUniforms[a].slot;}
62    uint32_t fragUniformSize(uint32_t a) const {return mCurrent->fragUniforms[a].arraySize;}
63
64protected:
65    bool link(const android::renderscript::Context *rsc);
66    bool mFragmentDirty;
67    bool mVertexDirty;
68    RsdShader *mVertex;
69    RsdShader *mFragment;
70
71    struct UniformQueryData {
72        char *name;
73        uint32_t nameLength;
74        int32_t writtenLength;
75        int32_t arraySize;
76        uint32_t type;
77        explicit UniformQueryData(uint32_t maxName) {
78            name = nullptr;
79            nameLength = maxName;
80            if (nameLength > 0 ) {
81                name = new char[nameLength];
82            }
83        }
84        ~UniformQueryData() {
85            if (name != nullptr) {
86                delete[] name;
87                name = nullptr;
88            }
89        }
90    };
91    struct UniformData {
92        int32_t slot;
93        uint32_t arraySize;
94    };
95    struct AttrData {
96        int32_t slot;
97        const char* name;
98    };
99    struct ProgramEntry {
100        ProgramEntry(uint32_t numVtxAttr, uint32_t numVtxUnis,
101                     uint32_t numFragUnis) : vtx(0), frag(0), program(0), vtxAttrCount(0),
102                                             vtxAttrs(0), vtxUniforms(0), fragUniforms(0),
103                                             fragUniformIsSTO(0) {
104            vtxAttrCount = numVtxAttr;
105            if (numVtxAttr) {
106                vtxAttrs = new AttrData[numVtxAttr];
107            }
108            if (numVtxUnis) {
109                vtxUniforms = new UniformData[numVtxUnis];
110            }
111            if (numFragUnis) {
112                fragUniforms = new UniformData[numFragUnis];
113                fragUniformIsSTO = new bool[numFragUnis];
114            }
115        }
116        ~ProgramEntry() {
117            if (vtxAttrs) {
118                delete[] vtxAttrs;
119                vtxAttrs = nullptr;
120            }
121            if (vtxUniforms) {
122                delete[] vtxUniforms;
123                vtxUniforms = nullptr;
124            }
125            if (fragUniforms) {
126                delete[] fragUniforms;
127                fragUniforms = nullptr;
128            }
129            if (fragUniformIsSTO) {
130                delete[] fragUniformIsSTO;
131                fragUniformIsSTO = nullptr;
132            }
133        }
134        uint32_t vtx;
135        uint32_t frag;
136        uint32_t program;
137        uint32_t vtxAttrCount;
138        AttrData *vtxAttrs;
139        UniformData *vtxUniforms;
140        UniformData *fragUniforms;
141        bool *fragUniformIsSTO;
142    };
143    std::vector<ProgramEntry*> mEntries;
144    ProgramEntry *mCurrent;
145
146    bool hasArrayUniforms(RsdShader *vtx, RsdShader *frag);
147    void populateUniformData(RsdShader *prog, uint32_t linkedID, UniformData *data);
148    void updateUniformArrayData(const android::renderscript::Context *rsc,
149                                RsdShader *prog, uint32_t linkedID,
150                                UniformData *data, const char* logTag,
151                                UniformQueryData **uniformList, uint32_t uniListSize);
152};
153
154
155#endif //ANDROID_RSD_SHADER_CACHE_H
156
157
158
159
160