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 "rsContext.h" 18 #include "rsProgram.h" 19 20 #include <inttypes.h> 21 22 using namespace android; 23 using namespace android::renderscript; 24 25 Program::Program(Context *rsc, const char * shaderText, size_t shaderLength, 26 const uintptr_t * params, size_t paramLength) 27 : ProgramBase(rsc) { 28 29 initMemberVars(); 30 for (uint32_t ct=0; ct < paramLength; ct+=2) { 31 if (params[ct] == RS_PROGRAM_PARAM_INPUT) { 32 mHal.state.inputElementsCount++; 33 } 34 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) { 35 mHal.state.constantsCount++; 36 } 37 if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) { 38 mHal.state.texturesCount++; 39 } 40 } 41 42 mTextures = new ObjectBaseRef<Allocation>[mHal.state.texturesCount]; 43 mSamplers = new ObjectBaseRef<Sampler>[mHal.state.texturesCount]; 44 mInputElements = new ObjectBaseRef<Element>[mHal.state.inputElementsCount]; 45 mConstantTypes = new ObjectBaseRef<Type>[mHal.state.constantsCount]; 46 mConstants = new ObjectBaseRef<Allocation>[mHal.state.constantsCount]; 47 48 mHal.state.textures = new Allocation*[mHal.state.texturesCount]; 49 mHal.state.samplers = new Sampler*[mHal.state.texturesCount]; 50 mHal.state.textureTargets = new RsTextureTarget[mHal.state.texturesCount]; 51 mHal.state.inputElements = new Element*[mHal.state.inputElementsCount]; 52 mHal.state.constantTypes = new Type*[mHal.state.constantsCount]; 53 mHal.state.constants = new Allocation*[mHal.state.constantsCount]; 54 55 // Will initialize everything 56 freeChildren(); 57 58 uint32_t input = 0; 59 uint32_t constant = 0; 60 uint32_t texture = 0; 61 for (uint32_t ct=0; ct < paramLength; ct+=2) { 62 if (params[ct] == RS_PROGRAM_PARAM_INPUT) { 63 mInputElements[input].set(reinterpret_cast<Element *>(params[ct+1])); 64 mHal.state.inputElements[input++] = reinterpret_cast<Element *>(params[ct+1]); 65 } 66 if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) { 67 mConstantTypes[constant].set(reinterpret_cast<Type *>(params[ct+1])); 68 mHal.state.constantTypes[constant++] = reinterpret_cast<Type *>(params[ct+1]); 69 } 70 if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) { 71 mHal.state.textureTargets[texture++] = (RsTextureTarget)params[ct+1]; 72 } 73 } 74 mIsInternal = false; 75 uint32_t internalTokenLen = strlen(RS_SHADER_INTERNAL); 76 if (shaderLength > internalTokenLen && 77 strncmp(RS_SHADER_INTERNAL, shaderText, internalTokenLen) == 0) { 78 mIsInternal = true; 79 shaderText += internalTokenLen; 80 shaderLength -= internalTokenLen; 81 } 82 83 mUserShader = rsuCopyString(shaderText, shaderLength); 84 mUserShaderLen = shaderLength; 85 } 86 87 Program::~Program() { 88 freeChildren(); 89 90 delete[] mTextures; 91 delete[] mSamplers; 92 delete[] mInputElements; 93 delete[] mConstantTypes; 94 delete[] mConstants; 95 96 delete[] mHal.state.textures; 97 delete[] mHal.state.samplers; 98 delete[] mHal.state.textureTargets; 99 delete[] mHal.state.inputElements; 100 delete[] mHal.state.constantTypes; 101 delete[] mHal.state.constants; 102 mHal.state.inputElementsCount = 0; 103 mHal.state.constantsCount = 0; 104 mHal.state.texturesCount = 0; 105 106 if (mUserShader != nullptr) { 107 delete[] mUserShader; 108 mUserShader = nullptr; 109 } 110 mUserShaderLen = 0; 111 } 112 113 bool Program::freeChildren() { 114 for (uint32_t ct=0; ct < mHal.state.constantsCount; ct++) { 115 bindAllocation(nullptr, nullptr, ct); 116 } 117 118 for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) { 119 bindTexture(nullptr, ct, nullptr); 120 bindSampler(nullptr, ct, nullptr); 121 } 122 return false; 123 } 124 125 void Program::initMemberVars() { 126 mDirty = true; 127 128 mHal.drv = nullptr; 129 mHal.state.textures = nullptr; 130 mHal.state.samplers = nullptr; 131 mHal.state.textureTargets = nullptr; 132 mHal.state.inputElements = nullptr; 133 mHal.state.constantTypes = nullptr; 134 mHal.state.constants = nullptr; 135 136 mHal.state.inputElementsCount = 0; 137 mHal.state.constantsCount = 0; 138 mHal.state.texturesCount = 0; 139 140 mTextures = nullptr; 141 mSamplers = nullptr; 142 mInputElements = nullptr; 143 mConstantTypes = nullptr; 144 mConstants = nullptr; 145 146 mIsInternal = false; 147 148 mUserShader = nullptr; 149 mUserShaderLen = 0; 150 } 151 152 void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot) { 153 if (alloc != nullptr) { 154 if (slot >= mHal.state.constantsCount) { 155 ALOGE("Attempt to bind alloc at slot %u, on shader id %" PRIuPTR ", but const count is %u", 156 slot, (uintptr_t)this, mHal.state.constantsCount); 157 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation"); 158 return; 159 } 160 if (alloc->getType() != mConstantTypes[slot].get()) { 161 ALOGE("Attempt to bind alloc at slot %u, on shader id %" PRIuPTR ", but types mismatch", 162 slot, (uintptr_t)this); 163 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation"); 164 return; 165 } 166 } 167 if (mConstants[slot].get() == alloc) { 168 return; 169 } 170 if (mConstants[slot].get()) { 171 mConstants[slot]->removeProgramToDirty(this); 172 } 173 mConstants[slot].set(alloc); 174 mHal.state.constants[slot] = alloc; 175 if (alloc) { 176 alloc->addProgramToDirty(this); 177 } 178 mDirty = true; 179 } 180 181 void Program::bindTexture(Context *rsc, uint32_t slot, Allocation *a) { 182 if (slot >= mHal.state.texturesCount) { 183 ALOGE("Attempt to bind texture to slot %u but tex count is %u", slot, mHal.state.texturesCount); 184 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind texture"); 185 return; 186 } 187 188 if (a && a->getType()->getDimFaces() && mHal.state.textureTargets[slot] != RS_TEXTURE_CUBE) { 189 ALOGE("Attempt to bind cubemap to slot %u but 2d texture needed", slot); 190 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind cubemap to 2d texture slot"); 191 return; 192 } 193 194 mTextures[slot].set(a); 195 mHal.state.textures[slot] = a; 196 197 mDirty = true; 198 } 199 200 void Program::bindSampler(Context *rsc, uint32_t slot, Sampler *s) { 201 if (slot >= mHal.state.texturesCount) { 202 ALOGE("Attempt to bind sampler to slot %u but tex count is %u", slot, mHal.state.texturesCount); 203 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind sampler"); 204 return; 205 } 206 207 mSamplers[slot].set(s); 208 mHal.state.samplers[slot] = s; 209 mDirty = true; 210 } 211 212 namespace android { 213 namespace renderscript { 214 215 void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants) { 216 Program *p = static_cast<Program *>(vp); 217 p->bindAllocation(rsc, static_cast<Allocation *>(constants), slot); 218 } 219 220 void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a) { 221 Program *p = static_cast<Program *>(vpf); 222 p->bindTexture(rsc, slot, static_cast<Allocation *>(a)); 223 } 224 225 void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s) { 226 Program *p = static_cast<Program *>(vpf); 227 p->bindSampler(rsc, slot, static_cast<Sampler *>(s)); 228 } 229 230 } 231 } 232 233