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 * 30 * Program is a base class for all the objects that modify 31 * various stages of the graphics pipeline 32 * 33 **/ 34 public class Program extends BaseObj { 35 static final int MAX_INPUT = 8; 36 static final int MAX_OUTPUT = 8; 37 static final int MAX_CONSTANT = 8; 38 static final int MAX_TEXTURE = 8; 39 40 /** 41 * 42 * TextureType specifies what textures are attached to Program 43 * objects 44 * 45 **/ 46 public enum TextureType { 47 TEXTURE_2D (0), 48 TEXTURE_CUBE (1); 49 50 int mID; TextureType(int id)51 TextureType(int id) { 52 mID = id; 53 } 54 } 55 56 enum ProgramParam { 57 INPUT (0), 58 OUTPUT (1), 59 CONSTANT (2), 60 TEXTURE_TYPE (3); 61 62 int mID; ProgramParam(int id)63 ProgramParam(int id) { 64 mID = id; 65 } 66 }; 67 68 Element mInputs[]; 69 Element mOutputs[]; 70 Type mConstants[]; 71 TextureType mTextures[]; 72 int mTextureCount; 73 String mShader; 74 Program(int id, RenderScript rs)75 Program(int id, RenderScript rs) { 76 super(id, rs); 77 } 78 79 /** 80 * Binds a constant buffer to be used as uniform inputs to the 81 * program 82 * 83 * @param a allocation containing uniform data 84 * @param slot index within the program's list of constant 85 * buffer allocations 86 */ bindConstants(Allocation a, int slot)87 public void bindConstants(Allocation a, int slot) { 88 if (slot < 0 || slot >= mConstants.length) { 89 throw new IllegalArgumentException("Slot ID out of range."); 90 } 91 if (a != null && 92 a.getType().getID() != mConstants[slot].getID()) { 93 throw new IllegalArgumentException("Allocation type does not match slot type."); 94 } 95 int id = a != null ? a.getID() : 0; 96 mRS.nProgramBindConstants(getID(), slot, id); 97 } 98 99 /** 100 * Binds a texture to be used in the program 101 * 102 * @param va allocation containing texture data 103 * @param slot index within the program's list of textures 104 * 105 */ bindTexture(Allocation va, int slot)106 public void bindTexture(Allocation va, int slot) 107 throws IllegalArgumentException { 108 mRS.validate(); 109 if ((slot < 0) || (slot >= mTextureCount)) { 110 throw new IllegalArgumentException("Slot ID out of range."); 111 } 112 if (va != null && va.getType().hasFaces() && 113 mTextures[slot] != TextureType.TEXTURE_CUBE) { 114 throw new IllegalArgumentException("Cannot bind cubemap to 2d texture slot"); 115 } 116 117 int id = va != null ? va.getID() : 0; 118 mRS.nProgramBindTexture(getID(), slot, id); 119 } 120 121 /** 122 * Binds an object that describes how a texture at the 123 * corresponding location is sampled 124 * 125 * @param vs sampler for a corresponding texture 126 * @param slot index within the program's list of textures to 127 * use the sampler on 128 * 129 */ bindSampler(Sampler vs, int slot)130 public void bindSampler(Sampler vs, int slot) 131 throws IllegalArgumentException { 132 mRS.validate(); 133 if ((slot < 0) || (slot >= mTextureCount)) { 134 throw new IllegalArgumentException("Slot ID out of range."); 135 } 136 137 int id = vs != null ? vs.getID() : 0; 138 mRS.nProgramBindSampler(getID(), slot, id); 139 } 140 141 142 public static class BaseProgramBuilder { 143 RenderScript mRS; 144 Element mInputs[]; 145 Element mOutputs[]; 146 Type mConstants[]; 147 Type mTextures[]; 148 TextureType mTextureTypes[]; 149 int mInputCount; 150 int mOutputCount; 151 int mConstantCount; 152 int mTextureCount; 153 String mShader; 154 155 BaseProgramBuilder(RenderScript rs)156 protected BaseProgramBuilder(RenderScript rs) { 157 mRS = rs; 158 mInputs = new Element[MAX_INPUT]; 159 mOutputs = new Element[MAX_OUTPUT]; 160 mConstants = new Type[MAX_CONSTANT]; 161 mInputCount = 0; 162 mOutputCount = 0; 163 mConstantCount = 0; 164 mTextureCount = 0; 165 mTextureTypes = new TextureType[MAX_TEXTURE]; 166 } 167 168 /** 169 * Sets the GLSL shader code to be used in the program 170 * 171 * @param s GLSL shader string 172 * @return self 173 */ setShader(String s)174 public BaseProgramBuilder setShader(String s) { 175 mShader = s; 176 return this; 177 } 178 179 /** 180 * Sets the GLSL shader code to be used in the program 181 * 182 * @param resources application resources 183 * @param resourceID id of the file containing GLSL shader code 184 * 185 * @return self 186 */ setShader(Resources resources, int resourceID)187 public BaseProgramBuilder setShader(Resources resources, int resourceID) { 188 byte[] str; 189 int strLength; 190 InputStream is = resources.openRawResource(resourceID); 191 try { 192 try { 193 str = new byte[1024]; 194 strLength = 0; 195 while(true) { 196 int bytesLeft = str.length - strLength; 197 if (bytesLeft == 0) { 198 byte[] buf2 = new byte[str.length * 2]; 199 System.arraycopy(str, 0, buf2, 0, str.length); 200 str = buf2; 201 bytesLeft = str.length - strLength; 202 } 203 int bytesRead = is.read(str, strLength, bytesLeft); 204 if (bytesRead <= 0) { 205 break; 206 } 207 strLength += bytesRead; 208 } 209 } finally { 210 is.close(); 211 } 212 } catch(IOException e) { 213 throw new Resources.NotFoundException(); 214 } 215 216 try { 217 mShader = new String(str, 0, strLength, "UTF-8"); 218 } catch (UnsupportedEncodingException e) { 219 Log.e("Renderscript shader creation", "Could not decode shader string"); 220 } 221 222 return this; 223 } 224 225 /** 226 * Queries the index of the last added constant buffer type 227 * 228 */ getCurrentConstantIndex()229 public int getCurrentConstantIndex() { 230 return mConstantCount - 1; 231 } 232 233 /** 234 * Queries the index of the last added texture type 235 * 236 */ getCurrentTextureIndex()237 public int getCurrentTextureIndex() { 238 return mTextureCount - 1; 239 } 240 241 /** 242 * Adds constant (uniform) inputs to the program 243 * 244 * @param t Type that describes the layout of the Allocation 245 * object to be used as constant inputs to the Program 246 * @return self 247 */ addConstant(Type t)248 public BaseProgramBuilder addConstant(Type t) throws IllegalStateException { 249 // Should check for consistant and non-conflicting names... 250 if(mConstantCount >= MAX_CONSTANT) { 251 throw new RSIllegalArgumentException("Max input count exceeded."); 252 } 253 if (t.getElement().isComplex()) { 254 throw new RSIllegalArgumentException("Complex elements not allowed."); 255 } 256 mConstants[mConstantCount] = t; 257 mConstantCount++; 258 return this; 259 } 260 261 /** 262 * Adds a texture input to the Program 263 * 264 * @param texType describes that the texture to append it (2D, 265 * Cubemap, etc.) 266 * @return self 267 */ addTexture(TextureType texType)268 public BaseProgramBuilder addTexture(TextureType texType) throws IllegalArgumentException { 269 if(mTextureCount >= MAX_TEXTURE) { 270 throw new IllegalArgumentException("Max texture count exceeded."); 271 } 272 mTextureTypes[mTextureCount ++] = texType; 273 return this; 274 } 275 initProgram(Program p)276 protected void initProgram(Program p) { 277 p.mInputs = new Element[mInputCount]; 278 System.arraycopy(mInputs, 0, p.mInputs, 0, mInputCount); 279 p.mOutputs = new Element[mOutputCount]; 280 System.arraycopy(mOutputs, 0, p.mOutputs, 0, mOutputCount); 281 p.mConstants = new Type[mConstantCount]; 282 System.arraycopy(mConstants, 0, p.mConstants, 0, mConstantCount); 283 p.mTextureCount = mTextureCount; 284 p.mTextures = new TextureType[mTextureCount]; 285 System.arraycopy(mTextureTypes, 0, p.mTextures, 0, mTextureCount); 286 } 287 } 288 289 } 290 291 292