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