blob: ab54d0bb75d11a19383dad77ce9504ee72d534e1 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// 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.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "Context.hpp"
16
John Bauman89401822014-05-06 15:04:28 -040017#include "Primitive.hpp"
18#include "Surface.hpp"
Nicolas Capens708c24b2017-10-26 13:07:10 -040019#include "Shader/PixelShader.hpp"
20#include "Shader/VertexShader.hpp"
21#include "Common/Memory.hpp"
22#include "Common/Debug.hpp"
John Bauman89401822014-05-06 15:04:28 -040023
24#include <string.h>
John Bauman89401822014-05-06 15:04:28 -040025
26namespace sw
27{
28 extern bool perspectiveCorrection;
29
John Bauman19bac1e2014-05-06 15:23:49 -040030 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;
Nicolas Capens3aa46cb2015-06-03 16:33:02 -040034 bool leadingVertexFirst = false; // Flat shading uses first vertex, else last
Nicolas Capens44ffb652015-08-04 16:11:24 -040035 bool secondaryColor = false; // Specular lighting is applied after texturing
Alexis Hetu56f256e2017-07-21 11:41:13 -040036 bool colorsDefaultToZero = false;
John Bauman19bac1e2014-05-06 15:23:49 -040037
John Bauman89401822014-05-06 15:04:28 -040038 bool forceWindowed = false;
39 bool quadLayoutEnabled = false;
40 bool veryEarlyDepthTest = true;
41 bool complementaryDepthBuffer = false;
42 bool postBlendSRGB = false;
43 bool exactColorRounding = false;
Nicolas Capensa0f4be82014-10-22 14:35:30 -040044 TransparencyAntialiasing transparencyAntialiasing = TRANSPARENCY_NONE;
John Bauman89401822014-05-06 15:04:28 -040045 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;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400101 case DRAW_QUADLIST:
102 return false;
John Bauman89401822014-05-06 15:04:28 -0400103 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;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400145 case DRAW_QUADLIST:
146 return false;
John Bauman89401822014-05-06 15:04:28 -0400147 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;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400189 case DRAW_QUADLIST:
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500190 // Quads are broken up into triangles
Nicolas Capens0bac2852016-05-07 06:09:58 -0400191 return fillModeAware ? fillMode == FILL_SOLID : true;
John Bauman89401822014-05-06 15:04:28 -0400192 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
Nicolas Capensf0aef1a2016-05-18 14:44:21 -0400207 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400208 {
209 input[i].defaults();
210 }
211
John Bauman89401822014-05-06 15:04:28 -0400212 fogStart = 0.0f;
213 fogEnd = 1.0f;
214
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400215 for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++) textureWrap[i] = 0;
John Bauman89401822014-05-06 15:04:28 -0400216 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;
Nicolas Capens895aa622016-01-02 22:01:47 -0500222
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500223 for(int i = 0; i < RENDERTARGETS; ++i)
224 {
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400225 renderTarget[i] = nullptr;
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500226 }
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400227 depthBuffer = nullptr;
228 stencilBuffer = nullptr;
John Bauman89401822014-05-06 15:04:28 -0400229
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;
Nicolas Capens895aa622016-01-02 22:01:47 -0500238
John Bauman89401822014-05-06 15:04:28 -0400239 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
Alexis Hetub0f247f2016-02-22 11:42:39 -0500260 rasterizerDiscard = false;
261
John Bauman89401822014-05-06 15:04:28 -0400262 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;
Nicolas Capensdd4c8632018-07-31 15:33:28 -0400277 frontFacingCCW = true;
Alexis Hetua818c452015-06-11 13:06:58 -0400278 alphaReference = 0.0f;
Nicolas Capensc98186a2016-04-18 12:07:22 -0400279
Nicolas Capens3cbeac52017-09-15 11:49:31 -0400280 depthBias = 0.0f;
281 slopeDepthBias = 0.0f;
282
Nicolas Capensc98186a2016-04-18 12:07:22 -0400283 for(int i = 0; i < RENDERTARGETS; i++)
284 {
285 colorWriteMask[i] = 0x0000000F;
286 }
John Bauman89401822014-05-06 15:04:28 -0400287
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400288 ambientMaterialSource = MATERIAL_MATERIAL;
289 diffuseMaterialSource = MATERIAL_COLOR1;
290 specularMaterialSource = MATERIAL_COLOR2;
291 emissiveMaterialSource = MATERIAL_MATERIAL;
John Bauman89401822014-05-06 15:04:28 -0400292 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
Alexis Hetu6743bbf2015-04-21 17:06:14 -0400306 instanceID = 0;
307
John Bauman89401822014-05-06 15:04:28 -0400308 occlusionEnabled = false;
Alexis Hetu16116cb2016-03-02 15:59:51 -0500309 transformFeedbackQueryEnabled = false;
Alexis Hetu6cb8c6c2016-04-07 11:33:13 -0400310 transformFeedbackEnabled = 0;
John Bauman89401822014-05-06 15:04:28 -0400311
312 pointSpriteEnable = false;
313 pointScaleEnable = false;
Nicolas Capens235781d2015-01-27 01:46:53 -0500314 lineWidth = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400315
316 writeSRGB = false;
317 sampleMask = 0xFFFFFFFF;
Maxime Grégoired9762742015-07-08 16:43:48 -0400318
319 colorLogicOpEnabled = false;
Nicolas Capens2afcc802015-08-04 10:34:43 -0400320 logicalOperation = LOGICALOP_COPY;
John Bauman89401822014-05-06 15:04:28 -0400321 }
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 }
Nicolas Capens895aa622016-01-02 22:01:47 -0500377
John Bauman89401822014-05-06 15:04:28 -0400378 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
Maxime Grégoired9762742015-07-08 16:43:48 -0400465 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
John Bauman89401822014-05-06 15:04:28 -0400479 void Context::setColorVertexEnable(bool colorVertexEnable)
480 {
481 Context::colorVertexEnable = colorVertexEnable;
482 }
483
484 bool Context::fogActive()
485 {
486 if(!colorUsed()) return false;
487
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500488 if(pixelShaderModel() >= 0x0300) return false;
John Bauman89401822014-05-06 15:04:28 -0400489
490 return fogEnable;
491 }
492
493 bool Context::pointSizeActive()
494 {
495 if(vertexShader)
496 {
497 return false;
498 }
499
John Bauman66b8ab22014-05-06 15:57:45 -0400500 return isDrawPoint(true) && (input[PointSize] || (!preTransformed && pointScaleActive()));
John Bauman89401822014-05-06 15:04:28 -0400501 }
502
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400503 FogMode Context::pixelFogActive()
John Bauman89401822014-05-06 15:04:28 -0400504 {
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 {
Alexis Hetua9beed32016-12-13 16:48:01 -0500522 if(transparencyAntialiasing != TRANSPARENCY_NONE) return true;
John Bauman89401822014-05-06 15:04:28 -0400523 if(!alphaTestEnable) return false;
524 if(alphaCompareMode == ALPHA_ALWAYS) return false;
Alexis Hetua818c452015-06-11 13:06:58 -0400525 if(alphaReference == 0.0f && alphaCompareMode == ALPHA_GREATEREQUAL) return false;
Nicolas Capens895aa622016-01-02 22:01:47 -0500526
John Bauman89401822014-05-06 15:04:28 -0400527 return true;
528 }
529
530 bool Context::depthBufferActive()
531 {
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400532 return depthBuffer && depthBufferEnable;
John Bauman89401822014-05-06 15:04:28 -0400533 }
534
535 bool Context::stencilActive()
536 {
Nicolas Capens3751c1e2016-03-21 14:14:14 -0400537 return stencilBuffer && stencilEnable;
John Bauman89401822014-05-06 15:04:28 -0400538 }
539
540 bool Context::vertexLightingActive()
541 {
542 if(vertexShader)
543 {
544 return false;
545 }
546
547 return lightingEnable && !preTransformed;
548 }
549
John Bauman19bac1e2014-05-06 15:23:49 -0400550 bool Context::texCoordActive(int coordinate, int component)
John Bauman89401822014-05-06 15:04:28 -0400551 {
552 bool hasTexture = pointSpriteActive();
553
554 if(vertexShader)
555 {
556 if(!preTransformed)
557 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400558 if(vertexShader->getOutput(T0 + coordinate, component).usage == Shader::USAGE_TEXCOORD)
John Bauman89401822014-05-06 15:04:28 -0400559 {
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 {
Nicolas Capens70583fa2015-05-14 18:17:14 -0400572 case TEXGEN_NONE:
573 hasTexture = true;
574 break;
John Bauman89401822014-05-06 15:04:28 -0400575 case TEXGEN_PASSTHRU:
Nicolas Capensd05a23d2015-01-29 04:07:10 -0500576 hasTexture = hasTexture || (component < input[TexCoord0 + textureStage[coordinate].texCoordIndex].count);
John Bauman89401822014-05-06 15:04:28 -0400577 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
John Bauman19bac1e2014-05-06 15:23:49 -0400610 bool Context::texCoordActive(int coordinate)
John Bauman89401822014-05-06 15:04:28 -0400611 {
John Bauman19bac1e2014-05-06 15:23:49 -0400612 return texCoordActive(coordinate, 0) ||
613 texCoordActive(coordinate, 1) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -0400614 texCoordActive(coordinate, 2) ||
615 texCoordActive(coordinate, 3);
John Bauman89401822014-05-06 15:04:28 -0400616 }
617
618 bool Context::isProjectionComponent(unsigned int coordinate, int component)
619 {
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500620 if(pixelShaderModel() <= 0x0103 && coordinate < 8 && textureTransformProject[coordinate])
John Bauman89401822014-05-06 15:04:28 -0400621 {
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
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400664 MaterialSource Context::vertexDiffuseMaterialSourceActive()
John Bauman89401822014-05-06 15:04:28 -0400665 {
666 if(vertexShader)
667 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400668 return MATERIAL_MATERIAL;
John Bauman89401822014-05-06 15:04:28 -0400669 }
670
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400671 if(diffuseMaterialSource == MATERIAL_MATERIAL || !colorVertexEnable ||
672 (diffuseMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
673 (diffuseMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
John Bauman89401822014-05-06 15:04:28 -0400674 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400675 return MATERIAL_MATERIAL;
John Bauman89401822014-05-06 15:04:28 -0400676 }
Nicolas Capens895aa622016-01-02 22:01:47 -0500677
John Bauman89401822014-05-06 15:04:28 -0400678 return diffuseMaterialSource;
679 }
680
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400681 MaterialSource Context::vertexSpecularMaterialSourceActive()
John Bauman89401822014-05-06 15:04:28 -0400682 {
683 if(vertexShader)
684 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400685 return MATERIAL_MATERIAL;
John Bauman89401822014-05-06 15:04:28 -0400686 }
687
Nicolas Capensd05a23d2015-01-29 04:07:10 -0500688 if(!colorVertexEnable ||
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400689 (specularMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
690 (specularMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
John Bauman89401822014-05-06 15:04:28 -0400691 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400692 return MATERIAL_MATERIAL;
John Bauman89401822014-05-06 15:04:28 -0400693 }
Nicolas Capens895aa622016-01-02 22:01:47 -0500694
John Bauman89401822014-05-06 15:04:28 -0400695 return specularMaterialSource;
696 }
697
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400698 MaterialSource Context::vertexAmbientMaterialSourceActive()
John Bauman89401822014-05-06 15:04:28 -0400699 {
700 if(vertexShader)
701 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400702 return MATERIAL_MATERIAL;
John Bauman89401822014-05-06 15:04:28 -0400703 }
704
Nicolas Capensd05a23d2015-01-29 04:07:10 -0500705 if(!colorVertexEnable ||
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400706 (ambientMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
707 (ambientMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
John Bauman89401822014-05-06 15:04:28 -0400708 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400709 return MATERIAL_MATERIAL;
John Bauman89401822014-05-06 15:04:28 -0400710 }
Nicolas Capens895aa622016-01-02 22:01:47 -0500711
John Bauman89401822014-05-06 15:04:28 -0400712 return ambientMaterialSource;
713 }
714
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400715 MaterialSource Context::vertexEmissiveMaterialSourceActive()
John Bauman89401822014-05-06 15:04:28 -0400716 {
717 if(vertexShader)
718 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400719 return MATERIAL_MATERIAL;
John Bauman89401822014-05-06 15:04:28 -0400720 }
721
Nicolas Capensd05a23d2015-01-29 04:07:10 -0500722 if(!colorVertexEnable ||
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400723 (emissiveMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
724 (emissiveMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
John Bauman89401822014-05-06 15:04:28 -0400725 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400726 return MATERIAL_MATERIAL;
John Bauman89401822014-05-06 15:04:28 -0400727 }
Nicolas Capens895aa622016-01-02 22:01:47 -0500728
John Bauman89401822014-05-06 15:04:28 -0400729 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
Maxime Grégoired9762742015-07-08 16:43:48 -0400765 LogicalOperation Context::colorLogicOp()
766 {
Nicolas Capens2afcc802015-08-04 10:34:43 -0400767 return colorLogicOpEnabled ? logicalOperation : LOGICALOP_COPY;
Maxime Grégoired9762742015-07-08 16:43:48 -0400768 }
769
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400770 BlendFactor Context::sourceBlendFactor()
John Bauman89401822014-05-06 15:04:28 -0400771 {
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:
Nicolas Capens895aa622016-01-02 22:01:47 -0500783 return BLEND_ONE;
John Bauman89401822014-05-06 15:04:28 -0400784 default:
785 ASSERT(false);
786 }
787
788 return sourceBlendFactorState;
789 }
790
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400791 BlendFactor Context::destBlendFactor()
John Bauman89401822014-05-06 15:04:28 -0400792 {
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:
Nicolas Capens895aa622016-01-02 22:01:47 -0500804 return BLEND_ONE;
John Bauman89401822014-05-06 15:04:28 -0400805 default:
806 ASSERT(false);
807 }
808
809 return destBlendFactorState;
810 }
811
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400812 BlendOperation Context::blendOperation()
John Bauman89401822014-05-06 15:04:28 -0400813 {
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
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400924 BlendFactor Context::sourceBlendFactorAlpha()
John Bauman89401822014-05-06 15:04:28 -0400925 {
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:
Nicolas Capens895aa622016-01-02 22:01:47 -0500941 return BLEND_ONE;
John Bauman89401822014-05-06 15:04:28 -0400942 default:
943 ASSERT(false);
944 }
945
946 return sourceBlendFactorStateAlpha;
947 }
948 }
949
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400950 BlendFactor Context::destBlendFactorAlpha()
John Bauman89401822014-05-06 15:04:28 -0400951 {
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:
Nicolas Capens895aa622016-01-02 22:01:47 -0500967 return BLEND_ONE;
John Bauman89401822014-05-06 15:04:28 -0400968 default:
969 ASSERT(false);
970 }
971
972 return destBlendFactorStateAlpha;
973 }
974 }
975
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400976 BlendOperation Context::blendOperationAlpha()
John Bauman89401822014-05-06 15:04:28 -0400977 {
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
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001133 FogMode Context::vertexFogModeActive()
John Bauman89401822014-05-06 15:04:28 -04001134 {
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
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001153 TexGen Context::texGenActive(int stage)
John Bauman89401822014-05-06 15:04:28 -04001154 {
John Bauman19bac1e2014-05-06 15:23:49 -04001155 if(vertexShader || !texCoordActive(stage))
John Bauman89401822014-05-06 15:04:28 -04001156 {
1157 return TEXGEN_PASSTHRU;
1158 }
1159
1160 return texGen[stage];
1161 }
Nicolas Capens895aa622016-01-02 22:01:47 -05001162
John Bauman89401822014-05-06 15:04:28 -04001163 int Context::textureTransformCountActive(int stage)
1164 {
John Bauman19bac1e2014-05-06 15:23:49 -04001165 if(vertexShader || !texCoordActive(stage))
John Bauman89401822014-05-06 15:04:28 -04001166 {
1167 return 0;
1168 }
1169
1170 return textureTransformCount[stage];
1171 }
1172
1173 int Context::texCoordIndexActive(int stage)
1174 {
John Bauman19bac1e2014-05-06 15:23:49 -04001175 if(vertexShader || !texCoordActive(stage))
John Bauman89401822014-05-06 15:04:28 -04001176 {
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;
Nicolas Capens895aa622016-01-02 22:01:47 -05001265
John Bauman89401822014-05-06 15:04:28 -04001266 if(vertexShader)
1267 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -04001268 vertexDiffuse = vertexShader->getOutput(C0, component).active();
John Bauman89401822014-05-06 15:04:28 -04001269 }
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;
Nicolas Capens895aa622016-01-02 22:01:47 -05001328
John Bauman89401822014-05-06 15:04:28 -04001329 if(!vertexShader)
1330 {
1331 vertexSpecular = input[Color1] || (lightingEnable && specularEnable);
1332 }
1333 else
1334 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -04001335 vertexSpecular = vertexShader->getOutput(C1, component).active();
John Bauman89401822014-05-06 15:04:28 -04001336 }
1337
1338 // Pixel processor requires specular component
Nicolas Capens5767c7d2015-01-29 04:48:40 -05001339 bool pixelSpecular = specularUsed(component);
John Bauman89401822014-05-06 15:04:28 -04001340
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
John Bauman19bac1e2014-05-06 15:23:49 -04001374 bool Context::textureActive(int coordinate, int component)
John Bauman89401822014-05-06 15:04:28 -04001375 {
1376 if(!colorUsed())
1377 {
1378 return false;
1379 }
1380
John Bauman19bac1e2014-05-06 15:23:49 -04001381 if(!texCoordActive(coordinate, component))
John Bauman89401822014-05-06 15:04:28 -04001382 {
1383 return false;
1384 }
1385
Alexis Hetu53ad4af2017-12-06 14:49:07 -05001386 if(textureTransformProject[coordinate] && pixelShaderModel() <= 0x0103)
John Bauman89401822014-05-06 15:04:28 -04001387 {
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 {
Nicolas Capens5767c7d2015-01-29 04:48:40 -05001410 for(int i = coordinate; i >= 0; i--)
John Bauman89401822014-05-06 15:04:28 -04001411 {
1412 if(textureStage[i].stageOperation == TextureStage::STAGE_DISABLE)
1413 {
Nicolas Capens5767c7d2015-01-29 04:48:40 -05001414 return false;
John Bauman89401822014-05-06 15:04:28 -04001415 }
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
Alexis Hetu53ad4af2017-12-06 14:49:07 -05001439 unsigned short Context::pixelShaderModel() const
John Bauman89401822014-05-06 15:04:28 -04001440 {
Alexis Hetu53ad4af2017-12-06 14:49:07 -05001441 return pixelShader ? pixelShader->getShaderModel() : 0x0000;
John Bauman89401822014-05-06 15:04:28 -04001442 }
1443
Alexis Hetu53ad4af2017-12-06 14:49:07 -05001444 unsigned short Context::vertexShaderModel() const
John Bauman89401822014-05-06 15:04:28 -04001445 {
Alexis Hetu53ad4af2017-12-06 14:49:07 -05001446 return vertexShader ? vertexShader->getShaderModel() : 0x0000;
John Bauman89401822014-05-06 15:04:28 -04001447 }
1448
John Bauman66b8ab22014-05-06 15:57:45 -04001449 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
John Bauman89401822014-05-06 15:04:28 -04001459 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
Chris Forbesbc63cf92019-02-28 09:03:38 -08001471 bool Context::colorWriteActive()
John Bauman89401822014-05-06 15:04:28 -04001472 {
Chris Forbesbc63cf92019-02-28 09:03:38 -08001473 for (int i = 0; i < RENDERTARGETS; i++)
1474 {
1475 if (colorWriteActive(i))
1476 {
1477 return true;
1478 }
1479 }
1480
1481 return false;
John Bauman89401822014-05-06 15:04:28 -04001482 }
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 {
John Bauman19bac1e2014-05-06 15:23:49 -04001502 return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->containsKill());
John Bauman89401822014-05-06 15:04:28 -04001503 }
1504}