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