1 /*
2 * Copyright (C) 2009 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
17 #include "rsContext.h"
18 #include "rsProgramFragment.h"
19
20 #include <GLES/gl.h>
21 #include <GLES/glext.h>
22 #include <GLES2/gl2.h>
23 #include <GLES2/gl2ext.h>
24
25 using namespace android;
26 using namespace android::renderscript;
27
28
ProgramFragment(Context * rsc,const uint32_t * params,uint32_t paramLength)29 ProgramFragment::ProgramFragment(Context *rsc, const uint32_t * params,
30 uint32_t paramLength) :
31 Program(rsc)
32 {
33 mAllocFile = __FILE__;
34 mAllocLine = __LINE__;
35 rsAssert(paramLength = 5);
36
37 mEnvModes[0] = (RsTexEnvMode)params[0];
38 mTextureFormats[0] = params[1];
39 mEnvModes[1] = (RsTexEnvMode)params[2];
40 mTextureFormats[1] = params[3];
41 mPointSpriteEnable = params[4] != 0;
42
43 mTextureEnableMask = 0;
44 if (mEnvModes[0]) {
45 mTextureEnableMask |= 1;
46 }
47 if (mEnvModes[1]) {
48 mTextureEnableMask |= 2;
49 }
50 init(rsc);
51 }
52
ProgramFragment(Context * rsc,const char * shaderText,uint32_t shaderLength,const uint32_t * params,uint32_t paramLength)53 ProgramFragment::ProgramFragment(Context *rsc, const char * shaderText,
54 uint32_t shaderLength, const uint32_t * params,
55 uint32_t paramLength) :
56 Program(rsc, shaderText, shaderLength, params, paramLength)
57 {
58 mAllocFile = __FILE__;
59 mAllocLine = __LINE__;
60
61 init(rsc);
62 mTextureEnableMask = (1 << mTextureCount) -1;
63 }
64
65
~ProgramFragment()66 ProgramFragment::~ProgramFragment()
67 {
68 }
69
setupGL(const Context * rsc,ProgramFragmentState * state)70 void ProgramFragment::setupGL(const Context *rsc, ProgramFragmentState *state)
71 {
72 if ((state->mLast.get() == this) && !mDirty) {
73 return;
74 }
75 state->mLast.set(this);
76
77 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
78 glActiveTexture(GL_TEXTURE0 + ct);
79 if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
80 glDisable(GL_TEXTURE_2D);
81 continue;
82 }
83
84 glEnable(GL_TEXTURE_2D);
85 if (rsc->checkVersion1_1()) {
86 if (mPointSpriteEnable) {
87 glEnable(GL_POINT_SPRITE_OES);
88 } else {
89 glDisable(GL_POINT_SPRITE_OES);
90 }
91 glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, mPointSpriteEnable);
92 }
93 mTextures[ct]->uploadCheck(rsc);
94 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
95
96 switch(mEnvModes[ct]) {
97 case RS_TEX_ENV_MODE_NONE:
98 rsAssert(0);
99 break;
100 case RS_TEX_ENV_MODE_REPLACE:
101 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
102 break;
103 case RS_TEX_ENV_MODE_MODULATE:
104 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
105 break;
106 case RS_TEX_ENV_MODE_DECAL:
107 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
108 break;
109 }
110
111 if (mSamplers[ct].get()) {
112 mSamplers[ct]->setupGL(rsc, mTextures[ct]->getType()->getIsNp2());
113 } else {
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
118 }
119
120 // Gross hack.
121 if (ct == 2) {
122 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
123
124 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
125 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
126 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
127 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
128 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
129
130 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
131 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
132 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
133 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
134 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
135 }
136 }
137 glActiveTexture(GL_TEXTURE0);
138 mDirty = false;
139 rsc->checkError("ProgramFragment::setupGL");
140 }
141
setupGL2(const Context * rsc,ProgramFragmentState * state,ShaderCache * sc)142 void ProgramFragment::setupGL2(const Context *rsc, ProgramFragmentState *state, ShaderCache *sc)
143 {
144
145 //LOGE("sgl2 frag1 %x", glGetError());
146 if ((state->mLast.get() == this) && !mDirty) {
147 //return;
148 }
149 state->mLast.set(this);
150
151 rsc->checkError("ProgramFragment::setupGL2 start");
152 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
153 glActiveTexture(GL_TEXTURE0 + ct);
154 if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
155 continue;
156 }
157
158 mTextures[ct]->uploadCheck(rsc);
159 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
160 rsc->checkError("ProgramFragment::setupGL2 tex bind");
161 if (mSamplers[ct].get()) {
162 mSamplers[ct]->setupGL(rsc, mTextures[ct]->getType()->getIsNp2());
163 } else {
164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
168 rsc->checkError("ProgramFragment::setupGL2 tex env");
169 }
170
171 glUniform1i(sc->fragUniformSlot(ct), ct);
172 rsc->checkError("ProgramFragment::setupGL2 uniforms");
173 }
174
175 glActiveTexture(GL_TEXTURE0);
176 mDirty = false;
177 rsc->checkError("ProgramFragment::setupGL2");
178 }
179
loadShader(Context * rsc)180 void ProgramFragment::loadShader(Context *rsc) {
181 Program::loadShader(rsc, GL_FRAGMENT_SHADER);
182 }
183
createShader()184 void ProgramFragment::createShader()
185 {
186 mShader.setTo("precision mediump float;\n");
187 mShader.append("varying vec4 varColor;\n");
188 mShader.append("varying vec4 varTex0;\n");
189
190 if (mUserShader.length() > 1) {
191 for (uint32_t ct=0; ct < mTextureCount; ct++) {
192 char buf[256];
193 sprintf(buf, "uniform sampler2D uni_Tex%i;\n", ct);
194 mShader.append(buf);
195 }
196
197 mShader.append(mUserShader);
198 } else {
199 uint32_t mask = mTextureEnableMask;
200 uint32_t texNum = 0;
201 while (mask) {
202 if (mask & 1) {
203 char buf[64];
204 mShader.append("uniform sampler2D uni_Tex");
205 sprintf(buf, "%i", texNum);
206 mShader.append(buf);
207 mShader.append(";\n");
208 }
209 mask >>= 1;
210 texNum++;
211 }
212
213
214 mShader.append("void main() {\n");
215 mShader.append(" vec4 col = varColor;\n");
216
217 if (mTextureEnableMask) {
218 if (mPointSpriteEnable) {
219 mShader.append(" vec2 t0 = gl_PointCoord;\n");
220 } else {
221 mShader.append(" vec2 t0 = varTex0.xy;\n");
222 }
223 }
224
225 mask = mTextureEnableMask;
226 texNum = 0;
227 while (mask) {
228 if (mask & 1) {
229 switch(mEnvModes[texNum]) {
230 case RS_TEX_ENV_MODE_NONE:
231 rsAssert(0);
232 break;
233 case RS_TEX_ENV_MODE_REPLACE:
234 switch(mTextureFormats[texNum]) {
235 case 1:
236 mShader.append(" col.a = texture2D(uni_Tex0, t0).a;\n");
237 break;
238 case 2:
239 mShader.append(" col.rgba = texture2D(uni_Tex0, t0).rgba;\n");
240 break;
241 case 3:
242 mShader.append(" col.rgb = texture2D(uni_Tex0, t0).rgb;\n");
243 break;
244 case 4:
245 mShader.append(" col.rgba = texture2D(uni_Tex0, t0).rgba;\n");
246 break;
247 }
248 break;
249 case RS_TEX_ENV_MODE_MODULATE:
250 switch(mTextureFormats[texNum]) {
251 case 1:
252 mShader.append(" col.a *= texture2D(uni_Tex0, t0).a;\n");
253 break;
254 case 2:
255 mShader.append(" col.rgba *= texture2D(uni_Tex0, t0).rgba;\n");
256 break;
257 case 3:
258 mShader.append(" col.rgb *= texture2D(uni_Tex0, t0).rgb;\n");
259 break;
260 case 4:
261 mShader.append(" col.rgba *= texture2D(uni_Tex0, t0).rgba;\n");
262 break;
263 }
264 break;
265 case RS_TEX_ENV_MODE_DECAL:
266 mShader.append(" col = texture2D(uni_Tex0, t0);\n");
267 break;
268 }
269
270 }
271 mask >>= 1;
272 texNum++;
273 }
274
275 //mShader.append(" col.a = 1.0;\n");
276 //mShader.append(" col.r = 0.5;\n");
277
278 mShader.append(" gl_FragColor = col;\n");
279 mShader.append("}\n");
280 }
281 }
282
init(Context * rsc)283 void ProgramFragment::init(Context *rsc)
284 {
285 mUniformCount = 2;
286 mUniformNames[0].setTo("uni_Tex0");
287 mUniformNames[1].setTo("uni_Tex1");
288
289 createShader();
290 }
291
ProgramFragmentState()292 ProgramFragmentState::ProgramFragmentState()
293 {
294 mPF = NULL;
295 }
296
~ProgramFragmentState()297 ProgramFragmentState::~ProgramFragmentState()
298 {
299 delete mPF;
300
301 }
302
init(Context * rsc,int32_t w,int32_t h)303 void ProgramFragmentState::init(Context *rsc, int32_t w, int32_t h)
304 {
305 uint32_t tmp[5] = {
306 RS_TEX_ENV_MODE_NONE, 0,
307 RS_TEX_ENV_MODE_NONE, 0,
308 0
309 };
310 ProgramFragment *pf = new ProgramFragment(rsc, tmp, 5);
311 mDefault.set(pf);
312 pf->init(rsc);
313 }
314
deinit(Context * rsc)315 void ProgramFragmentState::deinit(Context *rsc)
316 {
317 mDefault.clear();
318 mLast.clear();
319 }
320
321
322 namespace android {
323 namespace renderscript {
324
rsi_ProgramFragmentCreate(Context * rsc,const uint32_t * params,uint32_t paramLength)325 RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc,
326 const uint32_t * params,
327 uint32_t paramLength)
328 {
329 ProgramFragment *pf = new ProgramFragment(rsc, params, paramLength);
330 pf->incUserRef();
331 return pf;
332 }
333
rsi_ProgramFragmentCreate2(Context * rsc,const char * shaderText,uint32_t shaderLength,const uint32_t * params,uint32_t paramLength)334 RsProgramFragment rsi_ProgramFragmentCreate2(Context *rsc, const char * shaderText,
335 uint32_t shaderLength, const uint32_t * params,
336 uint32_t paramLength)
337 {
338 ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength, params, paramLength);
339 pf->incUserRef();
340 return pf;
341 }
342
343 }
344 }
345
346