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