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