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