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