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 "PixelProcessor.hpp"
16 
17 #include "Surface.hpp"
18 #include "Primitive.hpp"
19 #include "Shader/PixelPipeline.hpp"
20 #include "Shader/PixelProgram.hpp"
21 #include "Shader/PixelShader.hpp"
22 #include "Shader/Constants.hpp"
23 #include "Common/Debug.hpp"
24 #include "Common/Memory.hpp"
25 
26 #include <cstring>
27 
28 namespace sw
29 {
30 	extern bool complementaryDepthBuffer;
31 	extern TransparencyAntialiasing transparencyAntialiasing;
32 	extern bool perspectiveCorrection;
33 
34 	bool precachePixel = false;
35 
computeHash()36 	uint32_t PixelProcessor::States::computeHash()
37 	{
38 		uint32_t *state = reinterpret_cast<uint32_t*>(this);
39 		uint32_t hash = 0;
40 
41 		for(unsigned int i = 0; i < sizeof(States) / sizeof(uint32_t); i++)
42 		{
43 			hash ^= state[i];
44 		}
45 
46 		return hash;
47 	}
48 
operator ==(const State & state) const49 	bool PixelProcessor::State::operator==(const State &state) const
50 	{
51 		if(hash != state.hash)
52 		{
53 			return false;
54 		}
55 
56 		static_assert(is_memcmparable<State>::value, "Cannot memcmp State");
57 		return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
58 	}
59 
UniformBufferInfo()60 	PixelProcessor::UniformBufferInfo::UniformBufferInfo()
61 	{
62 		buffer = nullptr;
63 		offset = 0;
64 	}
65 
PixelProcessor(Context * context)66 	PixelProcessor::PixelProcessor(Context *context) : context(context)
67 	{
68 		setGlobalMipmapBias(0.0f);   // Round to highest LOD [0.5, 1.0]: -0.5
69 		                             // Round to nearest LOD [0.7, 1.4]:  0.0
70 		                             // Round to lowest LOD  [1.0, 2.0]:  0.5
71 
72 		routineCache = 0;
73 		setRoutineCacheSize(1024);
74 	}
75 
~PixelProcessor()76 	PixelProcessor::~PixelProcessor()
77 	{
78 		delete routineCache;
79 		routineCache = nullptr;
80 	}
81 
82 	// This object has to be mem aligned
operator new(size_t size)83 	void *PixelProcessor::operator new(size_t size)
84 	{
85 		ASSERT(size == sizeof(PixelProcessor)); // This operator can't be called from a derived class
86 		return sw::allocate(sizeof(PixelProcessor), 16);
87 	}
88 
operator delete(void * mem)89 	void PixelProcessor::operator delete(void *mem)
90 	{
91 		sw::deallocate(mem);
92 	}
93 
setFloatConstant(unsigned int index,const float value[4])94 	void PixelProcessor::setFloatConstant(unsigned int index, const float value[4])
95 	{
96 		if(index < FRAGMENT_UNIFORM_VECTORS)
97 		{
98 			c[index][0] = value[0];
99 			c[index][1] = value[1];
100 			c[index][2] = value[2];
101 			c[index][3] = value[3];
102 		}
103 		else ASSERT(false);
104 
105 		if(index < 8)   // ps_1_x constants
106 		{
107 			// TODO: Compact into generic function
108 			short x = iround(4095 * clamp_s(value[0], -1.0f, 1.0f));
109 			short y = iround(4095 * clamp_s(value[1], -1.0f, 1.0f));
110 			short z = iround(4095 * clamp_s(value[2], -1.0f, 1.0f));
111 			short w = iround(4095 * clamp_s(value[3], -1.0f, 1.0f));
112 
113 			cW[index][0][0] = x;
114 			cW[index][0][1] = x;
115 			cW[index][0][2] = x;
116 			cW[index][0][3] = x;
117 
118 			cW[index][1][0] = y;
119 			cW[index][1][1] = y;
120 			cW[index][1][2] = y;
121 			cW[index][1][3] = y;
122 
123 			cW[index][2][0] = z;
124 			cW[index][2][1] = z;
125 			cW[index][2][2] = z;
126 			cW[index][2][3] = z;
127 
128 			cW[index][3][0] = w;
129 			cW[index][3][1] = w;
130 			cW[index][3][2] = w;
131 			cW[index][3][3] = w;
132 		}
133 	}
134 
setIntegerConstant(unsigned int index,const int value[4])135 	void PixelProcessor::setIntegerConstant(unsigned int index, const int value[4])
136 	{
137 		if(index < 16)
138 		{
139 			i[index][0] = value[0];
140 			i[index][1] = value[1];
141 			i[index][2] = value[2];
142 			i[index][3] = value[3];
143 		}
144 		else ASSERT(false);
145 	}
146 
setBooleanConstant(unsigned int index,int boolean)147 	void PixelProcessor::setBooleanConstant(unsigned int index, int boolean)
148 	{
149 		if(index < 16)
150 		{
151 			b[index] = boolean != 0;
152 		}
153 		else ASSERT(false);
154 	}
155 
setUniformBuffer(int index,sw::Resource * buffer,int offset)156 	void PixelProcessor::setUniformBuffer(int index, sw::Resource* buffer, int offset)
157 	{
158 		uniformBufferInfo[index].buffer = buffer;
159 		uniformBufferInfo[index].offset = offset;
160 	}
161 
lockUniformBuffers(byte ** u,sw::Resource * uniformBuffers[])162 	void PixelProcessor::lockUniformBuffers(byte** u, sw::Resource* uniformBuffers[])
163 	{
164 		for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i)
165 		{
166 			u[i] = uniformBufferInfo[i].buffer ? static_cast<byte*>(uniformBufferInfo[i].buffer->lock(PUBLIC, PRIVATE)) + uniformBufferInfo[i].offset : nullptr;
167 			uniformBuffers[i] = uniformBufferInfo[i].buffer;
168 		}
169 	}
170 
setRenderTarget(int index,Surface * renderTarget,unsigned int layer)171 	void PixelProcessor::setRenderTarget(int index, Surface *renderTarget, unsigned int layer)
172 	{
173 		context->renderTarget[index] = renderTarget;
174 		context->renderTargetLayer[index] = layer;
175 	}
176 
setDepthBuffer(Surface * depthBuffer,unsigned int layer)177 	void PixelProcessor::setDepthBuffer(Surface *depthBuffer, unsigned int layer)
178 	{
179 		context->depthBuffer = depthBuffer;
180 		context->depthBufferLayer = layer;
181 	}
182 
setStencilBuffer(Surface * stencilBuffer,unsigned int layer)183 	void PixelProcessor::setStencilBuffer(Surface *stencilBuffer, unsigned int layer)
184 	{
185 		context->stencilBuffer = stencilBuffer;
186 		context->stencilBufferLayer = layer;
187 	}
188 
setTexCoordIndex(unsigned int stage,int texCoordIndex)189 	void PixelProcessor::setTexCoordIndex(unsigned int stage, int texCoordIndex)
190 	{
191 		if(stage < 8)
192 		{
193 			context->textureStage[stage].setTexCoordIndex(texCoordIndex);
194 		}
195 		else ASSERT(false);
196 	}
197 
setStageOperation(unsigned int stage,TextureStage::StageOperation stageOperation)198 	void PixelProcessor::setStageOperation(unsigned int stage, TextureStage::StageOperation stageOperation)
199 	{
200 		if(stage < 8)
201 		{
202 			context->textureStage[stage].setStageOperation(stageOperation);
203 		}
204 		else ASSERT(false);
205 	}
206 
setFirstArgument(unsigned int stage,TextureStage::SourceArgument firstArgument)207 	void PixelProcessor::setFirstArgument(unsigned int stage, TextureStage::SourceArgument firstArgument)
208 	{
209 		if(stage < 8)
210 		{
211 			context->textureStage[stage].setFirstArgument(firstArgument);
212 		}
213 		else ASSERT(false);
214 	}
215 
setSecondArgument(unsigned int stage,TextureStage::SourceArgument secondArgument)216 	void PixelProcessor::setSecondArgument(unsigned int stage, TextureStage::SourceArgument secondArgument)
217 	{
218 		if(stage < 8)
219 		{
220 			context->textureStage[stage].setSecondArgument(secondArgument);
221 		}
222 		else ASSERT(false);
223 	}
224 
setThirdArgument(unsigned int stage,TextureStage::SourceArgument thirdArgument)225 	void PixelProcessor::setThirdArgument(unsigned int stage, TextureStage::SourceArgument thirdArgument)
226 	{
227 		if(stage < 8)
228 		{
229 			context->textureStage[stage].setThirdArgument(thirdArgument);
230 		}
231 		else ASSERT(false);
232 	}
233 
setStageOperationAlpha(unsigned int stage,TextureStage::StageOperation stageOperationAlpha)234 	void PixelProcessor::setStageOperationAlpha(unsigned int stage, TextureStage::StageOperation stageOperationAlpha)
235 	{
236 		if(stage < 8)
237 		{
238 			context->textureStage[stage].setStageOperationAlpha(stageOperationAlpha);
239 		}
240 		else ASSERT(false);
241 	}
242 
setFirstArgumentAlpha(unsigned int stage,TextureStage::SourceArgument firstArgumentAlpha)243 	void PixelProcessor::setFirstArgumentAlpha(unsigned int stage, TextureStage::SourceArgument firstArgumentAlpha)
244 	{
245 		if(stage < 8)
246 		{
247 			context->textureStage[stage].setFirstArgumentAlpha(firstArgumentAlpha);
248 		}
249 		else ASSERT(false);
250 	}
251 
setSecondArgumentAlpha(unsigned int stage,TextureStage::SourceArgument secondArgumentAlpha)252 	void PixelProcessor::setSecondArgumentAlpha(unsigned int stage, TextureStage::SourceArgument secondArgumentAlpha)
253 	{
254 		if(stage < 8)
255 		{
256 			context->textureStage[stage].setSecondArgumentAlpha(secondArgumentAlpha);
257 		}
258 		else ASSERT(false);
259 	}
260 
setThirdArgumentAlpha(unsigned int stage,TextureStage::SourceArgument thirdArgumentAlpha)261 	void PixelProcessor::setThirdArgumentAlpha(unsigned int stage, TextureStage::SourceArgument thirdArgumentAlpha)
262 	{
263 		if(stage < 8)
264 		{
265 			context->textureStage[stage].setThirdArgumentAlpha(thirdArgumentAlpha);
266 		}
267 		else ASSERT(false);
268 	}
269 
setFirstModifier(unsigned int stage,TextureStage::ArgumentModifier firstModifier)270 	void PixelProcessor::setFirstModifier(unsigned int stage, TextureStage::ArgumentModifier firstModifier)
271 	{
272 		if(stage < 8)
273 		{
274 			context->textureStage[stage].setFirstModifier(firstModifier);
275 		}
276 		else ASSERT(false);
277 	}
278 
setSecondModifier(unsigned int stage,TextureStage::ArgumentModifier secondModifier)279 	void PixelProcessor::setSecondModifier(unsigned int stage, TextureStage::ArgumentModifier secondModifier)
280 	{
281 		if(stage < 8)
282 		{
283 			context->textureStage[stage].setSecondModifier(secondModifier);
284 		}
285 		else ASSERT(false);
286 	}
287 
setThirdModifier(unsigned int stage,TextureStage::ArgumentModifier thirdModifier)288 	void PixelProcessor::setThirdModifier(unsigned int stage, TextureStage::ArgumentModifier thirdModifier)
289 	{
290 		if(stage < 8)
291 		{
292 			context->textureStage[stage].setThirdModifier(thirdModifier);
293 		}
294 		else ASSERT(false);
295 	}
296 
setFirstModifierAlpha(unsigned int stage,TextureStage::ArgumentModifier firstModifierAlpha)297 	void PixelProcessor::setFirstModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier firstModifierAlpha)
298 	{
299 		if(stage < 8)
300 		{
301 			context->textureStage[stage].setFirstModifierAlpha(firstModifierAlpha);
302 		}
303 		else ASSERT(false);
304 	}
305 
setSecondModifierAlpha(unsigned int stage,TextureStage::ArgumentModifier secondModifierAlpha)306 	void PixelProcessor::setSecondModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier secondModifierAlpha)
307 	{
308 		if(stage < 8)
309 		{
310 			context->textureStage[stage].setSecondModifierAlpha(secondModifierAlpha);
311 		}
312 		else ASSERT(false);
313 	}
314 
setThirdModifierAlpha(unsigned int stage,TextureStage::ArgumentModifier thirdModifierAlpha)315 	void PixelProcessor::setThirdModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier thirdModifierAlpha)
316 	{
317 		if(stage < 8)
318 		{
319 			context->textureStage[stage].setThirdModifierAlpha(thirdModifierAlpha);
320 		}
321 		else ASSERT(false);
322 	}
323 
setDestinationArgument(unsigned int stage,TextureStage::DestinationArgument destinationArgument)324 	void PixelProcessor::setDestinationArgument(unsigned int stage, TextureStage::DestinationArgument destinationArgument)
325 	{
326 		if(stage < 8)
327 		{
328 			context->textureStage[stage].setDestinationArgument(destinationArgument);
329 		}
330 		else ASSERT(false);
331 	}
332 
setConstantColor(unsigned int stage,const Color<float> & constantColor)333 	void PixelProcessor::setConstantColor(unsigned int stage, const Color<float> &constantColor)
334 	{
335 		if(stage < 8)
336 		{
337 			context->textureStage[stage].setConstantColor(constantColor);
338 		}
339 		else ASSERT(false);
340 	}
341 
setBumpmapMatrix(unsigned int stage,int element,float value)342 	void PixelProcessor::setBumpmapMatrix(unsigned int stage, int element, float value)
343 	{
344 		if(stage < 8)
345 		{
346 			context->textureStage[stage].setBumpmapMatrix(element, value);
347 		}
348 		else ASSERT(false);
349 	}
350 
setLuminanceScale(unsigned int stage,float value)351 	void PixelProcessor::setLuminanceScale(unsigned int stage, float value)
352 	{
353 		if(stage < 8)
354 		{
355 			context->textureStage[stage].setLuminanceScale(value);
356 		}
357 		else ASSERT(false);
358 	}
359 
setLuminanceOffset(unsigned int stage,float value)360 	void PixelProcessor::setLuminanceOffset(unsigned int stage, float value)
361 	{
362 		if(stage < 8)
363 		{
364 			context->textureStage[stage].setLuminanceOffset(value);
365 		}
366 		else ASSERT(false);
367 	}
368 
setTextureFilter(unsigned int sampler,FilterType textureFilter)369 	void PixelProcessor::setTextureFilter(unsigned int sampler, FilterType textureFilter)
370 	{
371 		if(sampler < TEXTURE_IMAGE_UNITS)
372 		{
373 			context->sampler[sampler].setTextureFilter(textureFilter);
374 		}
375 		else ASSERT(false);
376 	}
377 
setMipmapFilter(unsigned int sampler,MipmapType mipmapFilter)378 	void PixelProcessor::setMipmapFilter(unsigned int sampler, MipmapType mipmapFilter)
379 	{
380 		if(sampler < TEXTURE_IMAGE_UNITS)
381 		{
382 			context->sampler[sampler].setMipmapFilter(mipmapFilter);
383 		}
384 		else ASSERT(false);
385 	}
386 
setGatherEnable(unsigned int sampler,bool enable)387 	void PixelProcessor::setGatherEnable(unsigned int sampler, bool enable)
388 	{
389 		if(sampler < TEXTURE_IMAGE_UNITS)
390 		{
391 			context->sampler[sampler].setGatherEnable(enable);
392 		}
393 		else ASSERT(false);
394 	}
395 
setAddressingModeU(unsigned int sampler,AddressingMode addressMode)396 	void PixelProcessor::setAddressingModeU(unsigned int sampler, AddressingMode addressMode)
397 	{
398 		if(sampler < TEXTURE_IMAGE_UNITS)
399 		{
400 			context->sampler[sampler].setAddressingModeU(addressMode);
401 		}
402 		else ASSERT(false);
403 	}
404 
setAddressingModeV(unsigned int sampler,AddressingMode addressMode)405 	void PixelProcessor::setAddressingModeV(unsigned int sampler, AddressingMode addressMode)
406 	{
407 		if(sampler < TEXTURE_IMAGE_UNITS)
408 		{
409 			context->sampler[sampler].setAddressingModeV(addressMode);
410 		}
411 		else ASSERT(false);
412 	}
413 
setAddressingModeW(unsigned int sampler,AddressingMode addressMode)414 	void PixelProcessor::setAddressingModeW(unsigned int sampler, AddressingMode addressMode)
415 	{
416 		if(sampler < TEXTURE_IMAGE_UNITS)
417 		{
418 			context->sampler[sampler].setAddressingModeW(addressMode);
419 		}
420 		else ASSERT(false);
421 	}
422 
setReadSRGB(unsigned int sampler,bool sRGB)423 	void PixelProcessor::setReadSRGB(unsigned int sampler, bool sRGB)
424 	{
425 		if(sampler < TEXTURE_IMAGE_UNITS)
426 		{
427 			context->sampler[sampler].setReadSRGB(sRGB);
428 		}
429 		else ASSERT(false);
430 	}
431 
setMipmapLOD(unsigned int sampler,float bias)432 	void PixelProcessor::setMipmapLOD(unsigned int sampler, float bias)
433 	{
434 		if(sampler < TEXTURE_IMAGE_UNITS)
435 		{
436 			context->sampler[sampler].setMipmapLOD(bias);
437 		}
438 		else ASSERT(false);
439 	}
440 
setBorderColor(unsigned int sampler,const Color<float> & borderColor)441 	void PixelProcessor::setBorderColor(unsigned int sampler, const Color<float> &borderColor)
442 	{
443 		if(sampler < TEXTURE_IMAGE_UNITS)
444 		{
445 			context->sampler[sampler].setBorderColor(borderColor);
446 		}
447 		else ASSERT(false);
448 	}
449 
setMaxAnisotropy(unsigned int sampler,float maxAnisotropy)450 	void PixelProcessor::setMaxAnisotropy(unsigned int sampler, float maxAnisotropy)
451 	{
452 		if(sampler < TEXTURE_IMAGE_UNITS)
453 		{
454 			context->sampler[sampler].setMaxAnisotropy(maxAnisotropy);
455 		}
456 		else ASSERT(false);
457 	}
458 
setHighPrecisionFiltering(unsigned int sampler,bool highPrecisionFiltering)459 	void PixelProcessor::setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering)
460 	{
461 		if(sampler < TEXTURE_IMAGE_UNITS)
462 		{
463 			context->sampler[sampler].setHighPrecisionFiltering(highPrecisionFiltering);
464 		}
465 		else ASSERT(false);
466 	}
467 
setSwizzleR(unsigned int sampler,SwizzleType swizzleR)468 	void PixelProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR)
469 	{
470 		if(sampler < TEXTURE_IMAGE_UNITS)
471 		{
472 			context->sampler[sampler].setSwizzleR(swizzleR);
473 		}
474 		else ASSERT(false);
475 	}
476 
setSwizzleG(unsigned int sampler,SwizzleType swizzleG)477 	void PixelProcessor::setSwizzleG(unsigned int sampler, SwizzleType swizzleG)
478 	{
479 		if(sampler < TEXTURE_IMAGE_UNITS)
480 		{
481 			context->sampler[sampler].setSwizzleG(swizzleG);
482 		}
483 		else ASSERT(false);
484 	}
485 
setSwizzleB(unsigned int sampler,SwizzleType swizzleB)486 	void PixelProcessor::setSwizzleB(unsigned int sampler, SwizzleType swizzleB)
487 	{
488 		if(sampler < TEXTURE_IMAGE_UNITS)
489 		{
490 			context->sampler[sampler].setSwizzleB(swizzleB);
491 		}
492 		else ASSERT(false);
493 	}
494 
setSwizzleA(unsigned int sampler,SwizzleType swizzleA)495 	void PixelProcessor::setSwizzleA(unsigned int sampler, SwizzleType swizzleA)
496 	{
497 		if(sampler < TEXTURE_IMAGE_UNITS)
498 		{
499 			context->sampler[sampler].setSwizzleA(swizzleA);
500 		}
501 		else ASSERT(false);
502 	}
503 
setCompareFunc(unsigned int sampler,CompareFunc compFunc)504 	void PixelProcessor::setCompareFunc(unsigned int sampler, CompareFunc compFunc)
505 	{
506 		if(sampler < TEXTURE_IMAGE_UNITS)
507 		{
508 			context->sampler[sampler].setCompareFunc(compFunc);
509 		}
510 		else ASSERT(false);
511 	}
512 
setBaseLevel(unsigned int sampler,int baseLevel)513 	void PixelProcessor::setBaseLevel(unsigned int sampler, int baseLevel)
514 	{
515 		if(sampler < TEXTURE_IMAGE_UNITS)
516 		{
517 			context->sampler[sampler].setBaseLevel(baseLevel);
518 		}
519 		else ASSERT(false);
520 	}
521 
setMaxLevel(unsigned int sampler,int maxLevel)522 	void PixelProcessor::setMaxLevel(unsigned int sampler, int maxLevel)
523 	{
524 		if(sampler < TEXTURE_IMAGE_UNITS)
525 		{
526 			context->sampler[sampler].setMaxLevel(maxLevel);
527 		}
528 		else ASSERT(false);
529 	}
530 
setMinLod(unsigned int sampler,float minLod)531 	void PixelProcessor::setMinLod(unsigned int sampler, float minLod)
532 	{
533 		if(sampler < TEXTURE_IMAGE_UNITS)
534 		{
535 			context->sampler[sampler].setMinLod(minLod);
536 		}
537 		else ASSERT(false);
538 	}
539 
setMaxLod(unsigned int sampler,float maxLod)540 	void PixelProcessor::setMaxLod(unsigned int sampler, float maxLod)
541 	{
542 		if(sampler < TEXTURE_IMAGE_UNITS)
543 		{
544 			context->sampler[sampler].setMaxLod(maxLod);
545 		}
546 		else ASSERT(false);
547 	}
548 
setSyncRequired(unsigned int sampler,bool isSincRequired)549 	void PixelProcessor::setSyncRequired(unsigned int sampler, bool isSincRequired)
550 	{
551 		if(sampler < TEXTURE_IMAGE_UNITS)
552 		{
553 			context->sampler[sampler].setSyncRequired(isSincRequired);
554 		}
555 		else ASSERT(false);
556 	}
557 
setWriteSRGB(bool sRGB)558 	void PixelProcessor::setWriteSRGB(bool sRGB)
559 	{
560 		context->setWriteSRGB(sRGB);
561 	}
562 
setColorLogicOpEnabled(bool colorLogicOpEnabled)563 	void PixelProcessor::setColorLogicOpEnabled(bool colorLogicOpEnabled)
564 	{
565 		context->setColorLogicOpEnabled(colorLogicOpEnabled);
566 	}
567 
setLogicalOperation(LogicalOperation logicalOperation)568 	void PixelProcessor::setLogicalOperation(LogicalOperation logicalOperation)
569 	{
570 		context->setLogicalOperation(logicalOperation);
571 	}
572 
setDepthBufferEnable(bool depthBufferEnable)573 	void PixelProcessor::setDepthBufferEnable(bool depthBufferEnable)
574 	{
575 		context->setDepthBufferEnable(depthBufferEnable);
576 	}
577 
setDepthCompare(DepthCompareMode depthCompareMode)578 	void PixelProcessor::setDepthCompare(DepthCompareMode depthCompareMode)
579 	{
580 		context->depthCompareMode = depthCompareMode;
581 	}
582 
setAlphaCompare(AlphaCompareMode alphaCompareMode)583 	void PixelProcessor::setAlphaCompare(AlphaCompareMode alphaCompareMode)
584 	{
585 		context->alphaCompareMode = alphaCompareMode;
586 	}
587 
setDepthWriteEnable(bool depthWriteEnable)588 	void PixelProcessor::setDepthWriteEnable(bool depthWriteEnable)
589 	{
590 		context->depthWriteEnable = depthWriteEnable;
591 	}
592 
setAlphaTestEnable(bool alphaTestEnable)593 	void PixelProcessor::setAlphaTestEnable(bool alphaTestEnable)
594 	{
595 		context->alphaTestEnable = alphaTestEnable;
596 	}
597 
setCullMode(CullMode cullMode,bool frontFacingCCW)598 	void PixelProcessor::setCullMode(CullMode cullMode, bool frontFacingCCW)
599 	{
600 		context->cullMode = cullMode;
601 		context->frontFacingCCW = frontFacingCCW;
602 	}
603 
setColorWriteMask(int index,int rgbaMask)604 	void PixelProcessor::setColorWriteMask(int index, int rgbaMask)
605 	{
606 		context->setColorWriteMask(index, rgbaMask);
607 	}
608 
setStencilEnable(bool stencilEnable)609 	void PixelProcessor::setStencilEnable(bool stencilEnable)
610 	{
611 		context->stencilEnable = stencilEnable;
612 	}
613 
setStencilCompare(StencilCompareMode stencilCompareMode)614 	void PixelProcessor::setStencilCompare(StencilCompareMode stencilCompareMode)
615 	{
616 		context->stencilCompareMode = stencilCompareMode;
617 	}
618 
setStencilReference(int stencilReference)619 	void PixelProcessor::setStencilReference(int stencilReference)
620 	{
621 		context->stencilReference = stencilReference;
622 		stencil.set(stencilReference, context->stencilMask, context->stencilWriteMask);
623 	}
624 
setStencilReferenceCCW(int stencilReferenceCCW)625 	void PixelProcessor::setStencilReferenceCCW(int stencilReferenceCCW)
626 	{
627 		context->stencilReferenceCCW = stencilReferenceCCW;
628 		stencilCCW.set(stencilReferenceCCW, context->stencilMaskCCW, context->stencilWriteMaskCCW);
629 	}
630 
setStencilMask(int stencilMask)631 	void PixelProcessor::setStencilMask(int stencilMask)
632 	{
633 		context->stencilMask = stencilMask;
634 		stencil.set(context->stencilReference, stencilMask, context->stencilWriteMask);
635 	}
636 
setStencilMaskCCW(int stencilMaskCCW)637 	void PixelProcessor::setStencilMaskCCW(int stencilMaskCCW)
638 	{
639 		context->stencilMaskCCW = stencilMaskCCW;
640 		stencilCCW.set(context->stencilReferenceCCW, stencilMaskCCW, context->stencilWriteMaskCCW);
641 	}
642 
setStencilFailOperation(StencilOperation stencilFailOperation)643 	void PixelProcessor::setStencilFailOperation(StencilOperation stencilFailOperation)
644 	{
645 		context->stencilFailOperation = stencilFailOperation;
646 	}
647 
setStencilPassOperation(StencilOperation stencilPassOperation)648 	void PixelProcessor::setStencilPassOperation(StencilOperation stencilPassOperation)
649 	{
650 		context->stencilPassOperation = stencilPassOperation;
651 	}
652 
setStencilZFailOperation(StencilOperation stencilZFailOperation)653 	void PixelProcessor::setStencilZFailOperation(StencilOperation stencilZFailOperation)
654 	{
655 		context->stencilZFailOperation = stencilZFailOperation;
656 	}
657 
setStencilWriteMask(int stencilWriteMask)658 	void PixelProcessor::setStencilWriteMask(int stencilWriteMask)
659 	{
660 		context->stencilWriteMask = stencilWriteMask;
661 		stencil.set(context->stencilReference, context->stencilMask, stencilWriteMask);
662 	}
663 
setStencilWriteMaskCCW(int stencilWriteMaskCCW)664 	void PixelProcessor::setStencilWriteMaskCCW(int stencilWriteMaskCCW)
665 	{
666 		context->stencilWriteMaskCCW = stencilWriteMaskCCW;
667 		stencilCCW.set(context->stencilReferenceCCW, context->stencilMaskCCW, stencilWriteMaskCCW);
668 	}
669 
setTwoSidedStencil(bool enable)670 	void PixelProcessor::setTwoSidedStencil(bool enable)
671 	{
672 		context->twoSidedStencil = enable;
673 	}
674 
setStencilCompareCCW(StencilCompareMode stencilCompareMode)675 	void PixelProcessor::setStencilCompareCCW(StencilCompareMode stencilCompareMode)
676 	{
677 		context->stencilCompareModeCCW = stencilCompareMode;
678 	}
679 
setStencilFailOperationCCW(StencilOperation stencilFailOperation)680 	void PixelProcessor::setStencilFailOperationCCW(StencilOperation stencilFailOperation)
681 	{
682 		context->stencilFailOperationCCW = stencilFailOperation;
683 	}
684 
setStencilPassOperationCCW(StencilOperation stencilPassOperation)685 	void PixelProcessor::setStencilPassOperationCCW(StencilOperation stencilPassOperation)
686 	{
687 		context->stencilPassOperationCCW = stencilPassOperation;
688 	}
689 
setStencilZFailOperationCCW(StencilOperation stencilZFailOperation)690 	void PixelProcessor::setStencilZFailOperationCCW(StencilOperation stencilZFailOperation)
691 	{
692 		context->stencilZFailOperationCCW = stencilZFailOperation;
693 	}
694 
setTextureFactor(const Color<float> & textureFactor)695 	void PixelProcessor::setTextureFactor(const Color<float> &textureFactor)
696 	{
697 		// FIXME: Compact into generic function   // FIXME: Clamp
698 		short textureFactorR = iround(4095 * textureFactor.r);
699 		short textureFactorG = iround(4095 * textureFactor.g);
700 		short textureFactorB = iround(4095 * textureFactor.b);
701 		short textureFactorA = iround(4095 * textureFactor.a);
702 
703 		factor.textureFactor4[0][0] = textureFactorR;
704 		factor.textureFactor4[0][1] = textureFactorR;
705 		factor.textureFactor4[0][2] = textureFactorR;
706 		factor.textureFactor4[0][3] = textureFactorR;
707 
708 		factor.textureFactor4[1][0] = textureFactorG;
709 		factor.textureFactor4[1][1] = textureFactorG;
710 		factor.textureFactor4[1][2] = textureFactorG;
711 		factor.textureFactor4[1][3] = textureFactorG;
712 
713 		factor.textureFactor4[2][0] = textureFactorB;
714 		factor.textureFactor4[2][1] = textureFactorB;
715 		factor.textureFactor4[2][2] = textureFactorB;
716 		factor.textureFactor4[2][3] = textureFactorB;
717 
718 		factor.textureFactor4[3][0] = textureFactorA;
719 		factor.textureFactor4[3][1] = textureFactorA;
720 		factor.textureFactor4[3][2] = textureFactorA;
721 		factor.textureFactor4[3][3] = textureFactorA;
722 	}
723 
setBlendConstant(const Color<float> & blendConstant)724 	void PixelProcessor::setBlendConstant(const Color<float> &blendConstant)
725 	{
726 		// FIXME: Compact into generic function   // FIXME: Clamp
727 		short blendConstantR = iround(65535 * blendConstant.r);
728 		short blendConstantG = iround(65535 * blendConstant.g);
729 		short blendConstantB = iround(65535 * blendConstant.b);
730 		short blendConstantA = iround(65535 * blendConstant.a);
731 
732 		factor.blendConstant4W[0][0] = blendConstantR;
733 		factor.blendConstant4W[0][1] = blendConstantR;
734 		factor.blendConstant4W[0][2] = blendConstantR;
735 		factor.blendConstant4W[0][3] = blendConstantR;
736 
737 		factor.blendConstant4W[1][0] = blendConstantG;
738 		factor.blendConstant4W[1][1] = blendConstantG;
739 		factor.blendConstant4W[1][2] = blendConstantG;
740 		factor.blendConstant4W[1][3] = blendConstantG;
741 
742 		factor.blendConstant4W[2][0] = blendConstantB;
743 		factor.blendConstant4W[2][1] = blendConstantB;
744 		factor.blendConstant4W[2][2] = blendConstantB;
745 		factor.blendConstant4W[2][3] = blendConstantB;
746 
747 		factor.blendConstant4W[3][0] = blendConstantA;
748 		factor.blendConstant4W[3][1] = blendConstantA;
749 		factor.blendConstant4W[3][2] = blendConstantA;
750 		factor.blendConstant4W[3][3] = blendConstantA;
751 
752 		// FIXME: Compact into generic function   // FIXME: Clamp
753 		short invBlendConstantR = iround(65535 * (1 - blendConstant.r));
754 		short invBlendConstantG = iround(65535 * (1 - blendConstant.g));
755 		short invBlendConstantB = iround(65535 * (1 - blendConstant.b));
756 		short invBlendConstantA = iround(65535 * (1 - blendConstant.a));
757 
758 		factor.invBlendConstant4W[0][0] = invBlendConstantR;
759 		factor.invBlendConstant4W[0][1] = invBlendConstantR;
760 		factor.invBlendConstant4W[0][2] = invBlendConstantR;
761 		factor.invBlendConstant4W[0][3] = invBlendConstantR;
762 
763 		factor.invBlendConstant4W[1][0] = invBlendConstantG;
764 		factor.invBlendConstant4W[1][1] = invBlendConstantG;
765 		factor.invBlendConstant4W[1][2] = invBlendConstantG;
766 		factor.invBlendConstant4W[1][3] = invBlendConstantG;
767 
768 		factor.invBlendConstant4W[2][0] = invBlendConstantB;
769 		factor.invBlendConstant4W[2][1] = invBlendConstantB;
770 		factor.invBlendConstant4W[2][2] = invBlendConstantB;
771 		factor.invBlendConstant4W[2][3] = invBlendConstantB;
772 
773 		factor.invBlendConstant4W[3][0] = invBlendConstantA;
774 		factor.invBlendConstant4W[3][1] = invBlendConstantA;
775 		factor.invBlendConstant4W[3][2] = invBlendConstantA;
776 		factor.invBlendConstant4W[3][3] = invBlendConstantA;
777 
778 		factor.blendConstant4F[0][0] = blendConstant.r;
779 		factor.blendConstant4F[0][1] = blendConstant.r;
780 		factor.blendConstant4F[0][2] = blendConstant.r;
781 		factor.blendConstant4F[0][3] = blendConstant.r;
782 
783 		factor.blendConstant4F[1][0] = blendConstant.g;
784 		factor.blendConstant4F[1][1] = blendConstant.g;
785 		factor.blendConstant4F[1][2] = blendConstant.g;
786 		factor.blendConstant4F[1][3] = blendConstant.g;
787 
788 		factor.blendConstant4F[2][0] = blendConstant.b;
789 		factor.blendConstant4F[2][1] = blendConstant.b;
790 		factor.blendConstant4F[2][2] = blendConstant.b;
791 		factor.blendConstant4F[2][3] = blendConstant.b;
792 
793 		factor.blendConstant4F[3][0] = blendConstant.a;
794 		factor.blendConstant4F[3][1] = blendConstant.a;
795 		factor.blendConstant4F[3][2] = blendConstant.a;
796 		factor.blendConstant4F[3][3] = blendConstant.a;
797 
798 		factor.invBlendConstant4F[0][0] = 1 - blendConstant.r;
799 		factor.invBlendConstant4F[0][1] = 1 - blendConstant.r;
800 		factor.invBlendConstant4F[0][2] = 1 - blendConstant.r;
801 		factor.invBlendConstant4F[0][3] = 1 - blendConstant.r;
802 
803 		factor.invBlendConstant4F[1][0] = 1 - blendConstant.g;
804 		factor.invBlendConstant4F[1][1] = 1 - blendConstant.g;
805 		factor.invBlendConstant4F[1][2] = 1 - blendConstant.g;
806 		factor.invBlendConstant4F[1][3] = 1 - blendConstant.g;
807 
808 		factor.invBlendConstant4F[2][0] = 1 - blendConstant.b;
809 		factor.invBlendConstant4F[2][1] = 1 - blendConstant.b;
810 		factor.invBlendConstant4F[2][2] = 1 - blendConstant.b;
811 		factor.invBlendConstant4F[2][3] = 1 - blendConstant.b;
812 
813 		factor.invBlendConstant4F[3][0] = 1 - blendConstant.a;
814 		factor.invBlendConstant4F[3][1] = 1 - blendConstant.a;
815 		factor.invBlendConstant4F[3][2] = 1 - blendConstant.a;
816 		factor.invBlendConstant4F[3][3] = 1 - blendConstant.a;
817 	}
818 
setFillMode(FillMode fillMode)819 	void PixelProcessor::setFillMode(FillMode fillMode)
820 	{
821 		context->fillMode = fillMode;
822 	}
823 
setShadingMode(ShadingMode shadingMode)824 	void PixelProcessor::setShadingMode(ShadingMode shadingMode)
825 	{
826 		context->shadingMode = shadingMode;
827 	}
828 
setAlphaBlendEnable(bool alphaBlendEnable)829 	void PixelProcessor::setAlphaBlendEnable(bool alphaBlendEnable)
830 	{
831 		context->setAlphaBlendEnable(alphaBlendEnable);
832 	}
833 
setSourceBlendFactor(BlendFactor sourceBlendFactor)834 	void PixelProcessor::setSourceBlendFactor(BlendFactor sourceBlendFactor)
835 	{
836 		context->setSourceBlendFactor(sourceBlendFactor);
837 	}
838 
setDestBlendFactor(BlendFactor destBlendFactor)839 	void PixelProcessor::setDestBlendFactor(BlendFactor destBlendFactor)
840 	{
841 		context->setDestBlendFactor(destBlendFactor);
842 	}
843 
setBlendOperation(BlendOperation blendOperation)844 	void PixelProcessor::setBlendOperation(BlendOperation blendOperation)
845 	{
846 		context->setBlendOperation(blendOperation);
847 	}
848 
setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)849 	void PixelProcessor::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)
850 	{
851 		context->setSeparateAlphaBlendEnable(separateAlphaBlendEnable);
852 	}
853 
setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)854 	void PixelProcessor::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)
855 	{
856 		context->setSourceBlendFactorAlpha(sourceBlendFactorAlpha);
857 	}
858 
setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)859 	void PixelProcessor::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)
860 	{
861 		context->setDestBlendFactorAlpha(destBlendFactorAlpha);
862 	}
863 
setBlendOperationAlpha(BlendOperation blendOperationAlpha)864 	void PixelProcessor::setBlendOperationAlpha(BlendOperation blendOperationAlpha)
865 	{
866 		context->setBlendOperationAlpha(blendOperationAlpha);
867 	}
868 
setAlphaReference(float alphaReference)869 	void PixelProcessor::setAlphaReference(float alphaReference)
870 	{
871 		context->alphaReference = alphaReference;
872 
873 		factor.alphaReference4[0] = (word)iround(alphaReference * 0x1000 / 0xFF);
874 		factor.alphaReference4[1] = (word)iround(alphaReference * 0x1000 / 0xFF);
875 		factor.alphaReference4[2] = (word)iround(alphaReference * 0x1000 / 0xFF);
876 		factor.alphaReference4[3] = (word)iround(alphaReference * 0x1000 / 0xFF);
877 	}
878 
setGlobalMipmapBias(float bias)879 	void PixelProcessor::setGlobalMipmapBias(float bias)
880 	{
881 		context->setGlobalMipmapBias(bias);
882 	}
883 
setFogStart(float start)884 	void PixelProcessor::setFogStart(float start)
885 	{
886 		setFogRanges(start, context->fogEnd);
887 	}
888 
setFogEnd(float end)889 	void PixelProcessor::setFogEnd(float end)
890 	{
891 		setFogRanges(context->fogStart, end);
892 	}
893 
setFogColor(Color<float> fogColor)894 	void PixelProcessor::setFogColor(Color<float> fogColor)
895 	{
896 		// TODO: Compact into generic function
897 		word fogR = (unsigned short)(65535 * fogColor.r);
898 		word fogG = (unsigned short)(65535 * fogColor.g);
899 		word fogB = (unsigned short)(65535 * fogColor.b);
900 
901 		fog.color4[0][0] = fogR;
902 		fog.color4[0][1] = fogR;
903 		fog.color4[0][2] = fogR;
904 		fog.color4[0][3] = fogR;
905 
906 		fog.color4[1][0] = fogG;
907 		fog.color4[1][1] = fogG;
908 		fog.color4[1][2] = fogG;
909 		fog.color4[1][3] = fogG;
910 
911 		fog.color4[2][0] = fogB;
912 		fog.color4[2][1] = fogB;
913 		fog.color4[2][2] = fogB;
914 		fog.color4[2][3] = fogB;
915 
916 		fog.colorF[0] = replicate(fogColor.r);
917 		fog.colorF[1] = replicate(fogColor.g);
918 		fog.colorF[2] = replicate(fogColor.b);
919 	}
920 
setFogDensity(float fogDensity)921 	void PixelProcessor::setFogDensity(float fogDensity)
922 	{
923 		fog.densityE = replicate(-fogDensity * 1.442695f);   // 1/e^x = 2^(-x*1.44)
924 		fog.density2E = replicate(-fogDensity * fogDensity * 1.442695f);
925 	}
926 
setPixelFogMode(FogMode fogMode)927 	void PixelProcessor::setPixelFogMode(FogMode fogMode)
928 	{
929 		context->pixelFogMode = fogMode;
930 	}
931 
setPerspectiveCorrection(bool perspectiveEnable)932 	void PixelProcessor::setPerspectiveCorrection(bool perspectiveEnable)
933 	{
934 		perspectiveCorrection = perspectiveEnable;
935 	}
936 
setOcclusionEnabled(bool enable)937 	void PixelProcessor::setOcclusionEnabled(bool enable)
938 	{
939 		context->occlusionEnabled = enable;
940 	}
941 
setRoutineCacheSize(int cacheSize)942 	void PixelProcessor::setRoutineCacheSize(int cacheSize)
943 	{
944 		delete routineCache;
945 		routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536));
946 	}
947 
setFogRanges(float start,float end)948 	void PixelProcessor::setFogRanges(float start, float end)
949 	{
950 		context->fogStart = start;
951 		context->fogEnd = end;
952 
953 		if(start == end)
954 		{
955 			end += 0.001f;   // Hack: ensure there is a small range
956 		}
957 
958 		float fogScale = -1.0f / (end - start);
959 		float fogOffset = end * -fogScale;
960 
961 		fog.scale = replicate(fogScale);
962 		fog.offset = replicate(fogOffset);
963 	}
964 
update() const965 	const PixelProcessor::State PixelProcessor::update() const
966 	{
967 		State state;
968 
969 		if(context->pixelShader)
970 		{
971 			state.shaderID = context->pixelShader->getSerialID();
972 		}
973 		else
974 		{
975 			state.shaderID = 0;
976 		}
977 
978 		state.depthOverride = context->pixelShader && context->pixelShader->depthOverride();
979 		state.shaderContainsKill = context->pixelShader ? context->pixelShader->containsKill() : false;
980 
981 		if(context->alphaTestActive())
982 		{
983 			state.alphaCompareMode = context->alphaCompareMode;
984 
985 			state.transparencyAntialiasing = context->getMultiSampleCount() > 1 ? transparencyAntialiasing : TRANSPARENCY_NONE;
986 		}
987 
988 		state.depthWriteEnable = context->depthWriteActive();
989 
990 		if(context->stencilActive())
991 		{
992 			state.stencilActive = true;
993 			state.stencilCompareMode = context->stencilCompareMode;
994 			state.stencilFailOperation = context->stencilFailOperation;
995 			state.stencilPassOperation = context->stencilPassOperation;
996 			state.stencilZFailOperation = context->stencilZFailOperation;
997 			state.noStencilMask = (context->stencilMask == 0xFF);
998 			state.noStencilWriteMask = (context->stencilWriteMask == 0xFF);
999 			state.stencilWriteMasked = (context->stencilWriteMask == 0x00);
1000 
1001 			state.twoSidedStencil = context->twoSidedStencil;
1002 			state.stencilCompareModeCCW = context->twoSidedStencil ? context->stencilCompareModeCCW : state.stencilCompareMode;
1003 			state.stencilFailOperationCCW = context->twoSidedStencil ? context->stencilFailOperationCCW : state.stencilFailOperation;
1004 			state.stencilPassOperationCCW = context->twoSidedStencil ? context->stencilPassOperationCCW : state.stencilPassOperation;
1005 			state.stencilZFailOperationCCW = context->twoSidedStencil ? context->stencilZFailOperationCCW : state.stencilZFailOperation;
1006 			state.noStencilMaskCCW = context->twoSidedStencil ? (context->stencilMaskCCW == 0xFF) : state.noStencilMask;
1007 			state.noStencilWriteMaskCCW = context->twoSidedStencil ? (context->stencilWriteMaskCCW == 0xFF) : state.noStencilWriteMask;
1008 			state.stencilWriteMaskedCCW = context->twoSidedStencil ? (context->stencilWriteMaskCCW == 0x00) : state.stencilWriteMasked;
1009 		}
1010 
1011 		if(context->depthBufferActive())
1012 		{
1013 			state.depthTestActive = true;
1014 			state.depthCompareMode = context->depthCompareMode;
1015 			state.quadLayoutDepthBuffer = Surface::hasQuadLayout(context->depthBuffer->getInternalFormat());
1016 		}
1017 
1018 		state.occlusionEnabled = context->occlusionEnabled;
1019 
1020 		state.fogActive = context->fogActive();
1021 		state.pixelFogMode = context->pixelFogActive();
1022 		state.wBasedFog = context->wBasedFog && context->pixelFogActive() != FOG_NONE;
1023 		state.perspective = context->perspectiveActive();
1024 		state.depthClamp = (context->depthBias != 0.0f) || (context->slopeDepthBias != 0.0f);
1025 
1026 		if(context->alphaBlendActive())
1027 		{
1028 			state.alphaBlendActive = true;
1029 			state.sourceBlendFactor = context->sourceBlendFactor();
1030 			state.destBlendFactor = context->destBlendFactor();
1031 			state.blendOperation = context->blendOperation();
1032 			state.sourceBlendFactorAlpha = context->sourceBlendFactorAlpha();
1033 			state.destBlendFactorAlpha = context->destBlendFactorAlpha();
1034 			state.blendOperationAlpha = context->blendOperationAlpha();
1035 		}
1036 
1037 		state.logicalOperation = context->colorLogicOp();
1038 
1039 		for(int i = 0; i < RENDERTARGETS; i++)
1040 		{
1041 			state.colorWriteMask |= context->colorWriteActive(i) << (4 * i);
1042 			state.targetFormat[i] = context->renderTargetInternalFormat(i);
1043 		}
1044 
1045 		state.writeSRGB	= context->writeSRGB && context->renderTarget[0] && Surface::isSRGBwritable(context->renderTarget[0]->getExternalFormat());
1046 		state.multiSample = context->getMultiSampleCount();
1047 		state.multiSampleMask = context->multiSampleMask;
1048 
1049 		if(state.multiSample > 1 && context->pixelShader)
1050 		{
1051 			state.centroid = context->pixelShader->containsCentroid();
1052 		}
1053 
1054 		state.frontFaceCCW = context->frontFacingCCW;
1055 
1056 		if(!context->pixelShader)
1057 		{
1058 			for(unsigned int i = 0; i < 8; i++)
1059 			{
1060 				state.textureStage[i] = context->textureStage[i].textureStageState();
1061 			}
1062 
1063 			state.specularAdd = context->specularActive() && context->specularEnable;
1064 		}
1065 
1066 		for(unsigned int i = 0; i < 16; i++)
1067 		{
1068 			if(context->pixelShader)
1069 			{
1070 				if(context->pixelShader->usesSampler(i))
1071 				{
1072 					state.sampler[i] = context->sampler[i].samplerState();
1073 				}
1074 			}
1075 			else
1076 			{
1077 				if(i < 8 && state.textureStage[i].stageOperation != TextureStage::STAGE_DISABLE)
1078 				{
1079 					state.sampler[i] = context->sampler[i].samplerState();
1080 				}
1081 				else break;
1082 			}
1083 		}
1084 
1085 		const bool point = context->isDrawPoint(true);
1086 		const bool sprite = context->pointSpriteActive();
1087 		const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
1088 
1089 		if(context->pixelShaderModel() < 0x0300)
1090 		{
1091 			for(int coordinate = 0; coordinate < 8; coordinate++)
1092 			{
1093 				for(int component = 0; component < 4; component++)
1094 				{
1095 					if(context->textureActive(coordinate, component))
1096 					{
1097 						state.texture[coordinate].component |= 1 << component;
1098 
1099 						if(point && !sprite)
1100 						{
1101 							state.texture[coordinate].flat |= 1 << component;
1102 						}
1103 					}
1104 				}
1105 
1106 				if(context->textureTransformProject[coordinate] && context->pixelShaderModel() <= 0x0103)
1107 				{
1108 					if(context->textureTransformCount[coordinate] == 2)
1109 					{
1110 						state.texture[coordinate].project = 1;
1111 					}
1112 					else if(context->textureTransformCount[coordinate] == 3)
1113 					{
1114 						state.texture[coordinate].project = 2;
1115 					}
1116 					else if(context->textureTransformCount[coordinate] == 4 || context->textureTransformCount[coordinate] == 0)
1117 					{
1118 						state.texture[coordinate].project = 3;
1119 					}
1120 				}
1121 			}
1122 
1123 			for(int color = 0; color < 2; color++)
1124 			{
1125 				for(int component = 0; component < 4; component++)
1126 				{
1127 					if(context->colorActive(color, component))
1128 					{
1129 						state.color[color].component |= 1 << component;
1130 
1131 						if(point || flatShading)
1132 						{
1133 							state.color[color].flat |= 1 << component;
1134 						}
1135 					}
1136 				}
1137 			}
1138 
1139 			if(context->fogActive())
1140 			{
1141 				state.fog.component = true;
1142 
1143 				if(point)
1144 				{
1145 					state.fog.flat = true;
1146 				}
1147 			}
1148 		}
1149 		else
1150 		{
1151 			for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
1152 			{
1153 				for(int component = 0; component < 4; component++)
1154 				{
1155 					const Shader::Semantic &semantic = context->pixelShader->getInput(interpolant, component);
1156 
1157 					if(semantic.active())
1158 					{
1159 						bool flat = point;
1160 
1161 						switch(semantic.usage)
1162 						{
1163 						case Shader::USAGE_TEXCOORD: flat = point && !sprite;             break;
1164 						case Shader::USAGE_COLOR:    flat = semantic.flat || flatShading; break;
1165 						}
1166 
1167 						state.interpolant[interpolant].component |= 1 << component;
1168 
1169 						if(flat)
1170 						{
1171 							state.interpolant[interpolant].flat |= 1 << component;
1172 						}
1173 					}
1174 				}
1175 			}
1176 		}
1177 
1178 		if(state.centroid)
1179 		{
1180 			for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
1181 			{
1182 				for(int component = 0; component < 4; component++)
1183 				{
1184 					state.interpolant[interpolant].centroid = context->pixelShader->getInput(interpolant, 0).centroid;
1185 				}
1186 			}
1187 		}
1188 
1189 		state.hash = state.computeHash();
1190 
1191 		return state;
1192 	}
1193 
routine(const State & state)1194 	std::shared_ptr<Routine> PixelProcessor::routine(const State &state)
1195 	{
1196 		auto routine = routineCache->query(state);
1197 
1198 		if(!routine)
1199 		{
1200 			const bool integerPipeline = (context->pixelShaderModel() <= 0x0104);
1201 			QuadRasterizer *generator = nullptr;
1202 
1203 			if(integerPipeline)
1204 			{
1205 				generator = new PixelPipeline(state, context->pixelShader);
1206 			}
1207 			else
1208 			{
1209 				generator = new PixelProgram(state, context->pixelShader);
1210 			}
1211 
1212 			generator->generate();
1213 			routine = (*generator)("PixelRoutine_%0.8X", state.shaderID);
1214 			delete generator;
1215 
1216 			routineCache->add(state, routine);
1217 		}
1218 
1219 		return routine;
1220 	}
1221 }
1222