• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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