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 frontFacingCCW = true; 278 alphaReference = 0.0f; 279 280 depthBias = 0.0f; 281 slopeDepthBias = 0.0f; 282 283 for(int i = 0; i < RENDERTARGETS; i++) 284 { 285 colorWriteMask[i] = 0x0000000F; 286 } 287 288 ambientMaterialSource = MATERIAL_MATERIAL; 289 diffuseMaterialSource = MATERIAL_COLOR1; 290 specularMaterialSource = MATERIAL_COLOR2; 291 emissiveMaterialSource = MATERIAL_MATERIAL; 292 colorVertexEnable = true; 293 294 fogEnable = false; 295 pixelFogMode = FOG_NONE; 296 vertexFogMode = FOG_NONE; 297 wBasedFog = false; 298 rangeFogEnable = false; 299 300 indexedVertexBlendEnable = false; 301 vertexBlendMatrixCount = 0; 302 303 pixelShader = 0; 304 vertexShader = 0; 305 306 instanceID = 0; 307 308 occlusionEnabled = false; 309 transformFeedbackQueryEnabled = false; 310 transformFeedbackEnabled = 0; 311 312 pointSpriteEnable = false; 313 pointScaleEnable = false; 314 lineWidth = 1.0f; 315 316 writeSRGB = false; 317 sampleMask = 0xFFFFFFFF; 318 319 colorLogicOpEnabled = false; 320 logicalOperation = LOGICALOP_COPY; 321 } 322 exp2Bias()323 const float &Context::exp2Bias() 324 { 325 return bias; 326 } 327 getLightPosition(int light)328 const Point &Context::getLightPosition(int light) 329 { 330 return worldLightPosition[light]; 331 } 332 setGlobalMipmapBias(float bias)333 void Context::setGlobalMipmapBias(float bias) 334 { 335 this->bias = exp2(bias + 0.5f); 336 } 337 setLightingEnable(bool lightingEnable)338 void Context::setLightingEnable(bool lightingEnable) 339 { 340 this->lightingEnable = lightingEnable; 341 } 342 setSpecularEnable(bool specularEnable)343 void Context::setSpecularEnable(bool specularEnable) 344 { 345 Context::specularEnable = specularEnable; 346 } 347 setLightEnable(int light,bool lightEnable)348 void Context::setLightEnable(int light, bool lightEnable) 349 { 350 Context::lightEnable[light] = lightEnable; 351 } 352 setLightPosition(int light,Point worldLightPosition)353 void Context::setLightPosition(int light, Point worldLightPosition) 354 { 355 Context::worldLightPosition[light] = worldLightPosition; 356 } 357 setAmbientMaterialSource(MaterialSource ambientMaterialSource)358 void Context::setAmbientMaterialSource(MaterialSource ambientMaterialSource) 359 { 360 Context::ambientMaterialSource = ambientMaterialSource; 361 } 362 setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)363 void Context::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource) 364 { 365 Context::diffuseMaterialSource = diffuseMaterialSource; 366 } 367 setSpecularMaterialSource(MaterialSource specularMaterialSource)368 void Context::setSpecularMaterialSource(MaterialSource specularMaterialSource) 369 { 370 Context::specularMaterialSource = specularMaterialSource; 371 } 372 setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)373 void Context::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource) 374 { 375 Context::emissiveMaterialSource = emissiveMaterialSource; 376 } 377 setPointSpriteEnable(bool pointSpriteEnable)378 void Context::setPointSpriteEnable(bool pointSpriteEnable) 379 { 380 Context::pointSpriteEnable = pointSpriteEnable; 381 } 382 setPointScaleEnable(bool pointScaleEnable)383 void Context::setPointScaleEnable(bool pointScaleEnable) 384 { 385 Context::pointScaleEnable = pointScaleEnable; 386 } 387 setDepthBufferEnable(bool depthBufferEnable)388 bool Context::setDepthBufferEnable(bool depthBufferEnable) 389 { 390 bool modified = (Context::depthBufferEnable != depthBufferEnable); 391 Context::depthBufferEnable = depthBufferEnable; 392 return modified; 393 } 394 setAlphaBlendEnable(bool alphaBlendEnable)395 bool Context::setAlphaBlendEnable(bool alphaBlendEnable) 396 { 397 bool modified = (Context::alphaBlendEnable != alphaBlendEnable); 398 Context::alphaBlendEnable = alphaBlendEnable; 399 return modified; 400 } 401 setSourceBlendFactor(BlendFactor sourceBlendFactor)402 bool Context::setSourceBlendFactor(BlendFactor sourceBlendFactor) 403 { 404 bool modified = (Context::sourceBlendFactorState != sourceBlendFactor); 405 Context::sourceBlendFactorState = sourceBlendFactor; 406 return modified; 407 } 408 setDestBlendFactor(BlendFactor destBlendFactor)409 bool Context::setDestBlendFactor(BlendFactor destBlendFactor) 410 { 411 bool modified = (Context::destBlendFactorState != destBlendFactor); 412 Context::destBlendFactorState = destBlendFactor; 413 return modified; 414 } 415 setBlendOperation(BlendOperation blendOperation)416 bool Context::setBlendOperation(BlendOperation blendOperation) 417 { 418 bool modified = (Context::blendOperationState != blendOperation); 419 Context::blendOperationState = blendOperation; 420 return modified; 421 } 422 setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)423 bool Context::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable) 424 { 425 bool modified = (Context::separateAlphaBlendEnable != separateAlphaBlendEnable); 426 Context::separateAlphaBlendEnable = separateAlphaBlendEnable; 427 return modified; 428 } 429 setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)430 bool Context::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha) 431 { 432 bool modified = (Context::sourceBlendFactorStateAlpha != sourceBlendFactorAlpha); 433 Context::sourceBlendFactorStateAlpha = sourceBlendFactorAlpha; 434 return modified; 435 } 436 setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)437 bool Context::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha) 438 { 439 bool modified = (Context::destBlendFactorStateAlpha != destBlendFactorAlpha); 440 Context::destBlendFactorStateAlpha = destBlendFactorAlpha; 441 return modified; 442 } 443 setBlendOperationAlpha(BlendOperation blendOperationAlpha)444 bool Context::setBlendOperationAlpha(BlendOperation blendOperationAlpha) 445 { 446 bool modified = (Context::blendOperationStateAlpha != blendOperationAlpha); 447 Context::blendOperationStateAlpha = blendOperationAlpha; 448 return modified; 449 } 450 setColorWriteMask(int index,int colorWriteMask)451 bool Context::setColorWriteMask(int index, int colorWriteMask) 452 { 453 bool modified = (Context::colorWriteMask[index] != colorWriteMask); 454 Context::colorWriteMask[index] = colorWriteMask; 455 return modified; 456 } 457 setWriteSRGB(bool sRGB)458 bool Context::setWriteSRGB(bool sRGB) 459 { 460 bool modified = (Context::writeSRGB != sRGB); 461 Context::writeSRGB = sRGB; 462 return modified; 463 } 464 setColorLogicOpEnabled(bool enabled)465 bool Context::setColorLogicOpEnabled(bool enabled) 466 { 467 bool modified = (Context::colorLogicOpEnabled != enabled); 468 Context::colorLogicOpEnabled = enabled; 469 return modified; 470 } 471 setLogicalOperation(LogicalOperation logicalOperation)472 bool Context::setLogicalOperation(LogicalOperation logicalOperation) 473 { 474 bool modified = (Context::logicalOperation != logicalOperation); 475 Context::logicalOperation = logicalOperation; 476 return modified; 477 } 478 setColorVertexEnable(bool colorVertexEnable)479 void Context::setColorVertexEnable(bool colorVertexEnable) 480 { 481 Context::colorVertexEnable = colorVertexEnable; 482 } 483 fogActive()484 bool Context::fogActive() 485 { 486 if(!colorUsed()) return false; 487 488 if(pixelShaderModel() >= 0x0300) return false; 489 490 return fogEnable; 491 } 492 pointSizeActive()493 bool Context::pointSizeActive() 494 { 495 if(vertexShader) 496 { 497 return false; 498 } 499 500 return isDrawPoint(true) && (input[PointSize] || (!preTransformed && pointScaleActive())); 501 } 502 pixelFogActive()503 FogMode Context::pixelFogActive() 504 { 505 if(fogActive()) 506 { 507 return pixelFogMode; 508 } 509 510 return FOG_NONE; 511 } 512 depthWriteActive()513 bool Context::depthWriteActive() 514 { 515 if(!depthBufferActive()) return false; 516 517 return depthWriteEnable; 518 } 519 alphaTestActive()520 bool Context::alphaTestActive() 521 { 522 if(transparencyAntialiasing != TRANSPARENCY_NONE) return true; 523 if(!alphaTestEnable) return false; 524 if(alphaCompareMode == ALPHA_ALWAYS) return false; 525 if(alphaReference == 0.0f && alphaCompareMode == ALPHA_GREATEREQUAL) return false; 526 527 return true; 528 } 529 depthBufferActive()530 bool Context::depthBufferActive() 531 { 532 return depthBuffer && depthBufferEnable; 533 } 534 stencilActive()535 bool Context::stencilActive() 536 { 537 return stencilBuffer && stencilEnable; 538 } 539 vertexLightingActive()540 bool Context::vertexLightingActive() 541 { 542 if(vertexShader) 543 { 544 return false; 545 } 546 547 return lightingEnable && !preTransformed; 548 } 549 texCoordActive(int coordinate,int component)550 bool Context::texCoordActive(int coordinate, int component) 551 { 552 bool hasTexture = pointSpriteActive(); 553 554 if(vertexShader) 555 { 556 if(!preTransformed) 557 { 558 if(vertexShader->getOutput(T0 + coordinate, component).usage == Shader::USAGE_TEXCOORD) 559 { 560 hasTexture = true; 561 } 562 } 563 else 564 { 565 hasTexture = true; // FIXME: Check vertex buffer streams 566 } 567 } 568 else 569 { 570 switch(texGen[coordinate]) 571 { 572 case TEXGEN_NONE: 573 hasTexture = true; 574 break; 575 case TEXGEN_PASSTHRU: 576 hasTexture = hasTexture || (component < input[TexCoord0 + textureStage[coordinate].texCoordIndex].count); 577 break; 578 case TEXGEN_NORMAL: 579 hasTexture = hasTexture || (component <= 2); 580 break; 581 case TEXGEN_POSITION: 582 hasTexture = hasTexture || (component <= 2); 583 break; 584 case TEXGEN_REFLECTION: 585 hasTexture = hasTexture || (component <= 2); 586 break; 587 case TEXGEN_SPHEREMAP: 588 hasTexture = hasTexture || (component <= 1); 589 break; 590 default: 591 ASSERT(false); 592 } 593 } 594 595 bool project = isProjectionComponent(coordinate, component); 596 bool usesTexture = false; 597 598 if(pixelShader) 599 { 600 usesTexture = pixelShader->usesTexture(coordinate, component) || project; 601 } 602 else 603 { 604 usesTexture = textureStage[coordinate].usesTexture() || project; 605 } 606 607 return hasTexture && usesTexture; 608 } 609 texCoordActive(int coordinate)610 bool Context::texCoordActive(int coordinate) 611 { 612 return texCoordActive(coordinate, 0) || 613 texCoordActive(coordinate, 1) || 614 texCoordActive(coordinate, 2) || 615 texCoordActive(coordinate, 3); 616 } 617 isProjectionComponent(unsigned int coordinate,int component)618 bool Context::isProjectionComponent(unsigned int coordinate, int component) 619 { 620 if(pixelShaderModel() <= 0x0103 && coordinate < 8 && textureTransformProject[coordinate]) 621 { 622 if(textureTransformCount[coordinate] == 2) 623 { 624 if(component == 1) return true; 625 } 626 else if(textureTransformCount[coordinate] == 3) 627 { 628 if(component == 2) return true; 629 } 630 else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0) 631 { 632 if(component == 3) return true; 633 } 634 } 635 636 return false; 637 } 638 vertexSpecularActive()639 bool Context::vertexSpecularActive() 640 { 641 return vertexLightingActive() && specularEnable && vertexNormalActive(); 642 } 643 vertexNormalActive()644 bool Context::vertexNormalActive() 645 { 646 if(vertexShader) 647 { 648 return false; 649 } 650 651 return input[Normal]; 652 } 653 vertexLightActive(int i)654 bool Context::vertexLightActive(int i) 655 { 656 if(vertexShader) 657 { 658 return false; 659 } 660 661 return lightingEnable && lightEnable[i]; 662 } 663 vertexDiffuseMaterialSourceActive()664 MaterialSource Context::vertexDiffuseMaterialSourceActive() 665 { 666 if(vertexShader) 667 { 668 return MATERIAL_MATERIAL; 669 } 670 671 if(diffuseMaterialSource == MATERIAL_MATERIAL || !colorVertexEnable || 672 (diffuseMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 673 (diffuseMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 674 { 675 return MATERIAL_MATERIAL; 676 } 677 678 return diffuseMaterialSource; 679 } 680 vertexSpecularMaterialSourceActive()681 MaterialSource Context::vertexSpecularMaterialSourceActive() 682 { 683 if(vertexShader) 684 { 685 return MATERIAL_MATERIAL; 686 } 687 688 if(!colorVertexEnable || 689 (specularMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 690 (specularMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 691 { 692 return MATERIAL_MATERIAL; 693 } 694 695 return specularMaterialSource; 696 } 697 vertexAmbientMaterialSourceActive()698 MaterialSource Context::vertexAmbientMaterialSourceActive() 699 { 700 if(vertexShader) 701 { 702 return MATERIAL_MATERIAL; 703 } 704 705 if(!colorVertexEnable || 706 (ambientMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 707 (ambientMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 708 { 709 return MATERIAL_MATERIAL; 710 } 711 712 return ambientMaterialSource; 713 } 714 vertexEmissiveMaterialSourceActive()715 MaterialSource Context::vertexEmissiveMaterialSourceActive() 716 { 717 if(vertexShader) 718 { 719 return MATERIAL_MATERIAL; 720 } 721 722 if(!colorVertexEnable || 723 (emissiveMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 724 (emissiveMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 725 { 726 return MATERIAL_MATERIAL; 727 } 728 729 return emissiveMaterialSource; 730 } 731 pointSpriteActive()732 bool Context::pointSpriteActive() 733 { 734 return isDrawPoint(true) && pointSpriteEnable; 735 } 736 pointScaleActive()737 bool Context::pointScaleActive() 738 { 739 if(vertexShader) 740 { 741 return false; 742 } 743 744 return isDrawPoint(true) && pointScaleEnable; 745 } 746 alphaBlendActive()747 bool Context::alphaBlendActive() 748 { 749 if(!alphaBlendEnable) 750 { 751 return false; 752 } 753 754 if(!colorUsed()) 755 { 756 return false; 757 } 758 759 bool colorBlend = !(blendOperation() == BLENDOP_SOURCE && sourceBlendFactor() == BLEND_ONE); 760 bool alphaBlend = separateAlphaBlendEnable ? !(blendOperationAlpha() == BLENDOP_SOURCE && sourceBlendFactorAlpha() == BLEND_ONE) : colorBlend; 761 762 return colorBlend || alphaBlend; 763 } 764 colorLogicOp()765 LogicalOperation Context::colorLogicOp() 766 { 767 return colorLogicOpEnabled ? logicalOperation : LOGICALOP_COPY; 768 } 769 sourceBlendFactor()770 BlendFactor Context::sourceBlendFactor() 771 { 772 if(!alphaBlendEnable) return BLEND_ONE; 773 774 switch(blendOperationState) 775 { 776 case BLENDOP_ADD: 777 case BLENDOP_SUB: 778 case BLENDOP_INVSUB: 779 return sourceBlendFactorState; 780 case BLENDOP_MIN: 781 return BLEND_ONE; 782 case BLENDOP_MAX: 783 return BLEND_ONE; 784 default: 785 ASSERT(false); 786 } 787 788 return sourceBlendFactorState; 789 } 790 destBlendFactor()791 BlendFactor Context::destBlendFactor() 792 { 793 if(!alphaBlendEnable) return BLEND_ZERO; 794 795 switch(blendOperationState) 796 { 797 case BLENDOP_ADD: 798 case BLENDOP_SUB: 799 case BLENDOP_INVSUB: 800 return destBlendFactorState; 801 case BLENDOP_MIN: 802 return BLEND_ONE; 803 case BLENDOP_MAX: 804 return BLEND_ONE; 805 default: 806 ASSERT(false); 807 } 808 809 return destBlendFactorState; 810 } 811 blendOperation()812 BlendOperation Context::blendOperation() 813 { 814 if(!alphaBlendEnable) return BLENDOP_SOURCE; 815 816 switch(blendOperationState) 817 { 818 case BLENDOP_ADD: 819 if(sourceBlendFactor() == BLEND_ZERO) 820 { 821 if(destBlendFactor() == BLEND_ZERO) 822 { 823 return BLENDOP_NULL; 824 } 825 else 826 { 827 return BLENDOP_DEST; 828 } 829 } 830 else if(sourceBlendFactor() == BLEND_ONE) 831 { 832 if(destBlendFactor() == BLEND_ZERO) 833 { 834 return BLENDOP_SOURCE; 835 } 836 else 837 { 838 return BLENDOP_ADD; 839 } 840 } 841 else 842 { 843 if(destBlendFactor() == BLEND_ZERO) 844 { 845 return BLENDOP_SOURCE; 846 } 847 else 848 { 849 return BLENDOP_ADD; 850 } 851 } 852 case BLENDOP_SUB: 853 if(sourceBlendFactor() == BLEND_ZERO) 854 { 855 return BLENDOP_NULL; // Negative, clamped to zero 856 } 857 else if(sourceBlendFactor() == BLEND_ONE) 858 { 859 if(destBlendFactor() == BLEND_ZERO) 860 { 861 return BLENDOP_SOURCE; 862 } 863 else 864 { 865 return BLENDOP_SUB; 866 } 867 } 868 else 869 { 870 if(destBlendFactor() == BLEND_ZERO) 871 { 872 return BLENDOP_SOURCE; 873 } 874 else 875 { 876 return BLENDOP_SUB; 877 } 878 } 879 case BLENDOP_INVSUB: 880 if(sourceBlendFactor() == BLEND_ZERO) 881 { 882 if(destBlendFactor() == BLEND_ZERO) 883 { 884 return BLENDOP_NULL; 885 } 886 else 887 { 888 return BLENDOP_DEST; 889 } 890 } 891 else if(sourceBlendFactor() == BLEND_ONE) 892 { 893 if(destBlendFactor() == BLEND_ZERO) 894 { 895 return BLENDOP_NULL; // Negative, clamped to zero 896 } 897 else 898 { 899 return BLENDOP_INVSUB; 900 } 901 } 902 else 903 { 904 if(destBlendFactor() == BLEND_ZERO) 905 { 906 return BLENDOP_NULL; // Negative, clamped to zero 907 } 908 else 909 { 910 return BLENDOP_INVSUB; 911 } 912 } 913 case BLENDOP_MIN: 914 return BLENDOP_MIN; 915 case BLENDOP_MAX: 916 return BLENDOP_MAX; 917 default: 918 ASSERT(false); 919 } 920 921 return blendOperationState; 922 } 923 sourceBlendFactorAlpha()924 BlendFactor Context::sourceBlendFactorAlpha() 925 { 926 if(!separateAlphaBlendEnable) 927 { 928 return sourceBlendFactor(); 929 } 930 else 931 { 932 switch(blendOperationStateAlpha) 933 { 934 case BLENDOP_ADD: 935 case BLENDOP_SUB: 936 case BLENDOP_INVSUB: 937 return sourceBlendFactorStateAlpha; 938 case BLENDOP_MIN: 939 return BLEND_ONE; 940 case BLENDOP_MAX: 941 return BLEND_ONE; 942 default: 943 ASSERT(false); 944 } 945 946 return sourceBlendFactorStateAlpha; 947 } 948 } 949 destBlendFactorAlpha()950 BlendFactor Context::destBlendFactorAlpha() 951 { 952 if(!separateAlphaBlendEnable) 953 { 954 return destBlendFactor(); 955 } 956 else 957 { 958 switch(blendOperationStateAlpha) 959 { 960 case BLENDOP_ADD: 961 case BLENDOP_SUB: 962 case BLENDOP_INVSUB: 963 return destBlendFactorStateAlpha; 964 case BLENDOP_MIN: 965 return BLEND_ONE; 966 case BLENDOP_MAX: 967 return BLEND_ONE; 968 default: 969 ASSERT(false); 970 } 971 972 return destBlendFactorStateAlpha; 973 } 974 } 975 blendOperationAlpha()976 BlendOperation Context::blendOperationAlpha() 977 { 978 if(!separateAlphaBlendEnable) 979 { 980 return blendOperation(); 981 } 982 else 983 { 984 switch(blendOperationStateAlpha) 985 { 986 case BLENDOP_ADD: 987 if(sourceBlendFactorAlpha() == BLEND_ZERO) 988 { 989 if(destBlendFactorAlpha() == BLEND_ZERO) 990 { 991 return BLENDOP_NULL; 992 } 993 else 994 { 995 return BLENDOP_DEST; 996 } 997 } 998 else if(sourceBlendFactorAlpha() == BLEND_ONE) 999 { 1000 if(destBlendFactorAlpha() == BLEND_ZERO) 1001 { 1002 return BLENDOP_SOURCE; 1003 } 1004 else 1005 { 1006 return BLENDOP_ADD; 1007 } 1008 } 1009 else 1010 { 1011 if(destBlendFactorAlpha() == BLEND_ZERO) 1012 { 1013 return BLENDOP_SOURCE; 1014 } 1015 else 1016 { 1017 return BLENDOP_ADD; 1018 } 1019 } 1020 case BLENDOP_SUB: 1021 if(sourceBlendFactorAlpha() == BLEND_ZERO) 1022 { 1023 return BLENDOP_NULL; // Negative, clamped to zero 1024 } 1025 else if(sourceBlendFactorAlpha() == BLEND_ONE) 1026 { 1027 if(destBlendFactorAlpha() == BLEND_ZERO) 1028 { 1029 return BLENDOP_SOURCE; 1030 } 1031 else 1032 { 1033 return BLENDOP_SUB; 1034 } 1035 } 1036 else 1037 { 1038 if(destBlendFactorAlpha() == BLEND_ZERO) 1039 { 1040 return BLENDOP_SOURCE; 1041 } 1042 else 1043 { 1044 return BLENDOP_SUB; 1045 } 1046 } 1047 case BLENDOP_INVSUB: 1048 if(sourceBlendFactorAlpha() == BLEND_ZERO) 1049 { 1050 if(destBlendFactorAlpha() == BLEND_ZERO) 1051 { 1052 return BLENDOP_NULL; 1053 } 1054 else 1055 { 1056 return BLENDOP_DEST; 1057 } 1058 } 1059 else if(sourceBlendFactorAlpha() == BLEND_ONE) 1060 { 1061 if(destBlendFactorAlpha() == BLEND_ZERO) 1062 { 1063 return BLENDOP_NULL; // Negative, clamped to zero 1064 } 1065 else 1066 { 1067 return BLENDOP_INVSUB; 1068 } 1069 } 1070 else 1071 { 1072 if(destBlendFactorAlpha() == BLEND_ZERO) 1073 { 1074 return BLENDOP_NULL; // Negative, clamped to zero 1075 } 1076 else 1077 { 1078 return BLENDOP_INVSUB; 1079 } 1080 } 1081 case BLENDOP_MIN: 1082 return BLENDOP_MIN; 1083 case BLENDOP_MAX: 1084 return BLENDOP_MAX; 1085 default: 1086 ASSERT(false); 1087 } 1088 1089 return blendOperationStateAlpha; 1090 } 1091 } 1092 indexedVertexBlendActive()1093 bool Context::indexedVertexBlendActive() 1094 { 1095 if(vertexShader) 1096 { 1097 return false; 1098 } 1099 1100 return indexedVertexBlendEnable; 1101 } 1102 vertexBlendMatrixCountActive()1103 int Context::vertexBlendMatrixCountActive() 1104 { 1105 if(vertexShader) 1106 { 1107 return 0; 1108 } 1109 1110 return vertexBlendMatrixCount; 1111 } 1112 localViewerActive()1113 bool Context::localViewerActive() 1114 { 1115 if(vertexShader) 1116 { 1117 return false; 1118 } 1119 1120 return localViewer; 1121 } 1122 normalizeNormalsActive()1123 bool Context::normalizeNormalsActive() 1124 { 1125 if(vertexShader) 1126 { 1127 return false; 1128 } 1129 1130 return normalizeNormals; 1131 } 1132 vertexFogModeActive()1133 FogMode Context::vertexFogModeActive() 1134 { 1135 if(vertexShader || !fogActive()) 1136 { 1137 return FOG_NONE; 1138 } 1139 1140 return vertexFogMode; 1141 } 1142 rangeFogActive()1143 bool Context::rangeFogActive() 1144 { 1145 if(vertexShader || !fogActive()) 1146 { 1147 return false; 1148 } 1149 1150 return rangeFogEnable; 1151 } 1152 texGenActive(int stage)1153 TexGen Context::texGenActive(int stage) 1154 { 1155 if(vertexShader || !texCoordActive(stage)) 1156 { 1157 return TEXGEN_PASSTHRU; 1158 } 1159 1160 return texGen[stage]; 1161 } 1162 textureTransformCountActive(int stage)1163 int Context::textureTransformCountActive(int stage) 1164 { 1165 if(vertexShader || !texCoordActive(stage)) 1166 { 1167 return 0; 1168 } 1169 1170 return textureTransformCount[stage]; 1171 } 1172 texCoordIndexActive(int stage)1173 int Context::texCoordIndexActive(int stage) 1174 { 1175 if(vertexShader || !texCoordActive(stage)) 1176 { 1177 return stage; 1178 } 1179 1180 return textureStage[stage].texCoordIndex; 1181 } 1182 perspectiveActive()1183 bool Context::perspectiveActive() 1184 { 1185 if(!colorUsed()) 1186 { 1187 return false; 1188 } 1189 1190 if(!perspectiveCorrection) 1191 { 1192 return false; 1193 } 1194 1195 if(isDrawPoint(true)) 1196 { 1197 return false; 1198 } 1199 1200 return true; 1201 } 1202 diffuseUsed()1203 bool Context::diffuseUsed() 1204 { 1205 return diffuseUsed(0) || diffuseUsed(1) || diffuseUsed(2) || diffuseUsed(3); 1206 } 1207 diffuseUsed(int component)1208 bool Context::diffuseUsed(int component) 1209 { 1210 if(!colorUsed()) 1211 { 1212 return false; 1213 } 1214 1215 if(pixelShader) 1216 { 1217 return pixelShader->usesDiffuse(component); 1218 } 1219 1220 // Directly using the diffuse input color 1221 for(int i = 0; i < 8; i++) 1222 { 1223 if(textureStage[i].isStageDisabled()) 1224 { 1225 break; 1226 } 1227 1228 if(textureStage[i].usesDiffuse()) 1229 { 1230 return true; 1231 } 1232 } 1233 1234 // Using the current color (initialized to diffuse) before it's overwritten 1235 for(int i = 0; i < 8; i++) 1236 { 1237 if(textureStage[i].usesCurrent() || textureStage[i].isStageDisabled()) // Current color contains diffuse before being overwritten 1238 { 1239 return true; 1240 } 1241 1242 if(textureStage[i].writesCurrent()) 1243 { 1244 return false; 1245 } 1246 } 1247 1248 return true; 1249 } 1250 diffuseActive()1251 bool Context::diffuseActive() 1252 { 1253 return diffuseActive(0) || diffuseActive(1) || diffuseActive(2) || diffuseActive(3); 1254 } 1255 diffuseActive(int component)1256 bool Context::diffuseActive(int component) 1257 { 1258 if(!colorUsed()) 1259 { 1260 return false; 1261 } 1262 1263 // Vertex processor provides diffuse component 1264 bool vertexDiffuse; 1265 1266 if(vertexShader) 1267 { 1268 vertexDiffuse = vertexShader->getOutput(C0, component).active(); 1269 } 1270 else if(!preTransformed) 1271 { 1272 vertexDiffuse = input[Color0] || lightingEnable; 1273 } 1274 else 1275 { 1276 vertexDiffuse = input[Color0]; 1277 } 1278 1279 // Pixel processor requires diffuse component 1280 bool pixelDiffuse = diffuseUsed(component); 1281 1282 return vertexDiffuse && pixelDiffuse; 1283 } 1284 specularUsed()1285 bool Context::specularUsed() 1286 { 1287 return Context::specularUsed(0) || Context::specularUsed(1) || Context::specularUsed(2) || Context::specularUsed(3); 1288 } 1289 specularUsed(int component)1290 bool Context::specularUsed(int component) 1291 { 1292 if(!colorUsed()) 1293 { 1294 return false; 1295 } 1296 1297 if(pixelShader) 1298 { 1299 return pixelShader->usesSpecular(component); 1300 } 1301 1302 bool pixelSpecular = specularEnable; 1303 1304 for(int i = 0; i < 8; i++) 1305 { 1306 if(textureStage[i].isStageDisabled()) break; 1307 1308 pixelSpecular = pixelSpecular || textureStage[i].usesSpecular(); 1309 } 1310 1311 return pixelSpecular; 1312 } 1313 specularActive()1314 bool Context::specularActive() 1315 { 1316 return specularActive(0) || specularActive(1) || specularActive(2) || specularActive(3); 1317 } 1318 specularActive(int component)1319 bool Context::specularActive(int component) 1320 { 1321 if(!colorUsed()) 1322 { 1323 return false; 1324 } 1325 1326 // Vertex processor provides specular component 1327 bool vertexSpecular; 1328 1329 if(!vertexShader) 1330 { 1331 vertexSpecular = input[Color1] || (lightingEnable && specularEnable); 1332 } 1333 else 1334 { 1335 vertexSpecular = vertexShader->getOutput(C1, component).active(); 1336 } 1337 1338 // Pixel processor requires specular component 1339 bool pixelSpecular = specularUsed(component); 1340 1341 return vertexSpecular && pixelSpecular; 1342 } 1343 colorActive(int color,int component)1344 bool Context::colorActive(int color, int component) 1345 { 1346 if(color == 0) 1347 { 1348 return diffuseActive(component); 1349 } 1350 else 1351 { 1352 return specularActive(component); 1353 } 1354 } 1355 textureActive()1356 bool Context::textureActive() 1357 { 1358 for(int i = 0; i < 8; i++) 1359 { 1360 if(textureActive(i)) 1361 { 1362 return true; 1363 } 1364 } 1365 1366 return false; 1367 } 1368 textureActive(int coordinate)1369 bool Context::textureActive(int coordinate) 1370 { 1371 return textureActive(coordinate, 0) || textureActive(coordinate, 1) || textureActive(coordinate, 2) || textureActive(coordinate, 3); 1372 } 1373 textureActive(int coordinate,int component)1374 bool Context::textureActive(int coordinate, int component) 1375 { 1376 if(!colorUsed()) 1377 { 1378 return false; 1379 } 1380 1381 if(!texCoordActive(coordinate, component)) 1382 { 1383 return false; 1384 } 1385 1386 if(textureTransformProject[coordinate] && pixelShaderModel() <= 0x0103) 1387 { 1388 if(textureTransformCount[coordinate] == 2) 1389 { 1390 if(component == 1) return true; 1391 } 1392 else if(textureTransformCount[coordinate] == 3) 1393 { 1394 if(component == 2) return true; 1395 } 1396 else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0) 1397 { 1398 if(component == 3) return true; 1399 } 1400 } 1401 1402 if(!pixelShader) 1403 { 1404 bool texture = textureStage[coordinate].usesTexture(); 1405 bool cube = sampler[coordinate].hasCubeTexture(); 1406 bool volume = sampler[coordinate].hasVolumeTexture(); 1407 1408 if(texture) 1409 { 1410 for(int i = coordinate; i >= 0; i--) 1411 { 1412 if(textureStage[i].stageOperation == TextureStage::STAGE_DISABLE) 1413 { 1414 return false; 1415 } 1416 } 1417 } 1418 1419 switch(component) 1420 { 1421 case 0: 1422 return texture; 1423 case 1: 1424 return texture; 1425 case 2: 1426 return (texture && (cube || volume)); 1427 case 3: 1428 return false; 1429 } 1430 } 1431 else 1432 { 1433 return pixelShader->usesTexture(coordinate, component); 1434 } 1435 1436 return false; 1437 } 1438 pixelShaderModel() const1439 unsigned short Context::pixelShaderModel() const 1440 { 1441 return pixelShader ? pixelShader->getShaderModel() : 0x0000; 1442 } 1443 vertexShaderModel() const1444 unsigned short Context::vertexShaderModel() const 1445 { 1446 return vertexShader ? vertexShader->getShaderModel() : 0x0000; 1447 } 1448 getMultiSampleCount() const1449 int Context::getMultiSampleCount() const 1450 { 1451 return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1; 1452 } 1453 getSuperSampleCount() const1454 int Context::getSuperSampleCount() const 1455 { 1456 return renderTarget[0] ? renderTarget[0]->getSuperSampleCount() : 1; 1457 } 1458 renderTargetInternalFormat(int index)1459 Format Context::renderTargetInternalFormat(int index) 1460 { 1461 if(renderTarget[index]) 1462 { 1463 return renderTarget[index]->getInternalFormat(); 1464 } 1465 else 1466 { 1467 return FORMAT_NULL; 1468 } 1469 } 1470 colorWriteActive()1471 int Context::colorWriteActive() 1472 { 1473 return colorWriteActive(0) | colorWriteActive(1) | colorWriteActive(2) | colorWriteActive(3); 1474 } 1475 colorWriteActive(int index)1476 int Context::colorWriteActive(int index) 1477 { 1478 if(!renderTarget[index] || renderTarget[index]->getInternalFormat() == FORMAT_NULL) 1479 { 1480 return 0; 1481 } 1482 1483 if(blendOperation() == BLENDOP_DEST && destBlendFactor() == BLEND_ONE && 1484 (!separateAlphaBlendEnable || (blendOperationAlpha() == BLENDOP_DEST && destBlendFactorAlpha() == BLEND_ONE))) 1485 { 1486 return 0; 1487 } 1488 1489 return colorWriteMask[index]; 1490 } 1491 colorUsed()1492 bool Context::colorUsed() 1493 { 1494 return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->containsKill()); 1495 } 1496 } 1497