Home | History | Annotate | Download | only in rs
      1 /*
      2  * Copyright (C) 2009 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 <GLES2/gl2.h>
     21 #include <GLES2/gl2ext.h>
     22 
     23 using namespace android;
     24 using namespace android::renderscript;
     25 
     26 
     27 Program::Program(Context *rsc) : ObjectBase(rsc)
     28 {
     29     mAllocFile = __FILE__;
     30     mAllocLine = __LINE__;
     31     mDirty = true;
     32     mShaderID = 0;
     33     mAttribCount = 0;
     34     mUniformCount = 0;
     35 
     36     mInputElements = NULL;
     37     mOutputElements = NULL;
     38     mConstantTypes = NULL;
     39     mInputCount = 0;
     40     mOutputCount = 0;
     41     mConstantCount = 0;
     42     mIsValid = false;
     43 }
     44 
     45 Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
     46                  const uint32_t * params, uint32_t paramLength) :
     47     ObjectBase(rsc)
     48 {
     49     mAllocFile = __FILE__;
     50     mAllocLine = __LINE__;
     51     mDirty = true;
     52     mShaderID = 0;
     53     mAttribCount = 0;
     54     mUniformCount = 0;
     55     mTextureCount = 0;
     56 
     57     mInputCount = 0;
     58     mOutputCount = 0;
     59     mConstantCount = 0;
     60 
     61     for (uint32_t ct=0; ct < paramLength; ct+=2) {
     62         if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
     63             mInputCount++;
     64         }
     65         if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
     66             mOutputCount++;
     67         }
     68         if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
     69             mConstantCount++;
     70         }
     71         if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) {
     72             mTextureCount = params[ct+1];
     73         }
     74     }
     75 
     76     mInputElements = new ObjectBaseRef<Element>[mInputCount];
     77     mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
     78     mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
     79 
     80     uint32_t input = 0;
     81     uint32_t output = 0;
     82     uint32_t constant = 0;
     83     for (uint32_t ct=0; ct < paramLength; ct+=2) {
     84         if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
     85             mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
     86         }
     87         if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
     88             mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
     89         }
     90         if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
     91             mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
     92         }
     93     }
     94     mUserShader.setTo(shaderText, shaderLength);
     95 }
     96 
     97 Program::~Program()
     98 {
     99     for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) {
    100         bindAllocation(NULL, ct);
    101     }
    102 
    103     delete[] mInputElements;
    104     delete[] mOutputElements;
    105     delete[] mConstantTypes;
    106     mInputCount = 0;
    107     mOutputCount = 0;
    108     mConstantCount = 0;
    109 }
    110 
    111 
    112 void Program::bindAllocation(Allocation *alloc, uint32_t slot)
    113 {
    114     if (mConstants[slot].get() == alloc) {
    115         return;
    116     }
    117     if (mConstants[slot].get()) {
    118         mConstants[slot].get()->removeProgramToDirty(this);
    119     }
    120     mConstants[slot].set(alloc);
    121     if (alloc) {
    122         alloc->addProgramToDirty(this);
    123     }
    124     mDirty = true;
    125 }
    126 
    127 void Program::bindTexture(uint32_t slot, Allocation *a)
    128 {
    129     if (slot >= MAX_TEXTURE) {
    130         LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
    131         return;
    132     }
    133 
    134     //LOGE("bindtex %i %p", slot, a);
    135     mTextures[slot].set(a);
    136     mDirty = true;
    137 }
    138 
    139 void Program::bindSampler(uint32_t slot, Sampler *s)
    140 {
    141     if (slot >= MAX_TEXTURE) {
    142         LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
    143         return;
    144     }
    145 
    146     mSamplers[slot].set(s);
    147     mDirty = true;
    148 }
    149 
    150 String8 Program::getGLSLInputString() const
    151 {
    152     String8 s;
    153     for (uint32_t ct=0; ct < mInputCount; ct++) {
    154         const Element *e = mInputElements[ct].get();
    155         for (uint32_t field=0; field < e->getFieldCount(); field++) {
    156             const Element *f = e->getField(field);
    157 
    158             // Cannot be complex
    159             rsAssert(!f->getFieldCount());
    160             switch(f->getComponent().getVectorSize()) {
    161             case 1: s.append("attribute float ATTRIB_"); break;
    162             case 2: s.append("attribute vec2 ATTRIB_"); break;
    163             case 3: s.append("attribute vec3 ATTRIB_"); break;
    164             case 4: s.append("attribute vec4 ATTRIB_"); break;
    165             default:
    166                 rsAssert(0);
    167             }
    168 
    169             s.append(e->getFieldName(field));
    170             s.append(";\n");
    171         }
    172     }
    173     return s;
    174 }
    175 
    176 String8 Program::getGLSLOutputString() const
    177 {
    178     return String8();
    179 }
    180 
    181 String8 Program::getGLSLConstantString() const
    182 {
    183     return String8();
    184 }
    185 
    186 
    187 void Program::createShader()
    188 {
    189 }
    190 
    191 bool Program::loadShader(Context *rsc, uint32_t type)
    192 {
    193     mShaderID = glCreateShader(type);
    194     rsAssert(mShaderID);
    195 
    196     if (rsc->props.mLogShaders) {
    197         LOGV("Loading shader type %x, ID %i", type, mShaderID);
    198         LOGV("%s", mShader.string());
    199     }
    200 
    201     if (mShaderID) {
    202         const char * ss = mShader.string();
    203         glShaderSource(mShaderID, 1, &ss, NULL);
    204         glCompileShader(mShaderID);
    205 
    206         GLint compiled = 0;
    207         glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
    208         if (!compiled) {
    209             GLint infoLen = 0;
    210             glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
    211             if (infoLen) {
    212                 char* buf = (char*) malloc(infoLen);
    213                 if (buf) {
    214                     glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
    215                     LOGE("Could not compile shader \n%s\n", buf);
    216                     free(buf);
    217                 }
    218                 glDeleteShader(mShaderID);
    219                 mShaderID = 0;
    220                 rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
    221                 return false;
    222             }
    223         }
    224     }
    225 
    226     if (rsc->props.mLogShaders) {
    227         LOGV("--Shader load result %x ", glGetError());
    228     }
    229     mIsValid = true;
    230     return true;
    231 }
    232 
    233 void Program::setShader(const char *txt, uint32_t len)
    234 {
    235     mUserShader.setTo(txt, len);
    236 }
    237 
    238 
    239 
    240 namespace android {
    241 namespace renderscript {
    242 
    243 
    244 void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants)
    245 {
    246     Program *p = static_cast<Program *>(vp);
    247     p->bindAllocation(static_cast<Allocation *>(constants), slot);
    248 }
    249 
    250 void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a)
    251 {
    252     Program *p = static_cast<Program *>(vpf);
    253     p->bindTexture(slot, static_cast<Allocation *>(a));
    254 }
    255 
    256 void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s)
    257 {
    258     Program *p = static_cast<Program *>(vpf);
    259     p->bindSampler(slot, static_cast<Sampler *>(s));
    260 }
    261 
    262 }
    263 }
    264 
    265