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