Home | History | Annotate | Download | only in rs
      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 namespace android {
     23 namespace 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 void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants) {
    213     Program *p = static_cast<Program *>(vp);
    214     p->bindAllocation(rsc, static_cast<Allocation *>(constants), slot);
    215 }
    216 
    217 void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a) {
    218     Program *p = static_cast<Program *>(vpf);
    219     p->bindTexture(rsc, slot, static_cast<Allocation *>(a));
    220 }
    221 
    222 void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s) {
    223     Program *p = static_cast<Program *>(vpf);
    224     p->bindSampler(rsc, slot, static_cast<Sampler *>(s));
    225 }
    226 
    227 } // namespace renderscript
    228 } // namespace android
    229