blob: 666a3e66c3a2cf975491500257fa5197af53ee61 [file] [log] [blame]
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -08001/*
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/**
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080025 * 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.
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080032 *
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
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080044 /**
45 * Creates ProgramFragmentFixedFunction from the current state
46 * of the builder
47 *
48 * @return ProgramFragmentFixedFunction
49 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080050 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
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080087 /**
88 * EnvMode describes how textures are combined with the existing
89 * color in the fixed function fragment shader
90 *
91 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080092 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
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800103 /**
104 * Format describes the pixel format of textures in the fixed
105 * function fragment shader and how they are sampled
106 *
107 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800108 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
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800194 /**
195 * Creates a builder for fixed function fragment program
196 *
Alex Sakhartchoukf5c876e2011-01-13 14:53:43 -0800197 * @param rs Context to which the program will belong.
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800198 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800199 public Builder(RenderScript rs) {
200 mRS = rs;
201 mSlots = new Slot[MAX_TEXTURE];
202 mPointSpriteEnable = false;
203 }
204
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800205 /**
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 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800218 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
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800227 /**
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 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800233 public Builder setPointSpriteTexCoordinateReplacement(boolean enable) {
234 mPointSpriteEnable = enable;
235 return this;
236 }
237
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800238 /**
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 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800245 public Builder setVaryingColor(boolean enable) {
246 mVaryingColorEnable = enable;
247 return this;
248 }
249
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800250 /**
251 * Creates the fixed function fragment program from the current
252 * state of the builder.
253 *
254 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800255 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);
Jason Samsb97b2512011-01-16 15:04:08 -0800283 FieldPacker fp = new FieldPacker(16);
284 Float4 f4 = new Float4(1.f, 1.f, 1.f, 1.f);
285 fp.addF32(f4);
286 constantData.setFromFieldPacker(0, fp);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800287 pf.bindConstants(constantData, 0);
288 }
289 return pf;
290 }
291 }
292}
293
294
295
296