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