Home | History | Annotate | Download | only in rs
      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 
     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 
     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 
     66 ProgramFragment::~ProgramFragment()
     67 {
     68 }
     69 
     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 
    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 
    180 void ProgramFragment::loadShader(Context *rsc) {
    181     Program::loadShader(rsc, GL_FRAGMENT_SHADER);
    182 }
    183 
    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 
    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 
    292 ProgramFragmentState::ProgramFragmentState()
    293 {
    294     mPF = NULL;
    295 }
    296 
    297 ProgramFragmentState::~ProgramFragmentState()
    298 {
    299     delete mPF;
    300 
    301 }
    302 
    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 
    315 void ProgramFragmentState::deinit(Context *rsc)
    316 {
    317     mDefault.clear();
    318     mLast.clear();
    319 }
    320 
    321 
    322 namespace android {
    323 namespace renderscript {
    324 
    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 
    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