rsProgramFragment.cpp revision d01d970cf5973aa5186cc02c80fb2c143a69b0b1
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
25using namespace android;
26using namespace android::renderscript;
27
28
29ProgramFragment::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
53ProgramFragment::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
66ProgramFragment::~ProgramFragment()
67{
68}
69
70void 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();
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}
140
141void ProgramFragment::setupGL2(const Context *rsc, ProgramFragmentState *state, ShaderCache *sc)
142{
143    //LOGE("sgl2 frag1 %x", glGetError());
144    if ((state->mLast.get() == this) && !mDirty) {
145        //return;
146    }
147    state->mLast.set(this);
148
149    for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
150        glActiveTexture(GL_TEXTURE0 + ct);
151        if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
152            glDisable(GL_TEXTURE_2D);
153            continue;
154        }
155
156        mTextures[ct]->uploadCheck(rsc);
157        glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
158        if (mSamplers[ct].get()) {
159            mSamplers[ct]->setupGL();
160        } else {
161            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
162            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
163            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
164            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
165        }
166
167        glEnable(GL_TEXTURE_2D);
168        glUniform1i(sc->fragUniformSlot(ct), ct);
169    }
170
171    glActiveTexture(GL_TEXTURE0);
172    mDirty = false;
173
174    //LOGE("sgl2 frag2 %x", glGetError());
175}
176
177void ProgramFragment::loadShader(Context *rsc) {
178    Program::loadShader(rsc, GL_FRAGMENT_SHADER);
179}
180
181void ProgramFragment::createShader()
182{
183    mShader.setTo("precision mediump float;\n");
184    mShader.append("varying vec4 varColor;\n");
185    mShader.append("varying vec4 varTex0;\n");
186
187    if (mUserShader.length() > 1) {
188        for (uint32_t ct=0; ct < mTextureCount; ct++) {
189            char buf[256];
190            sprintf(buf, "uniform sampler2D uni_Tex%i;\n", ct);
191            mShader.append(buf);
192        }
193
194        mShader.append(mUserShader);
195    } else {
196        uint32_t mask = mTextureEnableMask;
197        uint32_t texNum = 0;
198        while (mask) {
199            if (mask & 1) {
200                char buf[64];
201                mShader.append("uniform sampler2D uni_Tex");
202                sprintf(buf, "%i", texNum);
203                mShader.append(buf);
204                mShader.append(";\n");
205            }
206            mask >>= 1;
207            texNum++;
208        }
209
210
211        mShader.append("void main() {\n");
212        mShader.append("  vec4 col = varColor;\n");
213
214        if (mTextureEnableMask) {
215            if (mPointSpriteEnable) {
216                mShader.append("  vec2 t0 = gl_PointCoord;\n");
217            } else {
218                mShader.append("  vec2 t0 = varTex0.xy;\n");
219            }
220        }
221
222        mask = mTextureEnableMask;
223        texNum = 0;
224        while (mask) {
225            if (mask & 1) {
226                switch(mEnvModes[texNum]) {
227                case RS_TEX_ENV_MODE_NONE:
228                    rsAssert(0);
229                    break;
230                case RS_TEX_ENV_MODE_REPLACE:
231                    switch(mTextureFormats[texNum]) {
232                    case 1:
233                        mShader.append("  col.a = texture2D(uni_Tex0, t0).a;\n");
234                        break;
235                    case 2:
236                        mShader.append("  col.rgba = texture2D(uni_Tex0, t0).rgba;\n");
237                        break;
238                    case 3:
239                        mShader.append("  col.rgb = texture2D(uni_Tex0, t0).rgb;\n");
240                        break;
241                    case 4:
242                        mShader.append("  col.rgba = texture2D(uni_Tex0, t0).rgba;\n");
243                        break;
244                    }
245                    break;
246                case RS_TEX_ENV_MODE_MODULATE:
247                    switch(mTextureFormats[texNum]) {
248                    case 1:
249                        mShader.append("  col.a *= texture2D(uni_Tex0, t0).a;\n");
250                        break;
251                    case 2:
252                        mShader.append("  col.rgba *= texture2D(uni_Tex0, t0).rgba;\n");
253                        break;
254                    case 3:
255                        mShader.append("  col.rgb *= texture2D(uni_Tex0, t0).rgb;\n");
256                        break;
257                    case 4:
258                        mShader.append("  col.rgba *= texture2D(uni_Tex0, t0).rgba;\n");
259                        break;
260                    }
261                    break;
262                case RS_TEX_ENV_MODE_DECAL:
263                    mShader.append("  col = texture2D(uni_Tex0, t0);\n");
264                    break;
265                }
266
267            }
268            mask >>= 1;
269            texNum++;
270        }
271
272        //mShader.append("  col.a = 1.0;\n");
273        //mShader.append("  col.r = 0.5;\n");
274
275        mShader.append("  gl_FragColor = col;\n");
276        mShader.append("}\n");
277    }
278}
279
280void ProgramFragment::init(Context *rsc)
281{
282    mUniformCount = 2;
283    mUniformNames[0].setTo("uni_Tex0");
284    mUniformNames[1].setTo("uni_Tex1");
285
286    createShader();
287}
288
289ProgramFragmentState::ProgramFragmentState()
290{
291    mPF = NULL;
292}
293
294ProgramFragmentState::~ProgramFragmentState()
295{
296    delete mPF;
297
298}
299
300void ProgramFragmentState::init(Context *rsc, int32_t w, int32_t h)
301{
302    uint32_t tmp[5] = {
303        RS_TEX_ENV_MODE_NONE, 0,
304        RS_TEX_ENV_MODE_NONE, 0,
305        0
306    };
307    ProgramFragment *pf = new ProgramFragment(rsc, tmp, 5);
308    mDefault.set(pf);
309    pf->init(rsc);
310}
311
312void ProgramFragmentState::deinit(Context *rsc)
313{
314    mDefault.clear();
315    mLast.clear();
316}
317
318
319namespace android {
320namespace renderscript {
321
322RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc,
323                                            const uint32_t * params,
324                                            uint32_t paramLength)
325{
326    ProgramFragment *pf = new ProgramFragment(rsc, params, paramLength);
327    pf->incUserRef();
328    return pf;
329}
330
331RsProgramFragment rsi_ProgramFragmentCreate2(Context *rsc, const char * shaderText,
332                             uint32_t shaderLength, const uint32_t * params,
333                             uint32_t paramLength)
334{
335    ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength, params, paramLength);
336    pf->incUserRef();
337    return pf;
338}
339
340}
341}
342
343