• 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 "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 		alphaReference = 0.0f;
278 
279 		depthBias = 0.0f;
280 		slopeDepthBias = 0.0f;
281 
282 		for(int i = 0; i < RENDERTARGETS; i++)
283 		{
284 			colorWriteMask[i] = 0x0000000F;
285 		}
286 
287 		ambientMaterialSource = MATERIAL_MATERIAL;
288 		diffuseMaterialSource = MATERIAL_COLOR1;
289 		specularMaterialSource = MATERIAL_COLOR2;
290 		emissiveMaterialSource = MATERIAL_MATERIAL;
291 		colorVertexEnable = true;
292 
293 		fogEnable = false;
294 		pixelFogMode = FOG_NONE;
295 		vertexFogMode = FOG_NONE;
296 		wBasedFog = false;
297 		rangeFogEnable = false;
298 
299 		indexedVertexBlendEnable = false;
300 		vertexBlendMatrixCount = 0;
301 
302 		pixelShader = 0;
303 		vertexShader = 0;
304 
305 		instanceID = 0;
306 
307 		occlusionEnabled = false;
308 		transformFeedbackQueryEnabled = false;
309 		transformFeedbackEnabled = 0;
310 
311 		pointSpriteEnable = false;
312 		pointScaleEnable = false;
313 		lineWidth = 1.0f;
314 
315 		writeSRGB = false;
316 		sampleMask = 0xFFFFFFFF;
317 
318 		colorLogicOpEnabled = false;
319 		logicalOperation = LOGICALOP_COPY;
320 	}
321 
exp2Bias()322 	const float &Context::exp2Bias()
323 	{
324 		return bias;
325 	}
326 
getLightPosition(int light)327 	const Point &Context::getLightPosition(int light)
328 	{
329 		return worldLightPosition[light];
330 	}
331 
setGlobalMipmapBias(float bias)332 	void Context::setGlobalMipmapBias(float bias)
333 	{
334 		this->bias = exp2(bias + 0.5f);
335 	}
336 
setLightingEnable(bool lightingEnable)337 	void Context::setLightingEnable(bool lightingEnable)
338 	{
339 		this->lightingEnable = lightingEnable;
340 	}
341 
setSpecularEnable(bool specularEnable)342 	void Context::setSpecularEnable(bool specularEnable)
343 	{
344 		Context::specularEnable = specularEnable;
345 	}
346 
setLightEnable(int light,bool lightEnable)347 	void Context::setLightEnable(int light, bool lightEnable)
348 	{
349 		Context::lightEnable[light] = lightEnable;
350 	}
351 
setLightPosition(int light,Point worldLightPosition)352 	void Context::setLightPosition(int light, Point worldLightPosition)
353 	{
354 		Context::worldLightPosition[light] = worldLightPosition;
355 	}
356 
setAmbientMaterialSource(MaterialSource ambientMaterialSource)357 	void Context::setAmbientMaterialSource(MaterialSource ambientMaterialSource)
358 	{
359 		Context::ambientMaterialSource = ambientMaterialSource;
360 	}
361 
setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)362 	void Context::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)
363 	{
364 		Context::diffuseMaterialSource = diffuseMaterialSource;
365 	}
366 
setSpecularMaterialSource(MaterialSource specularMaterialSource)367 	void Context::setSpecularMaterialSource(MaterialSource specularMaterialSource)
368 	{
369 		Context::specularMaterialSource = specularMaterialSource;
370 	}
371 
setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)372 	void Context::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)
373 	{
374 		Context::emissiveMaterialSource = emissiveMaterialSource;
375 	}
376 
setPointSpriteEnable(bool pointSpriteEnable)377 	void Context::setPointSpriteEnable(bool pointSpriteEnable)
378 	{
379 		Context::pointSpriteEnable = pointSpriteEnable;
380 	}
381 
setPointScaleEnable(bool pointScaleEnable)382 	void Context::setPointScaleEnable(bool pointScaleEnable)
383 	{
384 		Context::pointScaleEnable = pointScaleEnable;
385 	}
386 
setDepthBufferEnable(bool depthBufferEnable)387 	bool Context::setDepthBufferEnable(bool depthBufferEnable)
388 	{
389 		bool modified = (Context::depthBufferEnable != depthBufferEnable);
390 		Context::depthBufferEnable = depthBufferEnable;
391 		return modified;
392 	}
393 
setAlphaBlendEnable(bool alphaBlendEnable)394 	bool Context::setAlphaBlendEnable(bool alphaBlendEnable)
395 	{
396 		bool modified = (Context::alphaBlendEnable != alphaBlendEnable);
397 		Context::alphaBlendEnable = alphaBlendEnable;
398 		return modified;
399 	}
400 
setSourceBlendFactor(BlendFactor sourceBlendFactor)401 	bool Context::setSourceBlendFactor(BlendFactor sourceBlendFactor)
402 	{
403 		bool modified = (Context::sourceBlendFactorState != sourceBlendFactor);
404 		Context::sourceBlendFactorState = sourceBlendFactor;
405 		return modified;
406 	}
407 
setDestBlendFactor(BlendFactor destBlendFactor)408 	bool Context::setDestBlendFactor(BlendFactor destBlendFactor)
409 	{
410 		bool modified = (Context::destBlendFactorState != destBlendFactor);
411 		Context::destBlendFactorState = destBlendFactor;
412 		return modified;
413 	}
414 
setBlendOperation(BlendOperation blendOperation)415 	bool Context::setBlendOperation(BlendOperation blendOperation)
416 	{
417 		bool modified = (Context::blendOperationState != blendOperation);
418 		Context::blendOperationState = blendOperation;
419 		return modified;
420 	}
421 
setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)422 	bool Context::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)
423 	{
424 		bool modified = (Context::separateAlphaBlendEnable != separateAlphaBlendEnable);
425 		Context::separateAlphaBlendEnable = separateAlphaBlendEnable;
426 		return modified;
427 	}
428 
setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)429 	bool Context::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)
430 	{
431 		bool modified = (Context::sourceBlendFactorStateAlpha != sourceBlendFactorAlpha);
432 		Context::sourceBlendFactorStateAlpha = sourceBlendFactorAlpha;
433 		return modified;
434 	}
435 
setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)436 	bool Context::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)
437 	{
438 		bool modified = (Context::destBlendFactorStateAlpha != destBlendFactorAlpha);
439 		Context::destBlendFactorStateAlpha = destBlendFactorAlpha;
440 		return modified;
441 	}
442 
setBlendOperationAlpha(BlendOperation blendOperationAlpha)443 	bool Context::setBlendOperationAlpha(BlendOperation blendOperationAlpha)
444 	{
445 		bool modified = (Context::blendOperationStateAlpha != blendOperationAlpha);
446 		Context::blendOperationStateAlpha = blendOperationAlpha;
447 		return modified;
448 	}
449 
setColorWriteMask(int index,int colorWriteMask)450 	bool Context::setColorWriteMask(int index, int colorWriteMask)
451 	{
452 		bool modified = (Context::colorWriteMask[index] != colorWriteMask);
453 		Context::colorWriteMask[index] = colorWriteMask;
454 		return modified;
455 	}
456 
setWriteSRGB(bool sRGB)457 	bool Context::setWriteSRGB(bool sRGB)
458 	{
459 		bool modified = (Context::writeSRGB != sRGB);
460 		Context::writeSRGB = sRGB;
461 		return modified;
462 	}
463 
setColorLogicOpEnabled(bool enabled)464 	bool Context::setColorLogicOpEnabled(bool enabled)
465 	{
466 		bool modified = (Context::colorLogicOpEnabled != enabled);
467 		Context::colorLogicOpEnabled = enabled;
468 		return modified;
469 	}
470 
setLogicalOperation(LogicalOperation logicalOperation)471 	bool Context::setLogicalOperation(LogicalOperation logicalOperation)
472 	{
473 		bool modified = (Context::logicalOperation != logicalOperation);
474 		Context::logicalOperation = logicalOperation;
475 		return modified;
476 	}
477 
setColorVertexEnable(bool colorVertexEnable)478 	void Context::setColorVertexEnable(bool colorVertexEnable)
479 	{
480 		Context::colorVertexEnable = colorVertexEnable;
481 	}
482 
fogActive()483 	bool Context::fogActive()
484 	{
485 		if(!colorUsed()) return false;
486 
487 		if(pixelShaderModel() >= 0x0300) return false;
488 
489 		return fogEnable;
490 	}
491 
pointSizeActive()492 	bool Context::pointSizeActive()
493 	{
494 		if(vertexShader)
495 		{
496 			return false;
497 		}
498 
499 		return isDrawPoint(true) && (input[PointSize] || (!preTransformed && pointScaleActive()));
500 	}
501 
pixelFogActive()502 	FogMode Context::pixelFogActive()
503 	{
504 		if(fogActive())
505 		{
506 			return pixelFogMode;
507 		}
508 
509 		return FOG_NONE;
510 	}
511 
depthWriteActive()512 	bool Context::depthWriteActive()
513 	{
514 		if(!depthBufferActive()) return false;
515 
516 		return depthWriteEnable;
517 	}
518 
alphaTestActive()519 	bool Context::alphaTestActive()
520 	{
521 		if(transparencyAntialiasing != TRANSPARENCY_NONE) return true;
522 		if(!alphaTestEnable) return false;
523 		if(alphaCompareMode == ALPHA_ALWAYS) return false;
524 		if(alphaReference == 0.0f && alphaCompareMode == ALPHA_GREATEREQUAL) return false;
525 
526 		return true;
527 	}
528 
depthBufferActive()529 	bool Context::depthBufferActive()
530 	{
531 		return depthBuffer && depthBufferEnable;
532 	}
533 
stencilActive()534 	bool Context::stencilActive()
535 	{
536 		return stencilBuffer && stencilEnable;
537 	}
538 
vertexLightingActive()539 	bool Context::vertexLightingActive()
540 	{
541 		if(vertexShader)
542 		{
543 			return false;
544 		}
545 
546 		return lightingEnable && !preTransformed;
547 	}
548 
texCoordActive(int coordinate,int component)549 	bool Context::texCoordActive(int coordinate, int component)
550 	{
551 		bool hasTexture = pointSpriteActive();
552 
553 		if(vertexShader)
554 		{
555 			if(!preTransformed)
556 			{
557 				if(vertexShader->getOutput(T0 + coordinate, component).usage == Shader::USAGE_TEXCOORD)
558 				{
559 					hasTexture = true;
560 				}
561 			}
562 			else
563 			{
564 				hasTexture = true;   // FIXME: Check vertex buffer streams
565 			}
566 		}
567 		else
568 		{
569 			switch(texGen[coordinate])
570 			{
571 			case TEXGEN_NONE:
572 				hasTexture = true;
573 				break;
574 			case TEXGEN_PASSTHRU:
575 				hasTexture = hasTexture || (component < input[TexCoord0 + textureStage[coordinate].texCoordIndex].count);
576 				break;
577 			case TEXGEN_NORMAL:
578 				hasTexture = hasTexture || (component <= 2);
579 				break;
580 			case TEXGEN_POSITION:
581 				hasTexture = hasTexture || (component <= 2);
582 				break;
583 			case TEXGEN_REFLECTION:
584 				hasTexture = hasTexture || (component <= 2);
585 				break;
586 			case TEXGEN_SPHEREMAP:
587 				hasTexture = hasTexture || (component <= 1);
588 				break;
589 			default:
590 				ASSERT(false);
591 			}
592 		}
593 
594 		bool project = isProjectionComponent(coordinate, component);
595 		bool usesTexture = false;
596 
597 		if(pixelShader)
598 		{
599 			usesTexture = pixelShader->usesTexture(coordinate, component) || project;
600 		}
601 		else
602 		{
603 			usesTexture = textureStage[coordinate].usesTexture() || project;
604 		}
605 
606 		return hasTexture && usesTexture;
607 	}
608 
texCoordActive(int coordinate)609 	bool Context::texCoordActive(int coordinate)
610 	{
611 		return texCoordActive(coordinate, 0) ||
612 		       texCoordActive(coordinate, 1) ||
613 		       texCoordActive(coordinate, 2) ||
614 		       texCoordActive(coordinate, 3);
615 	}
616 
isProjectionComponent(unsigned int coordinate,int component)617 	bool Context::isProjectionComponent(unsigned int coordinate, int component)
618 	{
619 		if(pixelShaderModel() <= 0x0103 && coordinate < 8 && textureTransformProject[coordinate])
620 		{
621 			if(textureTransformCount[coordinate] == 2)
622 			{
623 				if(component == 1) return true;
624 			}
625 			else if(textureTransformCount[coordinate] == 3)
626 			{
627 				if(component == 2) return true;
628 			}
629 			else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0)
630 			{
631 				if(component == 3) return true;
632 			}
633 		}
634 
635 		return false;
636 	}
637 
vertexSpecularActive()638 	bool Context::vertexSpecularActive()
639 	{
640 		return vertexLightingActive() && specularEnable && vertexNormalActive();
641 	}
642 
vertexNormalActive()643 	bool Context::vertexNormalActive()
644 	{
645 		if(vertexShader)
646 		{
647 			return false;
648 		}
649 
650 		return input[Normal];
651 	}
652 
vertexLightActive(int i)653 	bool Context::vertexLightActive(int i)
654 	{
655 		if(vertexShader)
656 		{
657 			return false;
658 		}
659 
660 		return lightingEnable && lightEnable[i];
661 	}
662 
vertexDiffuseMaterialSourceActive()663 	MaterialSource Context::vertexDiffuseMaterialSourceActive()
664 	{
665 		if(vertexShader)
666 		{
667 			return MATERIAL_MATERIAL;
668 		}
669 
670 		if(diffuseMaterialSource == MATERIAL_MATERIAL || !colorVertexEnable ||
671 		   (diffuseMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
672 		   (diffuseMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
673 		{
674 			return MATERIAL_MATERIAL;
675 		}
676 
677 		return diffuseMaterialSource;
678 	}
679 
vertexSpecularMaterialSourceActive()680 	MaterialSource Context::vertexSpecularMaterialSourceActive()
681 	{
682 		if(vertexShader)
683 		{
684 			return MATERIAL_MATERIAL;
685 		}
686 
687 		if(!colorVertexEnable ||
688 		   (specularMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
689 		   (specularMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
690 		{
691 			return MATERIAL_MATERIAL;
692 		}
693 
694 		return specularMaterialSource;
695 	}
696 
vertexAmbientMaterialSourceActive()697 	MaterialSource Context::vertexAmbientMaterialSourceActive()
698 	{
699 		if(vertexShader)
700 		{
701 			return MATERIAL_MATERIAL;
702 		}
703 
704 		if(!colorVertexEnable ||
705 		   (ambientMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
706 		   (ambientMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
707 		{
708 			return MATERIAL_MATERIAL;
709 		}
710 
711 		return ambientMaterialSource;
712 	}
713 
vertexEmissiveMaterialSourceActive()714 	MaterialSource Context::vertexEmissiveMaterialSourceActive()
715 	{
716 		if(vertexShader)
717 		{
718 			return MATERIAL_MATERIAL;
719 		}
720 
721 		if(!colorVertexEnable ||
722 		   (emissiveMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
723 		   (emissiveMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
724 		{
725 			return MATERIAL_MATERIAL;
726 		}
727 
728 		return emissiveMaterialSource;
729 	}
730 
pointSpriteActive()731 	bool Context::pointSpriteActive()
732 	{
733 		return isDrawPoint(true) && pointSpriteEnable;
734 	}
735 
pointScaleActive()736 	bool Context::pointScaleActive()
737 	{
738 		if(vertexShader)
739 		{
740 			return false;
741 		}
742 
743 		return isDrawPoint(true) && pointScaleEnable;
744 	}
745 
alphaBlendActive()746 	bool Context::alphaBlendActive()
747 	{
748 		if(!alphaBlendEnable)
749 		{
750 			return false;
751 		}
752 
753 		if(!colorUsed())
754 		{
755 			return false;
756 		}
757 
758 		bool colorBlend = !(blendOperation() == BLENDOP_SOURCE && sourceBlendFactor() == BLEND_ONE);
759 		bool alphaBlend = separateAlphaBlendEnable ? !(blendOperationAlpha() == BLENDOP_SOURCE && sourceBlendFactorAlpha() == BLEND_ONE) : colorBlend;
760 
761 		return colorBlend || alphaBlend;
762 	}
763 
colorLogicOp()764 	LogicalOperation Context::colorLogicOp()
765 	{
766 		return colorLogicOpEnabled ? logicalOperation : LOGICALOP_COPY;
767 	}
768 
sourceBlendFactor()769 	BlendFactor Context::sourceBlendFactor()
770 	{
771 		if(!alphaBlendEnable) return BLEND_ONE;
772 
773 		switch(blendOperationState)
774 		{
775 		case BLENDOP_ADD:
776 		case BLENDOP_SUB:
777 		case BLENDOP_INVSUB:
778 			return sourceBlendFactorState;
779 		case BLENDOP_MIN:
780 			return BLEND_ONE;
781 		case BLENDOP_MAX:
782 			return BLEND_ONE;
783 		default:
784 			ASSERT(false);
785 		}
786 
787 		return sourceBlendFactorState;
788 	}
789 
destBlendFactor()790 	BlendFactor Context::destBlendFactor()
791 	{
792 		if(!alphaBlendEnable) return BLEND_ZERO;
793 
794 		switch(blendOperationState)
795 		{
796 		case BLENDOP_ADD:
797 		case BLENDOP_SUB:
798 		case BLENDOP_INVSUB:
799 			return destBlendFactorState;
800 		case BLENDOP_MIN:
801 			return BLEND_ONE;
802 		case BLENDOP_MAX:
803 			return BLEND_ONE;
804 		default:
805 			ASSERT(false);
806 		}
807 
808 		return destBlendFactorState;
809 	}
810 
blendOperation()811 	BlendOperation Context::blendOperation()
812 	{
813 		if(!alphaBlendEnable) return BLENDOP_SOURCE;
814 
815 		switch(blendOperationState)
816 		{
817 		case BLENDOP_ADD:
818 			if(sourceBlendFactor() == BLEND_ZERO)
819 			{
820 				if(destBlendFactor() == BLEND_ZERO)
821 				{
822 					return BLENDOP_NULL;
823 				}
824 				else
825 				{
826 					return BLENDOP_DEST;
827 				}
828 			}
829 			else if(sourceBlendFactor() == BLEND_ONE)
830 			{
831 				if(destBlendFactor() == BLEND_ZERO)
832 				{
833 					return BLENDOP_SOURCE;
834 				}
835 				else
836 				{
837 					return BLENDOP_ADD;
838 				}
839 			}
840 			else
841 			{
842 				if(destBlendFactor() == BLEND_ZERO)
843 				{
844 					return BLENDOP_SOURCE;
845 				}
846 				else
847 				{
848 					return BLENDOP_ADD;
849 				}
850 			}
851 		case BLENDOP_SUB:
852 			if(sourceBlendFactor() == BLEND_ZERO)
853 			{
854 				return BLENDOP_NULL;   // Negative, clamped to zero
855 			}
856 			else if(sourceBlendFactor() == BLEND_ONE)
857 			{
858 				if(destBlendFactor() == BLEND_ZERO)
859 				{
860 					return BLENDOP_SOURCE;
861 				}
862 				else
863 				{
864 					return BLENDOP_SUB;
865 				}
866 			}
867 			else
868 			{
869 				if(destBlendFactor() == BLEND_ZERO)
870 				{
871 					return BLENDOP_SOURCE;
872 				}
873 				else
874 				{
875 					return BLENDOP_SUB;
876 				}
877 			}
878 		case BLENDOP_INVSUB:
879 			if(sourceBlendFactor() == BLEND_ZERO)
880 			{
881 				if(destBlendFactor() == BLEND_ZERO)
882 				{
883 					return BLENDOP_NULL;
884 				}
885 				else
886 				{
887 					return BLENDOP_DEST;
888 				}
889 			}
890 			else if(sourceBlendFactor() == BLEND_ONE)
891 			{
892 				if(destBlendFactor() == BLEND_ZERO)
893 				{
894 					return BLENDOP_NULL;   // Negative, clamped to zero
895 				}
896 				else
897 				{
898 					return BLENDOP_INVSUB;
899 				}
900 			}
901 			else
902 			{
903 				if(destBlendFactor() == BLEND_ZERO)
904 				{
905 					return BLENDOP_NULL;   // Negative, clamped to zero
906 				}
907 				else
908 				{
909 					return BLENDOP_INVSUB;
910 				}
911 			}
912 		case BLENDOP_MIN:
913 			return BLENDOP_MIN;
914 		case BLENDOP_MAX:
915 			return BLENDOP_MAX;
916 		default:
917 			ASSERT(false);
918 		}
919 
920 		return blendOperationState;
921 	}
922 
sourceBlendFactorAlpha()923 	BlendFactor Context::sourceBlendFactorAlpha()
924 	{
925 		if(!separateAlphaBlendEnable)
926 		{
927 			return sourceBlendFactor();
928 		}
929 		else
930 		{
931 			switch(blendOperationStateAlpha)
932 			{
933 			case BLENDOP_ADD:
934 			case BLENDOP_SUB:
935 			case BLENDOP_INVSUB:
936 				return sourceBlendFactorStateAlpha;
937 			case BLENDOP_MIN:
938 				return BLEND_ONE;
939 			case BLENDOP_MAX:
940 				return BLEND_ONE;
941 			default:
942 				ASSERT(false);
943 			}
944 
945 			return sourceBlendFactorStateAlpha;
946 		}
947 	}
948 
destBlendFactorAlpha()949 	BlendFactor Context::destBlendFactorAlpha()
950 	{
951 		if(!separateAlphaBlendEnable)
952 		{
953 			return destBlendFactor();
954 		}
955 		else
956 		{
957 			switch(blendOperationStateAlpha)
958 			{
959 			case BLENDOP_ADD:
960 			case BLENDOP_SUB:
961 			case BLENDOP_INVSUB:
962 				return destBlendFactorStateAlpha;
963 			case BLENDOP_MIN:
964 				return BLEND_ONE;
965 			case BLENDOP_MAX:
966 				return BLEND_ONE;
967 			default:
968 				ASSERT(false);
969 			}
970 
971 			return destBlendFactorStateAlpha;
972 		}
973 	}
974 
blendOperationAlpha()975 	BlendOperation Context::blendOperationAlpha()
976 	{
977 		if(!separateAlphaBlendEnable)
978 		{
979 			return blendOperation();
980 		}
981 		else
982 		{
983 			switch(blendOperationStateAlpha)
984 			{
985 			case BLENDOP_ADD:
986 				if(sourceBlendFactorAlpha() == BLEND_ZERO)
987 				{
988 					if(destBlendFactorAlpha() == BLEND_ZERO)
989 					{
990 						return BLENDOP_NULL;
991 					}
992 					else
993 					{
994 						return BLENDOP_DEST;
995 					}
996 				}
997 				else if(sourceBlendFactorAlpha() == BLEND_ONE)
998 				{
999 					if(destBlendFactorAlpha() == BLEND_ZERO)
1000 					{
1001 						return BLENDOP_SOURCE;
1002 					}
1003 					else
1004 					{
1005 						return BLENDOP_ADD;
1006 					}
1007 				}
1008 				else
1009 				{
1010 					if(destBlendFactorAlpha() == BLEND_ZERO)
1011 					{
1012 						return BLENDOP_SOURCE;
1013 					}
1014 					else
1015 					{
1016 						return BLENDOP_ADD;
1017 					}
1018 				}
1019 			case BLENDOP_SUB:
1020 				if(sourceBlendFactorAlpha() == BLEND_ZERO)
1021 				{
1022 					return BLENDOP_NULL;   // Negative, clamped to zero
1023 				}
1024 				else if(sourceBlendFactorAlpha() == BLEND_ONE)
1025 				{
1026 					if(destBlendFactorAlpha() == BLEND_ZERO)
1027 					{
1028 						return BLENDOP_SOURCE;
1029 					}
1030 					else
1031 					{
1032 						return BLENDOP_SUB;
1033 					}
1034 				}
1035 				else
1036 				{
1037 					if(destBlendFactorAlpha() == BLEND_ZERO)
1038 					{
1039 						return BLENDOP_SOURCE;
1040 					}
1041 					else
1042 					{
1043 						return BLENDOP_SUB;
1044 					}
1045 				}
1046 			case BLENDOP_INVSUB:
1047 				if(sourceBlendFactorAlpha() == BLEND_ZERO)
1048 				{
1049 					if(destBlendFactorAlpha() == BLEND_ZERO)
1050 					{
1051 						return BLENDOP_NULL;
1052 					}
1053 					else
1054 					{
1055 						return BLENDOP_DEST;
1056 					}
1057 				}
1058 				else if(sourceBlendFactorAlpha() == BLEND_ONE)
1059 				{
1060 					if(destBlendFactorAlpha() == BLEND_ZERO)
1061 					{
1062 						return BLENDOP_NULL;   // Negative, clamped to zero
1063 					}
1064 					else
1065 					{
1066 						return BLENDOP_INVSUB;
1067 					}
1068 				}
1069 				else
1070 				{
1071 					if(destBlendFactorAlpha() == BLEND_ZERO)
1072 					{
1073 						return BLENDOP_NULL;   // Negative, clamped to zero
1074 					}
1075 					else
1076 					{
1077 						return BLENDOP_INVSUB;
1078 					}
1079 				}
1080 			case BLENDOP_MIN:
1081 				return BLENDOP_MIN;
1082 			case BLENDOP_MAX:
1083 				return BLENDOP_MAX;
1084 			default:
1085 				ASSERT(false);
1086 			}
1087 
1088 			return blendOperationStateAlpha;
1089 		}
1090 	}
1091 
indexedVertexBlendActive()1092 	bool Context::indexedVertexBlendActive()
1093 	{
1094 		if(vertexShader)
1095 		{
1096 			return false;
1097 		}
1098 
1099 		return indexedVertexBlendEnable;
1100 	}
1101 
vertexBlendMatrixCountActive()1102 	int Context::vertexBlendMatrixCountActive()
1103 	{
1104 		if(vertexShader)
1105 		{
1106 			return 0;
1107 		}
1108 
1109 		return vertexBlendMatrixCount;
1110 	}
1111 
localViewerActive()1112 	bool Context::localViewerActive()
1113 	{
1114 		if(vertexShader)
1115 		{
1116 			return false;
1117 		}
1118 
1119 		return localViewer;
1120 	}
1121 
normalizeNormalsActive()1122 	bool Context::normalizeNormalsActive()
1123 	{
1124 		if(vertexShader)
1125 		{
1126 			return false;
1127 		}
1128 
1129 		return normalizeNormals;
1130 	}
1131 
vertexFogModeActive()1132 	FogMode Context::vertexFogModeActive()
1133 	{
1134 		if(vertexShader || !fogActive())
1135 		{
1136 			return FOG_NONE;
1137 		}
1138 
1139 		return vertexFogMode;
1140 	}
1141 
rangeFogActive()1142 	bool Context::rangeFogActive()
1143 	{
1144 		if(vertexShader || !fogActive())
1145 		{
1146 			return false;
1147 		}
1148 
1149 		return rangeFogEnable;
1150 	}
1151 
texGenActive(int stage)1152 	TexGen Context::texGenActive(int stage)
1153 	{
1154 		if(vertexShader || !texCoordActive(stage))
1155 		{
1156 			return TEXGEN_PASSTHRU;
1157 		}
1158 
1159 		return texGen[stage];
1160 	}
1161 
textureTransformCountActive(int stage)1162 	int Context::textureTransformCountActive(int stage)
1163 	{
1164 		if(vertexShader || !texCoordActive(stage))
1165 		{
1166 			return 0;
1167 		}
1168 
1169 		return textureTransformCount[stage];
1170 	}
1171 
texCoordIndexActive(int stage)1172 	int Context::texCoordIndexActive(int stage)
1173 	{
1174 		if(vertexShader || !texCoordActive(stage))
1175 		{
1176 			return stage;
1177 		}
1178 
1179 		return textureStage[stage].texCoordIndex;
1180 	}
1181 
perspectiveActive()1182 	bool Context::perspectiveActive()
1183 	{
1184 		if(!colorUsed())
1185 		{
1186 			return false;
1187 		}
1188 
1189 		if(!perspectiveCorrection)
1190 		{
1191 			return false;
1192 		}
1193 
1194 		if(isDrawPoint(true))
1195 		{
1196 			return false;
1197 		}
1198 
1199 		return true;
1200 	}
1201 
diffuseUsed()1202 	bool Context::diffuseUsed()
1203 	{
1204 		return diffuseUsed(0) || diffuseUsed(1) || diffuseUsed(2) || diffuseUsed(3);
1205 	}
1206 
diffuseUsed(int component)1207 	bool Context::diffuseUsed(int component)
1208 	{
1209 		if(!colorUsed())
1210 		{
1211 			return false;
1212 		}
1213 
1214 		if(pixelShader)
1215 		{
1216 			return pixelShader->usesDiffuse(component);
1217 		}
1218 
1219 		// Directly using the diffuse input color
1220 		for(int i = 0; i < 8; i++)
1221 		{
1222 			if(textureStage[i].isStageDisabled())
1223 			{
1224 				break;
1225 			}
1226 
1227 			if(textureStage[i].usesDiffuse())
1228 			{
1229 				return true;
1230 			}
1231 		}
1232 
1233 		// Using the current color (initialized to diffuse) before it's overwritten
1234 		for(int i = 0; i < 8; i++)
1235 		{
1236 			if(textureStage[i].usesCurrent() || textureStage[i].isStageDisabled())   // Current color contains diffuse before being overwritten
1237 			{
1238 				return true;
1239 			}
1240 
1241 			if(textureStage[i].writesCurrent())
1242 			{
1243 				return false;
1244 			}
1245 		}
1246 
1247 		return true;
1248 	}
1249 
diffuseActive()1250 	bool Context::diffuseActive()
1251 	{
1252 		return diffuseActive(0) || diffuseActive(1) || diffuseActive(2) || diffuseActive(3);
1253 	}
1254 
diffuseActive(int component)1255 	bool Context::diffuseActive(int component)
1256 	{
1257 		if(!colorUsed())
1258 		{
1259 			return false;
1260 		}
1261 
1262 		// Vertex processor provides diffuse component
1263 		bool vertexDiffuse;
1264 
1265 		if(vertexShader)
1266 		{
1267 			vertexDiffuse = vertexShader->getOutput(C0, component).active();
1268 		}
1269 		else if(!preTransformed)
1270 		{
1271 			vertexDiffuse = input[Color0] || lightingEnable;
1272 		}
1273 		else
1274 		{
1275 			vertexDiffuse = input[Color0];
1276 		}
1277 
1278 		// Pixel processor requires diffuse component
1279 		bool pixelDiffuse = diffuseUsed(component);
1280 
1281 		return vertexDiffuse && pixelDiffuse;
1282 	}
1283 
specularUsed()1284 	bool Context::specularUsed()
1285 	{
1286 		return Context::specularUsed(0) || Context::specularUsed(1) || Context::specularUsed(2) || Context::specularUsed(3);
1287 	}
1288 
specularUsed(int component)1289 	bool Context::specularUsed(int component)
1290 	{
1291 		if(!colorUsed())
1292 		{
1293 			return false;
1294 		}
1295 
1296 		if(pixelShader)
1297 		{
1298 			return pixelShader->usesSpecular(component);
1299 		}
1300 
1301 		bool pixelSpecular = specularEnable;
1302 
1303 		for(int i = 0; i < 8; i++)
1304 		{
1305 			if(textureStage[i].isStageDisabled()) break;
1306 
1307 			pixelSpecular = pixelSpecular || textureStage[i].usesSpecular();
1308 		}
1309 
1310 		return pixelSpecular;
1311 	}
1312 
specularActive()1313 	bool Context::specularActive()
1314 	{
1315 		return specularActive(0) || specularActive(1) || specularActive(2) || specularActive(3);
1316 	}
1317 
specularActive(int component)1318 	bool Context::specularActive(int component)
1319 	{
1320 		if(!colorUsed())
1321 		{
1322 			return false;
1323 		}
1324 
1325 		// Vertex processor provides specular component
1326 		bool vertexSpecular;
1327 
1328 		if(!vertexShader)
1329 		{
1330 			vertexSpecular = input[Color1] || (lightingEnable && specularEnable);
1331 		}
1332 		else
1333 		{
1334 			vertexSpecular = vertexShader->getOutput(C1, component).active();
1335 		}
1336 
1337 		// Pixel processor requires specular component
1338 		bool pixelSpecular = specularUsed(component);
1339 
1340 		return vertexSpecular && pixelSpecular;
1341 	}
1342 
colorActive(int color,int component)1343 	bool Context::colorActive(int color, int component)
1344 	{
1345 		if(color == 0)
1346 		{
1347 			return diffuseActive(component);
1348 		}
1349 		else
1350 		{
1351 			return specularActive(component);
1352 		}
1353 	}
1354 
textureActive()1355 	bool Context::textureActive()
1356 	{
1357 		for(int i = 0; i < 8; i++)
1358 		{
1359 			if(textureActive(i))
1360 			{
1361 				return true;
1362 			}
1363 		}
1364 
1365 		return false;
1366 	}
1367 
textureActive(int coordinate)1368 	bool Context::textureActive(int coordinate)
1369 	{
1370 		return textureActive(coordinate, 0) || textureActive(coordinate, 1) || textureActive(coordinate, 2) || textureActive(coordinate, 3);
1371 	}
1372 
textureActive(int coordinate,int component)1373 	bool Context::textureActive(int coordinate, int component)
1374 	{
1375 		if(!colorUsed())
1376 		{
1377 			return false;
1378 		}
1379 
1380 		if(!texCoordActive(coordinate, component))
1381 		{
1382 			return false;
1383 		}
1384 
1385 		if(textureTransformProject[coordinate] && pixelShaderModel() <= 0x0103)
1386 		{
1387 			if(textureTransformCount[coordinate] == 2)
1388 			{
1389 				if(component == 1) return true;
1390 			}
1391 			else if(textureTransformCount[coordinate] == 3)
1392 			{
1393 				if(component == 2) return true;
1394 			}
1395 			else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0)
1396 			{
1397 				if(component == 3) return true;
1398 			}
1399 		}
1400 
1401 		if(!pixelShader)
1402 		{
1403 			bool texture = textureStage[coordinate].usesTexture();
1404 			bool cube = sampler[coordinate].hasCubeTexture();
1405 			bool volume = sampler[coordinate].hasVolumeTexture();
1406 
1407 			if(texture)
1408 			{
1409 				for(int i = coordinate; i >= 0; i--)
1410 				{
1411 					if(textureStage[i].stageOperation == TextureStage::STAGE_DISABLE)
1412 					{
1413 						return false;
1414 					}
1415 				}
1416 			}
1417 
1418 			switch(component)
1419 			{
1420 			case 0:
1421 				return texture;
1422 			case 1:
1423 				return texture;
1424 			case 2:
1425 				return (texture && (cube || volume));
1426 			case 3:
1427 				return false;
1428 			}
1429 		}
1430 		else
1431 		{
1432 			return pixelShader->usesTexture(coordinate, component);
1433 		}
1434 
1435 		return false;
1436 	}
1437 
pixelShaderModel() const1438 	unsigned short Context::pixelShaderModel() const
1439 	{
1440 		return pixelShader ? pixelShader->getShaderModel() : 0x0000;
1441 	}
1442 
vertexShaderModel() const1443 	unsigned short Context::vertexShaderModel() const
1444 	{
1445 		return vertexShader ? vertexShader->getShaderModel() : 0x0000;
1446 	}
1447 
getMultiSampleCount() const1448 	int Context::getMultiSampleCount() const
1449 	{
1450 		return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1;
1451 	}
1452 
getSuperSampleCount() const1453 	int Context::getSuperSampleCount() const
1454 	{
1455 		return renderTarget[0] ? renderTarget[0]->getSuperSampleCount() : 1;
1456 	}
1457 
renderTargetInternalFormat(int index)1458 	Format Context::renderTargetInternalFormat(int index)
1459 	{
1460 		if(renderTarget[index])
1461 		{
1462 			return renderTarget[index]->getInternalFormat();
1463 		}
1464 		else
1465 		{
1466 			return FORMAT_NULL;
1467 		}
1468 	}
1469 
colorWriteActive()1470 	int Context::colorWriteActive()
1471 	{
1472 		return colorWriteActive(0) | colorWriteActive(1) | colorWriteActive(2) | colorWriteActive(3);
1473 	}
1474 
colorWriteActive(int index)1475 	int Context::colorWriteActive(int index)
1476 	{
1477 		if(!renderTarget[index] || renderTarget[index]->getInternalFormat() == FORMAT_NULL)
1478 		{
1479 			return 0;
1480 		}
1481 
1482 		if(blendOperation() == BLENDOP_DEST && destBlendFactor() == BLEND_ONE &&
1483 		   (!separateAlphaBlendEnable || (blendOperationAlpha() == BLENDOP_DEST && destBlendFactorAlpha() == BLEND_ONE)))
1484 		{
1485 			return 0;
1486 		}
1487 
1488 		return colorWriteMask[index];
1489 	}
1490 
colorUsed()1491 	bool Context::colorUsed()
1492 	{
1493 		return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->containsKill());
1494 	}
1495 }
1496