1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "TextureStage.hpp" 16 17 #include "Sampler.hpp" 18 #include "Common/Debug.hpp" 19 20 #include <string.h> 21 22 namespace sw 23 { State()24 TextureStage::State::State() 25 { 26 memset(this, 0, sizeof(State)); 27 } 28 TextureStage()29 TextureStage::TextureStage() : sampler(0), previousStage(0) 30 { 31 } 32 ~TextureStage()33 TextureStage::~TextureStage() 34 { 35 } 36 init(int stage,const Sampler * sampler,const TextureStage * previousStage)37 void TextureStage::init(int stage, const Sampler *sampler, const TextureStage *previousStage) 38 { 39 this->stage = stage; 40 41 stageOperation = (stage == 0 ? STAGE_MODULATE : STAGE_DISABLE); 42 firstArgument = SOURCE_TEXTURE; 43 secondArgument = SOURCE_CURRENT; 44 thirdArgument = SOURCE_CURRENT; 45 stageOperationAlpha = (stage == 0 ? STAGE_SELECTARG1 : STAGE_DISABLE); 46 firstArgumentAlpha = SOURCE_DIFFUSE; 47 secondArgumentAlpha = SOURCE_CURRENT; 48 thirdArgumentAlpha = SOURCE_CURRENT; 49 firstModifier = MODIFIER_COLOR; 50 secondModifier = MODIFIER_COLOR; 51 thirdModifier = MODIFIER_COLOR; 52 firstModifierAlpha = MODIFIER_COLOR; 53 secondModifierAlpha = MODIFIER_COLOR; 54 thirdModifierAlpha = MODIFIER_COLOR; 55 destinationArgument = DESTINATION_CURRENT; 56 57 texCoordIndex = stage; 58 this->sampler = sampler; 59 this->previousStage = previousStage; 60 } 61 textureStageState() const62 TextureStage::State TextureStage::textureStageState() const 63 { 64 State state; 65 66 if(!isStageDisabled()) 67 { 68 state.stageOperation = stageOperation; 69 state.firstArgument = firstArgument; 70 state.secondArgument = secondArgument; 71 state.thirdArgument = thirdArgument; 72 state.stageOperationAlpha = stageOperationAlpha; 73 state.firstArgumentAlpha = firstArgumentAlpha; 74 state.secondArgumentAlpha = secondArgumentAlpha; 75 state.thirdArgumentAlpha = thirdArgumentAlpha; 76 state.firstModifier = firstModifier; 77 state.secondModifier = secondModifier; 78 state.thirdModifier = thirdModifier; 79 state.firstModifierAlpha = firstModifierAlpha; 80 state.secondModifierAlpha = secondModifierAlpha; 81 state.thirdModifierAlpha = thirdModifierAlpha; 82 state.destinationArgument = destinationArgument; 83 state.texCoordIndex = texCoordIndex; 84 85 state.cantUnderflow = sampler->hasUnsignedTexture() || !usesTexture(); 86 state.usesTexture = usesTexture(); 87 } 88 89 return state; 90 } 91 setConstantColor(const Color<float> & constantColor)92 void TextureStage::setConstantColor(const Color<float> &constantColor) 93 { 94 // FIXME: Compact into generic function // FIXME: Clamp 95 short r = iround(4095 * constantColor.r); 96 short g = iround(4095 * constantColor.g); 97 short b = iround(4095 * constantColor.b); 98 short a = iround(4095 * constantColor.a); 99 100 uniforms.constantColor4[0][0] = uniforms.constantColor4[0][1] = uniforms.constantColor4[0][2] = uniforms.constantColor4[0][3] = r; 101 uniforms.constantColor4[1][0] = uniforms.constantColor4[1][1] = uniforms.constantColor4[1][2] = uniforms.constantColor4[1][3] = g; 102 uniforms.constantColor4[2][0] = uniforms.constantColor4[2][1] = uniforms.constantColor4[2][2] = uniforms.constantColor4[2][3] = b; 103 uniforms.constantColor4[3][0] = uniforms.constantColor4[3][1] = uniforms.constantColor4[3][2] = uniforms.constantColor4[3][3] = a; 104 } 105 setBumpmapMatrix(int element,float value)106 void TextureStage::setBumpmapMatrix(int element, float value) 107 { 108 uniforms.bumpmapMatrix4F[element / 2][element % 2][0] = value; 109 uniforms.bumpmapMatrix4F[element / 2][element % 2][1] = value; 110 uniforms.bumpmapMatrix4F[element / 2][element % 2][2] = value; 111 uniforms.bumpmapMatrix4F[element / 2][element % 2][3] = value; 112 113 uniforms.bumpmapMatrix4W[element / 2][element % 2][0] = iround(4095 * value); 114 uniforms.bumpmapMatrix4W[element / 2][element % 2][1] = iround(4095 * value); 115 uniforms.bumpmapMatrix4W[element / 2][element % 2][2] = iround(4095 * value); 116 uniforms.bumpmapMatrix4W[element / 2][element % 2][3] = iround(4095 * value); 117 } 118 setLuminanceScale(float value)119 void TextureStage::setLuminanceScale(float value) 120 { 121 short scale = iround(4095 * value); 122 123 uniforms.luminanceScale4[0] = uniforms.luminanceScale4[1] = uniforms.luminanceScale4[2] = uniforms.luminanceScale4[3] = scale; 124 } 125 setLuminanceOffset(float value)126 void TextureStage::setLuminanceOffset(float value) 127 { 128 short offset = iround(4095 * value); 129 130 uniforms.luminanceOffset4[0] = uniforms.luminanceOffset4[1] = uniforms.luminanceOffset4[2] = uniforms.luminanceOffset4[3] = offset; 131 } 132 setTexCoordIndex(unsigned int texCoordIndex)133 void TextureStage::setTexCoordIndex(unsigned int texCoordIndex) 134 { 135 ASSERT(texCoordIndex < 8); 136 137 this->texCoordIndex = texCoordIndex; 138 } 139 setStageOperation(StageOperation stageOperation)140 void TextureStage::setStageOperation(StageOperation stageOperation) 141 { 142 this->stageOperation = stageOperation; 143 } 144 setFirstArgument(SourceArgument firstArgument)145 void TextureStage::setFirstArgument(SourceArgument firstArgument) 146 { 147 this->firstArgument = firstArgument; 148 } 149 setSecondArgument(SourceArgument secondArgument)150 void TextureStage::setSecondArgument(SourceArgument secondArgument) 151 { 152 this->secondArgument = secondArgument; 153 } 154 setThirdArgument(SourceArgument thirdArgument)155 void TextureStage::setThirdArgument(SourceArgument thirdArgument) 156 { 157 this->thirdArgument = thirdArgument; 158 } 159 setStageOperationAlpha(StageOperation stageOperationAlpha)160 void TextureStage::setStageOperationAlpha(StageOperation stageOperationAlpha) 161 { 162 this->stageOperationAlpha = stageOperationAlpha; 163 } 164 setFirstArgumentAlpha(SourceArgument firstArgumentAlpha)165 void TextureStage::setFirstArgumentAlpha(SourceArgument firstArgumentAlpha) 166 { 167 this->firstArgumentAlpha = firstArgumentAlpha; 168 } 169 setSecondArgumentAlpha(SourceArgument secondArgumentAlpha)170 void TextureStage::setSecondArgumentAlpha(SourceArgument secondArgumentAlpha) 171 { 172 this->secondArgumentAlpha = secondArgumentAlpha; 173 } 174 setThirdArgumentAlpha(SourceArgument thirdArgumentAlpha)175 void TextureStage::setThirdArgumentAlpha(SourceArgument thirdArgumentAlpha) 176 { 177 this->thirdArgumentAlpha= thirdArgumentAlpha; 178 } 179 setFirstModifier(ArgumentModifier firstModifier)180 void TextureStage::setFirstModifier(ArgumentModifier firstModifier) 181 { 182 this->firstModifier = firstModifier; 183 } 184 setSecondModifier(ArgumentModifier secondModifier)185 void TextureStage::setSecondModifier(ArgumentModifier secondModifier) 186 { 187 this->secondModifier = secondModifier; 188 } 189 setThirdModifier(ArgumentModifier thirdModifier)190 void TextureStage::setThirdModifier(ArgumentModifier thirdModifier) 191 { 192 this->thirdModifier = thirdModifier; 193 } 194 setFirstModifierAlpha(ArgumentModifier firstModifierAlpha)195 void TextureStage::setFirstModifierAlpha(ArgumentModifier firstModifierAlpha) 196 { 197 this->firstModifierAlpha = firstModifierAlpha; 198 } 199 setSecondModifierAlpha(ArgumentModifier secondModifierAlpha)200 void TextureStage::setSecondModifierAlpha(ArgumentModifier secondModifierAlpha) 201 { 202 this->secondModifierAlpha = secondModifierAlpha; 203 } 204 setThirdModifierAlpha(ArgumentModifier thirdModifierAlpha)205 void TextureStage::setThirdModifierAlpha(ArgumentModifier thirdModifierAlpha) 206 { 207 this->thirdModifierAlpha = thirdModifierAlpha; 208 } 209 setDestinationArgument(DestinationArgument destinationArgument)210 void TextureStage::setDestinationArgument(DestinationArgument destinationArgument) 211 { 212 this->destinationArgument = destinationArgument; 213 } 214 usesColor(SourceArgument source) const215 bool TextureStage::usesColor(SourceArgument source) const 216 { 217 // One argument 218 if(stageOperation == STAGE_SELECTARG1 || stageOperation == STAGE_PREMODULATE) 219 { 220 return firstArgument == source; 221 } 222 else if(stageOperation == STAGE_SELECTARG2) 223 { 224 return secondArgument == source; 225 } 226 else if(stageOperation == STAGE_SELECTARG3) 227 { 228 return thirdArgument == source; 229 } 230 else 231 { 232 // Two arguments or more 233 if(firstArgument == source || secondArgument == source) 234 { 235 return true; 236 } 237 238 // Three arguments 239 if(stageOperation == STAGE_MULTIPLYADD || stageOperation == STAGE_LERP) 240 { 241 return thirdArgument == source; 242 } 243 } 244 245 return false; 246 } 247 usesAlpha(SourceArgument source) const248 bool TextureStage::usesAlpha(SourceArgument source) const 249 { 250 if(stageOperationAlpha == STAGE_DISABLE) 251 { 252 return false; 253 } 254 255 if(source == SOURCE_TEXTURE) 256 { 257 if(stageOperation == STAGE_BLENDTEXTUREALPHA || stageOperation == STAGE_BLENDTEXTUREALPHAPM) 258 { 259 return true; 260 } 261 } 262 else if(source == SOURCE_CURRENT) 263 { 264 if(stageOperation == STAGE_BLENDCURRENTALPHA) 265 { 266 return true; 267 } 268 } 269 else if(source == SOURCE_DIFFUSE) 270 { 271 if(stageOperation == STAGE_BLENDDIFFUSEALPHA) 272 { 273 return true; 274 } 275 } 276 else if(source == SOURCE_TFACTOR) 277 { 278 if(stageOperation == STAGE_BLENDFACTORALPHA) 279 { 280 return true; 281 } 282 } 283 284 // One argument 285 if(stageOperation == STAGE_SELECTARG1 || stageOperation == STAGE_PREMODULATE) 286 { 287 if(firstArgument == source && (firstModifier == MODIFIER_ALPHA || firstModifier == MODIFIER_INVALPHA)) 288 { 289 return true; 290 } 291 } 292 else if(stageOperation == STAGE_SELECTARG2) 293 { 294 if(secondArgument == source && (secondModifier == MODIFIER_ALPHA || secondModifier == MODIFIER_INVALPHA)) 295 { 296 return true; 297 } 298 } 299 else if(stageOperation == STAGE_SELECTARG3) 300 { 301 if(thirdArgument == source && (thirdModifier == MODIFIER_ALPHA || thirdModifier == MODIFIER_INVALPHA)) 302 { 303 return true; 304 } 305 } 306 else 307 { 308 // Two arguments or more 309 if(firstArgument == source || secondArgument == source) 310 { 311 if(firstArgument == source && (firstModifier == MODIFIER_ALPHA || firstModifier == MODIFIER_INVALPHA)) 312 { 313 return true; 314 } 315 316 if(secondArgument == source && (secondModifier == MODIFIER_ALPHA || secondModifier == MODIFIER_INVALPHA)) 317 { 318 return true; 319 } 320 } 321 322 // Three arguments 323 if(stageOperation == STAGE_MULTIPLYADD || stageOperation == STAGE_LERP) 324 { 325 if(thirdArgument == source && (thirdModifier == MODIFIER_ALPHA || thirdModifier == MODIFIER_INVALPHA)) 326 { 327 return true; 328 } 329 } 330 } 331 332 // One argument 333 if(stageOperationAlpha == STAGE_SELECTARG1 || stageOperationAlpha == STAGE_PREMODULATE) 334 { 335 return firstArgumentAlpha == source; 336 } 337 else if(stageOperationAlpha == STAGE_SELECTARG2) 338 { 339 return secondArgumentAlpha == source; 340 } 341 else if(stageOperationAlpha == STAGE_SELECTARG3) 342 { 343 return thirdArgumentAlpha == source; 344 } 345 else 346 { 347 // Two arguments or more 348 if(firstArgumentAlpha == source || secondArgumentAlpha == source) 349 { 350 return true; 351 } 352 353 // Three arguments 354 if(stageOperationAlpha == STAGE_MULTIPLYADD || stageOperationAlpha == STAGE_LERP) 355 { 356 return thirdArgumentAlpha == source; 357 } 358 } 359 360 return false; 361 } 362 uses(SourceArgument source) const363 bool TextureStage::uses(SourceArgument source) const 364 { 365 return usesColor(source) || usesAlpha(source); 366 } 367 usesCurrent() const368 bool TextureStage::usesCurrent() const 369 { 370 return uses(SOURCE_CURRENT) || (stageOperation == STAGE_BLENDCURRENTALPHA || stageOperationAlpha == STAGE_BLENDCURRENTALPHA); 371 } 372 usesDiffuse() const373 bool TextureStage::usesDiffuse() const 374 { 375 return uses(SOURCE_DIFFUSE) || (stageOperation == STAGE_BLENDDIFFUSEALPHA || stageOperationAlpha == STAGE_BLENDDIFFUSEALPHA); 376 } 377 usesSpecular() const378 bool TextureStage::usesSpecular() const 379 { 380 return uses(SOURCE_SPECULAR); 381 } 382 usesTexture() const383 bool TextureStage::usesTexture() const 384 { 385 return uses(SOURCE_TEXTURE) || 386 stageOperation == STAGE_BLENDTEXTUREALPHA || 387 stageOperationAlpha == STAGE_BLENDTEXTUREALPHA || 388 stageOperation == STAGE_BLENDTEXTUREALPHAPM || 389 stageOperationAlpha == STAGE_BLENDTEXTUREALPHAPM || 390 (previousStage && previousStage->stageOperation == STAGE_PREMODULATE) || 391 (previousStage && previousStage->stageOperationAlpha == STAGE_PREMODULATE); 392 } 393 isStageDisabled() const394 bool TextureStage::isStageDisabled() const 395 { 396 bool disabled = (stageOperation == STAGE_DISABLE) || (!sampler->hasTexture() && usesTexture()); 397 398 if(!previousStage || disabled) 399 { 400 return disabled; 401 } 402 else 403 { 404 return previousStage->isStageDisabled(); 405 } 406 } 407 writesCurrent() const408 bool TextureStage::writesCurrent() const 409 { 410 return !isStageDisabled() && destinationArgument == DESTINATION_CURRENT && stageOperation != STAGE_BUMPENVMAP && stageOperation != STAGE_BUMPENVMAPLUMINANCE; 411 } 412 } 413