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