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