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(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 142void 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 180void ProgramFragment::loadShader(Context *rsc) { 181 Program::loadShader(rsc, GL_FRAGMENT_SHADER); 182} 183 184void 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 283void 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 292ProgramFragmentState::ProgramFragmentState() 293{ 294 mPF = NULL; 295} 296 297ProgramFragmentState::~ProgramFragmentState() 298{ 299 delete mPF; 300 301} 302 303void 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 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 return pf; 332} 333 334RsProgramFragment 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