ProgramFragmentFixedFunction.java revision 2123b46ba85adb2cfb78068f8368e830640118d3
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 android.util.Log; 21 22 23/** 24 * <p>ProgramFragmentFixedFunction is a helper class that provides 25 * a way to make a simple fragment shader without writing any 26 * GLSL code. This class allows for display of constant color, interpolated 27 * color from the vertex shader, or combinations of the both 28 * blended with results of up to two texture lookups.</p 29 * 30 **/ 31public class ProgramFragmentFixedFunction extends ProgramFragment { 32 ProgramFragmentFixedFunction(int id, RenderScript rs) { 33 super(id, rs); 34 } 35 36 static class InternalBuilder extends BaseProgramBuilder { 37 public InternalBuilder(RenderScript rs) { 38 super(rs); 39 } 40 41 /** 42 * Creates ProgramFragmentFixedFunction from the current state 43 * of the builder 44 * 45 * @return ProgramFragmentFixedFunction 46 */ 47 public ProgramFragmentFixedFunction create() { 48 mRS.validate(); 49 int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2]; 50 String[] texNames = new String[mTextureCount]; 51 int idx = 0; 52 53 for (int i=0; i < mInputCount; i++) { 54 tmp[idx++] = ProgramParam.INPUT.mID; 55 tmp[idx++] = mInputs[i].getID(); 56 } 57 for (int i=0; i < mOutputCount; i++) { 58 tmp[idx++] = ProgramParam.OUTPUT.mID; 59 tmp[idx++] = mOutputs[i].getID(); 60 } 61 for (int i=0; i < mConstantCount; i++) { 62 tmp[idx++] = ProgramParam.CONSTANT.mID; 63 tmp[idx++] = mConstants[i].getID(); 64 } 65 for (int i=0; i < mTextureCount; i++) { 66 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID; 67 tmp[idx++] = mTextureTypes[i].mID; 68 texNames[i] = mTextureNames[i]; 69 } 70 71 int id = mRS.nProgramFragmentCreate(mShader, texNames, tmp); 72 ProgramFragmentFixedFunction pf = new ProgramFragmentFixedFunction(id, mRS); 73 initProgram(pf); 74 return pf; 75 } 76 } 77 78 public static class Builder { 79 public static final int MAX_TEXTURE = 2; 80 int mNumTextures; 81 boolean mPointSpriteEnable; 82 boolean mVaryingColorEnable; 83 String mShader; 84 RenderScript mRS; 85 86 /** 87 * EnvMode describes how textures are combined with the existing 88 * color in the fixed function fragment shader 89 * 90 **/ 91 public enum EnvMode { 92 REPLACE (1), 93 MODULATE (2), 94 DECAL (3); 95 96 int mID; 97 EnvMode(int id) { 98 mID = id; 99 } 100 } 101 102 /** 103 * Format describes the pixel format of textures in the fixed 104 * function fragment shader and how they are sampled 105 * 106 **/ 107 public enum Format { 108 ALPHA (1), 109 LUMINANCE_ALPHA (2), 110 RGB (3), 111 RGBA (4); 112 113 int mID; 114 Format(int id) { 115 mID = id; 116 } 117 } 118 119 private class Slot { 120 EnvMode env; 121 Format format; 122 Slot(EnvMode _env, Format _fmt) { 123 env = _env; 124 format = _fmt; 125 } 126 } 127 Slot[] mSlots; 128 129 private void buildShaderString() { 130 mShader = "//rs_shader_internal\n"; 131 mShader += "varying lowp vec4 varColor;\n"; 132 mShader += "varying vec2 varTex0;\n"; 133 134 mShader += "void main() {\n"; 135 if (mVaryingColorEnable) { 136 mShader += " lowp vec4 col = varColor;\n"; 137 } else { 138 mShader += " lowp vec4 col = UNI_Color;\n"; 139 } 140 141 if (mNumTextures != 0) { 142 if (mPointSpriteEnable) { 143 mShader += " vec2 t0 = gl_PointCoord;\n"; 144 } else { 145 mShader += " vec2 t0 = varTex0.xy;\n"; 146 } 147 } 148 149 for(int i = 0; i < mNumTextures; i ++) { 150 switch(mSlots[i].env) { 151 case REPLACE: 152 switch (mSlots[i].format) { 153 case ALPHA: 154 mShader += " col.a = texture2D(UNI_Tex0, t0).a;\n"; 155 break; 156 case LUMINANCE_ALPHA: 157 mShader += " col.rgba = texture2D(UNI_Tex0, t0).rgba;\n"; 158 break; 159 case RGB: 160 mShader += " col.rgb = texture2D(UNI_Tex0, t0).rgb;\n"; 161 break; 162 case RGBA: 163 mShader += " col.rgba = texture2D(UNI_Tex0, t0).rgba;\n"; 164 break; 165 } 166 break; 167 case MODULATE: 168 switch (mSlots[i].format) { 169 case ALPHA: 170 mShader += " col.a *= texture2D(UNI_Tex0, t0).a;\n"; 171 break; 172 case LUMINANCE_ALPHA: 173 mShader += " col.rgba *= texture2D(UNI_Tex0, t0).rgba;\n"; 174 break; 175 case RGB: 176 mShader += " col.rgb *= texture2D(UNI_Tex0, t0).rgb;\n"; 177 break; 178 case RGBA: 179 mShader += " col.rgba *= texture2D(UNI_Tex0, t0).rgba;\n"; 180 break; 181 } 182 break; 183 case DECAL: 184 mShader += " col = texture2D(UNI_Tex0, t0);\n"; 185 break; 186 } 187 } 188 189 mShader += " gl_FragColor = col;\n"; 190 mShader += "}\n"; 191 } 192 193 /** 194 * Creates a builder for fixed function fragment program 195 * 196 * @param rs Context to which the program will belong. 197 */ 198 public Builder(RenderScript rs) { 199 mRS = rs; 200 mSlots = new Slot[MAX_TEXTURE]; 201 mPointSpriteEnable = false; 202 } 203 204 /** 205 * Adds a texture to be fetched as part of the fixed function 206 * fragment program 207 * 208 * @param env specifies how the texture is combined with the 209 * current color 210 * @param fmt specifies the format of the texture and how its 211 * components will be used to combine with the 212 * current color 213 * @param slot index of the texture to apply the operations on 214 * 215 * @return this 216 */ 217 public Builder setTexture(EnvMode env, Format fmt, int slot) 218 throws IllegalArgumentException { 219 if((slot < 0) || (slot >= MAX_TEXTURE)) { 220 throw new IllegalArgumentException("MAX_TEXTURE exceeded."); 221 } 222 mSlots[slot] = new Slot(env, fmt); 223 return this; 224 } 225 226 /** 227 * Specifies whether the texture coordinate passed from the 228 * vertex program is replaced with an openGL internal point 229 * sprite texture coordinate 230 * 231 **/ 232 public Builder setPointSpriteTexCoordinateReplacement(boolean enable) { 233 mPointSpriteEnable = enable; 234 return this; 235 } 236 237 /** 238 * Specifies whether the varying color passed from the vertex 239 * program or the constant color set on the fragment program is 240 * used in the final color calculation in the fixed function 241 * fragment shader 242 * 243 **/ 244 public Builder setVaryingColor(boolean enable) { 245 mVaryingColorEnable = enable; 246 return this; 247 } 248 249 /** 250 * Creates the fixed function fragment program from the current 251 * state of the builder. 252 * 253 */ 254 public ProgramFragmentFixedFunction create() { 255 InternalBuilder sb = new InternalBuilder(mRS); 256 mNumTextures = 0; 257 for(int i = 0; i < MAX_TEXTURE; i ++) { 258 if(mSlots[i] != null) { 259 mNumTextures ++; 260 } 261 } 262 buildShaderString(); 263 sb.setShader(mShader); 264 265 Type constType = null; 266 if (!mVaryingColorEnable) { 267 Element.Builder b = new Element.Builder(mRS); 268 b.add(Element.F32_4(mRS), "Color"); 269 Type.Builder typeBuilder = new Type.Builder(mRS, b.create()); 270 typeBuilder.setX(1); 271 constType = typeBuilder.create(); 272 sb.addConstant(constType); 273 } 274 for (int i = 0; i < mNumTextures; i ++) { 275 sb.addTexture(TextureType.TEXTURE_2D); 276 } 277 278 ProgramFragmentFixedFunction pf = sb.create(); 279 pf.mTextureCount = MAX_TEXTURE; 280 if (!mVaryingColorEnable) { 281 Allocation constantData = Allocation.createTyped(mRS,constType); 282 FieldPacker fp = new FieldPacker(16); 283 Float4 f4 = new Float4(1.f, 1.f, 1.f, 1.f); 284 fp.addF32(f4); 285 constantData.setFromFieldPacker(0, fp); 286 pf.bindConstants(constantData, 0); 287 } 288 return pf; 289 } 290 } 291} 292 293 294 295 296