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#include <GLES2/gl2.h>
18#include <GLES2/gl2ext.h>
19
20#include <rs_hal.h>
21#include <rsContext.h>
22#include <rsProgram.h>
23
24#include "rsdCore.h"
25#include "rsdAllocation.h"
26#include "rsdShader.h"
27#include "rsdShaderCache.h"
28
29using android::renderscript::Allocation;
30using android::renderscript::Context;
31using android::renderscript::Element;
32using android::renderscript::Program;
33using android::renderscript::Sampler;
34using android::renderscript::rsMin;
35
36RsdShader::RsdShader(const Program *p, uint32_t type,
37                     const char * shaderText, size_t shaderLength,
38                     const char** textureNames, size_t textureNamesCount,
39                     const size_t *textureNamesLength) {
40    mUserShader.replace(0, shaderLength, shaderText);
41    mRSProgram = p;
42    mType = type;
43    initMemberVars();
44    initAttribAndUniformArray();
45    init(textureNames, textureNamesCount, textureNamesLength);
46
47    for(size_t i=0; i < textureNamesCount; i++) {
48        mTextureNames.push_back(std::string(textureNames[i], textureNamesLength[i]));
49    }
50}
51
52RsdShader::~RsdShader() {
53    for (uint32_t i = 0; i < mStateBasedShaders.size(); i ++) {
54        StateBasedKey *state = mStateBasedShaders.at(i);
55        if (state->mShaderID) {
56            glDeleteShader(state->mShaderID);
57        }
58        delete state;
59    }
60
61    delete[] mAttribNames;
62    delete[] mUniformNames;
63    delete[] mUniformArraySizes;
64}
65
66void RsdShader::initMemberVars() {
67    mDirty = true;
68    mAttribCount = 0;
69    mUniformCount = 0;
70
71    mAttribNames = nullptr;
72    mUniformNames = nullptr;
73    mUniformArraySizes = nullptr;
74    mCurrentState = nullptr;
75
76    mIsValid = false;
77}
78
79RsdShader::StateBasedKey *RsdShader::getExistingState() {
80    RsdShader::StateBasedKey *returnKey = nullptr;
81
82    for (uint32_t i = 0; i < mStateBasedShaders.size(); i ++) {
83        returnKey = mStateBasedShaders.at(i);
84
85        for (uint32_t ct = 0; ct < mRSProgram->mHal.state.texturesCount; ct ++) {
86            uint32_t texType = 0;
87            if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) {
88                Allocation *a = mRSProgram->mHal.state.textures[ct];
89                if (a && a->mHal.state.surfaceTextureID) {
90                    texType = GL_TEXTURE_EXTERNAL_OES;
91                } else {
92                    texType = GL_TEXTURE_2D;
93                }
94            } else {
95                texType = GL_TEXTURE_CUBE_MAP;
96            }
97            if (texType != returnKey->mTextureTargets[ct]) {
98                returnKey = nullptr;
99                break;
100            }
101        }
102    }
103    return returnKey;
104}
105
106uint32_t RsdShader::getStateBasedShaderID(const Context *rsc) {
107    StateBasedKey *state = getExistingState();
108    if (state != nullptr) {
109        mCurrentState = state;
110        return mCurrentState->mShaderID;
111    }
112    // We have not created a shader for this particular state yet
113    state = new StateBasedKey(mTextureCount);
114    mCurrentState = state;
115    mStateBasedShaders.push_back(state);
116    createShader();
117    loadShader(rsc);
118    return mCurrentState->mShaderID;
119}
120
121void RsdShader::init(const char** textureNames, size_t textureNamesCount,
122                     const size_t *textureNamesLength) {
123    uint32_t attribCount = 0;
124    uint32_t uniformCount = 0;
125    for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
126        initAddUserElement(mRSProgram->mHal.state.inputElements[ct], mAttribNames,
127                           nullptr, &attribCount, RS_SHADER_ATTR);
128    }
129    for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
130        initAddUserElement(mRSProgram->mHal.state.constantTypes[ct]->getElement(),
131                           mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
132    }
133
134    mTextureUniformIndexStart = uniformCount;
135    for (uint32_t ct=0; ct < mRSProgram->mHal.state.texturesCount; ct++) {
136        mUniformNames[uniformCount] = "UNI_";
137        mUniformNames[uniformCount].append(textureNames[ct], textureNamesLength[ct]);
138        mUniformArraySizes[uniformCount] = 1;
139        uniformCount++;
140    }
141}
142
143std::string RsdShader::getGLSLInputString() const {
144    std::string s;
145    for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
146        const Element *e = mRSProgram->mHal.state.inputElements[ct];
147        for (uint32_t field=0; field < e->mHal.state.fieldsCount; field++) {
148            const Element *f = e->mHal.state.fields[field];
149
150            // Cannot be complex
151            rsAssert(!f->mHal.state.fieldsCount);
152            switch (f->mHal.state.vectorSize) {
153            case 1: s.append("attribute float ATTRIB_"); break;
154            case 2: s.append("attribute vec2 ATTRIB_"); break;
155            case 3: s.append("attribute vec3 ATTRIB_"); break;
156            case 4: s.append("attribute vec4 ATTRIB_"); break;
157            default:
158                rsAssert(0);
159            }
160
161            s.append(e->mHal.state.fieldNames[field]);
162            s.append(";\n");
163        }
164    }
165    return s;
166}
167
168void RsdShader::appendAttributes() {
169    for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
170        const Element *e = mRSProgram->mHal.state.inputElements[ct];
171        for (uint32_t field=0; field < e->mHal.state.fieldsCount; field++) {
172            const Element *f = e->mHal.state.fields[field];
173            const char *fn = e->mHal.state.fieldNames[field];
174
175            // Cannot be complex
176            rsAssert(!f->mHal.state.fieldsCount);
177            switch (f->mHal.state.vectorSize) {
178            case 1: mShader.append("attribute float ATTRIB_"); break;
179            case 2: mShader.append("attribute vec2 ATTRIB_"); break;
180            case 3: mShader.append("attribute vec3 ATTRIB_"); break;
181            case 4: mShader.append("attribute vec4 ATTRIB_"); break;
182            default:
183                rsAssert(0);
184            }
185
186            mShader.append(fn);
187            mShader.append(";\n");
188        }
189    }
190}
191
192void RsdShader::appendTextures() {
193
194    // TODO: this does not yet handle cases where the texture changes between IO
195    // input and local
196    bool appendUsing = true;
197    for (uint32_t ct = 0; ct < mRSProgram->mHal.state.texturesCount; ct ++) {
198        if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) {
199            Allocation *a = mRSProgram->mHal.state.textures[ct];
200            if (a && a->mHal.state.surfaceTextureID) {
201                if(appendUsing) {
202                    mShader.append("#extension GL_OES_EGL_image_external : require\n");
203                    appendUsing = false;
204                }
205                mShader.append("uniform samplerExternalOES UNI_");
206                mCurrentState->mTextureTargets[ct] = GL_TEXTURE_EXTERNAL_OES;
207            } else {
208                mShader.append("uniform sampler2D UNI_");
209                mCurrentState->mTextureTargets[ct] = GL_TEXTURE_2D;
210            }
211        } else {
212            mShader.append("uniform samplerCube UNI_");
213            mCurrentState->mTextureTargets[ct] = GL_TEXTURE_CUBE_MAP;
214        }
215
216        mShader.append(mTextureNames[ct]);
217        mShader.append(";\n");
218    }
219}
220
221bool RsdShader::createShader() {
222    mShader.clear();
223    if (mType == GL_FRAGMENT_SHADER) {
224        mShader.append("precision mediump float;\n");
225    }
226    appendUserConstants();
227    appendAttributes();
228    appendTextures();
229    mShader.append(mUserShader);
230
231    return true;
232}
233
234bool RsdShader::loadShader(const Context *rsc) {
235    mCurrentState->mShaderID = glCreateShader(mType);
236    rsAssert(mCurrentState->mShaderID);
237
238    if(!mShader.length()) {
239        createShader();
240    }
241
242    if (rsc->props.mLogShaders) {
243        ALOGV("Loading shader type %x, ID %i", mType, mCurrentState->mShaderID);
244        ALOGV("%s", mShader.c_str());
245    }
246
247    if (mCurrentState->mShaderID) {
248        const char * ss = mShader.c_str();
249        RSD_CALL_GL(glShaderSource, mCurrentState->mShaderID, 1, &ss, nullptr);
250        RSD_CALL_GL(glCompileShader, mCurrentState->mShaderID);
251
252        GLint compiled = 0;
253        RSD_CALL_GL(glGetShaderiv, mCurrentState->mShaderID, GL_COMPILE_STATUS, &compiled);
254        if (!compiled) {
255            GLint infoLen = 0;
256            RSD_CALL_GL(glGetShaderiv, mCurrentState->mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
257            if (infoLen) {
258                char* buf = (char*) malloc(infoLen);
259                if (buf) {
260                    RSD_CALL_GL(glGetShaderInfoLog, mCurrentState->mShaderID, infoLen, nullptr, buf);
261                    rsc->setError(RS_ERROR_FATAL_PROGRAM_LINK, buf);
262                    free(buf);
263                }
264                RSD_CALL_GL(glDeleteShader, mCurrentState->mShaderID);
265                mCurrentState->mShaderID = 0;
266                return false;
267            }
268        }
269    }
270
271    if (rsc->props.mLogShaders) {
272        ALOGV("--Shader load result %x ", glGetError());
273    }
274    mIsValid = true;
275    return true;
276}
277
278void RsdShader::appendUserConstants() {
279    for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
280        const Element *e = mRSProgram->mHal.state.constantTypes[ct]->getElement();
281        for (uint32_t field=0; field < e->mHal.state.fieldsCount; field++) {
282            const Element *f = e->mHal.state.fields[field];
283            const char *fn = e->mHal.state.fieldNames[field];
284
285            // Cannot be complex
286            rsAssert(!f->mHal.state.fieldsCount);
287            if (f->mHal.state.dataType == RS_TYPE_MATRIX_4X4) {
288                mShader.append("uniform mat4 UNI_");
289            } else if (f->mHal.state.dataType == RS_TYPE_MATRIX_3X3) {
290                mShader.append("uniform mat3 UNI_");
291            } else if (f->mHal.state.dataType == RS_TYPE_MATRIX_2X2) {
292                mShader.append("uniform mat2 UNI_");
293            } else {
294                switch (f->mHal.state.vectorSize) {
295                case 1: mShader.append("uniform float UNI_"); break;
296                case 2: mShader.append("uniform vec2 UNI_"); break;
297                case 3: mShader.append("uniform vec3 UNI_"); break;
298                case 4: mShader.append("uniform vec4 UNI_"); break;
299                default:
300                    rsAssert(0);
301                }
302            }
303
304            mShader.append(fn);
305            if (e->mHal.state.fieldArraySizes[field] > 1) {
306                mShader += "[";
307                mShader += std::to_string(e->mHal.state.fieldArraySizes[field]);
308                mShader += "]";
309            }
310            mShader.append(";\n");
311        }
312    }
313}
314
315void RsdShader::logUniform(const Element *field, const float *fd, uint32_t arraySize ) {
316    RsDataType dataType = field->mHal.state.dataType;
317    uint32_t elementSize = field->mHal.state.elementSizeBytes / sizeof(float);
318    for (uint32_t i = 0; i < arraySize; i ++) {
319        if (arraySize > 1) {
320            ALOGV("Array Element [%u]", i);
321        }
322        if (dataType == RS_TYPE_MATRIX_4X4) {
323            ALOGV("Matrix4x4");
324            ALOGV("{%f, %f, %f, %f",  fd[0], fd[4], fd[8], fd[12]);
325            ALOGV(" %f, %f, %f, %f",  fd[1], fd[5], fd[9], fd[13]);
326            ALOGV(" %f, %f, %f, %f",  fd[2], fd[6], fd[10], fd[14]);
327            ALOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]);
328        } else if (dataType == RS_TYPE_MATRIX_3X3) {
329            ALOGV("Matrix3x3");
330            ALOGV("{%f, %f, %f",  fd[0], fd[3], fd[6]);
331            ALOGV(" %f, %f, %f",  fd[1], fd[4], fd[7]);
332            ALOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]);
333        } else if (dataType == RS_TYPE_MATRIX_2X2) {
334            ALOGV("Matrix2x2");
335            ALOGV("{%f, %f",  fd[0], fd[2]);
336            ALOGV(" %f, %f}", fd[1], fd[3]);
337        } else {
338            switch (field->mHal.state.vectorSize) {
339            case 1:
340                ALOGV("Uniform 1 = %f", fd[0]);
341                break;
342            case 2:
343                ALOGV("Uniform 2 = %f %f", fd[0], fd[1]);
344                break;
345            case 3:
346                ALOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
347                break;
348            case 4:
349                ALOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
350                break;
351            default:
352                rsAssert(0);
353            }
354        }
355        ALOGV("Element size %u data=%p", elementSize, fd);
356        fd += elementSize;
357        ALOGV("New data=%p", fd);
358    }
359}
360
361void RsdShader::setUniform(const Context *rsc, const Element *field, const float *fd,
362                         int32_t slot, uint32_t arraySize ) {
363    RsDataType dataType = field->mHal.state.dataType;
364    if (dataType == RS_TYPE_MATRIX_4X4) {
365        RSD_CALL_GL(glUniformMatrix4fv, slot, arraySize, GL_FALSE, fd);
366    } else if (dataType == RS_TYPE_MATRIX_3X3) {
367        RSD_CALL_GL(glUniformMatrix3fv, slot, arraySize, GL_FALSE, fd);
368    } else if (dataType == RS_TYPE_MATRIX_2X2) {
369        RSD_CALL_GL(glUniformMatrix2fv, slot, arraySize, GL_FALSE, fd);
370    } else {
371        switch (field->mHal.state.vectorSize) {
372        case 1:
373            RSD_CALL_GL(glUniform1fv, slot, arraySize, fd);
374            break;
375        case 2:
376            RSD_CALL_GL(glUniform2fv, slot, arraySize, fd);
377            break;
378        case 3:
379            RSD_CALL_GL(glUniform3fv, slot, arraySize, fd);
380            break;
381        case 4:
382            RSD_CALL_GL(glUniform4fv, slot, arraySize, fd);
383            break;
384        default:
385            rsAssert(0);
386        }
387    }
388}
389
390void RsdShader::setupSampler(const Context *rsc, const Sampler *s, const Allocation *tex) {
391    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
392
393    GLenum trans[] = {
394        GL_NEAREST, //RS_SAMPLER_NEAREST,
395        GL_LINEAR, //RS_SAMPLER_LINEAR,
396        GL_LINEAR_MIPMAP_LINEAR, //RS_SAMPLER_LINEAR_MIP_LINEAR,
397        GL_REPEAT, //RS_SAMPLER_WRAP,
398        GL_CLAMP_TO_EDGE, //RS_SAMPLER_CLAMP
399        GL_LINEAR_MIPMAP_NEAREST, //RS_SAMPLER_LINEAR_MIP_NEAREST
400    };
401
402    GLenum transNP[] = {
403        GL_NEAREST, //RS_SAMPLER_NEAREST,
404        GL_LINEAR, //RS_SAMPLER_LINEAR,
405        GL_LINEAR, //RS_SAMPLER_LINEAR_MIP_LINEAR,
406        GL_CLAMP_TO_EDGE, //RS_SAMPLER_WRAP,
407        GL_CLAMP_TO_EDGE, //RS_SAMPLER_CLAMP
408        GL_LINEAR, //RS_SAMPLER_LINEAR_MIP_NEAREST,
409    };
410
411    // This tells us the correct texture type
412    DrvAllocation *drvTex = (DrvAllocation *)tex->mHal.drv;
413    const GLenum target = drvTex->glTarget;
414    if (!target) {
415        // this can happen if the user set the wrong allocation flags.
416        rsc->setError(RS_ERROR_BAD_VALUE, "Allocation not compatible with sampler");
417        return;
418    }
419
420    if (!dc->gl.gl.OES_texture_npot && tex->getType()->getIsNp2()) {
421        if (tex->getHasGraphicsMipmaps() &&
422            (dc->gl.gl.NV_texture_npot_2D_mipmap || dc->gl.gl.IMG_texture_npot)) {
423            if (dc->gl.gl.NV_texture_npot_2D_mipmap) {
424                RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
425                            trans[s->mHal.state.minFilter]);
426            } else {
427                switch (trans[s->mHal.state.minFilter]) {
428                case GL_LINEAR_MIPMAP_LINEAR:
429                    RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
430                                GL_LINEAR_MIPMAP_NEAREST);
431                    break;
432                default:
433                    RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
434                                trans[s->mHal.state.minFilter]);
435                    break;
436                }
437            }
438        } else {
439            RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
440                        transNP[s->mHal.state.minFilter]);
441        }
442        RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MAG_FILTER,
443                    transNP[s->mHal.state.magFilter]);
444        RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_S, transNP[s->mHal.state.wrapS]);
445        RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_T, transNP[s->mHal.state.wrapT]);
446    } else {
447        if (tex->getHasGraphicsMipmaps()) {
448            RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
449                        trans[s->mHal.state.minFilter]);
450        } else {
451            RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER,
452                        transNP[s->mHal.state.minFilter]);
453        }
454        RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MAG_FILTER, trans[s->mHal.state.magFilter]);
455        RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_S, trans[s->mHal.state.wrapS]);
456        RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_WRAP_T, trans[s->mHal.state.wrapT]);
457    }
458
459    float anisoValue = rsMin(dc->gl.gl.EXT_texture_max_aniso, s->mHal.state.aniso);
460    if (dc->gl.gl.EXT_texture_max_aniso > 1.0f) {
461        RSD_CALL_GL(glTexParameterf, target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoValue);
462    }
463
464    rsdGLCheckError(rsc, "Sampler::setup tex env");
465}
466
467void RsdShader::setupTextures(const Context *rsc, RsdShaderCache *sc) {
468    if (mRSProgram->mHal.state.texturesCount == 0) {
469        return;
470    }
471
472    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
473
474    uint32_t numTexturesToBind = mRSProgram->mHal.state.texturesCount;
475    uint32_t numTexturesAvailable = dc->gl.gl.maxFragmentTextureImageUnits;
476    if (numTexturesToBind >= numTexturesAvailable) {
477        ALOGE("Attempting to bind %u textures on shader id %p, but only %u are available",
478             mRSProgram->mHal.state.texturesCount, this, numTexturesAvailable);
479        rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind more textuers than available");
480        numTexturesToBind = numTexturesAvailable;
481    }
482
483    for (uint32_t ct=0; ct < numTexturesToBind; ct++) {
484        RSD_CALL_GL(glActiveTexture, GL_TEXTURE0 + ct);
485        RSD_CALL_GL(glUniform1i, sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct);
486
487        if (!mRSProgram->mHal.state.textures[ct]) {
488            // if nothing is bound, reset to default GL texture
489            RSD_CALL_GL(glBindTexture, mCurrentState->mTextureTargets[ct], 0);
490            continue;
491        }
492
493        DrvAllocation *drvTex = (DrvAllocation *)mRSProgram->mHal.state.textures[ct]->mHal.drv;
494
495        if (mCurrentState->mTextureTargets[ct] != GL_TEXTURE_2D &&
496            mCurrentState->mTextureTargets[ct] != GL_TEXTURE_CUBE_MAP &&
497            mCurrentState->mTextureTargets[ct] != GL_TEXTURE_EXTERNAL_OES) {
498            ALOGE("Attempting to bind unknown texture to shader id %p, texture unit %u",
499                  this, ct);
500            rsc->setError(RS_ERROR_BAD_SHADER, "Non-texture allocation bound to a shader");
501        }
502        RSD_CALL_GL(glBindTexture, mCurrentState->mTextureTargets[ct], drvTex->textureID);
503        rsdGLCheckError(rsc, "ProgramFragment::setup tex bind");
504        if (mRSProgram->mHal.state.samplers[ct]) {
505            setupSampler(rsc, mRSProgram->mHal.state.samplers[ct],
506                         mRSProgram->mHal.state.textures[ct]);
507        } else {
508            RSD_CALL_GL(glTexParameteri, mCurrentState->mTextureTargets[ct],
509                GL_TEXTURE_MIN_FILTER, GL_NEAREST);
510            RSD_CALL_GL(glTexParameteri, mCurrentState->mTextureTargets[ct],
511                GL_TEXTURE_MAG_FILTER, GL_NEAREST);
512            RSD_CALL_GL(glTexParameteri, mCurrentState->mTextureTargets[ct],
513                GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
514            RSD_CALL_GL(glTexParameteri, mCurrentState->mTextureTargets[ct],
515                GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
516            rsdGLCheckError(rsc, "ProgramFragment::setup basic tex env");
517        }
518        rsdGLCheckError(rsc, "ProgramFragment::setup uniforms");
519    }
520
521    RSD_CALL_GL(glActiveTexture, GL_TEXTURE0);
522    mDirty = false;
523    rsdGLCheckError(rsc, "ProgramFragment::setup");
524}
525
526void RsdShader::setupUserConstants(const Context *rsc, RsdShaderCache *sc, bool isFragment) {
527    uint32_t uidx = 0;
528    for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
529        Allocation *alloc = mRSProgram->mHal.state.constants[ct];
530
531        if (!alloc) {
532            ALOGE("Attempting to set constants on shader id %p, but alloc at slot %u is not set",
533                  this, ct);
534            rsc->setError(RS_ERROR_BAD_SHADER, "No constant allocation bound");
535            continue;
536        }
537
538        const uint8_t *data = static_cast<const uint8_t *>(alloc->mHal.drvState.lod[0].mallocPtr);
539        const Element *e = mRSProgram->mHal.state.constantTypes[ct]->getElement();
540        for (uint32_t field=0; field < e->mHal.state.fieldsCount; field++) {
541            const Element *f = e->mHal.state.fields[field];
542            const char *fieldName = e->mHal.state.fieldNames[field];
543
544            uint32_t offset = e->mHal.state.fieldOffsetBytes[field];
545            const float *fd = reinterpret_cast<const float *>(&data[offset]);
546
547            int32_t slot = -1;
548            uint32_t arraySize = 1;
549            if (!isFragment) {
550                slot = sc->vtxUniformSlot(uidx);
551                arraySize = sc->vtxUniformSize(uidx);
552            } else {
553                slot = sc->fragUniformSlot(uidx);
554                arraySize = sc->fragUniformSize(uidx);
555            }
556            if (rsc->props.mLogShadersUniforms) {
557                ALOGV("Uniform  slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s",
558                     slot, offset, ct, field, uidx, fieldName);
559            }
560            uidx ++;
561            if (slot < 0) {
562                continue;
563            }
564
565            if (rsc->props.mLogShadersUniforms) {
566                logUniform(f, fd, arraySize);
567            }
568            setUniform(rsc, f, fd, slot, arraySize);
569        }
570    }
571}
572
573void RsdShader::setup(const android::renderscript::Context *rsc, RsdShaderCache *sc) {
574
575    setupUserConstants(rsc, sc, mType == GL_FRAGMENT_SHADER);
576    setupTextures(rsc, sc);
577}
578
579void RsdShader::initAttribAndUniformArray() {
580    mAttribCount = 0;
581    for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
582        const Element *elem = mRSProgram->mHal.state.inputElements[ct];
583        mAttribCount += elem->mHal.state.fieldsCount;
584    }
585
586    mUniformCount = 0;
587    for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
588        const Element *elem = mRSProgram->mHal.state.constantTypes[ct]->getElement();
589        mUniformCount += elem->mHal.state.fieldsCount;
590    }
591    mUniformCount += mRSProgram->mHal.state.texturesCount;
592
593    if (mAttribCount) {
594        mAttribNames = new std::string[mAttribCount];
595    }
596    if (mUniformCount) {
597        mUniformNames = new std::string[mUniformCount];
598        mUniformArraySizes = new uint32_t[mUniformCount];
599    }
600
601    mTextureCount = mRSProgram->mHal.state.texturesCount;
602}
603
604void RsdShader::initAddUserElement(const Element *e, std::string *names,
605                                   uint32_t *arrayLengths, uint32_t *count,
606                                   const char *prefix) {
607    rsAssert(e->mHal.state.fieldsCount);
608    for (uint32_t ct=0; ct < e->mHal.state.fieldsCount; ct++) {
609        const Element *ce = e->mHal.state.fields[ct];
610        if (ce->mHal.state.fieldsCount) {
611            initAddUserElement(ce, names, arrayLengths, count, prefix);
612        } else {
613            std::string tmp(prefix);
614            tmp.append(e->mHal.state.fieldNames[ct]);
615            names[*count] = tmp;
616            if (arrayLengths) {
617                arrayLengths[*count] = e->mHal.state.fieldArraySizes[ct];
618            }
619            (*count)++;
620        }
621    }
622}
623