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
26namespace 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
47 Context::Context()
48 {
49 init();
50 }
51
52 Context::~Context()
53 {
54 }
55
56 void *Context::operator new(size_t bytes)
57 {
58 return allocate((unsigned int)bytes);
59 }
60
61 void Context::operator delete(void *pointer, size_t bytes)
62 {
63 deallocate(pointer);
64 }
65
66 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
110 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
154 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
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
323 const float &Context::exp2Bias()
324 {
325 return bias;
326 }
327
328 const Point &Context::getLightPosition(int light)
329 {
330 return worldLightPosition[light];
331 }
332
333 void Context::setGlobalMipmapBias(float bias)
334 {
335 this->bias = exp2(bias + 0.5f);
336 }
337
338 void Context::setLightingEnable(bool lightingEnable)
339 {
340 this->lightingEnable = lightingEnable;
341 }
342
343 void Context::setSpecularEnable(bool specularEnable)
344 {
345 Context::specularEnable = specularEnable;
346 }
347
348 void Context::setLightEnable(int light, bool lightEnable)
349 {
350 Context::lightEnable[light] = lightEnable;
351 }
352
353 void Context::setLightPosition(int light, Point worldLightPosition)
354 {
355 Context::worldLightPosition[light] = worldLightPosition;
356 }
357
358 void Context::setAmbientMaterialSource(MaterialSource ambientMaterialSource)
359 {
360 Context::ambientMaterialSource = ambientMaterialSource;
361 }
362
363 void Context::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)
364 {
365 Context::diffuseMaterialSource = diffuseMaterialSource;
366 }
367
368 void Context::setSpecularMaterialSource(MaterialSource specularMaterialSource)
369 {
370 Context::specularMaterialSource = specularMaterialSource;
371 }
372
373 void Context::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)
374 {
375 Context::emissiveMaterialSource = emissiveMaterialSource;
376 }
377
378 void Context::setPointSpriteEnable(bool pointSpriteEnable)
379 {
380 Context::pointSpriteEnable = pointSpriteEnable;
381 }
382
383 void Context::setPointScaleEnable(bool pointScaleEnable)
384 {
385 Context::pointScaleEnable = pointScaleEnable;
386 }
387
388 bool Context::setDepthBufferEnable(bool depthBufferEnable)
389 {
390 bool modified = (Context::depthBufferEnable != depthBufferEnable);
391 Context::depthBufferEnable = depthBufferEnable;
392 return modified;
393 }
394
395 bool Context::setAlphaBlendEnable(bool alphaBlendEnable)
396 {
397 bool modified = (Context::alphaBlendEnable != alphaBlendEnable);
398 Context::alphaBlendEnable = alphaBlendEnable;
399 return modified;
400 }
401
402 bool Context::setSourceBlendFactor(BlendFactor sourceBlendFactor)
403 {
404 bool modified = (Context::sourceBlendFactorState != sourceBlendFactor);
405 Context::sourceBlendFactorState = sourceBlendFactor;
406 return modified;
407 }
408
409 bool Context::setDestBlendFactor(BlendFactor destBlendFactor)
410 {
411 bool modified = (Context::destBlendFactorState != destBlendFactor);
412 Context::destBlendFactorState = destBlendFactor;
413 return modified;
414 }
415
416 bool Context::setBlendOperation(BlendOperation blendOperation)
417 {
418 bool modified = (Context::blendOperationState != blendOperation);
419 Context::blendOperationState = blendOperation;
420 return modified;
421 }
422
423 bool Context::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)
424 {
425 bool modified = (Context::separateAlphaBlendEnable != separateAlphaBlendEnable);
426 Context::separateAlphaBlendEnable = separateAlphaBlendEnable;
427 return modified;
428 }
429
430 bool Context::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)
431 {
432 bool modified = (Context::sourceBlendFactorStateAlpha != sourceBlendFactorAlpha);
433 Context::sourceBlendFactorStateAlpha = sourceBlendFactorAlpha;
434 return modified;
435 }
436
437 bool Context::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)
438 {
439 bool modified = (Context::destBlendFactorStateAlpha != destBlendFactorAlpha);
440 Context::destBlendFactorStateAlpha = destBlendFactorAlpha;
441 return modified;
442 }
443
444 bool Context::setBlendOperationAlpha(BlendOperation blendOperationAlpha)
445 {
446 bool modified = (Context::blendOperationStateAlpha != blendOperationAlpha);
447 Context::blendOperationStateAlpha = blendOperationAlpha;
448 return modified;
449 }
450
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
458 bool Context::setWriteSRGB(bool sRGB)
459 {
460 bool modified = (Context::writeSRGB != sRGB);
461 Context::writeSRGB = sRGB;
462 return modified;
463 }
464
465 bool Context::setColorLogicOpEnabled(bool enabled)
466 {
467 bool modified = (Context::colorLogicOpEnabled != enabled);
468 Context::colorLogicOpEnabled = enabled;
469 return modified;
470 }
471
472 bool Context::setLogicalOperation(LogicalOperation logicalOperation)
473 {
474 bool modified = (Context::logicalOperation != logicalOperation);
475 Context::logicalOperation = logicalOperation;
476 return modified;
477 }
478
479 void Context::setColorVertexEnable(bool colorVertexEnable)
480 {
481 Context::colorVertexEnable = colorVertexEnable;
482 }
483
484 bool Context::fogActive()
485 {
486 if(!colorUsed()) return false;
487
488 if(pixelShaderModel() >= 0x0300) return false;
489
490 return fogEnable;
491 }
492
493 bool Context::pointSizeActive()
494 {
495 if(vertexShader)
496 {
497 return false;
498 }
499
500 return isDrawPoint(true) && (input[PointSize] || (!preTransformed && pointScaleActive()));
501 }
502
503 FogMode Context::pixelFogActive()
504 {
505 if(fogActive())
506 {
507 return pixelFogMode;
508 }
509
510 return FOG_NONE;
511 }
512
513 bool Context::depthWriteActive()
514 {
515 if(!depthBufferActive()) return false;
516
517 return depthWriteEnable;
518 }
519
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
530 bool Context::depthBufferActive()
531 {
532 return depthBuffer && depthBufferEnable;
533 }
534
535 bool Context::stencilActive()
536 {
537 return stencilBuffer && stencilEnable;
538 }
539
540 bool Context::vertexLightingActive()
541 {
542 if(vertexShader)
543 {
544 return false;
545 }
546
547 return lightingEnable && !preTransformed;
548 }
549
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
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
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
639 bool Context::vertexSpecularActive()
640 {
641 return vertexLightingActive() && specularEnable && vertexNormalActive();
642 }
643
644 bool Context::vertexNormalActive()
645 {
646 if(vertexShader)
647 {
648 return false;
649 }
650
651 return input[Normal];
652 }
653
654 bool Context::vertexLightActive(int i)
655 {
656 if(vertexShader)
657 {
658 return false;
659 }
660
661 return lightingEnable && lightEnable[i];
662 }
663
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
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
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
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
732 bool Context::pointSpriteActive()
733 {
734 return isDrawPoint(true) && pointSpriteEnable;
735 }
736
737 bool Context::pointScaleActive()
738 {
739 if(vertexShader)
740 {
741 return false;
742 }
743
744 return isDrawPoint(true) && pointScaleEnable;
745 }
746
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
765 LogicalOperation Context::colorLogicOp()
766 {
767 return colorLogicOpEnabled ? logicalOperation : LOGICALOP_COPY;
768 }
769
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
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
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
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
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
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
1093 bool Context::indexedVertexBlendActive()
1094 {
1095 if(vertexShader)
1096 {
1097 return false;
1098 }
1099
1100 return indexedVertexBlendEnable;
1101 }
1102
1103 int Context::vertexBlendMatrixCountActive()
1104 {
1105 if(vertexShader)
1106 {
1107 return 0;
1108 }
1109
1110 return vertexBlendMatrixCount;
1111 }
1112
1113 bool Context::localViewerActive()
1114 {
1115 if(vertexShader)
1116 {
1117 return false;
1118 }
1119
1120 return localViewer;
1121 }
1122
1123 bool Context::normalizeNormalsActive()
1124 {
1125 if(vertexShader)
1126 {
1127 return false;
1128 }
1129
1130 return normalizeNormals;
1131 }
1132
1133 FogMode Context::vertexFogModeActive()
1134 {
1135 if(vertexShader || !fogActive())
1136 {
1137 return FOG_NONE;
1138 }
1139
1140 return vertexFogMode;
1141 }
1142
1143 bool Context::rangeFogActive()
1144 {
1145 if(vertexShader || !fogActive())
1146 {
1147 return false;
1148 }
1149
1150 return rangeFogEnable;
1151 }
1152
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
1163 int Context::textureTransformCountActive(int stage)
1164 {
1165 if(vertexShader || !texCoordActive(stage))
1166 {
1167 return 0;
1168 }
1169
1170 return textureTransformCount[stage];
1171 }
1172
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
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
1203 bool Context::diffuseUsed()
1204 {
1205 return diffuseUsed(0) || diffuseUsed(1) || diffuseUsed(2) || diffuseUsed(3);
1206 }
1207
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
1251 bool Context::diffuseActive()
1252 {
1253 return diffuseActive(0) || diffuseActive(1) || diffuseActive(2) || diffuseActive(3);
1254 }
1255
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
1285 bool Context::specularUsed()
1286 {
1287 return Context::specularUsed(0) || Context::specularUsed(1) || Context::specularUsed(2) || Context::specularUsed(3);
1288 }
1289
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
1314 bool Context::specularActive()
1315 {
1316 return specularActive(0) || specularActive(1) || specularActive(2) || specularActive(3);
1317 }
1318
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
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
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
1369 bool Context::textureActive(int coordinate)
1370 {
1371 return textureActive(coordinate, 0) || textureActive(coordinate, 1) || textureActive(coordinate, 2) || textureActive(coordinate, 3);
1372 }
1373
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
1439 unsigned short Context::pixelShaderModel() const
1440 {
1441 return pixelShader ? pixelShader->getShaderModel() : 0x0000;
1442 }
1443
1444 unsigned short Context::vertexShaderModel() const
1445 {
1446 return vertexShader ? vertexShader->getShaderModel() : 0x0000;
1447 }
1448
1449 int Context::getMultiSampleCount() const
1450 {
1451 return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1;
1452 }
1453
1454 int Context::getSuperSampleCount() const
1455 {
1456 return renderTarget[0] ? renderTarget[0]->getSuperSampleCount() : 1;
1457 }
1458
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
1471 bool Context::colorWriteActive()
1472 {
1473 for (int i = 0; i < RENDERTARGETS; i++)
1474 {
1475 if (colorWriteActive(i))
1476 {
1477 return true;
1478 }
1479 }
1480
1481 return false;
1482 }
1483
1484 int Context::colorWriteActive(int index)
1485 {
1486 if(!renderTarget[index] || renderTarget[index]->getInternalFormat() == FORMAT_NULL)
1487 {
1488 return 0;
1489 }
1490
1491 if(blendOperation() == BLENDOP_DEST && destBlendFactor() == BLEND_ONE &&
1492 (!separateAlphaBlendEnable || (blendOperationAlpha() == BLENDOP_DEST && destBlendFactorAlpha() == BLEND_ONE)))
1493 {
1494 return 0;
1495 }
1496
1497 return colorWriteMask[index];
1498 }
1499
1500 bool Context::colorUsed()
1501 {
1502 return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->containsKill());
1503 }
1504}
1505