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