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 "Context.hpp" 16 17 #include "Primitive.hpp" 18 #include "Surface.hpp" 19 #include "Shader/PixelShader.hpp" 20 #include "Shader/VertexShader.hpp" 21 #include "Common/Memory.hpp" 22 #include "Common/Debug.hpp" 23 24 #include <string.h> 25 26 namespace sw 27 { 28 extern bool perspectiveCorrection; 29 30 bool halfIntegerCoordinates = false; // Pixel centers are not at integer coordinates 31 bool symmetricNormalizedDepth = false; // [-1, 1] instead of [0, 1] 32 bool booleanFaceRegister = false; 33 bool fullPixelPositionRegister = false; 34 bool leadingVertexFirst = false; // Flat shading uses first vertex, else last 35 bool secondaryColor = false; // Specular lighting is applied after texturing 36 bool colorsDefaultToZero = false; 37 38 bool forceWindowed = false; 39 bool quadLayoutEnabled = false; 40 bool veryEarlyDepthTest = true; 41 bool complementaryDepthBuffer = false; 42 bool postBlendSRGB = false; 43 bool exactColorRounding = false; 44 TransparencyAntialiasing transparencyAntialiasing = TRANSPARENCY_NONE; 45 bool forceClearRegisters = false; 46 Context()47 Context::Context() 48 { 49 init(); 50 } 51 ~Context()52 Context::~Context() 53 { 54 } 55 operator new(size_t bytes)56 void *Context::operator new(size_t bytes) 57 { 58 return allocate((unsigned int)bytes); 59 } 60 operator delete(void * pointer,size_t bytes)61 void Context::operator delete(void *pointer, size_t bytes) 62 { 63 deallocate(pointer); 64 } 65 isDrawPoint(bool fillModeAware) const66 bool Context::isDrawPoint(bool fillModeAware) const 67 { 68 switch(drawType) 69 { 70 case DRAW_POINTLIST: 71 case DRAW_INDEXEDPOINTLIST8: 72 case DRAW_INDEXEDPOINTLIST16: 73 case DRAW_INDEXEDPOINTLIST32: 74 return true; 75 case DRAW_LINELIST: 76 case DRAW_LINESTRIP: 77 case DRAW_LINELOOP: 78 case DRAW_INDEXEDLINELIST8: 79 case DRAW_INDEXEDLINESTRIP8: 80 case DRAW_INDEXEDLINELOOP8: 81 case DRAW_INDEXEDLINELIST16: 82 case DRAW_INDEXEDLINESTRIP16: 83 case DRAW_INDEXEDLINELOOP16: 84 case DRAW_INDEXEDLINELIST32: 85 case DRAW_INDEXEDLINESTRIP32: 86 case DRAW_INDEXEDLINELOOP32: 87 return false; 88 case DRAW_TRIANGLELIST: 89 case DRAW_TRIANGLESTRIP: 90 case DRAW_TRIANGLEFAN: 91 case DRAW_INDEXEDTRIANGLELIST8: 92 case DRAW_INDEXEDTRIANGLESTRIP8: 93 case DRAW_INDEXEDTRIANGLEFAN8: 94 case DRAW_INDEXEDTRIANGLELIST16: 95 case DRAW_INDEXEDTRIANGLESTRIP16: 96 case DRAW_INDEXEDTRIANGLEFAN16: 97 case DRAW_INDEXEDTRIANGLELIST32: 98 case DRAW_INDEXEDTRIANGLESTRIP32: 99 case DRAW_INDEXEDTRIANGLEFAN32: 100 return fillModeAware ? fillMode == FILL_VERTEX : false; 101 case DRAW_QUADLIST: 102 return false; 103 default: 104 ASSERT(false); 105 } 106 107 return false; 108 } 109 isDrawLine(bool fillModeAware) const110 bool Context::isDrawLine(bool fillModeAware) const 111 { 112 switch(drawType) 113 { 114 case DRAW_POINTLIST: 115 case DRAW_INDEXEDPOINTLIST8: 116 case DRAW_INDEXEDPOINTLIST16: 117 case DRAW_INDEXEDPOINTLIST32: 118 return false; 119 case DRAW_LINELIST: 120 case DRAW_LINESTRIP: 121 case DRAW_LINELOOP: 122 case DRAW_INDEXEDLINELIST8: 123 case DRAW_INDEXEDLINESTRIP8: 124 case DRAW_INDEXEDLINELOOP8: 125 case DRAW_INDEXEDLINELIST16: 126 case DRAW_INDEXEDLINESTRIP16: 127 case DRAW_INDEXEDLINELOOP16: 128 case DRAW_INDEXEDLINELIST32: 129 case DRAW_INDEXEDLINESTRIP32: 130 case DRAW_INDEXEDLINELOOP32: 131 return true; 132 case DRAW_TRIANGLELIST: 133 case DRAW_TRIANGLESTRIP: 134 case DRAW_TRIANGLEFAN: 135 case DRAW_INDEXEDTRIANGLELIST8: 136 case DRAW_INDEXEDTRIANGLESTRIP8: 137 case DRAW_INDEXEDTRIANGLEFAN8: 138 case DRAW_INDEXEDTRIANGLELIST16: 139 case DRAW_INDEXEDTRIANGLESTRIP16: 140 case DRAW_INDEXEDTRIANGLEFAN16: 141 case DRAW_INDEXEDTRIANGLELIST32: 142 case DRAW_INDEXEDTRIANGLESTRIP32: 143 case DRAW_INDEXEDTRIANGLEFAN32: 144 return fillModeAware ? fillMode == FILL_WIREFRAME : false; 145 case DRAW_QUADLIST: 146 return false; 147 default: 148 ASSERT(false); 149 } 150 151 return false; 152 } 153 isDrawTriangle(bool fillModeAware) const154 bool Context::isDrawTriangle(bool fillModeAware) const 155 { 156 switch(drawType) 157 { 158 case DRAW_POINTLIST: 159 case DRAW_INDEXEDPOINTLIST8: 160 case DRAW_INDEXEDPOINTLIST16: 161 case DRAW_INDEXEDPOINTLIST32: 162 return false; 163 case DRAW_LINELIST: 164 case DRAW_LINESTRIP: 165 case DRAW_LINELOOP: 166 case DRAW_INDEXEDLINELIST8: 167 case DRAW_INDEXEDLINESTRIP8: 168 case DRAW_INDEXEDLINELOOP8: 169 case DRAW_INDEXEDLINELIST16: 170 case DRAW_INDEXEDLINESTRIP16: 171 case DRAW_INDEXEDLINELOOP16: 172 case DRAW_INDEXEDLINELIST32: 173 case DRAW_INDEXEDLINESTRIP32: 174 case DRAW_INDEXEDLINELOOP32: 175 return false; 176 case DRAW_TRIANGLELIST: 177 case DRAW_TRIANGLESTRIP: 178 case DRAW_TRIANGLEFAN: 179 case DRAW_INDEXEDTRIANGLELIST8: 180 case DRAW_INDEXEDTRIANGLESTRIP8: 181 case DRAW_INDEXEDTRIANGLEFAN8: 182 case DRAW_INDEXEDTRIANGLELIST16: 183 case DRAW_INDEXEDTRIANGLESTRIP16: 184 case DRAW_INDEXEDTRIANGLEFAN16: 185 case DRAW_INDEXEDTRIANGLELIST32: 186 case DRAW_INDEXEDTRIANGLESTRIP32: 187 case DRAW_INDEXEDTRIANGLEFAN32: 188 return fillModeAware ? fillMode == FILL_SOLID : true; 189 case DRAW_QUADLIST: 190 // Quads are broken up into triangles 191 return fillModeAware ? fillMode == FILL_SOLID : true; 192 default: 193 ASSERT(false); 194 } 195 196 return true; 197 } 198 init()199 void Context::init() 200 { 201 for(int i = 0; i < 8; i++) 202 { 203 textureStage[i].init(i, &sampler[i], (i >= 1) ? &textureStage[i - 1] : 0); 204 } 205 206 // Set vertex streams to null stream 207 for(int i = 0; i < MAX_VERTEX_INPUTS; i++) 208 { 209 input[i].defaults(); 210 } 211 212 fogStart = 0.0f; 213 fogEnd = 1.0f; 214 215 for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++) textureWrap[i] = 0; 216 for(int i = 0; i < 8; i++) texGen[i] = TEXGEN_PASSTHRU; 217 for(int i = 0; i < 8; i++) textureTransformCount[i] = 0; 218 for(int i = 0; i < 8; i++) textureTransformProject[i] = false; 219 textureWrapActive = false; 220 localViewer = true; 221 normalizeNormals = false; 222 223 for(int i = 0; i < RENDERTARGETS; ++i) 224 { 225 renderTarget[i] = nullptr; 226 } 227 depthBuffer = nullptr; 228 stencilBuffer = nullptr; 229 230 stencilEnable = false; 231 stencilCompareMode = STENCIL_ALWAYS; 232 stencilReference = 0; 233 stencilMask = 0xFFFFFFFF; 234 stencilFailOperation = OPERATION_KEEP; 235 stencilPassOperation = OPERATION_KEEP; 236 stencilZFailOperation = OPERATION_KEEP; 237 stencilWriteMask = 0xFFFFFFFF; 238 239 twoSidedStencil = false; 240 stencilCompareModeCCW = STENCIL_ALWAYS; 241 stencilReferenceCCW = 0; 242 stencilMaskCCW = 0xFFFFFFFF; 243 stencilFailOperationCCW = OPERATION_KEEP; 244 stencilPassOperationCCW = OPERATION_KEEP; 245 stencilZFailOperationCCW = OPERATION_KEEP; 246 stencilWriteMaskCCW = 0xFFFFFFFF; 247 248 setGlobalMipmapBias(0); 249 250 lightingEnable = true; 251 specularEnable = false; 252 for(int i = 0; i < 8; i++) lightEnable[i] = false; 253 for(int i = 0; i < 8; i++) worldLightPosition[i] = 0; 254 255 alphaCompareMode = ALPHA_ALWAYS; 256 alphaTestEnable = false; 257 fillMode = FILL_SOLID; 258 shadingMode = SHADING_GOURAUD; 259 260 rasterizerDiscard = false; 261 262 depthCompareMode = DEPTH_LESS; 263 depthBufferEnable = true; 264 depthWriteEnable = true; 265 266 alphaBlendEnable = false; 267 sourceBlendFactorState = BLEND_ONE; 268 destBlendFactorState = BLEND_ZERO; 269 blendOperationState = BLENDOP_ADD; 270 271 separateAlphaBlendEnable = false; 272 sourceBlendFactorStateAlpha = BLEND_ONE; 273 destBlendFactorStateAlpha = BLEND_ZERO; 274 blendOperationStateAlpha = BLENDOP_ADD; 275 276 cullMode = CULL_CLOCKWISE; 277 alphaReference = 0.0f; 278 279 depthBias = 0.0f; 280 slopeDepthBias = 0.0f; 281 282 for(int i = 0; i < RENDERTARGETS; i++) 283 { 284 colorWriteMask[i] = 0x0000000F; 285 } 286 287 ambientMaterialSource = MATERIAL_MATERIAL; 288 diffuseMaterialSource = MATERIAL_COLOR1; 289 specularMaterialSource = MATERIAL_COLOR2; 290 emissiveMaterialSource = MATERIAL_MATERIAL; 291 colorVertexEnable = true; 292 293 fogEnable = false; 294 pixelFogMode = FOG_NONE; 295 vertexFogMode = FOG_NONE; 296 wBasedFog = false; 297 rangeFogEnable = false; 298 299 indexedVertexBlendEnable = false; 300 vertexBlendMatrixCount = 0; 301 302 pixelShader = 0; 303 vertexShader = 0; 304 305 instanceID = 0; 306 307 occlusionEnabled = false; 308 transformFeedbackQueryEnabled = false; 309 transformFeedbackEnabled = 0; 310 311 pointSpriteEnable = false; 312 pointScaleEnable = false; 313 lineWidth = 1.0f; 314 315 writeSRGB = false; 316 sampleMask = 0xFFFFFFFF; 317 318 colorLogicOpEnabled = false; 319 logicalOperation = LOGICALOP_COPY; 320 } 321 exp2Bias()322 const float &Context::exp2Bias() 323 { 324 return bias; 325 } 326 getLightPosition(int light)327 const Point &Context::getLightPosition(int light) 328 { 329 return worldLightPosition[light]; 330 } 331 setGlobalMipmapBias(float bias)332 void Context::setGlobalMipmapBias(float bias) 333 { 334 this->bias = exp2(bias + 0.5f); 335 } 336 setLightingEnable(bool lightingEnable)337 void Context::setLightingEnable(bool lightingEnable) 338 { 339 this->lightingEnable = lightingEnable; 340 } 341 setSpecularEnable(bool specularEnable)342 void Context::setSpecularEnable(bool specularEnable) 343 { 344 Context::specularEnable = specularEnable; 345 } 346 setLightEnable(int light,bool lightEnable)347 void Context::setLightEnable(int light, bool lightEnable) 348 { 349 Context::lightEnable[light] = lightEnable; 350 } 351 setLightPosition(int light,Point worldLightPosition)352 void Context::setLightPosition(int light, Point worldLightPosition) 353 { 354 Context::worldLightPosition[light] = worldLightPosition; 355 } 356 setAmbientMaterialSource(MaterialSource ambientMaterialSource)357 void Context::setAmbientMaterialSource(MaterialSource ambientMaterialSource) 358 { 359 Context::ambientMaterialSource = ambientMaterialSource; 360 } 361 setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)362 void Context::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource) 363 { 364 Context::diffuseMaterialSource = diffuseMaterialSource; 365 } 366 setSpecularMaterialSource(MaterialSource specularMaterialSource)367 void Context::setSpecularMaterialSource(MaterialSource specularMaterialSource) 368 { 369 Context::specularMaterialSource = specularMaterialSource; 370 } 371 setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)372 void Context::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource) 373 { 374 Context::emissiveMaterialSource = emissiveMaterialSource; 375 } 376 setPointSpriteEnable(bool pointSpriteEnable)377 void Context::setPointSpriteEnable(bool pointSpriteEnable) 378 { 379 Context::pointSpriteEnable = pointSpriteEnable; 380 } 381 setPointScaleEnable(bool pointScaleEnable)382 void Context::setPointScaleEnable(bool pointScaleEnable) 383 { 384 Context::pointScaleEnable = pointScaleEnable; 385 } 386 setDepthBufferEnable(bool depthBufferEnable)387 bool Context::setDepthBufferEnable(bool depthBufferEnable) 388 { 389 bool modified = (Context::depthBufferEnable != depthBufferEnable); 390 Context::depthBufferEnable = depthBufferEnable; 391 return modified; 392 } 393 setAlphaBlendEnable(bool alphaBlendEnable)394 bool Context::setAlphaBlendEnable(bool alphaBlendEnable) 395 { 396 bool modified = (Context::alphaBlendEnable != alphaBlendEnable); 397 Context::alphaBlendEnable = alphaBlendEnable; 398 return modified; 399 } 400 setSourceBlendFactor(BlendFactor sourceBlendFactor)401 bool Context::setSourceBlendFactor(BlendFactor sourceBlendFactor) 402 { 403 bool modified = (Context::sourceBlendFactorState != sourceBlendFactor); 404 Context::sourceBlendFactorState = sourceBlendFactor; 405 return modified; 406 } 407 setDestBlendFactor(BlendFactor destBlendFactor)408 bool Context::setDestBlendFactor(BlendFactor destBlendFactor) 409 { 410 bool modified = (Context::destBlendFactorState != destBlendFactor); 411 Context::destBlendFactorState = destBlendFactor; 412 return modified; 413 } 414 setBlendOperation(BlendOperation blendOperation)415 bool Context::setBlendOperation(BlendOperation blendOperation) 416 { 417 bool modified = (Context::blendOperationState != blendOperation); 418 Context::blendOperationState = blendOperation; 419 return modified; 420 } 421 setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)422 bool Context::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable) 423 { 424 bool modified = (Context::separateAlphaBlendEnable != separateAlphaBlendEnable); 425 Context::separateAlphaBlendEnable = separateAlphaBlendEnable; 426 return modified; 427 } 428 setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)429 bool Context::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha) 430 { 431 bool modified = (Context::sourceBlendFactorStateAlpha != sourceBlendFactorAlpha); 432 Context::sourceBlendFactorStateAlpha = sourceBlendFactorAlpha; 433 return modified; 434 } 435 setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)436 bool Context::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha) 437 { 438 bool modified = (Context::destBlendFactorStateAlpha != destBlendFactorAlpha); 439 Context::destBlendFactorStateAlpha = destBlendFactorAlpha; 440 return modified; 441 } 442 setBlendOperationAlpha(BlendOperation blendOperationAlpha)443 bool Context::setBlendOperationAlpha(BlendOperation blendOperationAlpha) 444 { 445 bool modified = (Context::blendOperationStateAlpha != blendOperationAlpha); 446 Context::blendOperationStateAlpha = blendOperationAlpha; 447 return modified; 448 } 449 setColorWriteMask(int index,int colorWriteMask)450 bool Context::setColorWriteMask(int index, int colorWriteMask) 451 { 452 bool modified = (Context::colorWriteMask[index] != colorWriteMask); 453 Context::colorWriteMask[index] = colorWriteMask; 454 return modified; 455 } 456 setWriteSRGB(bool sRGB)457 bool Context::setWriteSRGB(bool sRGB) 458 { 459 bool modified = (Context::writeSRGB != sRGB); 460 Context::writeSRGB = sRGB; 461 return modified; 462 } 463 setColorLogicOpEnabled(bool enabled)464 bool Context::setColorLogicOpEnabled(bool enabled) 465 { 466 bool modified = (Context::colorLogicOpEnabled != enabled); 467 Context::colorLogicOpEnabled = enabled; 468 return modified; 469 } 470 setLogicalOperation(LogicalOperation logicalOperation)471 bool Context::setLogicalOperation(LogicalOperation logicalOperation) 472 { 473 bool modified = (Context::logicalOperation != logicalOperation); 474 Context::logicalOperation = logicalOperation; 475 return modified; 476 } 477 setColorVertexEnable(bool colorVertexEnable)478 void Context::setColorVertexEnable(bool colorVertexEnable) 479 { 480 Context::colorVertexEnable = colorVertexEnable; 481 } 482 fogActive()483 bool Context::fogActive() 484 { 485 if(!colorUsed()) return false; 486 487 if(pixelShaderModel() >= 0x0300) return false; 488 489 return fogEnable; 490 } 491 pointSizeActive()492 bool Context::pointSizeActive() 493 { 494 if(vertexShader) 495 { 496 return false; 497 } 498 499 return isDrawPoint(true) && (input[PointSize] || (!preTransformed && pointScaleActive())); 500 } 501 pixelFogActive()502 FogMode Context::pixelFogActive() 503 { 504 if(fogActive()) 505 { 506 return pixelFogMode; 507 } 508 509 return FOG_NONE; 510 } 511 depthWriteActive()512 bool Context::depthWriteActive() 513 { 514 if(!depthBufferActive()) return false; 515 516 return depthWriteEnable; 517 } 518 alphaTestActive()519 bool Context::alphaTestActive() 520 { 521 if(transparencyAntialiasing != TRANSPARENCY_NONE) return true; 522 if(!alphaTestEnable) return false; 523 if(alphaCompareMode == ALPHA_ALWAYS) return false; 524 if(alphaReference == 0.0f && alphaCompareMode == ALPHA_GREATEREQUAL) return false; 525 526 return true; 527 } 528 depthBufferActive()529 bool Context::depthBufferActive() 530 { 531 return depthBuffer && depthBufferEnable; 532 } 533 stencilActive()534 bool Context::stencilActive() 535 { 536 return stencilBuffer && stencilEnable; 537 } 538 vertexLightingActive()539 bool Context::vertexLightingActive() 540 { 541 if(vertexShader) 542 { 543 return false; 544 } 545 546 return lightingEnable && !preTransformed; 547 } 548 texCoordActive(int coordinate,int component)549 bool Context::texCoordActive(int coordinate, int component) 550 { 551 bool hasTexture = pointSpriteActive(); 552 553 if(vertexShader) 554 { 555 if(!preTransformed) 556 { 557 if(vertexShader->getOutput(T0 + coordinate, component).usage == Shader::USAGE_TEXCOORD) 558 { 559 hasTexture = true; 560 } 561 } 562 else 563 { 564 hasTexture = true; // FIXME: Check vertex buffer streams 565 } 566 } 567 else 568 { 569 switch(texGen[coordinate]) 570 { 571 case TEXGEN_NONE: 572 hasTexture = true; 573 break; 574 case TEXGEN_PASSTHRU: 575 hasTexture = hasTexture || (component < input[TexCoord0 + textureStage[coordinate].texCoordIndex].count); 576 break; 577 case TEXGEN_NORMAL: 578 hasTexture = hasTexture || (component <= 2); 579 break; 580 case TEXGEN_POSITION: 581 hasTexture = hasTexture || (component <= 2); 582 break; 583 case TEXGEN_REFLECTION: 584 hasTexture = hasTexture || (component <= 2); 585 break; 586 case TEXGEN_SPHEREMAP: 587 hasTexture = hasTexture || (component <= 1); 588 break; 589 default: 590 ASSERT(false); 591 } 592 } 593 594 bool project = isProjectionComponent(coordinate, component); 595 bool usesTexture = false; 596 597 if(pixelShader) 598 { 599 usesTexture = pixelShader->usesTexture(coordinate, component) || project; 600 } 601 else 602 { 603 usesTexture = textureStage[coordinate].usesTexture() || project; 604 } 605 606 return hasTexture && usesTexture; 607 } 608 texCoordActive(int coordinate)609 bool Context::texCoordActive(int coordinate) 610 { 611 return texCoordActive(coordinate, 0) || 612 texCoordActive(coordinate, 1) || 613 texCoordActive(coordinate, 2) || 614 texCoordActive(coordinate, 3); 615 } 616 isProjectionComponent(unsigned int coordinate,int component)617 bool Context::isProjectionComponent(unsigned int coordinate, int component) 618 { 619 if(pixelShaderModel() <= 0x0103 && coordinate < 8 && textureTransformProject[coordinate]) 620 { 621 if(textureTransformCount[coordinate] == 2) 622 { 623 if(component == 1) return true; 624 } 625 else if(textureTransformCount[coordinate] == 3) 626 { 627 if(component == 2) return true; 628 } 629 else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0) 630 { 631 if(component == 3) return true; 632 } 633 } 634 635 return false; 636 } 637 vertexSpecularActive()638 bool Context::vertexSpecularActive() 639 { 640 return vertexLightingActive() && specularEnable && vertexNormalActive(); 641 } 642 vertexNormalActive()643 bool Context::vertexNormalActive() 644 { 645 if(vertexShader) 646 { 647 return false; 648 } 649 650 return input[Normal]; 651 } 652 vertexLightActive(int i)653 bool Context::vertexLightActive(int i) 654 { 655 if(vertexShader) 656 { 657 return false; 658 } 659 660 return lightingEnable && lightEnable[i]; 661 } 662 vertexDiffuseMaterialSourceActive()663 MaterialSource Context::vertexDiffuseMaterialSourceActive() 664 { 665 if(vertexShader) 666 { 667 return MATERIAL_MATERIAL; 668 } 669 670 if(diffuseMaterialSource == MATERIAL_MATERIAL || !colorVertexEnable || 671 (diffuseMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 672 (diffuseMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 673 { 674 return MATERIAL_MATERIAL; 675 } 676 677 return diffuseMaterialSource; 678 } 679 vertexSpecularMaterialSourceActive()680 MaterialSource Context::vertexSpecularMaterialSourceActive() 681 { 682 if(vertexShader) 683 { 684 return MATERIAL_MATERIAL; 685 } 686 687 if(!colorVertexEnable || 688 (specularMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 689 (specularMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 690 { 691 return MATERIAL_MATERIAL; 692 } 693 694 return specularMaterialSource; 695 } 696 vertexAmbientMaterialSourceActive()697 MaterialSource Context::vertexAmbientMaterialSourceActive() 698 { 699 if(vertexShader) 700 { 701 return MATERIAL_MATERIAL; 702 } 703 704 if(!colorVertexEnable || 705 (ambientMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 706 (ambientMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 707 { 708 return MATERIAL_MATERIAL; 709 } 710 711 return ambientMaterialSource; 712 } 713 vertexEmissiveMaterialSourceActive()714 MaterialSource Context::vertexEmissiveMaterialSourceActive() 715 { 716 if(vertexShader) 717 { 718 return MATERIAL_MATERIAL; 719 } 720 721 if(!colorVertexEnable || 722 (emissiveMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 723 (emissiveMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 724 { 725 return MATERIAL_MATERIAL; 726 } 727 728 return emissiveMaterialSource; 729 } 730 pointSpriteActive()731 bool Context::pointSpriteActive() 732 { 733 return isDrawPoint(true) && pointSpriteEnable; 734 } 735 pointScaleActive()736 bool Context::pointScaleActive() 737 { 738 if(vertexShader) 739 { 740 return false; 741 } 742 743 return isDrawPoint(true) && pointScaleEnable; 744 } 745 alphaBlendActive()746 bool Context::alphaBlendActive() 747 { 748 if(!alphaBlendEnable) 749 { 750 return false; 751 } 752 753 if(!colorUsed()) 754 { 755 return false; 756 } 757 758 bool colorBlend = !(blendOperation() == BLENDOP_SOURCE && sourceBlendFactor() == BLEND_ONE); 759 bool alphaBlend = separateAlphaBlendEnable ? !(blendOperationAlpha() == BLENDOP_SOURCE && sourceBlendFactorAlpha() == BLEND_ONE) : colorBlend; 760 761 return colorBlend || alphaBlend; 762 } 763 colorLogicOp()764 LogicalOperation Context::colorLogicOp() 765 { 766 return colorLogicOpEnabled ? logicalOperation : LOGICALOP_COPY; 767 } 768 sourceBlendFactor()769 BlendFactor Context::sourceBlendFactor() 770 { 771 if(!alphaBlendEnable) return BLEND_ONE; 772 773 switch(blendOperationState) 774 { 775 case BLENDOP_ADD: 776 case BLENDOP_SUB: 777 case BLENDOP_INVSUB: 778 return sourceBlendFactorState; 779 case BLENDOP_MIN: 780 return BLEND_ONE; 781 case BLENDOP_MAX: 782 return BLEND_ONE; 783 default: 784 ASSERT(false); 785 } 786 787 return sourceBlendFactorState; 788 } 789 destBlendFactor()790 BlendFactor Context::destBlendFactor() 791 { 792 if(!alphaBlendEnable) return BLEND_ZERO; 793 794 switch(blendOperationState) 795 { 796 case BLENDOP_ADD: 797 case BLENDOP_SUB: 798 case BLENDOP_INVSUB: 799 return destBlendFactorState; 800 case BLENDOP_MIN: 801 return BLEND_ONE; 802 case BLENDOP_MAX: 803 return BLEND_ONE; 804 default: 805 ASSERT(false); 806 } 807 808 return destBlendFactorState; 809 } 810 blendOperation()811 BlendOperation Context::blendOperation() 812 { 813 if(!alphaBlendEnable) return BLENDOP_SOURCE; 814 815 switch(blendOperationState) 816 { 817 case BLENDOP_ADD: 818 if(sourceBlendFactor() == BLEND_ZERO) 819 { 820 if(destBlendFactor() == BLEND_ZERO) 821 { 822 return BLENDOP_NULL; 823 } 824 else 825 { 826 return BLENDOP_DEST; 827 } 828 } 829 else if(sourceBlendFactor() == BLEND_ONE) 830 { 831 if(destBlendFactor() == BLEND_ZERO) 832 { 833 return BLENDOP_SOURCE; 834 } 835 else 836 { 837 return BLENDOP_ADD; 838 } 839 } 840 else 841 { 842 if(destBlendFactor() == BLEND_ZERO) 843 { 844 return BLENDOP_SOURCE; 845 } 846 else 847 { 848 return BLENDOP_ADD; 849 } 850 } 851 case BLENDOP_SUB: 852 if(sourceBlendFactor() == BLEND_ZERO) 853 { 854 return BLENDOP_NULL; // Negative, clamped to zero 855 } 856 else if(sourceBlendFactor() == BLEND_ONE) 857 { 858 if(destBlendFactor() == BLEND_ZERO) 859 { 860 return BLENDOP_SOURCE; 861 } 862 else 863 { 864 return BLENDOP_SUB; 865 } 866 } 867 else 868 { 869 if(destBlendFactor() == BLEND_ZERO) 870 { 871 return BLENDOP_SOURCE; 872 } 873 else 874 { 875 return BLENDOP_SUB; 876 } 877 } 878 case BLENDOP_INVSUB: 879 if(sourceBlendFactor() == BLEND_ZERO) 880 { 881 if(destBlendFactor() == BLEND_ZERO) 882 { 883 return BLENDOP_NULL; 884 } 885 else 886 { 887 return BLENDOP_DEST; 888 } 889 } 890 else if(sourceBlendFactor() == BLEND_ONE) 891 { 892 if(destBlendFactor() == BLEND_ZERO) 893 { 894 return BLENDOP_NULL; // Negative, clamped to zero 895 } 896 else 897 { 898 return BLENDOP_INVSUB; 899 } 900 } 901 else 902 { 903 if(destBlendFactor() == BLEND_ZERO) 904 { 905 return BLENDOP_NULL; // Negative, clamped to zero 906 } 907 else 908 { 909 return BLENDOP_INVSUB; 910 } 911 } 912 case BLENDOP_MIN: 913 return BLENDOP_MIN; 914 case BLENDOP_MAX: 915 return BLENDOP_MAX; 916 default: 917 ASSERT(false); 918 } 919 920 return blendOperationState; 921 } 922 sourceBlendFactorAlpha()923 BlendFactor Context::sourceBlendFactorAlpha() 924 { 925 if(!separateAlphaBlendEnable) 926 { 927 return sourceBlendFactor(); 928 } 929 else 930 { 931 switch(blendOperationStateAlpha) 932 { 933 case BLENDOP_ADD: 934 case BLENDOP_SUB: 935 case BLENDOP_INVSUB: 936 return sourceBlendFactorStateAlpha; 937 case BLENDOP_MIN: 938 return BLEND_ONE; 939 case BLENDOP_MAX: 940 return BLEND_ONE; 941 default: 942 ASSERT(false); 943 } 944 945 return sourceBlendFactorStateAlpha; 946 } 947 } 948 destBlendFactorAlpha()949 BlendFactor Context::destBlendFactorAlpha() 950 { 951 if(!separateAlphaBlendEnable) 952 { 953 return destBlendFactor(); 954 } 955 else 956 { 957 switch(blendOperationStateAlpha) 958 { 959 case BLENDOP_ADD: 960 case BLENDOP_SUB: 961 case BLENDOP_INVSUB: 962 return destBlendFactorStateAlpha; 963 case BLENDOP_MIN: 964 return BLEND_ONE; 965 case BLENDOP_MAX: 966 return BLEND_ONE; 967 default: 968 ASSERT(false); 969 } 970 971 return destBlendFactorStateAlpha; 972 } 973 } 974 blendOperationAlpha()975 BlendOperation Context::blendOperationAlpha() 976 { 977 if(!separateAlphaBlendEnable) 978 { 979 return blendOperation(); 980 } 981 else 982 { 983 switch(blendOperationStateAlpha) 984 { 985 case BLENDOP_ADD: 986 if(sourceBlendFactorAlpha() == BLEND_ZERO) 987 { 988 if(destBlendFactorAlpha() == BLEND_ZERO) 989 { 990 return BLENDOP_NULL; 991 } 992 else 993 { 994 return BLENDOP_DEST; 995 } 996 } 997 else if(sourceBlendFactorAlpha() == BLEND_ONE) 998 { 999 if(destBlendFactorAlpha() == BLEND_ZERO) 1000 { 1001 return BLENDOP_SOURCE; 1002 } 1003 else 1004 { 1005 return BLENDOP_ADD; 1006 } 1007 } 1008 else 1009 { 1010 if(destBlendFactorAlpha() == BLEND_ZERO) 1011 { 1012 return BLENDOP_SOURCE; 1013 } 1014 else 1015 { 1016 return BLENDOP_ADD; 1017 } 1018 } 1019 case BLENDOP_SUB: 1020 if(sourceBlendFactorAlpha() == BLEND_ZERO) 1021 { 1022 return BLENDOP_NULL; // Negative, clamped to zero 1023 } 1024 else if(sourceBlendFactorAlpha() == BLEND_ONE) 1025 { 1026 if(destBlendFactorAlpha() == BLEND_ZERO) 1027 { 1028 return BLENDOP_SOURCE; 1029 } 1030 else 1031 { 1032 return BLENDOP_SUB; 1033 } 1034 } 1035 else 1036 { 1037 if(destBlendFactorAlpha() == BLEND_ZERO) 1038 { 1039 return BLENDOP_SOURCE; 1040 } 1041 else 1042 { 1043 return BLENDOP_SUB; 1044 } 1045 } 1046 case BLENDOP_INVSUB: 1047 if(sourceBlendFactorAlpha() == BLEND_ZERO) 1048 { 1049 if(destBlendFactorAlpha() == BLEND_ZERO) 1050 { 1051 return BLENDOP_NULL; 1052 } 1053 else 1054 { 1055 return BLENDOP_DEST; 1056 } 1057 } 1058 else if(sourceBlendFactorAlpha() == BLEND_ONE) 1059 { 1060 if(destBlendFactorAlpha() == BLEND_ZERO) 1061 { 1062 return BLENDOP_NULL; // Negative, clamped to zero 1063 } 1064 else 1065 { 1066 return BLENDOP_INVSUB; 1067 } 1068 } 1069 else 1070 { 1071 if(destBlendFactorAlpha() == BLEND_ZERO) 1072 { 1073 return BLENDOP_NULL; // Negative, clamped to zero 1074 } 1075 else 1076 { 1077 return BLENDOP_INVSUB; 1078 } 1079 } 1080 case BLENDOP_MIN: 1081 return BLENDOP_MIN; 1082 case BLENDOP_MAX: 1083 return BLENDOP_MAX; 1084 default: 1085 ASSERT(false); 1086 } 1087 1088 return blendOperationStateAlpha; 1089 } 1090 } 1091 indexedVertexBlendActive()1092 bool Context::indexedVertexBlendActive() 1093 { 1094 if(vertexShader) 1095 { 1096 return false; 1097 } 1098 1099 return indexedVertexBlendEnable; 1100 } 1101 vertexBlendMatrixCountActive()1102 int Context::vertexBlendMatrixCountActive() 1103 { 1104 if(vertexShader) 1105 { 1106 return 0; 1107 } 1108 1109 return vertexBlendMatrixCount; 1110 } 1111 localViewerActive()1112 bool Context::localViewerActive() 1113 { 1114 if(vertexShader) 1115 { 1116 return false; 1117 } 1118 1119 return localViewer; 1120 } 1121 normalizeNormalsActive()1122 bool Context::normalizeNormalsActive() 1123 { 1124 if(vertexShader) 1125 { 1126 return false; 1127 } 1128 1129 return normalizeNormals; 1130 } 1131 vertexFogModeActive()1132 FogMode Context::vertexFogModeActive() 1133 { 1134 if(vertexShader || !fogActive()) 1135 { 1136 return FOG_NONE; 1137 } 1138 1139 return vertexFogMode; 1140 } 1141 rangeFogActive()1142 bool Context::rangeFogActive() 1143 { 1144 if(vertexShader || !fogActive()) 1145 { 1146 return false; 1147 } 1148 1149 return rangeFogEnable; 1150 } 1151 texGenActive(int stage)1152 TexGen Context::texGenActive(int stage) 1153 { 1154 if(vertexShader || !texCoordActive(stage)) 1155 { 1156 return TEXGEN_PASSTHRU; 1157 } 1158 1159 return texGen[stage]; 1160 } 1161 textureTransformCountActive(int stage)1162 int Context::textureTransformCountActive(int stage) 1163 { 1164 if(vertexShader || !texCoordActive(stage)) 1165 { 1166 return 0; 1167 } 1168 1169 return textureTransformCount[stage]; 1170 } 1171 texCoordIndexActive(int stage)1172 int Context::texCoordIndexActive(int stage) 1173 { 1174 if(vertexShader || !texCoordActive(stage)) 1175 { 1176 return stage; 1177 } 1178 1179 return textureStage[stage].texCoordIndex; 1180 } 1181 perspectiveActive()1182 bool Context::perspectiveActive() 1183 { 1184 if(!colorUsed()) 1185 { 1186 return false; 1187 } 1188 1189 if(!perspectiveCorrection) 1190 { 1191 return false; 1192 } 1193 1194 if(isDrawPoint(true)) 1195 { 1196 return false; 1197 } 1198 1199 return true; 1200 } 1201 diffuseUsed()1202 bool Context::diffuseUsed() 1203 { 1204 return diffuseUsed(0) || diffuseUsed(1) || diffuseUsed(2) || diffuseUsed(3); 1205 } 1206 diffuseUsed(int component)1207 bool Context::diffuseUsed(int component) 1208 { 1209 if(!colorUsed()) 1210 { 1211 return false; 1212 } 1213 1214 if(pixelShader) 1215 { 1216 return pixelShader->usesDiffuse(component); 1217 } 1218 1219 // Directly using the diffuse input color 1220 for(int i = 0; i < 8; i++) 1221 { 1222 if(textureStage[i].isStageDisabled()) 1223 { 1224 break; 1225 } 1226 1227 if(textureStage[i].usesDiffuse()) 1228 { 1229 return true; 1230 } 1231 } 1232 1233 // Using the current color (initialized to diffuse) before it's overwritten 1234 for(int i = 0; i < 8; i++) 1235 { 1236 if(textureStage[i].usesCurrent() || textureStage[i].isStageDisabled()) // Current color contains diffuse before being overwritten 1237 { 1238 return true; 1239 } 1240 1241 if(textureStage[i].writesCurrent()) 1242 { 1243 return false; 1244 } 1245 } 1246 1247 return true; 1248 } 1249 diffuseActive()1250 bool Context::diffuseActive() 1251 { 1252 return diffuseActive(0) || diffuseActive(1) || diffuseActive(2) || diffuseActive(3); 1253 } 1254 diffuseActive(int component)1255 bool Context::diffuseActive(int component) 1256 { 1257 if(!colorUsed()) 1258 { 1259 return false; 1260 } 1261 1262 // Vertex processor provides diffuse component 1263 bool vertexDiffuse; 1264 1265 if(vertexShader) 1266 { 1267 vertexDiffuse = vertexShader->getOutput(C0, component).active(); 1268 } 1269 else if(!preTransformed) 1270 { 1271 vertexDiffuse = input[Color0] || lightingEnable; 1272 } 1273 else 1274 { 1275 vertexDiffuse = input[Color0]; 1276 } 1277 1278 // Pixel processor requires diffuse component 1279 bool pixelDiffuse = diffuseUsed(component); 1280 1281 return vertexDiffuse && pixelDiffuse; 1282 } 1283 specularUsed()1284 bool Context::specularUsed() 1285 { 1286 return Context::specularUsed(0) || Context::specularUsed(1) || Context::specularUsed(2) || Context::specularUsed(3); 1287 } 1288 specularUsed(int component)1289 bool Context::specularUsed(int component) 1290 { 1291 if(!colorUsed()) 1292 { 1293 return false; 1294 } 1295 1296 if(pixelShader) 1297 { 1298 return pixelShader->usesSpecular(component); 1299 } 1300 1301 bool pixelSpecular = specularEnable; 1302 1303 for(int i = 0; i < 8; i++) 1304 { 1305 if(textureStage[i].isStageDisabled()) break; 1306 1307 pixelSpecular = pixelSpecular || textureStage[i].usesSpecular(); 1308 } 1309 1310 return pixelSpecular; 1311 } 1312 specularActive()1313 bool Context::specularActive() 1314 { 1315 return specularActive(0) || specularActive(1) || specularActive(2) || specularActive(3); 1316 } 1317 specularActive(int component)1318 bool Context::specularActive(int component) 1319 { 1320 if(!colorUsed()) 1321 { 1322 return false; 1323 } 1324 1325 // Vertex processor provides specular component 1326 bool vertexSpecular; 1327 1328 if(!vertexShader) 1329 { 1330 vertexSpecular = input[Color1] || (lightingEnable && specularEnable); 1331 } 1332 else 1333 { 1334 vertexSpecular = vertexShader->getOutput(C1, component).active(); 1335 } 1336 1337 // Pixel processor requires specular component 1338 bool pixelSpecular = specularUsed(component); 1339 1340 return vertexSpecular && pixelSpecular; 1341 } 1342 colorActive(int color,int component)1343 bool Context::colorActive(int color, int component) 1344 { 1345 if(color == 0) 1346 { 1347 return diffuseActive(component); 1348 } 1349 else 1350 { 1351 return specularActive(component); 1352 } 1353 } 1354 textureActive()1355 bool Context::textureActive() 1356 { 1357 for(int i = 0; i < 8; i++) 1358 { 1359 if(textureActive(i)) 1360 { 1361 return true; 1362 } 1363 } 1364 1365 return false; 1366 } 1367 textureActive(int coordinate)1368 bool Context::textureActive(int coordinate) 1369 { 1370 return textureActive(coordinate, 0) || textureActive(coordinate, 1) || textureActive(coordinate, 2) || textureActive(coordinate, 3); 1371 } 1372 textureActive(int coordinate,int component)1373 bool Context::textureActive(int coordinate, int component) 1374 { 1375 if(!colorUsed()) 1376 { 1377 return false; 1378 } 1379 1380 if(!texCoordActive(coordinate, component)) 1381 { 1382 return false; 1383 } 1384 1385 if(textureTransformProject[coordinate] && pixelShaderModel() <= 0x0103) 1386 { 1387 if(textureTransformCount[coordinate] == 2) 1388 { 1389 if(component == 1) return true; 1390 } 1391 else if(textureTransformCount[coordinate] == 3) 1392 { 1393 if(component == 2) return true; 1394 } 1395 else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0) 1396 { 1397 if(component == 3) return true; 1398 } 1399 } 1400 1401 if(!pixelShader) 1402 { 1403 bool texture = textureStage[coordinate].usesTexture(); 1404 bool cube = sampler[coordinate].hasCubeTexture(); 1405 bool volume = sampler[coordinate].hasVolumeTexture(); 1406 1407 if(texture) 1408 { 1409 for(int i = coordinate; i >= 0; i--) 1410 { 1411 if(textureStage[i].stageOperation == TextureStage::STAGE_DISABLE) 1412 { 1413 return false; 1414 } 1415 } 1416 } 1417 1418 switch(component) 1419 { 1420 case 0: 1421 return texture; 1422 case 1: 1423 return texture; 1424 case 2: 1425 return (texture && (cube || volume)); 1426 case 3: 1427 return false; 1428 } 1429 } 1430 else 1431 { 1432 return pixelShader->usesTexture(coordinate, component); 1433 } 1434 1435 return false; 1436 } 1437 pixelShaderModel() const1438 unsigned short Context::pixelShaderModel() const 1439 { 1440 return pixelShader ? pixelShader->getShaderModel() : 0x0000; 1441 } 1442 vertexShaderModel() const1443 unsigned short Context::vertexShaderModel() const 1444 { 1445 return vertexShader ? vertexShader->getShaderModel() : 0x0000; 1446 } 1447 getMultiSampleCount() const1448 int Context::getMultiSampleCount() const 1449 { 1450 return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1; 1451 } 1452 getSuperSampleCount() const1453 int Context::getSuperSampleCount() const 1454 { 1455 return renderTarget[0] ? renderTarget[0]->getSuperSampleCount() : 1; 1456 } 1457 renderTargetInternalFormat(int index)1458 Format Context::renderTargetInternalFormat(int index) 1459 { 1460 if(renderTarget[index]) 1461 { 1462 return renderTarget[index]->getInternalFormat(); 1463 } 1464 else 1465 { 1466 return FORMAT_NULL; 1467 } 1468 } 1469 colorWriteActive()1470 int Context::colorWriteActive() 1471 { 1472 return colorWriteActive(0) | colorWriteActive(1) | colorWriteActive(2) | colorWriteActive(3); 1473 } 1474 colorWriteActive(int index)1475 int Context::colorWriteActive(int index) 1476 { 1477 if(!renderTarget[index] || renderTarget[index]->getInternalFormat() == FORMAT_NULL) 1478 { 1479 return 0; 1480 } 1481 1482 if(blendOperation() == BLENDOP_DEST && destBlendFactor() == BLEND_ONE && 1483 (!separateAlphaBlendEnable || (blendOperationAlpha() == BLENDOP_DEST && destBlendFactorAlpha() == BLEND_ONE))) 1484 { 1485 return 0; 1486 } 1487 1488 return colorWriteMask[index]; 1489 } 1490 colorUsed()1491 bool Context::colorUsed() 1492 { 1493 return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->containsKill()); 1494 } 1495 } 1496