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 "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 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(transparencyAntialiasing != TRANSPARENCY_NONE) return true; 519 if(!alphaTestEnable) return false; 520 if(alphaCompareMode == ALPHA_ALWAYS) return false; 521 if(alphaReference == 0.0f && alphaCompareMode == ALPHA_GREATEREQUAL) return false; 522 523 return true; 524 } 525 depthBufferActive()526 bool Context::depthBufferActive() 527 { 528 return depthBuffer && depthBufferEnable; 529 } 530 stencilActive()531 bool Context::stencilActive() 532 { 533 return stencilBuffer && stencilEnable; 534 } 535 vertexLightingActive()536 bool Context::vertexLightingActive() 537 { 538 if(vertexShader) 539 { 540 return false; 541 } 542 543 return lightingEnable && !preTransformed; 544 } 545 texCoordActive(int coordinate,int component)546 bool Context::texCoordActive(int coordinate, int component) 547 { 548 bool hasTexture = pointSpriteActive(); 549 550 if(vertexShader) 551 { 552 if(!preTransformed) 553 { 554 if(vertexShader->getOutput(T0 + coordinate, component).usage == Shader::USAGE_TEXCOORD) 555 { 556 hasTexture = true; 557 } 558 } 559 else 560 { 561 hasTexture = true; // FIXME: Check vertex buffer streams 562 } 563 } 564 else 565 { 566 switch(texGen[coordinate]) 567 { 568 case TEXGEN_NONE: 569 hasTexture = true; 570 break; 571 case TEXGEN_PASSTHRU: 572 hasTexture = hasTexture || (component < input[TexCoord0 + textureStage[coordinate].texCoordIndex].count); 573 break; 574 case TEXGEN_NORMAL: 575 hasTexture = hasTexture || (component <= 2); 576 break; 577 case TEXGEN_POSITION: 578 hasTexture = hasTexture || (component <= 2); 579 break; 580 case TEXGEN_REFLECTION: 581 hasTexture = hasTexture || (component <= 2); 582 break; 583 case TEXGEN_SPHEREMAP: 584 hasTexture = hasTexture || (component <= 1); 585 break; 586 default: 587 ASSERT(false); 588 } 589 } 590 591 bool project = isProjectionComponent(coordinate, component); 592 bool usesTexture = false; 593 594 if(pixelShader) 595 { 596 usesTexture = pixelShader->usesTexture(coordinate, component) || project; 597 } 598 else 599 { 600 usesTexture = textureStage[coordinate].usesTexture() || project; 601 } 602 603 return hasTexture && usesTexture; 604 } 605 texCoordActive(int coordinate)606 bool Context::texCoordActive(int coordinate) 607 { 608 return texCoordActive(coordinate, 0) || 609 texCoordActive(coordinate, 1) || 610 texCoordActive(coordinate, 2) || 611 texCoordActive(coordinate, 3); 612 } 613 isProjectionComponent(unsigned int coordinate,int component)614 bool Context::isProjectionComponent(unsigned int coordinate, int component) 615 { 616 if(pixelShaderVersion() <= 0x0103 && coordinate < 8 && textureTransformProject[coordinate]) 617 { 618 if(textureTransformCount[coordinate] == 2) 619 { 620 if(component == 1) return true; 621 } 622 else if(textureTransformCount[coordinate] == 3) 623 { 624 if(component == 2) return true; 625 } 626 else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0) 627 { 628 if(component == 3) return true; 629 } 630 } 631 632 return false; 633 } 634 vertexSpecularActive()635 bool Context::vertexSpecularActive() 636 { 637 return vertexLightingActive() && specularEnable && vertexNormalActive(); 638 } 639 vertexNormalActive()640 bool Context::vertexNormalActive() 641 { 642 if(vertexShader) 643 { 644 return false; 645 } 646 647 return input[Normal]; 648 } 649 vertexLightActive(int i)650 bool Context::vertexLightActive(int i) 651 { 652 if(vertexShader) 653 { 654 return false; 655 } 656 657 return lightingEnable && lightEnable[i]; 658 } 659 vertexDiffuseMaterialSourceActive()660 MaterialSource Context::vertexDiffuseMaterialSourceActive() 661 { 662 if(vertexShader) 663 { 664 return MATERIAL_MATERIAL; 665 } 666 667 if(diffuseMaterialSource == MATERIAL_MATERIAL || !colorVertexEnable || 668 (diffuseMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 669 (diffuseMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 670 { 671 return MATERIAL_MATERIAL; 672 } 673 674 return diffuseMaterialSource; 675 } 676 vertexSpecularMaterialSourceActive()677 MaterialSource Context::vertexSpecularMaterialSourceActive() 678 { 679 if(vertexShader) 680 { 681 return MATERIAL_MATERIAL; 682 } 683 684 if(!colorVertexEnable || 685 (specularMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 686 (specularMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 687 { 688 return MATERIAL_MATERIAL; 689 } 690 691 return specularMaterialSource; 692 } 693 vertexAmbientMaterialSourceActive()694 MaterialSource Context::vertexAmbientMaterialSourceActive() 695 { 696 if(vertexShader) 697 { 698 return MATERIAL_MATERIAL; 699 } 700 701 if(!colorVertexEnable || 702 (ambientMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 703 (ambientMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 704 { 705 return MATERIAL_MATERIAL; 706 } 707 708 return ambientMaterialSource; 709 } 710 vertexEmissiveMaterialSourceActive()711 MaterialSource Context::vertexEmissiveMaterialSourceActive() 712 { 713 if(vertexShader) 714 { 715 return MATERIAL_MATERIAL; 716 } 717 718 if(!colorVertexEnable || 719 (emissiveMaterialSource == MATERIAL_COLOR1 && !input[Color0]) || 720 (emissiveMaterialSource == MATERIAL_COLOR2 && !input[Color1])) 721 { 722 return MATERIAL_MATERIAL; 723 } 724 725 return emissiveMaterialSource; 726 } 727 pointSpriteActive()728 bool Context::pointSpriteActive() 729 { 730 return isDrawPoint(true) && pointSpriteEnable; 731 } 732 pointScaleActive()733 bool Context::pointScaleActive() 734 { 735 if(vertexShader) 736 { 737 return false; 738 } 739 740 return isDrawPoint(true) && pointScaleEnable; 741 } 742 alphaBlendActive()743 bool Context::alphaBlendActive() 744 { 745 if(!alphaBlendEnable) 746 { 747 return false; 748 } 749 750 if(!colorUsed()) 751 { 752 return false; 753 } 754 755 bool colorBlend = !(blendOperation() == BLENDOP_SOURCE && sourceBlendFactor() == BLEND_ONE); 756 bool alphaBlend = separateAlphaBlendEnable ? !(blendOperationAlpha() == BLENDOP_SOURCE && sourceBlendFactorAlpha() == BLEND_ONE) : colorBlend; 757 758 return colorBlend || alphaBlend; 759 } 760 colorLogicOp()761 LogicalOperation Context::colorLogicOp() 762 { 763 return colorLogicOpEnabled ? logicalOperation : LOGICALOP_COPY; 764 } 765 sourceBlendFactor()766 BlendFactor Context::sourceBlendFactor() 767 { 768 if(!alphaBlendEnable) return BLEND_ONE; 769 770 switch(blendOperationState) 771 { 772 case BLENDOP_ADD: 773 case BLENDOP_SUB: 774 case BLENDOP_INVSUB: 775 return sourceBlendFactorState; 776 case BLENDOP_MIN: 777 return BLEND_ONE; 778 case BLENDOP_MAX: 779 return BLEND_ONE; 780 default: 781 ASSERT(false); 782 } 783 784 return sourceBlendFactorState; 785 } 786 destBlendFactor()787 BlendFactor Context::destBlendFactor() 788 { 789 if(!alphaBlendEnable) return BLEND_ZERO; 790 791 switch(blendOperationState) 792 { 793 case BLENDOP_ADD: 794 case BLENDOP_SUB: 795 case BLENDOP_INVSUB: 796 return destBlendFactorState; 797 case BLENDOP_MIN: 798 return BLEND_ONE; 799 case BLENDOP_MAX: 800 return BLEND_ONE; 801 default: 802 ASSERT(false); 803 } 804 805 return destBlendFactorState; 806 } 807 blendOperation()808 BlendOperation Context::blendOperation() 809 { 810 if(!alphaBlendEnable) return BLENDOP_SOURCE; 811 812 switch(blendOperationState) 813 { 814 case BLENDOP_ADD: 815 if(sourceBlendFactor() == BLEND_ZERO) 816 { 817 if(destBlendFactor() == BLEND_ZERO) 818 { 819 return BLENDOP_NULL; 820 } 821 else 822 { 823 return BLENDOP_DEST; 824 } 825 } 826 else if(sourceBlendFactor() == BLEND_ONE) 827 { 828 if(destBlendFactor() == BLEND_ZERO) 829 { 830 return BLENDOP_SOURCE; 831 } 832 else 833 { 834 return BLENDOP_ADD; 835 } 836 } 837 else 838 { 839 if(destBlendFactor() == BLEND_ZERO) 840 { 841 return BLENDOP_SOURCE; 842 } 843 else 844 { 845 return BLENDOP_ADD; 846 } 847 } 848 case BLENDOP_SUB: 849 if(sourceBlendFactor() == BLEND_ZERO) 850 { 851 return BLENDOP_NULL; // Negative, clamped to zero 852 } 853 else if(sourceBlendFactor() == BLEND_ONE) 854 { 855 if(destBlendFactor() == BLEND_ZERO) 856 { 857 return BLENDOP_SOURCE; 858 } 859 else 860 { 861 return BLENDOP_SUB; 862 } 863 } 864 else 865 { 866 if(destBlendFactor() == BLEND_ZERO) 867 { 868 return BLENDOP_SOURCE; 869 } 870 else 871 { 872 return BLENDOP_SUB; 873 } 874 } 875 case BLENDOP_INVSUB: 876 if(sourceBlendFactor() == BLEND_ZERO) 877 { 878 if(destBlendFactor() == BLEND_ZERO) 879 { 880 return BLENDOP_NULL; 881 } 882 else 883 { 884 return BLENDOP_DEST; 885 } 886 } 887 else if(sourceBlendFactor() == BLEND_ONE) 888 { 889 if(destBlendFactor() == BLEND_ZERO) 890 { 891 return BLENDOP_NULL; // Negative, clamped to zero 892 } 893 else 894 { 895 return BLENDOP_INVSUB; 896 } 897 } 898 else 899 { 900 if(destBlendFactor() == BLEND_ZERO) 901 { 902 return BLENDOP_NULL; // Negative, clamped to zero 903 } 904 else 905 { 906 return BLENDOP_INVSUB; 907 } 908 } 909 case BLENDOP_MIN: 910 return BLENDOP_MIN; 911 case BLENDOP_MAX: 912 return BLENDOP_MAX; 913 default: 914 ASSERT(false); 915 } 916 917 return blendOperationState; 918 } 919 sourceBlendFactorAlpha()920 BlendFactor Context::sourceBlendFactorAlpha() 921 { 922 if(!separateAlphaBlendEnable) 923 { 924 return sourceBlendFactor(); 925 } 926 else 927 { 928 switch(blendOperationStateAlpha) 929 { 930 case BLENDOP_ADD: 931 case BLENDOP_SUB: 932 case BLENDOP_INVSUB: 933 return sourceBlendFactorStateAlpha; 934 case BLENDOP_MIN: 935 return BLEND_ONE; 936 case BLENDOP_MAX: 937 return BLEND_ONE; 938 default: 939 ASSERT(false); 940 } 941 942 return sourceBlendFactorStateAlpha; 943 } 944 } 945 destBlendFactorAlpha()946 BlendFactor Context::destBlendFactorAlpha() 947 { 948 if(!separateAlphaBlendEnable) 949 { 950 return destBlendFactor(); 951 } 952 else 953 { 954 switch(blendOperationStateAlpha) 955 { 956 case BLENDOP_ADD: 957 case BLENDOP_SUB: 958 case BLENDOP_INVSUB: 959 return destBlendFactorStateAlpha; 960 case BLENDOP_MIN: 961 return BLEND_ONE; 962 case BLENDOP_MAX: 963 return BLEND_ONE; 964 default: 965 ASSERT(false); 966 } 967 968 return destBlendFactorStateAlpha; 969 } 970 } 971 blendOperationAlpha()972 BlendOperation Context::blendOperationAlpha() 973 { 974 if(!separateAlphaBlendEnable) 975 { 976 return blendOperation(); 977 } 978 else 979 { 980 switch(blendOperationStateAlpha) 981 { 982 case BLENDOP_ADD: 983 if(sourceBlendFactorAlpha() == BLEND_ZERO) 984 { 985 if(destBlendFactorAlpha() == BLEND_ZERO) 986 { 987 return BLENDOP_NULL; 988 } 989 else 990 { 991 return BLENDOP_DEST; 992 } 993 } 994 else if(sourceBlendFactorAlpha() == BLEND_ONE) 995 { 996 if(destBlendFactorAlpha() == BLEND_ZERO) 997 { 998 return BLENDOP_SOURCE; 999 } 1000 else 1001 { 1002 return BLENDOP_ADD; 1003 } 1004 } 1005 else 1006 { 1007 if(destBlendFactorAlpha() == BLEND_ZERO) 1008 { 1009 return BLENDOP_SOURCE; 1010 } 1011 else 1012 { 1013 return BLENDOP_ADD; 1014 } 1015 } 1016 case BLENDOP_SUB: 1017 if(sourceBlendFactorAlpha() == BLEND_ZERO) 1018 { 1019 return BLENDOP_NULL; // Negative, clamped to zero 1020 } 1021 else if(sourceBlendFactorAlpha() == BLEND_ONE) 1022 { 1023 if(destBlendFactorAlpha() == BLEND_ZERO) 1024 { 1025 return BLENDOP_SOURCE; 1026 } 1027 else 1028 { 1029 return BLENDOP_SUB; 1030 } 1031 } 1032 else 1033 { 1034 if(destBlendFactorAlpha() == BLEND_ZERO) 1035 { 1036 return BLENDOP_SOURCE; 1037 } 1038 else 1039 { 1040 return BLENDOP_SUB; 1041 } 1042 } 1043 case BLENDOP_INVSUB: 1044 if(sourceBlendFactorAlpha() == BLEND_ZERO) 1045 { 1046 if(destBlendFactorAlpha() == BLEND_ZERO) 1047 { 1048 return BLENDOP_NULL; 1049 } 1050 else 1051 { 1052 return BLENDOP_DEST; 1053 } 1054 } 1055 else if(sourceBlendFactorAlpha() == BLEND_ONE) 1056 { 1057 if(destBlendFactorAlpha() == BLEND_ZERO) 1058 { 1059 return BLENDOP_NULL; // Negative, clamped to zero 1060 } 1061 else 1062 { 1063 return BLENDOP_INVSUB; 1064 } 1065 } 1066 else 1067 { 1068 if(destBlendFactorAlpha() == BLEND_ZERO) 1069 { 1070 return BLENDOP_NULL; // Negative, clamped to zero 1071 } 1072 else 1073 { 1074 return BLENDOP_INVSUB; 1075 } 1076 } 1077 case BLENDOP_MIN: 1078 return BLENDOP_MIN; 1079 case BLENDOP_MAX: 1080 return BLENDOP_MAX; 1081 default: 1082 ASSERT(false); 1083 } 1084 1085 return blendOperationStateAlpha; 1086 } 1087 } 1088 indexedVertexBlendActive()1089 bool Context::indexedVertexBlendActive() 1090 { 1091 if(vertexShader) 1092 { 1093 return false; 1094 } 1095 1096 return indexedVertexBlendEnable; 1097 } 1098 vertexBlendMatrixCountActive()1099 int Context::vertexBlendMatrixCountActive() 1100 { 1101 if(vertexShader) 1102 { 1103 return 0; 1104 } 1105 1106 return vertexBlendMatrixCount; 1107 } 1108 localViewerActive()1109 bool Context::localViewerActive() 1110 { 1111 if(vertexShader) 1112 { 1113 return false; 1114 } 1115 1116 return localViewer; 1117 } 1118 normalizeNormalsActive()1119 bool Context::normalizeNormalsActive() 1120 { 1121 if(vertexShader) 1122 { 1123 return false; 1124 } 1125 1126 return normalizeNormals; 1127 } 1128 vertexFogModeActive()1129 FogMode Context::vertexFogModeActive() 1130 { 1131 if(vertexShader || !fogActive()) 1132 { 1133 return FOG_NONE; 1134 } 1135 1136 return vertexFogMode; 1137 } 1138 rangeFogActive()1139 bool Context::rangeFogActive() 1140 { 1141 if(vertexShader || !fogActive()) 1142 { 1143 return false; 1144 } 1145 1146 return rangeFogEnable; 1147 } 1148 texGenActive(int stage)1149 TexGen Context::texGenActive(int stage) 1150 { 1151 if(vertexShader || !texCoordActive(stage)) 1152 { 1153 return TEXGEN_PASSTHRU; 1154 } 1155 1156 return texGen[stage]; 1157 } 1158 textureTransformCountActive(int stage)1159 int Context::textureTransformCountActive(int stage) 1160 { 1161 if(vertexShader || !texCoordActive(stage)) 1162 { 1163 return 0; 1164 } 1165 1166 return textureTransformCount[stage]; 1167 } 1168 texCoordIndexActive(int stage)1169 int Context::texCoordIndexActive(int stage) 1170 { 1171 if(vertexShader || !texCoordActive(stage)) 1172 { 1173 return stage; 1174 } 1175 1176 return textureStage[stage].texCoordIndex; 1177 } 1178 perspectiveActive()1179 bool Context::perspectiveActive() 1180 { 1181 if(!colorUsed()) 1182 { 1183 return false; 1184 } 1185 1186 if(!perspectiveCorrection) 1187 { 1188 return false; 1189 } 1190 1191 if(isDrawPoint(true)) 1192 { 1193 return false; 1194 } 1195 1196 return true; 1197 } 1198 diffuseUsed()1199 bool Context::diffuseUsed() 1200 { 1201 return diffuseUsed(0) || diffuseUsed(1) || diffuseUsed(2) || diffuseUsed(3); 1202 } 1203 diffuseUsed(int component)1204 bool Context::diffuseUsed(int component) 1205 { 1206 if(!colorUsed()) 1207 { 1208 return false; 1209 } 1210 1211 if(pixelShader) 1212 { 1213 return pixelShader->usesDiffuse(component); 1214 } 1215 1216 // Directly using the diffuse input color 1217 for(int i = 0; i < 8; i++) 1218 { 1219 if(textureStage[i].isStageDisabled()) 1220 { 1221 break; 1222 } 1223 1224 if(textureStage[i].usesDiffuse()) 1225 { 1226 return true; 1227 } 1228 } 1229 1230 // Using the current color (initialized to diffuse) before it's overwritten 1231 for(int i = 0; i < 8; i++) 1232 { 1233 if(textureStage[i].usesCurrent() || textureStage[i].isStageDisabled()) // Current color contains diffuse before being overwritten 1234 { 1235 return true; 1236 } 1237 1238 if(textureStage[i].writesCurrent()) 1239 { 1240 return false; 1241 } 1242 } 1243 1244 return true; 1245 } 1246 diffuseActive()1247 bool Context::diffuseActive() 1248 { 1249 return diffuseActive(0) || diffuseActive(1) || diffuseActive(2) || diffuseActive(3); 1250 } 1251 diffuseActive(int component)1252 bool Context::diffuseActive(int component) 1253 { 1254 if(!colorUsed()) 1255 { 1256 return false; 1257 } 1258 1259 // Vertex processor provides diffuse component 1260 bool vertexDiffuse; 1261 1262 if(vertexShader) 1263 { 1264 vertexDiffuse = vertexShader->getOutput(C0, component).active(); 1265 } 1266 else if(!preTransformed) 1267 { 1268 vertexDiffuse = input[Color0] || lightingEnable; 1269 } 1270 else 1271 { 1272 vertexDiffuse = input[Color0]; 1273 } 1274 1275 // Pixel processor requires diffuse component 1276 bool pixelDiffuse = diffuseUsed(component); 1277 1278 return vertexDiffuse && pixelDiffuse; 1279 } 1280 specularUsed()1281 bool Context::specularUsed() 1282 { 1283 return Context::specularUsed(0) || Context::specularUsed(1) || Context::specularUsed(2) || Context::specularUsed(3); 1284 } 1285 specularUsed(int component)1286 bool Context::specularUsed(int component) 1287 { 1288 if(!colorUsed()) 1289 { 1290 return false; 1291 } 1292 1293 if(pixelShader) 1294 { 1295 return pixelShader->usesSpecular(component); 1296 } 1297 1298 bool pixelSpecular = specularEnable; 1299 1300 for(int i = 0; i < 8; i++) 1301 { 1302 if(textureStage[i].isStageDisabled()) break; 1303 1304 pixelSpecular = pixelSpecular || textureStage[i].usesSpecular(); 1305 } 1306 1307 return pixelSpecular; 1308 } 1309 specularActive()1310 bool Context::specularActive() 1311 { 1312 return specularActive(0) || specularActive(1) || specularActive(2) || specularActive(3); 1313 } 1314 specularActive(int component)1315 bool Context::specularActive(int component) 1316 { 1317 if(!colorUsed()) 1318 { 1319 return false; 1320 } 1321 1322 // Vertex processor provides specular component 1323 bool vertexSpecular; 1324 1325 if(!vertexShader) 1326 { 1327 vertexSpecular = input[Color1] || (lightingEnable && specularEnable); 1328 } 1329 else 1330 { 1331 vertexSpecular = vertexShader->getOutput(C1, component).active(); 1332 } 1333 1334 // Pixel processor requires specular component 1335 bool pixelSpecular = specularUsed(component); 1336 1337 return vertexSpecular && pixelSpecular; 1338 } 1339 colorActive(int color,int component)1340 bool Context::colorActive(int color, int component) 1341 { 1342 if(color == 0) 1343 { 1344 return diffuseActive(component); 1345 } 1346 else 1347 { 1348 return specularActive(component); 1349 } 1350 } 1351 textureActive()1352 bool Context::textureActive() 1353 { 1354 for(int i = 0; i < 8; i++) 1355 { 1356 if(textureActive(i)) 1357 { 1358 return true; 1359 } 1360 } 1361 1362 return false; 1363 } 1364 textureActive(int coordinate)1365 bool Context::textureActive(int coordinate) 1366 { 1367 return textureActive(coordinate, 0) || textureActive(coordinate, 1) || textureActive(coordinate, 2) || textureActive(coordinate, 3); 1368 } 1369 textureActive(int coordinate,int component)1370 bool Context::textureActive(int coordinate, int component) 1371 { 1372 if(!colorUsed()) 1373 { 1374 return false; 1375 } 1376 1377 if(!texCoordActive(coordinate, component)) 1378 { 1379 return false; 1380 } 1381 1382 if(textureTransformProject[coordinate] && pixelShaderVersion() <= 0x0103) 1383 { 1384 if(textureTransformCount[coordinate] == 2) 1385 { 1386 if(component == 1) return true; 1387 } 1388 else if(textureTransformCount[coordinate] == 3) 1389 { 1390 if(component == 2) return true; 1391 } 1392 else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0) 1393 { 1394 if(component == 3) return true; 1395 } 1396 } 1397 1398 if(!pixelShader) 1399 { 1400 bool texture = textureStage[coordinate].usesTexture(); 1401 bool cube = sampler[coordinate].hasCubeTexture(); 1402 bool volume = sampler[coordinate].hasVolumeTexture(); 1403 1404 if(texture) 1405 { 1406 for(int i = coordinate; i >= 0; i--) 1407 { 1408 if(textureStage[i].stageOperation == TextureStage::STAGE_DISABLE) 1409 { 1410 return false; 1411 } 1412 } 1413 } 1414 1415 switch(component) 1416 { 1417 case 0: 1418 return texture; 1419 case 1: 1420 return texture; 1421 case 2: 1422 return (texture && (cube || volume)); 1423 case 3: 1424 return false; 1425 } 1426 } 1427 else 1428 { 1429 return pixelShader->usesTexture(coordinate, component); 1430 } 1431 1432 return false; 1433 } 1434 pixelShaderVersion() const1435 unsigned short Context::pixelShaderVersion() const 1436 { 1437 return pixelShader ? pixelShader->getVersion() : 0x0000; 1438 } 1439 vertexShaderVersion() const1440 unsigned short Context::vertexShaderVersion() const 1441 { 1442 return vertexShader ? vertexShader->getVersion() : 0x0000; 1443 } 1444 getMultiSampleCount() const1445 int Context::getMultiSampleCount() const 1446 { 1447 return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1; 1448 } 1449 getSuperSampleCount() const1450 int Context::getSuperSampleCount() const 1451 { 1452 return renderTarget[0] ? renderTarget[0]->getSuperSampleCount() : 1; 1453 } 1454 renderTargetInternalFormat(int index)1455 Format Context::renderTargetInternalFormat(int index) 1456 { 1457 if(renderTarget[index]) 1458 { 1459 return renderTarget[index]->getInternalFormat(); 1460 } 1461 else 1462 { 1463 return FORMAT_NULL; 1464 } 1465 } 1466 colorWriteActive()1467 int Context::colorWriteActive() 1468 { 1469 return colorWriteActive(0) | colorWriteActive(1) | colorWriteActive(2) | colorWriteActive(3); 1470 } 1471 colorWriteActive(int index)1472 int Context::colorWriteActive(int index) 1473 { 1474 if(!renderTarget[index] || renderTarget[index]->getInternalFormat() == FORMAT_NULL) 1475 { 1476 return 0; 1477 } 1478 1479 if(blendOperation() == BLENDOP_DEST && destBlendFactor() == BLEND_ONE && 1480 (!separateAlphaBlendEnable || (blendOperationAlpha() == BLENDOP_DEST && destBlendFactorAlpha() == BLEND_ONE))) 1481 { 1482 return 0; 1483 } 1484 1485 return colorWriteMask[index]; 1486 } 1487 colorUsed()1488 bool Context::colorUsed() 1489 { 1490 return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->containsKill()); 1491 } 1492 } 1493