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