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