1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Context.hpp"
16 
17 #include "Primitive.hpp"
18 #include "Surface.hpp"
19 #include "Shader/PixelShader.hpp"
20 #include "Shader/VertexShader.hpp"
21 #include "Common/Memory.hpp"
22 #include "Common/Debug.hpp"
23 
24 #include <string.h>
25 
26 namespace sw
27 {
28 	extern bool perspectiveCorrection;
29 
30 	bool halfIntegerCoordinates = false;     // Pixel centers are not at integer coordinates
31 	bool symmetricNormalizedDepth = false;   // [-1, 1] instead of [0, 1]
32 	bool booleanFaceRegister = false;
33 	bool fullPixelPositionRegister = false;
34 	bool leadingVertexFirst = false;         // Flat shading uses first vertex, else last
35 	bool secondaryColor = false;             // Specular lighting is applied after texturing
36 	bool colorsDefaultToZero = false;
37 
38 	bool forceWindowed = false;
39 	bool quadLayoutEnabled = false;
40 	bool veryEarlyDepthTest = true;
41 	bool complementaryDepthBuffer = false;
42 	bool postBlendSRGB = false;
43 	bool exactColorRounding = false;
44 	TransparencyAntialiasing transparencyAntialiasing = TRANSPARENCY_NONE;
45 	bool forceClearRegisters = false;
46 
Context()47 	Context::Context()
48 	{
49 		init();
50 	}
51 
~Context()52 	Context::~Context()
53 	{
54 	}
55 
operator new(size_t bytes)56 	void *Context::operator new(size_t bytes)
57 	{
58 		return allocate((unsigned int)bytes);
59 	}
60 
operator delete(void * pointer,size_t bytes)61 	void Context::operator delete(void *pointer, size_t bytes)
62 	{
63 		deallocate(pointer);
64 	}
65 
isDrawPoint(bool fillModeAware) const66 	bool Context::isDrawPoint(bool fillModeAware) const
67 	{
68 		switch(drawType)
69 		{
70 		case DRAW_POINTLIST:
71 		case DRAW_INDEXEDPOINTLIST8:
72 		case DRAW_INDEXEDPOINTLIST16:
73 		case DRAW_INDEXEDPOINTLIST32:
74 			return true;
75 		case DRAW_LINELIST:
76 		case DRAW_LINESTRIP:
77 		case DRAW_LINELOOP:
78 		case DRAW_INDEXEDLINELIST8:
79 		case DRAW_INDEXEDLINESTRIP8:
80 		case DRAW_INDEXEDLINELOOP8:
81 		case DRAW_INDEXEDLINELIST16:
82 		case DRAW_INDEXEDLINESTRIP16:
83 		case DRAW_INDEXEDLINELOOP16:
84 		case DRAW_INDEXEDLINELIST32:
85 		case DRAW_INDEXEDLINESTRIP32:
86 		case DRAW_INDEXEDLINELOOP32:
87 			return false;
88 		case DRAW_TRIANGLELIST:
89 		case DRAW_TRIANGLESTRIP:
90 		case DRAW_TRIANGLEFAN:
91 		case DRAW_INDEXEDTRIANGLELIST8:
92 		case DRAW_INDEXEDTRIANGLESTRIP8:
93 		case DRAW_INDEXEDTRIANGLEFAN8:
94 		case DRAW_INDEXEDTRIANGLELIST16:
95 		case DRAW_INDEXEDTRIANGLESTRIP16:
96 		case DRAW_INDEXEDTRIANGLEFAN16:
97 		case DRAW_INDEXEDTRIANGLELIST32:
98 		case DRAW_INDEXEDTRIANGLESTRIP32:
99 		case DRAW_INDEXEDTRIANGLEFAN32:
100 			return fillModeAware ? fillMode == FILL_VERTEX : false;
101 		case DRAW_QUADLIST:
102 			return false;
103 		default:
104 			ASSERT(false);
105 		}
106 
107 		return false;
108 	}
109 
isDrawLine(bool fillModeAware) const110 	bool Context::isDrawLine(bool fillModeAware) const
111 	{
112 		switch(drawType)
113 		{
114 		case DRAW_POINTLIST:
115 		case DRAW_INDEXEDPOINTLIST8:
116 		case DRAW_INDEXEDPOINTLIST16:
117 		case DRAW_INDEXEDPOINTLIST32:
118 			return false;
119 		case DRAW_LINELIST:
120 		case DRAW_LINESTRIP:
121 		case DRAW_LINELOOP:
122 		case DRAW_INDEXEDLINELIST8:
123 		case DRAW_INDEXEDLINESTRIP8:
124 		case DRAW_INDEXEDLINELOOP8:
125 		case DRAW_INDEXEDLINELIST16:
126 		case DRAW_INDEXEDLINESTRIP16:
127 		case DRAW_INDEXEDLINELOOP16:
128 		case DRAW_INDEXEDLINELIST32:
129 		case DRAW_INDEXEDLINESTRIP32:
130 		case DRAW_INDEXEDLINELOOP32:
131 			return true;
132 		case DRAW_TRIANGLELIST:
133 		case DRAW_TRIANGLESTRIP:
134 		case DRAW_TRIANGLEFAN:
135 		case DRAW_INDEXEDTRIANGLELIST8:
136 		case DRAW_INDEXEDTRIANGLESTRIP8:
137 		case DRAW_INDEXEDTRIANGLEFAN8:
138 		case DRAW_INDEXEDTRIANGLELIST16:
139 		case DRAW_INDEXEDTRIANGLESTRIP16:
140 		case DRAW_INDEXEDTRIANGLEFAN16:
141 		case DRAW_INDEXEDTRIANGLELIST32:
142 		case DRAW_INDEXEDTRIANGLESTRIP32:
143 		case DRAW_INDEXEDTRIANGLEFAN32:
144 			return fillModeAware ? fillMode == FILL_WIREFRAME : false;
145 		case DRAW_QUADLIST:
146 			return false;
147 		default:
148 			ASSERT(false);
149 		}
150 
151 		return false;
152 	}
153 
isDrawTriangle(bool fillModeAware) const154 	bool Context::isDrawTriangle(bool fillModeAware) const
155 	{
156 		switch(drawType)
157 		{
158 		case DRAW_POINTLIST:
159 		case DRAW_INDEXEDPOINTLIST8:
160 		case DRAW_INDEXEDPOINTLIST16:
161 		case DRAW_INDEXEDPOINTLIST32:
162 			return false;
163 		case DRAW_LINELIST:
164 		case DRAW_LINESTRIP:
165 		case DRAW_LINELOOP:
166 		case DRAW_INDEXEDLINELIST8:
167 		case DRAW_INDEXEDLINESTRIP8:
168 		case DRAW_INDEXEDLINELOOP8:
169 		case DRAW_INDEXEDLINELIST16:
170 		case DRAW_INDEXEDLINESTRIP16:
171 		case DRAW_INDEXEDLINELOOP16:
172 		case DRAW_INDEXEDLINELIST32:
173 		case DRAW_INDEXEDLINESTRIP32:
174 		case DRAW_INDEXEDLINELOOP32:
175 			return false;
176 		case DRAW_TRIANGLELIST:
177 		case DRAW_TRIANGLESTRIP:
178 		case DRAW_TRIANGLEFAN:
179 		case DRAW_INDEXEDTRIANGLELIST8:
180 		case DRAW_INDEXEDTRIANGLESTRIP8:
181 		case DRAW_INDEXEDTRIANGLEFAN8:
182 		case DRAW_INDEXEDTRIANGLELIST16:
183 		case DRAW_INDEXEDTRIANGLESTRIP16:
184 		case DRAW_INDEXEDTRIANGLEFAN16:
185 		case DRAW_INDEXEDTRIANGLELIST32:
186 		case DRAW_INDEXEDTRIANGLESTRIP32:
187 		case DRAW_INDEXEDTRIANGLEFAN32:
188 			return fillModeAware ? fillMode == FILL_SOLID : true;
189 		case DRAW_QUADLIST:
190 			// Quads are broken up into triangles
191 			return fillModeAware ? fillMode == FILL_SOLID : true;
192 		default:
193 			ASSERT(false);
194 		}
195 
196 		return true;
197 	}
198 
init()199 	void Context::init()
200 	{
201 		for(int i = 0; i < 8; i++)
202 		{
203 			textureStage[i].init(i, &sampler[i], (i >= 1) ? &textureStage[i - 1] : 0);
204 		}
205 
206 		// Set vertex streams to null stream
207 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
208 		{
209 			input[i].defaults();
210 		}
211 
212 		fogStart = 0.0f;
213 		fogEnd = 1.0f;
214 
215 		for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++) textureWrap[i] = 0;
216 		for(int i = 0; i < 8; i++) texGen[i] = TEXGEN_PASSTHRU;
217 		for(int i = 0; i < 8; i++) textureTransformCount[i] = 0;
218 		for(int i = 0; i < 8; i++) textureTransformProject[i] = false;
219 		textureWrapActive = false;
220 		localViewer = true;
221 		normalizeNormals = false;
222 
223 		for(int i = 0; i < RENDERTARGETS; ++i)
224 		{
225 			renderTarget[i] = nullptr;
226 		}
227 		depthBuffer = nullptr;
228 		stencilBuffer = nullptr;
229 
230 		stencilEnable = false;
231 		stencilCompareMode = STENCIL_ALWAYS;
232 		stencilReference = 0;
233 		stencilMask = 0xFFFFFFFF;
234 		stencilFailOperation = OPERATION_KEEP;
235 		stencilPassOperation = OPERATION_KEEP;
236 		stencilZFailOperation = OPERATION_KEEP;
237 		stencilWriteMask = 0xFFFFFFFF;
238 
239 		twoSidedStencil = false;
240 		stencilCompareModeCCW = STENCIL_ALWAYS;
241 		stencilReferenceCCW = 0;
242 		stencilMaskCCW = 0xFFFFFFFF;
243 		stencilFailOperationCCW = OPERATION_KEEP;
244 		stencilPassOperationCCW = OPERATION_KEEP;
245 		stencilZFailOperationCCW = OPERATION_KEEP;
246 		stencilWriteMaskCCW = 0xFFFFFFFF;
247 
248 		setGlobalMipmapBias(0);
249 
250 		lightingEnable = true;
251 		specularEnable = false;
252 		for(int i = 0; i < 8; i++) lightEnable[i] = false;
253 		for(int i = 0; i < 8; i++) worldLightPosition[i] = 0;
254 
255 		alphaCompareMode = ALPHA_ALWAYS;
256 		alphaTestEnable = false;
257 		fillMode = FILL_SOLID;
258 		shadingMode = SHADING_GOURAUD;
259 
260 		rasterizerDiscard = false;
261 
262 		depthCompareMode = DEPTH_LESS;
263 		depthBufferEnable = true;
264 		depthWriteEnable = true;
265 
266 		alphaBlendEnable = false;
267 		sourceBlendFactorState = BLEND_ONE;
268 		destBlendFactorState = BLEND_ZERO;
269 		blendOperationState = BLENDOP_ADD;
270 
271 		separateAlphaBlendEnable = false;
272 		sourceBlendFactorStateAlpha = BLEND_ONE;
273 		destBlendFactorStateAlpha = BLEND_ZERO;
274 		blendOperationStateAlpha = BLENDOP_ADD;
275 
276 		cullMode = CULL_CLOCKWISE;
277 		frontFacingCCW = true;
278 		alphaReference = 0.0f;
279 
280 		depthBias = 0.0f;
281 		slopeDepthBias = 0.0f;
282 
283 		for(int i = 0; i < RENDERTARGETS; i++)
284 		{
285 			colorWriteMask[i] = 0x0000000F;
286 		}
287 
288 		ambientMaterialSource = MATERIAL_MATERIAL;
289 		diffuseMaterialSource = MATERIAL_COLOR1;
290 		specularMaterialSource = MATERIAL_COLOR2;
291 		emissiveMaterialSource = MATERIAL_MATERIAL;
292 		colorVertexEnable = true;
293 
294 		fogEnable = false;
295 		pixelFogMode = FOG_NONE;
296 		vertexFogMode = FOG_NONE;
297 		wBasedFog = false;
298 		rangeFogEnable = false;
299 
300 		indexedVertexBlendEnable = false;
301 		vertexBlendMatrixCount = 0;
302 
303 		pixelShader = 0;
304 		vertexShader = 0;
305 
306 		instanceID = 0;
307 
308 		occlusionEnabled = false;
309 		transformFeedbackQueryEnabled = false;
310 		transformFeedbackEnabled = 0;
311 
312 		pointSpriteEnable = false;
313 		pointScaleEnable = false;
314 		lineWidth = 1.0f;
315 
316 		writeSRGB = false;
317 		sampleMask = 0xFFFFFFFF;
318 
319 		colorLogicOpEnabled = false;
320 		logicalOperation = LOGICALOP_COPY;
321 	}
322 
exp2Bias()323 	const float &Context::exp2Bias()
324 	{
325 		return bias;
326 	}
327 
getLightPosition(int light)328 	const Point &Context::getLightPosition(int light)
329 	{
330 		return worldLightPosition[light];
331 	}
332 
setGlobalMipmapBias(float bias)333 	void Context::setGlobalMipmapBias(float bias)
334 	{
335 		this->bias = exp2(bias + 0.5f);
336 	}
337 
setLightingEnable(bool lightingEnable)338 	void Context::setLightingEnable(bool lightingEnable)
339 	{
340 		this->lightingEnable = lightingEnable;
341 	}
342 
setSpecularEnable(bool specularEnable)343 	void Context::setSpecularEnable(bool specularEnable)
344 	{
345 		Context::specularEnable = specularEnable;
346 	}
347 
setLightEnable(int light,bool lightEnable)348 	void Context::setLightEnable(int light, bool lightEnable)
349 	{
350 		Context::lightEnable[light] = lightEnable;
351 	}
352 
setLightPosition(int light,Point worldLightPosition)353 	void Context::setLightPosition(int light, Point worldLightPosition)
354 	{
355 		Context::worldLightPosition[light] = worldLightPosition;
356 	}
357 
setAmbientMaterialSource(MaterialSource ambientMaterialSource)358 	void Context::setAmbientMaterialSource(MaterialSource ambientMaterialSource)
359 	{
360 		Context::ambientMaterialSource = ambientMaterialSource;
361 	}
362 
setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)363 	void Context::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)
364 	{
365 		Context::diffuseMaterialSource = diffuseMaterialSource;
366 	}
367 
setSpecularMaterialSource(MaterialSource specularMaterialSource)368 	void Context::setSpecularMaterialSource(MaterialSource specularMaterialSource)
369 	{
370 		Context::specularMaterialSource = specularMaterialSource;
371 	}
372 
setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)373 	void Context::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)
374 	{
375 		Context::emissiveMaterialSource = emissiveMaterialSource;
376 	}
377 
setPointSpriteEnable(bool pointSpriteEnable)378 	void Context::setPointSpriteEnable(bool pointSpriteEnable)
379 	{
380 		Context::pointSpriteEnable = pointSpriteEnable;
381 	}
382 
setPointScaleEnable(bool pointScaleEnable)383 	void Context::setPointScaleEnable(bool pointScaleEnable)
384 	{
385 		Context::pointScaleEnable = pointScaleEnable;
386 	}
387 
setDepthBufferEnable(bool depthBufferEnable)388 	bool Context::setDepthBufferEnable(bool depthBufferEnable)
389 	{
390 		bool modified = (Context::depthBufferEnable != depthBufferEnable);
391 		Context::depthBufferEnable = depthBufferEnable;
392 		return modified;
393 	}
394 
setAlphaBlendEnable(bool alphaBlendEnable)395 	bool Context::setAlphaBlendEnable(bool alphaBlendEnable)
396 	{
397 		bool modified = (Context::alphaBlendEnable != alphaBlendEnable);
398 		Context::alphaBlendEnable = alphaBlendEnable;
399 		return modified;
400 	}
401 
setSourceBlendFactor(BlendFactor sourceBlendFactor)402 	bool Context::setSourceBlendFactor(BlendFactor sourceBlendFactor)
403 	{
404 		bool modified = (Context::sourceBlendFactorState != sourceBlendFactor);
405 		Context::sourceBlendFactorState = sourceBlendFactor;
406 		return modified;
407 	}
408 
setDestBlendFactor(BlendFactor destBlendFactor)409 	bool Context::setDestBlendFactor(BlendFactor destBlendFactor)
410 	{
411 		bool modified = (Context::destBlendFactorState != destBlendFactor);
412 		Context::destBlendFactorState = destBlendFactor;
413 		return modified;
414 	}
415 
setBlendOperation(BlendOperation blendOperation)416 	bool Context::setBlendOperation(BlendOperation blendOperation)
417 	{
418 		bool modified = (Context::blendOperationState != blendOperation);
419 		Context::blendOperationState = blendOperation;
420 		return modified;
421 	}
422 
setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)423 	bool Context::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)
424 	{
425 		bool modified = (Context::separateAlphaBlendEnable != separateAlphaBlendEnable);
426 		Context::separateAlphaBlendEnable = separateAlphaBlendEnable;
427 		return modified;
428 	}
429 
setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)430 	bool Context::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)
431 	{
432 		bool modified = (Context::sourceBlendFactorStateAlpha != sourceBlendFactorAlpha);
433 		Context::sourceBlendFactorStateAlpha = sourceBlendFactorAlpha;
434 		return modified;
435 	}
436 
setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)437 	bool Context::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)
438 	{
439 		bool modified = (Context::destBlendFactorStateAlpha != destBlendFactorAlpha);
440 		Context::destBlendFactorStateAlpha = destBlendFactorAlpha;
441 		return modified;
442 	}
443 
setBlendOperationAlpha(BlendOperation blendOperationAlpha)444 	bool Context::setBlendOperationAlpha(BlendOperation blendOperationAlpha)
445 	{
446 		bool modified = (Context::blendOperationStateAlpha != blendOperationAlpha);
447 		Context::blendOperationStateAlpha = blendOperationAlpha;
448 		return modified;
449 	}
450 
setColorWriteMask(int index,int colorWriteMask)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 
setWriteSRGB(bool sRGB)458 	bool Context::setWriteSRGB(bool sRGB)
459 	{
460 		bool modified = (Context::writeSRGB != sRGB);
461 		Context::writeSRGB = sRGB;
462 		return modified;
463 	}
464 
setColorLogicOpEnabled(bool enabled)465 	bool Context::setColorLogicOpEnabled(bool enabled)
466 	{
467 		bool modified = (Context::colorLogicOpEnabled != enabled);
468 		Context::colorLogicOpEnabled = enabled;
469 		return modified;
470 	}
471 
setLogicalOperation(LogicalOperation logicalOperation)472 	bool Context::setLogicalOperation(LogicalOperation logicalOperation)
473 	{
474 		bool modified = (Context::logicalOperation != logicalOperation);
475 		Context::logicalOperation = logicalOperation;
476 		return modified;
477 	}
478 
setColorVertexEnable(bool colorVertexEnable)479 	void Context::setColorVertexEnable(bool colorVertexEnable)
480 	{
481 		Context::colorVertexEnable = colorVertexEnable;
482 	}
483 
fogActive()484 	bool Context::fogActive()
485 	{
486 		if(!colorUsed()) return false;
487 
488 		if(pixelShaderModel() >= 0x0300) return false;
489 
490 		return fogEnable;
491 	}
492 
pointSizeActive()493 	bool Context::pointSizeActive()
494 	{
495 		if(vertexShader)
496 		{
497 			return false;
498 		}
499 
500 		return isDrawPoint(true) && (input[PointSize] || (!preTransformed && pointScaleActive()));
501 	}
502 
pixelFogActive()503 	FogMode Context::pixelFogActive()
504 	{
505 		if(fogActive())
506 		{
507 			return pixelFogMode;
508 		}
509 
510 		return FOG_NONE;
511 	}
512 
depthWriteActive()513 	bool Context::depthWriteActive()
514 	{
515 		if(!depthBufferActive()) return false;
516 
517 		return depthWriteEnable;
518 	}
519 
alphaTestActive()520 	bool Context::alphaTestActive()
521 	{
522 		if(transparencyAntialiasing != TRANSPARENCY_NONE) return true;
523 		if(!alphaTestEnable) return false;
524 		if(alphaCompareMode == ALPHA_ALWAYS) return false;
525 		if(alphaReference == 0.0f && alphaCompareMode == ALPHA_GREATEREQUAL) return false;
526 
527 		return true;
528 	}
529 
depthBufferActive()530 	bool Context::depthBufferActive()
531 	{
532 		return depthBuffer && depthBufferEnable;
533 	}
534 
stencilActive()535 	bool Context::stencilActive()
536 	{
537 		return stencilBuffer && stencilEnable;
538 	}
539 
vertexLightingActive()540 	bool Context::vertexLightingActive()
541 	{
542 		if(vertexShader)
543 		{
544 			return false;
545 		}
546 
547 		return lightingEnable && !preTransformed;
548 	}
549 
texCoordActive(int coordinate,int component)550 	bool Context::texCoordActive(int coordinate, int component)
551 	{
552 		bool hasTexture = pointSpriteActive();
553 
554 		if(vertexShader)
555 		{
556 			if(!preTransformed)
557 			{
558 				if(vertexShader->getOutput(T0 + coordinate, component).usage == Shader::USAGE_TEXCOORD)
559 				{
560 					hasTexture = true;
561 				}
562 			}
563 			else
564 			{
565 				hasTexture = true;   // FIXME: Check vertex buffer streams
566 			}
567 		}
568 		else
569 		{
570 			switch(texGen[coordinate])
571 			{
572 			case TEXGEN_NONE:
573 				hasTexture = true;
574 				break;
575 			case TEXGEN_PASSTHRU:
576 				hasTexture = hasTexture || (component < input[TexCoord0 + textureStage[coordinate].texCoordIndex].count);
577 				break;
578 			case TEXGEN_NORMAL:
579 				hasTexture = hasTexture || (component <= 2);
580 				break;
581 			case TEXGEN_POSITION:
582 				hasTexture = hasTexture || (component <= 2);
583 				break;
584 			case TEXGEN_REFLECTION:
585 				hasTexture = hasTexture || (component <= 2);
586 				break;
587 			case TEXGEN_SPHEREMAP:
588 				hasTexture = hasTexture || (component <= 1);
589 				break;
590 			default:
591 				ASSERT(false);
592 			}
593 		}
594 
595 		bool project = isProjectionComponent(coordinate, component);
596 		bool usesTexture = false;
597 
598 		if(pixelShader)
599 		{
600 			usesTexture = pixelShader->usesTexture(coordinate, component) || project;
601 		}
602 		else
603 		{
604 			usesTexture = textureStage[coordinate].usesTexture() || project;
605 		}
606 
607 		return hasTexture && usesTexture;
608 	}
609 
texCoordActive(int coordinate)610 	bool Context::texCoordActive(int coordinate)
611 	{
612 		return texCoordActive(coordinate, 0) ||
613 		       texCoordActive(coordinate, 1) ||
614 		       texCoordActive(coordinate, 2) ||
615 		       texCoordActive(coordinate, 3);
616 	}
617 
isProjectionComponent(unsigned int coordinate,int component)618 	bool Context::isProjectionComponent(unsigned int coordinate, int component)
619 	{
620 		if(pixelShaderModel() <= 0x0103 && coordinate < 8 && textureTransformProject[coordinate])
621 		{
622 			if(textureTransformCount[coordinate] == 2)
623 			{
624 				if(component == 1) return true;
625 			}
626 			else if(textureTransformCount[coordinate] == 3)
627 			{
628 				if(component == 2) return true;
629 			}
630 			else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0)
631 			{
632 				if(component == 3) return true;
633 			}
634 		}
635 
636 		return false;
637 	}
638 
vertexSpecularActive()639 	bool Context::vertexSpecularActive()
640 	{
641 		return vertexLightingActive() && specularEnable && vertexNormalActive();
642 	}
643 
vertexNormalActive()644 	bool Context::vertexNormalActive()
645 	{
646 		if(vertexShader)
647 		{
648 			return false;
649 		}
650 
651 		return input[Normal];
652 	}
653 
vertexLightActive(int i)654 	bool Context::vertexLightActive(int i)
655 	{
656 		if(vertexShader)
657 		{
658 			return false;
659 		}
660 
661 		return lightingEnable && lightEnable[i];
662 	}
663 
vertexDiffuseMaterialSourceActive()664 	MaterialSource Context::vertexDiffuseMaterialSourceActive()
665 	{
666 		if(vertexShader)
667 		{
668 			return MATERIAL_MATERIAL;
669 		}
670 
671 		if(diffuseMaterialSource == MATERIAL_MATERIAL || !colorVertexEnable ||
672 		   (diffuseMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
673 		   (diffuseMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
674 		{
675 			return MATERIAL_MATERIAL;
676 		}
677 
678 		return diffuseMaterialSource;
679 	}
680 
vertexSpecularMaterialSourceActive()681 	MaterialSource Context::vertexSpecularMaterialSourceActive()
682 	{
683 		if(vertexShader)
684 		{
685 			return MATERIAL_MATERIAL;
686 		}
687 
688 		if(!colorVertexEnable ||
689 		   (specularMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
690 		   (specularMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
691 		{
692 			return MATERIAL_MATERIAL;
693 		}
694 
695 		return specularMaterialSource;
696 	}
697 
vertexAmbientMaterialSourceActive()698 	MaterialSource Context::vertexAmbientMaterialSourceActive()
699 	{
700 		if(vertexShader)
701 		{
702 			return MATERIAL_MATERIAL;
703 		}
704 
705 		if(!colorVertexEnable ||
706 		   (ambientMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
707 		   (ambientMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
708 		{
709 			return MATERIAL_MATERIAL;
710 		}
711 
712 		return ambientMaterialSource;
713 	}
714 
vertexEmissiveMaterialSourceActive()715 	MaterialSource Context::vertexEmissiveMaterialSourceActive()
716 	{
717 		if(vertexShader)
718 		{
719 			return MATERIAL_MATERIAL;
720 		}
721 
722 		if(!colorVertexEnable ||
723 		   (emissiveMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
724 		   (emissiveMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
725 		{
726 			return MATERIAL_MATERIAL;
727 		}
728 
729 		return emissiveMaterialSource;
730 	}
731 
pointSpriteActive()732 	bool Context::pointSpriteActive()
733 	{
734 		return isDrawPoint(true) && pointSpriteEnable;
735 	}
736 
pointScaleActive()737 	bool Context::pointScaleActive()
738 	{
739 		if(vertexShader)
740 		{
741 			return false;
742 		}
743 
744 		return isDrawPoint(true) && pointScaleEnable;
745 	}
746 
alphaBlendActive()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 
colorLogicOp()765 	LogicalOperation Context::colorLogicOp()
766 	{
767 		return colorLogicOpEnabled ? logicalOperation : LOGICALOP_COPY;
768 	}
769 
sourceBlendFactor()770 	BlendFactor Context::sourceBlendFactor()
771 	{
772 		if(!alphaBlendEnable) return BLEND_ONE;
773 
774 		switch(blendOperationState)
775 		{
776 		case BLENDOP_ADD:
777 		case BLENDOP_SUB:
778 		case BLENDOP_INVSUB:
779 			return sourceBlendFactorState;
780 		case BLENDOP_MIN:
781 			return BLEND_ONE;
782 		case BLENDOP_MAX:
783 			return BLEND_ONE;
784 		default:
785 			ASSERT(false);
786 		}
787 
788 		return sourceBlendFactorState;
789 	}
790 
destBlendFactor()791 	BlendFactor Context::destBlendFactor()
792 	{
793 		if(!alphaBlendEnable) return BLEND_ZERO;
794 
795 		switch(blendOperationState)
796 		{
797 		case BLENDOP_ADD:
798 		case BLENDOP_SUB:
799 		case BLENDOP_INVSUB:
800 			return destBlendFactorState;
801 		case BLENDOP_MIN:
802 			return BLEND_ONE;
803 		case BLENDOP_MAX:
804 			return BLEND_ONE;
805 		default:
806 			ASSERT(false);
807 		}
808 
809 		return destBlendFactorState;
810 	}
811 
blendOperation()812 	BlendOperation Context::blendOperation()
813 	{
814 		if(!alphaBlendEnable) return BLENDOP_SOURCE;
815 
816 		switch(blendOperationState)
817 		{
818 		case BLENDOP_ADD:
819 			if(sourceBlendFactor() == BLEND_ZERO)
820 			{
821 				if(destBlendFactor() == BLEND_ZERO)
822 				{
823 					return BLENDOP_NULL;
824 				}
825 				else
826 				{
827 					return BLENDOP_DEST;
828 				}
829 			}
830 			else if(sourceBlendFactor() == BLEND_ONE)
831 			{
832 				if(destBlendFactor() == BLEND_ZERO)
833 				{
834 					return BLENDOP_SOURCE;
835 				}
836 				else
837 				{
838 					return BLENDOP_ADD;
839 				}
840 			}
841 			else
842 			{
843 				if(destBlendFactor() == BLEND_ZERO)
844 				{
845 					return BLENDOP_SOURCE;
846 				}
847 				else
848 				{
849 					return BLENDOP_ADD;
850 				}
851 			}
852 		case BLENDOP_SUB:
853 			if(sourceBlendFactor() == BLEND_ZERO)
854 			{
855 				return BLENDOP_NULL;   // Negative, clamped to zero
856 			}
857 			else if(sourceBlendFactor() == BLEND_ONE)
858 			{
859 				if(destBlendFactor() == BLEND_ZERO)
860 				{
861 					return BLENDOP_SOURCE;
862 				}
863 				else
864 				{
865 					return BLENDOP_SUB;
866 				}
867 			}
868 			else
869 			{
870 				if(destBlendFactor() == BLEND_ZERO)
871 				{
872 					return BLENDOP_SOURCE;
873 				}
874 				else
875 				{
876 					return BLENDOP_SUB;
877 				}
878 			}
879 		case BLENDOP_INVSUB:
880 			if(sourceBlendFactor() == BLEND_ZERO)
881 			{
882 				if(destBlendFactor() == BLEND_ZERO)
883 				{
884 					return BLENDOP_NULL;
885 				}
886 				else
887 				{
888 					return BLENDOP_DEST;
889 				}
890 			}
891 			else if(sourceBlendFactor() == BLEND_ONE)
892 			{
893 				if(destBlendFactor() == BLEND_ZERO)
894 				{
895 					return BLENDOP_NULL;   // Negative, clamped to zero
896 				}
897 				else
898 				{
899 					return BLENDOP_INVSUB;
900 				}
901 			}
902 			else
903 			{
904 				if(destBlendFactor() == BLEND_ZERO)
905 				{
906 					return BLENDOP_NULL;   // Negative, clamped to zero
907 				}
908 				else
909 				{
910 					return BLENDOP_INVSUB;
911 				}
912 			}
913 		case BLENDOP_MIN:
914 			return BLENDOP_MIN;
915 		case BLENDOP_MAX:
916 			return BLENDOP_MAX;
917 		default:
918 			ASSERT(false);
919 		}
920 
921 		return blendOperationState;
922 	}
923 
sourceBlendFactorAlpha()924 	BlendFactor Context::sourceBlendFactorAlpha()
925 	{
926 		if(!separateAlphaBlendEnable)
927 		{
928 			return sourceBlendFactor();
929 		}
930 		else
931 		{
932 			switch(blendOperationStateAlpha)
933 			{
934 			case BLENDOP_ADD:
935 			case BLENDOP_SUB:
936 			case BLENDOP_INVSUB:
937 				return sourceBlendFactorStateAlpha;
938 			case BLENDOP_MIN:
939 				return BLEND_ONE;
940 			case BLENDOP_MAX:
941 				return BLEND_ONE;
942 			default:
943 				ASSERT(false);
944 			}
945 
946 			return sourceBlendFactorStateAlpha;
947 		}
948 	}
949 
destBlendFactorAlpha()950 	BlendFactor Context::destBlendFactorAlpha()
951 	{
952 		if(!separateAlphaBlendEnable)
953 		{
954 			return destBlendFactor();
955 		}
956 		else
957 		{
958 			switch(blendOperationStateAlpha)
959 			{
960 			case BLENDOP_ADD:
961 			case BLENDOP_SUB:
962 			case BLENDOP_INVSUB:
963 				return destBlendFactorStateAlpha;
964 			case BLENDOP_MIN:
965 				return BLEND_ONE;
966 			case BLENDOP_MAX:
967 				return BLEND_ONE;
968 			default:
969 				ASSERT(false);
970 			}
971 
972 			return destBlendFactorStateAlpha;
973 		}
974 	}
975 
blendOperationAlpha()976 	BlendOperation Context::blendOperationAlpha()
977 	{
978 		if(!separateAlphaBlendEnable)
979 		{
980 			return blendOperation();
981 		}
982 		else
983 		{
984 			switch(blendOperationStateAlpha)
985 			{
986 			case BLENDOP_ADD:
987 				if(sourceBlendFactorAlpha() == BLEND_ZERO)
988 				{
989 					if(destBlendFactorAlpha() == BLEND_ZERO)
990 					{
991 						return BLENDOP_NULL;
992 					}
993 					else
994 					{
995 						return BLENDOP_DEST;
996 					}
997 				}
998 				else if(sourceBlendFactorAlpha() == BLEND_ONE)
999 				{
1000 					if(destBlendFactorAlpha() == BLEND_ZERO)
1001 					{
1002 						return BLENDOP_SOURCE;
1003 					}
1004 					else
1005 					{
1006 						return BLENDOP_ADD;
1007 					}
1008 				}
1009 				else
1010 				{
1011 					if(destBlendFactorAlpha() == BLEND_ZERO)
1012 					{
1013 						return BLENDOP_SOURCE;
1014 					}
1015 					else
1016 					{
1017 						return BLENDOP_ADD;
1018 					}
1019 				}
1020 			case BLENDOP_SUB:
1021 				if(sourceBlendFactorAlpha() == BLEND_ZERO)
1022 				{
1023 					return BLENDOP_NULL;   // Negative, clamped to zero
1024 				}
1025 				else if(sourceBlendFactorAlpha() == BLEND_ONE)
1026 				{
1027 					if(destBlendFactorAlpha() == BLEND_ZERO)
1028 					{
1029 						return BLENDOP_SOURCE;
1030 					}
1031 					else
1032 					{
1033 						return BLENDOP_SUB;
1034 					}
1035 				}
1036 				else
1037 				{
1038 					if(destBlendFactorAlpha() == BLEND_ZERO)
1039 					{
1040 						return BLENDOP_SOURCE;
1041 					}
1042 					else
1043 					{
1044 						return BLENDOP_SUB;
1045 					}
1046 				}
1047 			case BLENDOP_INVSUB:
1048 				if(sourceBlendFactorAlpha() == BLEND_ZERO)
1049 				{
1050 					if(destBlendFactorAlpha() == BLEND_ZERO)
1051 					{
1052 						return BLENDOP_NULL;
1053 					}
1054 					else
1055 					{
1056 						return BLENDOP_DEST;
1057 					}
1058 				}
1059 				else if(sourceBlendFactorAlpha() == BLEND_ONE)
1060 				{
1061 					if(destBlendFactorAlpha() == BLEND_ZERO)
1062 					{
1063 						return BLENDOP_NULL;   // Negative, clamped to zero
1064 					}
1065 					else
1066 					{
1067 						return BLENDOP_INVSUB;
1068 					}
1069 				}
1070 				else
1071 				{
1072 					if(destBlendFactorAlpha() == BLEND_ZERO)
1073 					{
1074 						return BLENDOP_NULL;   // Negative, clamped to zero
1075 					}
1076 					else
1077 					{
1078 						return BLENDOP_INVSUB;
1079 					}
1080 				}
1081 			case BLENDOP_MIN:
1082 				return BLENDOP_MIN;
1083 			case BLENDOP_MAX:
1084 				return BLENDOP_MAX;
1085 			default:
1086 				ASSERT(false);
1087 			}
1088 
1089 			return blendOperationStateAlpha;
1090 		}
1091 	}
1092 
indexedVertexBlendActive()1093 	bool Context::indexedVertexBlendActive()
1094 	{
1095 		if(vertexShader)
1096 		{
1097 			return false;
1098 		}
1099 
1100 		return indexedVertexBlendEnable;
1101 	}
1102 
vertexBlendMatrixCountActive()1103 	int Context::vertexBlendMatrixCountActive()
1104 	{
1105 		if(vertexShader)
1106 		{
1107 			return 0;
1108 		}
1109 
1110 		return vertexBlendMatrixCount;
1111 	}
1112 
localViewerActive()1113 	bool Context::localViewerActive()
1114 	{
1115 		if(vertexShader)
1116 		{
1117 			return false;
1118 		}
1119 
1120 		return localViewer;
1121 	}
1122 
normalizeNormalsActive()1123 	bool Context::normalizeNormalsActive()
1124 	{
1125 		if(vertexShader)
1126 		{
1127 			return false;
1128 		}
1129 
1130 		return normalizeNormals;
1131 	}
1132 
vertexFogModeActive()1133 	FogMode Context::vertexFogModeActive()
1134 	{
1135 		if(vertexShader || !fogActive())
1136 		{
1137 			return FOG_NONE;
1138 		}
1139 
1140 		return vertexFogMode;
1141 	}
1142 
rangeFogActive()1143 	bool Context::rangeFogActive()
1144 	{
1145 		if(vertexShader || !fogActive())
1146 		{
1147 			return false;
1148 		}
1149 
1150 		return rangeFogEnable;
1151 	}
1152 
texGenActive(int stage)1153 	TexGen Context::texGenActive(int stage)
1154 	{
1155 		if(vertexShader || !texCoordActive(stage))
1156 		{
1157 			return TEXGEN_PASSTHRU;
1158 		}
1159 
1160 		return texGen[stage];
1161 	}
1162 
textureTransformCountActive(int stage)1163 	int Context::textureTransformCountActive(int stage)
1164 	{
1165 		if(vertexShader || !texCoordActive(stage))
1166 		{
1167 			return 0;
1168 		}
1169 
1170 		return textureTransformCount[stage];
1171 	}
1172 
texCoordIndexActive(int stage)1173 	int Context::texCoordIndexActive(int stage)
1174 	{
1175 		if(vertexShader || !texCoordActive(stage))
1176 		{
1177 			return stage;
1178 		}
1179 
1180 		return textureStage[stage].texCoordIndex;
1181 	}
1182 
perspectiveActive()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 
diffuseUsed()1203 	bool Context::diffuseUsed()
1204 	{
1205 		return diffuseUsed(0) || diffuseUsed(1) || diffuseUsed(2) || diffuseUsed(3);
1206 	}
1207 
diffuseUsed(int component)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 
diffuseActive()1251 	bool Context::diffuseActive()
1252 	{
1253 		return diffuseActive(0) || diffuseActive(1) || diffuseActive(2) || diffuseActive(3);
1254 	}
1255 
diffuseActive(int component)1256 	bool Context::diffuseActive(int component)
1257 	{
1258 		if(!colorUsed())
1259 		{
1260 			return false;
1261 		}
1262 
1263 		// Vertex processor provides diffuse component
1264 		bool vertexDiffuse;
1265 
1266 		if(vertexShader)
1267 		{
1268 			vertexDiffuse = vertexShader->getOutput(C0, component).active();
1269 		}
1270 		else if(!preTransformed)
1271 		{
1272 			vertexDiffuse = input[Color0] || lightingEnable;
1273 		}
1274 		else
1275 		{
1276 			vertexDiffuse = input[Color0];
1277 		}
1278 
1279 		// Pixel processor requires diffuse component
1280 		bool pixelDiffuse = diffuseUsed(component);
1281 
1282 		return vertexDiffuse && pixelDiffuse;
1283 	}
1284 
specularUsed()1285 	bool Context::specularUsed()
1286 	{
1287 		return Context::specularUsed(0) || Context::specularUsed(1) || Context::specularUsed(2) || Context::specularUsed(3);
1288 	}
1289 
specularUsed(int component)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 
specularActive()1314 	bool Context::specularActive()
1315 	{
1316 		return specularActive(0) || specularActive(1) || specularActive(2) || specularActive(3);
1317 	}
1318 
specularActive(int component)1319 	bool Context::specularActive(int component)
1320 	{
1321 		if(!colorUsed())
1322 		{
1323 			return false;
1324 		}
1325 
1326 		// Vertex processor provides specular component
1327 		bool vertexSpecular;
1328 
1329 		if(!vertexShader)
1330 		{
1331 			vertexSpecular = input[Color1] || (lightingEnable && specularEnable);
1332 		}
1333 		else
1334 		{
1335 			vertexSpecular = vertexShader->getOutput(C1, component).active();
1336 		}
1337 
1338 		// Pixel processor requires specular component
1339 		bool pixelSpecular = specularUsed(component);
1340 
1341 		return vertexSpecular && pixelSpecular;
1342 	}
1343 
colorActive(int color,int component)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 
textureActive()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 
textureActive(int coordinate)1369 	bool Context::textureActive(int coordinate)
1370 	{
1371 		return textureActive(coordinate, 0) || textureActive(coordinate, 1) || textureActive(coordinate, 2) || textureActive(coordinate, 3);
1372 	}
1373 
textureActive(int coordinate,int component)1374 	bool Context::textureActive(int coordinate, int component)
1375 	{
1376 		if(!colorUsed())
1377 		{
1378 			return false;
1379 		}
1380 
1381 		if(!texCoordActive(coordinate, component))
1382 		{
1383 			return false;
1384 		}
1385 
1386 		if(textureTransformProject[coordinate] && pixelShaderModel() <= 0x0103)
1387 		{
1388 			if(textureTransformCount[coordinate] == 2)
1389 			{
1390 				if(component == 1) return true;
1391 			}
1392 			else if(textureTransformCount[coordinate] == 3)
1393 			{
1394 				if(component == 2) return true;
1395 			}
1396 			else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0)
1397 			{
1398 				if(component == 3) return true;
1399 			}
1400 		}
1401 
1402 		if(!pixelShader)
1403 		{
1404 			bool texture = textureStage[coordinate].usesTexture();
1405 			bool cube = sampler[coordinate].hasCubeTexture();
1406 			bool volume = sampler[coordinate].hasVolumeTexture();
1407 
1408 			if(texture)
1409 			{
1410 				for(int i = coordinate; i >= 0; i--)
1411 				{
1412 					if(textureStage[i].stageOperation == TextureStage::STAGE_DISABLE)
1413 					{
1414 						return false;
1415 					}
1416 				}
1417 			}
1418 
1419 			switch(component)
1420 			{
1421 			case 0:
1422 				return texture;
1423 			case 1:
1424 				return texture;
1425 			case 2:
1426 				return (texture && (cube || volume));
1427 			case 3:
1428 				return false;
1429 			}
1430 		}
1431 		else
1432 		{
1433 			return pixelShader->usesTexture(coordinate, component);
1434 		}
1435 
1436 		return false;
1437 	}
1438 
pixelShaderModel() const1439 	unsigned short Context::pixelShaderModel() const
1440 	{
1441 		return pixelShader ? pixelShader->getShaderModel() : 0x0000;
1442 	}
1443 
vertexShaderModel() const1444 	unsigned short Context::vertexShaderModel() const
1445 	{
1446 		return vertexShader ? vertexShader->getShaderModel() : 0x0000;
1447 	}
1448 
getMultiSampleCount() const1449 	int Context::getMultiSampleCount() const
1450 	{
1451 		return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1;
1452 	}
1453 
getSuperSampleCount() const1454 	int Context::getSuperSampleCount() const
1455 	{
1456 		return renderTarget[0] ? renderTarget[0]->getSuperSampleCount() : 1;
1457 	}
1458 
renderTargetInternalFormat(int index)1459 	Format Context::renderTargetInternalFormat(int index)
1460 	{
1461 		if(renderTarget[index])
1462 		{
1463 			return renderTarget[index]->getInternalFormat();
1464 		}
1465 		else
1466 		{
1467 			return FORMAT_NULL;
1468 		}
1469 	}
1470 
colorWriteActive()1471 	bool Context::colorWriteActive()
1472 	{
1473 		for (int i = 0; i < RENDERTARGETS; i++)
1474 		{
1475 			if (colorWriteActive(i))
1476 			{
1477 				return true;
1478 			}
1479 		}
1480 
1481 		return false;
1482 	}
1483 
colorWriteActive(int index)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 
colorUsed()1500 	bool Context::colorUsed()
1501 	{
1502 		return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->containsKill());
1503 	}
1504 }
1505