OSDN Git Service

Fix resetting current display when no current context.
[android-x86/external-swiftshader.git] / src / Renderer / Context.cpp
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
37         bool forceWindowed = false;
38         bool quadLayoutEnabled = false;
39         bool veryEarlyDepthTest = true;
40         bool complementaryDepthBuffer = false;
41         bool postBlendSRGB = false;
42         bool exactColorRounding = false;
43         TransparencyAntialiasing transparencyAntialiasing = TRANSPARENCY_NONE;
44         bool forceClearRegisters = false;
45
46         Context::Context()
47         {
48                 init();
49         }
50
51         Context::~Context()
52         {
53         }
54
55         void *Context::operator new(size_t bytes)
56         {
57                 return allocate((unsigned int)bytes);
58         }
59
60         void Context::operator delete(void *pointer, size_t bytes)
61         {
62                 deallocate(pointer);
63         }
64
65         bool Context::isDrawPoint(bool fillModeAware) const
66         {
67                 switch(drawType)
68                 {
69                 case DRAW_POINTLIST:
70                 case DRAW_INDEXEDPOINTLIST8:
71                 case DRAW_INDEXEDPOINTLIST16:
72                 case DRAW_INDEXEDPOINTLIST32:
73                         return true;
74                 case DRAW_LINELIST:
75                 case DRAW_LINESTRIP:
76                 case DRAW_LINELOOP:
77                 case DRAW_INDEXEDLINELIST8:
78                 case DRAW_INDEXEDLINESTRIP8:
79                 case DRAW_INDEXEDLINELOOP8:
80                 case DRAW_INDEXEDLINELIST16:
81                 case DRAW_INDEXEDLINESTRIP16:
82                 case DRAW_INDEXEDLINELOOP16:
83                 case DRAW_INDEXEDLINELIST32:
84                 case DRAW_INDEXEDLINESTRIP32:
85                 case DRAW_INDEXEDLINELOOP32:
86                         return false;
87                 case DRAW_TRIANGLELIST:
88                 case DRAW_TRIANGLESTRIP:
89                 case DRAW_TRIANGLEFAN:
90                 case DRAW_INDEXEDTRIANGLELIST8:
91                 case DRAW_INDEXEDTRIANGLESTRIP8:
92                 case DRAW_INDEXEDTRIANGLEFAN8:
93                 case DRAW_INDEXEDTRIANGLELIST16:
94                 case DRAW_INDEXEDTRIANGLESTRIP16:
95                 case DRAW_INDEXEDTRIANGLEFAN16:
96                 case DRAW_INDEXEDTRIANGLELIST32:
97                 case DRAW_INDEXEDTRIANGLESTRIP32:
98                 case DRAW_INDEXEDTRIANGLEFAN32:
99                         return fillModeAware ? fillMode == FILL_VERTEX : false;
100                 case DRAW_QUADLIST:
101                         return false;
102                 default:
103                         ASSERT(false);
104                 }
105
106                 return false;
107         }
108
109         bool Context::isDrawLine(bool fillModeAware) const
110         {
111                 switch(drawType)
112                 {
113                 case DRAW_POINTLIST:
114                 case DRAW_INDEXEDPOINTLIST8:
115                 case DRAW_INDEXEDPOINTLIST16:
116                 case DRAW_INDEXEDPOINTLIST32:
117                         return false;
118                 case DRAW_LINELIST:
119                 case DRAW_LINESTRIP:
120                 case DRAW_LINELOOP:
121                 case DRAW_INDEXEDLINELIST8:
122                 case DRAW_INDEXEDLINESTRIP8:
123                 case DRAW_INDEXEDLINELOOP8:
124                 case DRAW_INDEXEDLINELIST16:
125                 case DRAW_INDEXEDLINESTRIP16:
126                 case DRAW_INDEXEDLINELOOP16:
127                 case DRAW_INDEXEDLINELIST32:
128                 case DRAW_INDEXEDLINESTRIP32:
129                 case DRAW_INDEXEDLINELOOP32:
130                         return true;
131                 case DRAW_TRIANGLELIST:
132                 case DRAW_TRIANGLESTRIP:
133                 case DRAW_TRIANGLEFAN:
134                 case DRAW_INDEXEDTRIANGLELIST8:
135                 case DRAW_INDEXEDTRIANGLESTRIP8:
136                 case DRAW_INDEXEDTRIANGLEFAN8:
137                 case DRAW_INDEXEDTRIANGLELIST16:
138                 case DRAW_INDEXEDTRIANGLESTRIP16:
139                 case DRAW_INDEXEDTRIANGLEFAN16:
140                 case DRAW_INDEXEDTRIANGLELIST32:
141                 case DRAW_INDEXEDTRIANGLESTRIP32:
142                 case DRAW_INDEXEDTRIANGLEFAN32:
143                         return fillModeAware ? fillMode == FILL_WIREFRAME : false;
144                 case DRAW_QUADLIST:
145                         return false;
146                 default:
147                         ASSERT(false);
148                 }
149
150                 return false;
151         }
152
153         bool Context::isDrawTriangle(bool fillModeAware) const
154         {
155                 switch(drawType)
156                 {
157                 case DRAW_POINTLIST:
158                 case DRAW_INDEXEDPOINTLIST8:
159                 case DRAW_INDEXEDPOINTLIST16:
160                 case DRAW_INDEXEDPOINTLIST32:
161                         return false;
162                 case DRAW_LINELIST:
163                 case DRAW_LINESTRIP:
164                 case DRAW_LINELOOP:
165                 case DRAW_INDEXEDLINELIST8:
166                 case DRAW_INDEXEDLINESTRIP8:
167                 case DRAW_INDEXEDLINELOOP8:
168                 case DRAW_INDEXEDLINELIST16:
169                 case DRAW_INDEXEDLINESTRIP16:
170                 case DRAW_INDEXEDLINELOOP16:
171                 case DRAW_INDEXEDLINELIST32:
172                 case DRAW_INDEXEDLINESTRIP32:
173                 case DRAW_INDEXEDLINELOOP32:
174                         return false;
175                 case DRAW_TRIANGLELIST:
176                 case DRAW_TRIANGLESTRIP:
177                 case DRAW_TRIANGLEFAN:
178                 case DRAW_INDEXEDTRIANGLELIST8:
179                 case DRAW_INDEXEDTRIANGLESTRIP8:
180                 case DRAW_INDEXEDTRIANGLEFAN8:
181                 case DRAW_INDEXEDTRIANGLELIST16:
182                 case DRAW_INDEXEDTRIANGLESTRIP16:
183                 case DRAW_INDEXEDTRIANGLEFAN16:
184                 case DRAW_INDEXEDTRIANGLELIST32:
185                 case DRAW_INDEXEDTRIANGLESTRIP32:
186                 case DRAW_INDEXEDTRIANGLEFAN32:
187                         return fillModeAware ? fillMode == FILL_SOLID : true;
188                 case DRAW_QUADLIST:
189                         // Quads are broken up into triangles
190                         return fillModeAware ? fillMode == FILL_SOLID : true;
191                 default:
192                         ASSERT(false);
193                 }
194
195                 return true;
196         }
197
198         void Context::init()
199         {
200                 for(int i = 0; i < 8; i++)
201                 {
202                         textureStage[i].init(i, &sampler[i], (i >= 1) ? &textureStage[i - 1] : 0);
203                 }
204
205                 // Set vertex streams to null stream
206                 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
207                 {
208                         input[i].defaults();
209                 }
210
211                 fogStart = 0.0f;
212                 fogEnd = 1.0f;
213
214                 for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++) textureWrap[i] = 0;
215                 for(int i = 0; i < 8; i++) texGen[i] = TEXGEN_PASSTHRU;
216                 for(int i = 0; i < 8; i++) textureTransformCount[i] = 0;
217                 for(int i = 0; i < 8; i++) textureTransformProject[i] = false;
218                 textureWrapActive = false;
219                 localViewer = true;
220                 normalizeNormals = false;
221
222                 for(int i = 0; i < RENDERTARGETS; ++i)
223                 {
224                         renderTarget[i] = nullptr;
225                 }
226                 depthBuffer = nullptr;
227                 stencilBuffer = nullptr;
228
229                 stencilEnable = false;
230                 stencilCompareMode = STENCIL_ALWAYS;
231                 stencilReference = 0;
232                 stencilMask = 0xFFFFFFFF;
233                 stencilFailOperation = OPERATION_KEEP;
234                 stencilPassOperation = OPERATION_KEEP;
235                 stencilZFailOperation = OPERATION_KEEP;
236                 stencilWriteMask = 0xFFFFFFFF;
237
238                 twoSidedStencil = false;
239                 stencilCompareModeCCW = STENCIL_ALWAYS;
240                 stencilReferenceCCW = 0;
241                 stencilMaskCCW = 0xFFFFFFFF;
242                 stencilFailOperationCCW = OPERATION_KEEP;
243                 stencilPassOperationCCW = OPERATION_KEEP;
244                 stencilZFailOperationCCW = OPERATION_KEEP;
245                 stencilWriteMaskCCW = 0xFFFFFFFF;
246
247                 setGlobalMipmapBias(0);
248
249                 lightingEnable = true;
250                 specularEnable = false;
251                 for(int i = 0; i < 8; i++) lightEnable[i] = false;
252                 for(int i = 0; i < 8; i++) worldLightPosition[i] = 0;
253
254                 alphaCompareMode = ALPHA_ALWAYS;
255                 alphaTestEnable = false;
256                 fillMode = FILL_SOLID;
257                 shadingMode = SHADING_GOURAUD;
258
259                 rasterizerDiscard = false;
260
261                 depthCompareMode = DEPTH_LESS;
262                 depthBufferEnable = true;
263                 depthWriteEnable = true;
264
265                 alphaBlendEnable = false;
266                 sourceBlendFactorState = BLEND_ONE;
267                 destBlendFactorState = BLEND_ZERO;
268                 blendOperationState = BLENDOP_ADD;
269
270                 separateAlphaBlendEnable = false;
271                 sourceBlendFactorStateAlpha = BLEND_ONE;
272                 destBlendFactorStateAlpha = BLEND_ZERO;
273                 blendOperationStateAlpha = BLENDOP_ADD;
274
275                 cullMode = CULL_CLOCKWISE;
276                 alphaReference = 0.0f;
277
278                 for(int i = 0; i < RENDERTARGETS; i++)
279                 {
280                         colorWriteMask[i] = 0x0000000F;
281                 }
282
283                 ambientMaterialSource = MATERIAL_MATERIAL;
284                 diffuseMaterialSource = MATERIAL_COLOR1;
285                 specularMaterialSource = MATERIAL_COLOR2;
286                 emissiveMaterialSource = MATERIAL_MATERIAL;
287                 colorVertexEnable = true;
288
289                 fogEnable = false;
290                 pixelFogMode = FOG_NONE;
291                 vertexFogMode = FOG_NONE;
292                 wBasedFog = false;
293                 rangeFogEnable = false;
294
295                 indexedVertexBlendEnable = false;
296                 vertexBlendMatrixCount = 0;
297
298                 pixelShader = 0;
299                 vertexShader = 0;
300
301                 instanceID = 0;
302
303                 occlusionEnabled = false;
304                 transformFeedbackQueryEnabled = false;
305                 transformFeedbackEnabled = 0;
306
307                 pointSpriteEnable = false;
308                 pointScaleEnable = false;
309                 lineWidth = 1.0f;
310
311                 writeSRGB = false;
312                 sampleMask = 0xFFFFFFFF;
313
314                 colorLogicOpEnabled = false;
315                 logicalOperation = LOGICALOP_COPY;
316         }
317
318         const float &Context::exp2Bias()
319         {
320                 return bias;
321         }
322
323         const Point &Context::getLightPosition(int light)
324         {
325                 return worldLightPosition[light];
326         }
327
328         void Context::setGlobalMipmapBias(float bias)
329         {
330                 this->bias = exp2(bias + 0.5f);
331         }
332
333         void Context::setLightingEnable(bool lightingEnable)
334         {
335                 this->lightingEnable = lightingEnable;
336         }
337
338         void Context::setSpecularEnable(bool specularEnable)
339         {
340                 Context::specularEnable = specularEnable;
341         }
342
343         void Context::setLightEnable(int light, bool lightEnable)
344         {
345                 Context::lightEnable[light] = lightEnable;
346         }
347
348         void Context::setLightPosition(int light, Point worldLightPosition)
349         {
350                 Context::worldLightPosition[light] = worldLightPosition;
351         }
352
353         void Context::setAmbientMaterialSource(MaterialSource ambientMaterialSource)
354         {
355                 Context::ambientMaterialSource = ambientMaterialSource;
356         }
357
358         void Context::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)
359         {
360                 Context::diffuseMaterialSource = diffuseMaterialSource;
361         }
362
363         void Context::setSpecularMaterialSource(MaterialSource specularMaterialSource)
364         {
365                 Context::specularMaterialSource = specularMaterialSource;
366         }
367
368         void Context::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)
369         {
370                 Context::emissiveMaterialSource = emissiveMaterialSource;
371         }
372
373         void Context::setPointSpriteEnable(bool pointSpriteEnable)
374         {
375                 Context::pointSpriteEnable = pointSpriteEnable;
376         }
377
378         void Context::setPointScaleEnable(bool pointScaleEnable)
379         {
380                 Context::pointScaleEnable = pointScaleEnable;
381         }
382
383         bool Context::setDepthBufferEnable(bool depthBufferEnable)
384         {
385                 bool modified = (Context::depthBufferEnable != depthBufferEnable);
386                 Context::depthBufferEnable = depthBufferEnable;
387                 return modified;
388         }
389
390         bool Context::setAlphaBlendEnable(bool alphaBlendEnable)
391         {
392                 bool modified = (Context::alphaBlendEnable != alphaBlendEnable);
393                 Context::alphaBlendEnable = alphaBlendEnable;
394                 return modified;
395         }
396
397         bool Context::setSourceBlendFactor(BlendFactor sourceBlendFactor)
398         {
399                 bool modified = (Context::sourceBlendFactorState != sourceBlendFactor);
400                 Context::sourceBlendFactorState = sourceBlendFactor;
401                 return modified;
402         }
403
404         bool Context::setDestBlendFactor(BlendFactor destBlendFactor)
405         {
406                 bool modified = (Context::destBlendFactorState != destBlendFactor);
407                 Context::destBlendFactorState = destBlendFactor;
408                 return modified;
409         }
410
411         bool Context::setBlendOperation(BlendOperation blendOperation)
412         {
413                 bool modified = (Context::blendOperationState != blendOperation);
414                 Context::blendOperationState = blendOperation;
415                 return modified;
416         }
417
418         bool Context::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)
419         {
420                 bool modified = (Context::separateAlphaBlendEnable != separateAlphaBlendEnable);
421                 Context::separateAlphaBlendEnable = separateAlphaBlendEnable;
422                 return modified;
423         }
424
425         bool Context::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)
426         {
427                 bool modified = (Context::sourceBlendFactorStateAlpha != sourceBlendFactorAlpha);
428                 Context::sourceBlendFactorStateAlpha = sourceBlendFactorAlpha;
429                 return modified;
430         }
431
432         bool Context::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)
433         {
434                 bool modified = (Context::destBlendFactorStateAlpha != destBlendFactorAlpha);
435                 Context::destBlendFactorStateAlpha = destBlendFactorAlpha;
436                 return modified;
437         }
438
439         bool Context::setBlendOperationAlpha(BlendOperation blendOperationAlpha)
440         {
441                 bool modified = (Context::blendOperationStateAlpha != blendOperationAlpha);
442                 Context::blendOperationStateAlpha = blendOperationAlpha;
443                 return modified;
444         }
445
446         bool Context::setColorWriteMask(int index, int colorWriteMask)
447         {
448                 bool modified = (Context::colorWriteMask[index] != colorWriteMask);
449                 Context::colorWriteMask[index] = colorWriteMask;
450                 return modified;
451         }
452
453         bool Context::setWriteSRGB(bool sRGB)
454         {
455                 bool modified = (Context::writeSRGB != sRGB);
456                 Context::writeSRGB = sRGB;
457                 return modified;
458         }
459
460         bool Context::setColorLogicOpEnabled(bool enabled)
461         {
462                 bool modified = (Context::colorLogicOpEnabled != enabled);
463                 Context::colorLogicOpEnabled = enabled;
464                 return modified;
465         }
466
467         bool Context::setLogicalOperation(LogicalOperation logicalOperation)
468         {
469                 bool modified = (Context::logicalOperation != logicalOperation);
470                 Context::logicalOperation = logicalOperation;
471                 return modified;
472         }
473
474         void Context::setColorVertexEnable(bool colorVertexEnable)
475         {
476                 Context::colorVertexEnable = colorVertexEnable;
477         }
478
479         bool Context::fogActive()
480         {
481                 if(!colorUsed()) return false;
482
483                 if(pixelShaderVersion() >= 0x0300) return false;
484
485                 return fogEnable;
486         }
487
488         bool Context::pointSizeActive()
489         {
490                 if(vertexShader)
491                 {
492                         return false;
493                 }
494
495                 return isDrawPoint(true) && (input[PointSize] || (!preTransformed && pointScaleActive()));
496         }
497
498         FogMode Context::pixelFogActive()
499         {
500                 if(fogActive())
501                 {
502                         return pixelFogMode;
503                 }
504
505                 return FOG_NONE;
506         }
507
508         bool Context::depthWriteActive()
509         {
510                 if(!depthBufferActive()) return false;
511
512                 return depthWriteEnable;
513         }
514
515         bool Context::alphaTestActive()
516         {
517                 if(transparencyAntialiasing != TRANSPARENCY_NONE) return true;
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
525         bool Context::depthBufferActive()
526         {
527                 return depthBuffer && depthBufferEnable;
528         }
529
530         bool Context::stencilActive()
531         {
532                 return stencilBuffer && stencilEnable;
533         }
534
535         bool Context::vertexLightingActive()
536         {
537                 if(vertexShader)
538                 {
539                         return false;
540                 }
541
542                 return lightingEnable && !preTransformed;
543         }
544
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->getOutput(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
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
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
634         bool Context::vertexSpecularActive()
635         {
636                 return vertexLightingActive() && specularEnable && vertexNormalActive();
637         }
638
639         bool Context::vertexNormalActive()
640         {
641                 if(vertexShader)
642                 {
643                         return false;
644                 }
645
646                 return input[Normal];
647         }
648
649         bool Context::vertexLightActive(int i)
650         {
651                 if(vertexShader)
652                 {
653                         return false;
654                 }
655
656                 return lightingEnable && lightEnable[i];
657         }
658
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
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
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
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
727         bool Context::pointSpriteActive()
728         {
729                 return isDrawPoint(true) && pointSpriteEnable;
730         }
731
732         bool Context::pointScaleActive()
733         {
734                 if(vertexShader)
735                 {
736                         return false;
737                 }
738
739                 return isDrawPoint(true) && pointScaleEnable;
740         }
741
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
760         LogicalOperation Context::colorLogicOp()
761         {
762                 return colorLogicOpEnabled ? logicalOperation : LOGICALOP_COPY;
763         }
764
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
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
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
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
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
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
1088         bool Context::indexedVertexBlendActive()
1089         {
1090                 if(vertexShader)
1091                 {
1092                         return false;
1093                 }
1094
1095                 return indexedVertexBlendEnable;
1096         }
1097
1098         int Context::vertexBlendMatrixCountActive()
1099         {
1100                 if(vertexShader)
1101                 {
1102                         return 0;
1103                 }
1104
1105                 return vertexBlendMatrixCount;
1106         }
1107
1108         bool Context::localViewerActive()
1109         {
1110                 if(vertexShader)
1111                 {
1112                         return false;
1113                 }
1114
1115                 return localViewer;
1116         }
1117
1118         bool Context::normalizeNormalsActive()
1119         {
1120                 if(vertexShader)
1121                 {
1122                         return false;
1123                 }
1124
1125                 return normalizeNormals;
1126         }
1127
1128         FogMode Context::vertexFogModeActive()
1129         {
1130                 if(vertexShader || !fogActive())
1131                 {
1132                         return FOG_NONE;
1133                 }
1134
1135                 return vertexFogMode;
1136         }
1137
1138         bool Context::rangeFogActive()
1139         {
1140                 if(vertexShader || !fogActive())
1141                 {
1142                         return false;
1143                 }
1144
1145                 return rangeFogEnable;
1146         }
1147
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
1158         int Context::textureTransformCountActive(int stage)
1159         {
1160                 if(vertexShader || !texCoordActive(stage))
1161                 {
1162                         return 0;
1163                 }
1164
1165                 return textureTransformCount[stage];
1166         }
1167
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
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
1198         bool Context::diffuseUsed()
1199         {
1200                 return diffuseUsed(0) || diffuseUsed(1) || diffuseUsed(2) || diffuseUsed(3);
1201         }
1202
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
1246         bool Context::diffuseActive()
1247         {
1248                 return diffuseActive(0) || diffuseActive(1) || diffuseActive(2) || diffuseActive(3);
1249         }
1250
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->getOutput(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
1280         bool Context::specularUsed()
1281         {
1282                 return Context::specularUsed(0) || Context::specularUsed(1) || Context::specularUsed(2) || Context::specularUsed(3);
1283         }
1284
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
1309         bool Context::specularActive()
1310         {
1311                 return specularActive(0) || specularActive(1) || specularActive(2) || specularActive(3);
1312         }
1313
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->getOutput(C1, component).active();
1331                 }
1332
1333                 // Pixel processor requires specular component
1334                 bool pixelSpecular = specularUsed(component);
1335
1336                 return vertexSpecular && pixelSpecular;
1337         }
1338
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
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
1364         bool Context::textureActive(int coordinate)
1365         {
1366                 return textureActive(coordinate, 0) || textureActive(coordinate, 1) || textureActive(coordinate, 2) || textureActive(coordinate, 3);
1367         }
1368
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
1434         unsigned short Context::pixelShaderVersion() const
1435         {
1436                 return pixelShader ? pixelShader->getVersion() : 0x0000;
1437         }
1438
1439         unsigned short Context::vertexShaderVersion() const
1440         {
1441                 return vertexShader ? vertexShader->getVersion() : 0x0000;
1442         }
1443
1444         int Context::getMultiSampleCount() const
1445         {
1446                 return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1;
1447         }
1448
1449         int Context::getSuperSampleCount() const
1450         {
1451                 return renderTarget[0] ? renderTarget[0]->getSuperSampleCount() : 1;
1452         }
1453
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
1466         int Context::colorWriteActive()
1467         {
1468                 return colorWriteActive(0) | colorWriteActive(1) | colorWriteActive(2) | colorWriteActive(3);
1469         }
1470
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
1487         bool Context::colorUsed()
1488         {
1489                 return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->containsKill());
1490         }
1491 }