blob: cd31db3a919b7aa1809ccee102ce85f6e540c8e7 [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];
Alex Sakhartchouk2123b462012-02-15 16:21:46 -080050 String[] texNames = new String[mTextureCount];
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080051 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;
Alex Sakhartchouk2123b462012-02-15 16:21:46 -080068 texNames[i] = mTextureNames[i];
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080069 }
70
Alex Sakhartchouk2123b462012-02-15 16:21:46 -080071 int id = mRS.nProgramFragmentCreate(mShader, texNames, tmp);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080072 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
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080086 /**
87 * EnvMode describes how textures are combined with the existing
88 * color in the fixed function fragment shader
89 *
90 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080091 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
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800102 /**
103 * Format describes the pixel format of textures in the fixed
104 * function fragment shader and how they are sampled
105 *
106 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800107 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
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800193 /**
194 * Creates a builder for fixed function fragment program
195 *
Alex Sakhartchoukf5c876e2011-01-13 14:53:43 -0800196 * @param rs Context to which the program will belong.
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800197 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800198 public Builder(RenderScript rs) {
199 mRS = rs;
200 mSlots = new Slot[MAX_TEXTURE];
201 mPointSpriteEnable = false;
202 }
203
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800204 /**
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 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800217 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
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800226 /**
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 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800232 public Builder setPointSpriteTexCoordinateReplacement(boolean enable) {
233 mPointSpriteEnable = enable;
234 return this;
235 }
236
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800237 /**
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 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800244 public Builder setVaryingColor(boolean enable) {
245 mVaryingColorEnable = enable;
246 return this;
247 }
248
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800249 /**
250 * Creates the fixed function fragment program from the current
251 * state of the builder.
252 *
253 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800254 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);
Jason Samsb97b2512011-01-16 15:04:08 -0800282 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);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800286 pf.bindConstants(constantData, 0);
287 }
288 return pf;
289 }
290 }
291}
292
293
294
295