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