Home | History | Annotate | Download | only in renderscript
      1 /*
      2  * Copyright (C) 2008 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 package android.renderscript;
     18 
     19 
     20 import java.io.IOException;
     21 import java.io.InputStream;
     22 import java.io.UnsupportedEncodingException;
     23 
     24 import android.content.res.Resources;
     25 import android.util.Log;
     26 
     27 
     28 /**
     29  * @hide
     30  *
     31  * Program is a base class for all the objects that modify
     32  * various stages of the graphics pipeline
     33  *
     34  **/
     35 public class Program extends BaseObj {
     36     static final int MAX_INPUT = 8;
     37     static final int MAX_OUTPUT = 8;
     38     static final int MAX_CONSTANT = 8;
     39     static final int MAX_TEXTURE = 8;
     40 
     41     /**
     42      *
     43      * TextureType specifies what textures are attached to Program
     44      * objects
     45      *
     46      **/
     47     public enum TextureType {
     48         TEXTURE_2D (0),
     49         TEXTURE_CUBE (1);
     50 
     51         int mID;
     52         TextureType(int id) {
     53             mID = id;
     54         }
     55     }
     56 
     57     enum ProgramParam {
     58         INPUT (0),
     59         OUTPUT (1),
     60         CONSTANT (2),
     61         TEXTURE_TYPE (3);
     62 
     63         int mID;
     64         ProgramParam(int id) {
     65             mID = id;
     66         }
     67     };
     68 
     69     Element mInputs[];
     70     Element mOutputs[];
     71     Type mConstants[];
     72     TextureType mTextures[];
     73     String mTextureNames[];
     74     int mTextureCount;
     75     String mShader;
     76 
     77     Program(long id, RenderScript rs) {
     78         super(id, rs);
     79         guard.open("destroy");
     80     }
     81 
     82     /**
     83      * Program object can have zero or more constant allocations
     84      * associated with it. This method returns the total count.
     85      * @return number of constant input types
     86      */
     87     public int getConstantCount() {
     88         return mConstants != null ? mConstants.length : 0;
     89     }
     90 
     91     /**
     92      * Returns the type of the constant buffer used in the program
     93      * object. It could be used to query internal elements or create
     94      * an allocation to store constant data.
     95      * @param slot index of the constant input type to return
     96      * @return constant input type
     97      */
     98     public Type getConstant(int slot) {
     99         if (slot < 0 || slot >= mConstants.length) {
    100             throw new IllegalArgumentException("Slot ID out of range.");
    101         }
    102         return mConstants[slot];
    103     }
    104 
    105     /**
    106      * Returns the number of textures used in this program object
    107      * @return number of texture inputs
    108      */
    109     public int getTextureCount() {
    110         return mTextureCount;
    111     }
    112 
    113     /**
    114      * Returns the type of texture at a given slot. e.g. 2D or Cube
    115      * @param slot index of the texture input
    116      * @return texture input type
    117      */
    118     public TextureType getTextureType(int slot) {
    119         if ((slot < 0) || (slot >= mTextureCount)) {
    120             throw new IllegalArgumentException("Slot ID out of range.");
    121         }
    122         return mTextures[slot];
    123     }
    124 
    125     /**
    126      * Returns the name of the texture input at a given slot. e.g.
    127      * tex0, diffuse, spec
    128      * @param slot index of the texture input
    129      * @return texture input name
    130      */
    131     public String getTextureName(int slot) {
    132         if ((slot < 0) || (slot >= mTextureCount)) {
    133             throw new IllegalArgumentException("Slot ID out of range.");
    134         }
    135         return mTextureNames[slot];
    136     }
    137 
    138     /**
    139      * Binds a constant buffer to be used as uniform inputs to the
    140      * program
    141      *
    142      * @param a allocation containing uniform data
    143      * @param slot index within the program's list of constant
    144      *             buffer allocations
    145      */
    146     public void bindConstants(Allocation a, int slot) {
    147         if (slot < 0 || slot >= mConstants.length) {
    148             throw new IllegalArgumentException("Slot ID out of range.");
    149         }
    150         if (a != null &&
    151             a.getType().getID(mRS) != mConstants[slot].getID(mRS)) {
    152             throw new IllegalArgumentException("Allocation type does not match slot type.");
    153         }
    154         long id = a != null ? a.getID(mRS) : 0;
    155         mRS.nProgramBindConstants(getID(mRS), slot, id);
    156     }
    157 
    158     /**
    159      * Binds a texture to be used in the program
    160      *
    161      * @param va allocation containing texture data
    162      * @param slot index within the program's list of textures
    163      *
    164      */
    165     public void bindTexture(Allocation va, int slot)
    166         throws IllegalArgumentException {
    167         mRS.validate();
    168         if ((slot < 0) || (slot >= mTextureCount)) {
    169             throw new IllegalArgumentException("Slot ID out of range.");
    170         }
    171         if (va != null && va.getType().hasFaces() &&
    172             mTextures[slot] != TextureType.TEXTURE_CUBE) {
    173             throw new IllegalArgumentException("Cannot bind cubemap to 2d texture slot");
    174         }
    175 
    176         long id = va != null ? va.getID(mRS) : 0;
    177         mRS.nProgramBindTexture(getID(mRS), slot, id);
    178     }
    179 
    180     /**
    181      * Binds an object that describes how a texture at the
    182      * corresponding location is sampled
    183      *
    184      * @param vs sampler for a corresponding texture
    185      * @param slot index within the program's list of textures to
    186      *             use the sampler on
    187      *
    188      */
    189     public void bindSampler(Sampler vs, int slot)
    190         throws IllegalArgumentException {
    191         mRS.validate();
    192         if ((slot < 0) || (slot >= mTextureCount)) {
    193             throw new IllegalArgumentException("Slot ID out of range.");
    194         }
    195 
    196         long id = vs != null ? vs.getID(mRS) : 0;
    197         mRS.nProgramBindSampler(getID(mRS), slot, id);
    198     }
    199 
    200 
    201     public static class BaseProgramBuilder {
    202         RenderScript mRS;
    203         Element mInputs[];
    204         Element mOutputs[];
    205         Type mConstants[];
    206         Type mTextures[];
    207         TextureType mTextureTypes[];
    208         String mTextureNames[];
    209         int mInputCount;
    210         int mOutputCount;
    211         int mConstantCount;
    212         int mTextureCount;
    213         String mShader;
    214 
    215 
    216         protected BaseProgramBuilder(RenderScript rs) {
    217             mRS = rs;
    218             mInputs = new Element[MAX_INPUT];
    219             mOutputs = new Element[MAX_OUTPUT];
    220             mConstants = new Type[MAX_CONSTANT];
    221             mInputCount = 0;
    222             mOutputCount = 0;
    223             mConstantCount = 0;
    224             mTextureCount = 0;
    225             mTextureTypes = new TextureType[MAX_TEXTURE];
    226             mTextureNames = new String[MAX_TEXTURE];
    227         }
    228 
    229         /**
    230          * Sets the GLSL shader code to be used in the program
    231          *
    232          * @param s GLSL shader string
    233          * @return  self
    234          */
    235         public BaseProgramBuilder setShader(String s) {
    236             mShader = s;
    237             return this;
    238         }
    239 
    240         /**
    241          * Sets the GLSL shader code to be used in the program
    242          *
    243          * @param resources application resources
    244          * @param resourceID id of the file containing GLSL shader code
    245          *
    246          * @return  self
    247          */
    248         public BaseProgramBuilder setShader(Resources resources, int resourceID) {
    249             byte[] str;
    250             int strLength;
    251             InputStream is = resources.openRawResource(resourceID);
    252             try {
    253                 try {
    254                     str = new byte[1024];
    255                     strLength = 0;
    256                     while(true) {
    257                         int bytesLeft = str.length - strLength;
    258                         if (bytesLeft == 0) {
    259                             byte[] buf2 = new byte[str.length * 2];
    260                             System.arraycopy(str, 0, buf2, 0, str.length);
    261                             str = buf2;
    262                             bytesLeft = str.length - strLength;
    263                         }
    264                         int bytesRead = is.read(str, strLength, bytesLeft);
    265                         if (bytesRead <= 0) {
    266                             break;
    267                         }
    268                         strLength += bytesRead;
    269                     }
    270                 } finally {
    271                     is.close();
    272                 }
    273             } catch(IOException e) {
    274                 throw new Resources.NotFoundException();
    275             }
    276 
    277             try {
    278                 mShader = new String(str, 0, strLength, "UTF-8");
    279             } catch (UnsupportedEncodingException e) {
    280                 Log.e("RenderScript shader creation", "Could not decode shader string");
    281             }
    282 
    283             return this;
    284         }
    285 
    286         /**
    287          * Queries the index of the last added constant buffer type
    288          *
    289          */
    290         public int getCurrentConstantIndex() {
    291             return mConstantCount - 1;
    292         }
    293 
    294         /**
    295          * Queries the index of the last added texture type
    296          *
    297          */
    298         public int getCurrentTextureIndex() {
    299             return mTextureCount - 1;
    300         }
    301 
    302         /**
    303          * Adds constant (uniform) inputs to the program
    304          *
    305          * @param t Type that describes the layout of the Allocation
    306          *          object to be used as constant inputs to the Program
    307          * @return  self
    308          */
    309         public BaseProgramBuilder addConstant(Type t) throws IllegalStateException {
    310             // Should check for consistant and non-conflicting names...
    311             if(mConstantCount >= MAX_CONSTANT) {
    312                 throw new RSIllegalArgumentException("Max input count exceeded.");
    313             }
    314             if (t.getElement().isComplex()) {
    315                 throw new RSIllegalArgumentException("Complex elements not allowed.");
    316             }
    317             mConstants[mConstantCount] = t;
    318             mConstantCount++;
    319             return this;
    320         }
    321 
    322         /**
    323          * Adds a texture input to the Program
    324          *
    325          * @param texType describes that the texture to append it (2D,
    326          *                Cubemap, etc.)
    327          * @return  self
    328          */
    329         public BaseProgramBuilder addTexture(TextureType texType) throws IllegalArgumentException {
    330             addTexture(texType, "Tex" + mTextureCount);
    331             return this;
    332         }
    333 
    334         /**
    335          * Adds a texture input to the Program
    336          *
    337          * @param texType describes that the texture to append it (2D,
    338          *                Cubemap, etc.)
    339          * @param texName what the texture should be called in the
    340          *                shader
    341          * @return  self
    342          */
    343         public BaseProgramBuilder addTexture(TextureType texType, String texName)
    344             throws IllegalArgumentException {
    345             if(mTextureCount >= MAX_TEXTURE) {
    346                 throw new IllegalArgumentException("Max texture count exceeded.");
    347             }
    348             mTextureTypes[mTextureCount] = texType;
    349             mTextureNames[mTextureCount] = texName;
    350             mTextureCount ++;
    351             return this;
    352         }
    353 
    354         protected void initProgram(Program p) {
    355             p.mInputs = new Element[mInputCount];
    356             System.arraycopy(mInputs, 0, p.mInputs, 0, mInputCount);
    357             p.mOutputs = new Element[mOutputCount];
    358             System.arraycopy(mOutputs, 0, p.mOutputs, 0, mOutputCount);
    359             p.mConstants = new Type[mConstantCount];
    360             System.arraycopy(mConstants, 0, p.mConstants, 0, mConstantCount);
    361             p.mTextureCount = mTextureCount;
    362             p.mTextures = new TextureType[mTextureCount];
    363             System.arraycopy(mTextureTypes, 0, p.mTextures, 0, mTextureCount);
    364             p.mTextureNames = new String[mTextureCount];
    365             System.arraycopy(mTextureNames, 0, p.mTextureNames, 0, mTextureCount);
    366         }
    367     }
    368 
    369 }
    370 
    371 
    372