rsProgramFragment.cpp revision c460e55d78cbe8bee95c5c947dfe541218142a5b
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, Element *in, Element *out, bool pointSpriteEnable) : 30 Program(rsc, in, out) 31{ 32 mAllocFile = __FILE__; 33 mAllocLine = __LINE__; 34 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) { 35 mEnvModes[ct] = RS_TEX_ENV_MODE_REPLACE; 36 mTextureDimensions[ct] = 2; 37 } 38 mTextureEnableMask = 0; 39 mPointSpriteEnable = pointSpriteEnable; 40 mEnvModes[1] = RS_TEX_ENV_MODE_DECAL; 41} 42 43ProgramFragment::~ProgramFragment() 44{ 45} 46 47void ProgramFragment::setupGL(const Context *rsc, ProgramFragmentState *state) 48{ 49 if ((state->mLast.get() == this) && !mDirty) { 50 return; 51 } 52 state->mLast.set(this); 53 54 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) { 55 glActiveTexture(GL_TEXTURE0 + ct); 56 if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) { 57 glDisable(GL_TEXTURE_2D); 58 continue; 59 } 60 61 glEnable(GL_TEXTURE_2D); 62 if (rsc->checkVersion1_1()) { 63 if (mPointSpriteEnable) { 64 glEnable(GL_POINT_SPRITE_OES); 65 } else { 66 glDisable(GL_POINT_SPRITE_OES); 67 } 68 glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, mPointSpriteEnable); 69 } 70 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID()); 71 72 switch(mEnvModes[ct]) { 73 case RS_TEX_ENV_MODE_REPLACE: 74 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 75 break; 76 case RS_TEX_ENV_MODE_MODULATE: 77 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 78 break; 79 case RS_TEX_ENV_MODE_DECAL: 80 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 81 break; 82 } 83 84 if (mSamplers[ct].get()) { 85 mSamplers[ct]->setupGL(); 86 } else { 87 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 88 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 89 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 90 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 91 } 92 93 // Gross hack. 94 if (ct == 2) { 95 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 96 97 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); 98 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); 99 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); 100 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); 101 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); 102 103 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD); 104 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); 105 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); 106 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); 107 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); 108 } 109 } 110 glActiveTexture(GL_TEXTURE0); 111 mDirty = false; 112} 113 114void ProgramFragment::setupGL2(const Context *rsc, ProgramFragmentState *state, ShaderCache *sc) 115{ 116 //LOGE("sgl2 frag1 %x", glGetError()); 117 if ((state->mLast.get() == this) && !mDirty) { 118 //return; 119 } 120 state->mLast.set(this); 121 122 for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) { 123 glActiveTexture(GL_TEXTURE0 + ct); 124 if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) { 125 glDisable(GL_TEXTURE_2D); 126 continue; 127 } 128 129 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID()); 130 if (mSamplers[ct].get()) { 131 mSamplers[ct]->setupGL(); 132 } else { 133 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 137 } 138 139 glEnable(GL_TEXTURE_2D); 140 glUniform1i(sc->fragUniformSlot(ct), ct); 141 } 142 143 glActiveTexture(GL_TEXTURE0); 144 mDirty = false; 145 146 //LOGE("sgl2 frag2 %x", glGetError()); 147} 148 149void ProgramFragment::loadShader() { 150 Program::loadShader(GL_FRAGMENT_SHADER); 151} 152 153void ProgramFragment::createShader() 154{ 155 mShader.setTo("precision mediump float;\n"); 156 mShader.append("varying vec4 varColor;\n"); 157 mShader.append("varying vec4 varTex0;\n"); 158 159 uint32_t mask = mTextureEnableMask; 160 uint32_t texNum = 0; 161 while (mask) { 162 if (mask & 1) { 163 char buf[64]; 164 mShader.append("uniform sampler2D uni_Tex"); 165 sprintf(buf, "%i", texNum); 166 mShader.append(buf); 167 mShader.append(";\n"); 168 } 169 mask >>= 1; 170 texNum++; 171 } 172 173 174 mShader.append("void main() {\n"); 175 //mShader.append(" gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"); 176 mShader.append(" vec4 col = varColor;\n"); 177 178 mask = mTextureEnableMask; 179 texNum = 0; 180 while (mask) { 181 if (mask & 1) { 182 switch(mEnvModes[texNum]) { 183 case RS_TEX_ENV_MODE_REPLACE: 184 mShader.append(" col = texture2D(uni_Tex0, varTex0.xy);\n"); 185 break; 186 case RS_TEX_ENV_MODE_MODULATE: 187 mShader.append(" col *= texture2D(uni_Tex0, varTex0.xy);\n"); 188 break; 189 case RS_TEX_ENV_MODE_DECAL: 190 mShader.append(" col = texture2D(uni_Tex0, varTex0.xy);\n"); 191 break; 192 } 193 194 } 195 mask >>= 1; 196 texNum++; 197 } 198 199 //mShader.append(" col.a = 1.0;\n"); 200 //mShader.append(" col.r = 0.5;\n"); 201 202 mShader.append(" gl_FragColor = col;\n"); 203 mShader.append("}\n"); 204} 205 206void ProgramFragment::bindTexture(uint32_t slot, Allocation *a) 207{ 208 if (slot >= MAX_TEXTURE) { 209 LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE"); 210 return; 211 } 212 213 //LOGE("bindtex %i %p", slot, a); 214 mTextures[slot].set(a); 215 mDirty = true; 216} 217 218void ProgramFragment::bindSampler(uint32_t slot, Sampler *s) 219{ 220 if (slot >= MAX_TEXTURE) { 221 LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE"); 222 return; 223 } 224 225 mSamplers[slot].set(s); 226 mDirty = true; 227} 228 229void ProgramFragment::setType(uint32_t slot, const Element *e, uint32_t dim) 230{ 231 if (slot >= MAX_TEXTURE) { 232 LOGE("Attempt to setType to a slot > MAX_TEXTURE"); 233 return; 234 } 235 236 if (dim >= 4) { 237 LOGE("Attempt to setType to a dimension > 3"); 238 return; 239 } 240 241 mTextureFormats[slot].set(e); 242 mTextureDimensions[slot] = dim; 243} 244 245void ProgramFragment::setEnvMode(uint32_t slot, RsTexEnvMode env) 246{ 247 if (slot >= MAX_TEXTURE) { 248 LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE"); 249 return; 250 } 251 252 mEnvModes[slot] = env; 253} 254 255void ProgramFragment::setTexEnable(uint32_t slot, bool enable) 256{ 257 if (slot >= MAX_TEXTURE) { 258 LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE"); 259 return; 260 } 261 262 uint32_t bit = 1 << slot; 263 mTextureEnableMask &= ~bit; 264 if (enable) { 265 mTextureEnableMask |= bit; 266 } 267} 268 269void ProgramFragment::init(Context *rsc) 270{ 271 mUniformCount = 2; 272 mUniformNames[0].setTo("uni_Tex0"); 273 mUniformNames[1].setTo("uni_Tex1"); 274 275 createShader(); 276} 277 278ProgramFragmentState::ProgramFragmentState() 279{ 280 mPF = NULL; 281} 282 283ProgramFragmentState::~ProgramFragmentState() 284{ 285 delete mPF; 286 287} 288 289void ProgramFragmentState::init(Context *rsc, int32_t w, int32_t h) 290{ 291 ProgramFragment *pf = new ProgramFragment(rsc, NULL, NULL, false); 292 mDefault.set(pf); 293 pf->init(rsc); 294} 295 296void ProgramFragmentState::deinit(Context *rsc) 297{ 298 mDefault.clear(); 299 mLast.clear(); 300} 301 302 303namespace android { 304namespace renderscript { 305 306void rsi_ProgramFragmentBegin(Context * rsc, RsElement in, RsElement out, bool pointSpriteEnable) 307{ 308 delete rsc->mStateFragment.mPF; 309 rsc->mStateFragment.mPF = new ProgramFragment(rsc, (Element *)in, (Element *)out, pointSpriteEnable); 310} 311 312void rsi_ProgramFragmentBindTexture(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsAllocation a) 313{ 314 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf); 315 pf->bindTexture(slot, static_cast<Allocation *>(a)); 316} 317 318void rsi_ProgramFragmentBindSampler(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsSampler s) 319{ 320 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf); 321 pf->bindSampler(slot, static_cast<Sampler *>(s)); 322} 323 324void rsi_ProgramFragmentSetSlot(Context *rsc, uint32_t slot, bool enable, RsTexEnvMode env, RsType vt) 325{ 326 const Type *t = static_cast<const Type *>(vt); 327 if (t) { 328 uint32_t dim = 1; 329 if (t->getDimY()) { 330 dim ++; 331 if (t->getDimZ()) { 332 dim ++; 333 } 334 } 335 rsc->mStateFragment.mPF->setType(slot, t->getElement(), dim); 336 } 337 rsc->mStateFragment.mPF->setEnvMode(slot, env); 338 rsc->mStateFragment.mPF->setTexEnable(slot, enable); 339} 340 341RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc) 342{ 343 ProgramFragment *pf = rsc->mStateFragment.mPF; 344 pf->incUserRef(); 345 pf->init(rsc); 346 rsc->mStateFragment.mPF = 0; 347 return pf; 348} 349 350 351} 352} 353 354