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