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