blob: 9f2b4fff27eabb0eb40d188912558e93e29188f6 [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001// SwiftShader Software Renderer
2//
John Bauman66b8ab22014-05-06 15:57:45 -04003// Copyright(c) 2005-2013 TransGaming Inc.
John Bauman89401822014-05-06 15:04:28 -04004//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#include "PixelProcessor.hpp"
13
14#include "QuadRasterizer.hpp"
15#include "PixelShader.hpp"
16#include "MetaMacro.hpp"
17#include "Surface.hpp"
18#include "Primitive.hpp"
19#include "Constants.hpp"
20#include "Debug.hpp"
21
John Bauman66b8ab22014-05-06 15:57:45 -040022#include <string.h>
23
John Bauman89401822014-05-06 15:04:28 -040024namespace sw
25{
26 extern bool complementaryDepthBuffer;
Nicolas Capensa0f4be82014-10-22 14:35:30 -040027 extern TransparencyAntialiasing transparencyAntialiasing;
John Bauman89401822014-05-06 15:04:28 -040028 extern bool perspectiveCorrection;
29
John Bauman66b8ab22014-05-06 15:57:45 -040030 bool precachePixel = false;
31
John Bauman89401822014-05-06 15:04:28 -040032 unsigned int PixelProcessor::States::computeHash()
33 {
34 unsigned int *state = (unsigned int*)this;
35 unsigned int hash = 0;
36
37 for(int i = 0; i < sizeof(States) / 4; i++)
38 {
39 hash ^= state[i];
40 }
41
42 return hash;
43 }
44
45 PixelProcessor::State::State()
46 {
47 memset(this, 0, sizeof(State));
48 }
49
50 bool PixelProcessor::State::operator==(const State &state) const
51 {
52 if(hash != state.hash)
53 {
54 return false;
55 }
56
57 return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
58 }
59
60 PixelProcessor::PixelProcessor(Context *context) : context(context)
61 {
62 setGlobalMipmapBias(0.0f); // Round to highest LOD [0.5, 1.0]: -0.5
63 // Round to nearest LOD [0.7, 1.4]: 0.0
64 // Round to lowest LOD [1.0, 2.0]: 0.5
65
66 routineCache = 0;
67 setRoutineCacheSize(1024);
68 }
69
70 PixelProcessor::~PixelProcessor()
71 {
72 delete routineCache;
73 routineCache = 0;
74 }
75
76 void PixelProcessor::setFloatConstant(unsigned int index, const float value[4])
77 {
Alexis Hetu04c967a2015-07-08 15:56:17 -040078 if(index < FRAGMENT_UNIFORM_VECTORS)
John Bauman89401822014-05-06 15:04:28 -040079 {
80 c[index][0] = value[0];
81 c[index][1] = value[1];
82 c[index][2] = value[2];
83 c[index][3] = value[3];
84 }
85 else ASSERT(false);
86
87 if(index < 8) // ps_1_x constants
88 {
89 // FIXME: Compact into generic function
90 short x = iround(4095 * clamp(value[0], -1.0f, 1.0f));
91 short y = iround(4095 * clamp(value[1], -1.0f, 1.0f));
92 short z = iround(4095 * clamp(value[2], -1.0f, 1.0f));
93 short w = iround(4095 * clamp(value[3], -1.0f, 1.0f));
94
95 cW[index][0][0] = x;
96 cW[index][0][1] = x;
97 cW[index][0][2] = x;
98 cW[index][0][3] = x;
99
100 cW[index][1][0] = y;
101 cW[index][1][1] = y;
102 cW[index][1][2] = y;
103 cW[index][1][3] = y;
104
105 cW[index][2][0] = z;
106 cW[index][2][1] = z;
107 cW[index][2][2] = z;
108 cW[index][2][3] = z;
109
110 cW[index][3][0] = w;
111 cW[index][3][1] = w;
112 cW[index][3][2] = w;
113 cW[index][3][3] = w;
114 }
115 }
116
117 void PixelProcessor::setIntegerConstant(unsigned int index, const int value[4])
118 {
119 if(index < 16)
120 {
121 i[index][0] = value[0];
122 i[index][1] = value[1];
123 i[index][2] = value[2];
124 i[index][3] = value[3];
125 }
126 else ASSERT(false);
127 }
128
129 void PixelProcessor::setBooleanConstant(unsigned int index, int boolean)
130 {
131 if(index < 16)
132 {
133 b[index] = boolean != 0;
134 }
135 else ASSERT(false);
136 }
137
138 void PixelProcessor::setRenderTarget(int index, Surface *renderTarget)
139 {
140 context->renderTarget[index] = renderTarget;
141 }
142
143 void PixelProcessor::setDepthStencil(Surface *depthStencil)
144 {
145 context->depthStencil = depthStencil;
146 }
147
148 void PixelProcessor::setTexCoordIndex(unsigned int stage, int texCoordIndex)
149 {
150 if(stage < 8)
151 {
152 context->textureStage[stage].setTexCoordIndex(texCoordIndex);
153 }
154 else ASSERT(false);
155 }
156
157 void PixelProcessor::setStageOperation(unsigned int stage, TextureStage::StageOperation stageOperation)
158 {
159 if(stage < 8)
160 {
161 context->textureStage[stage].setStageOperation(stageOperation);
162 }
163 else ASSERT(false);
164 }
165
166 void PixelProcessor::setFirstArgument(unsigned int stage, TextureStage::SourceArgument firstArgument)
167 {
168 if(stage < 8)
169 {
170 context->textureStage[stage].setFirstArgument(firstArgument);
171 }
172 else ASSERT(false);
173 }
174
175 void PixelProcessor::setSecondArgument(unsigned int stage, TextureStage::SourceArgument secondArgument)
176 {
177 if(stage < 8)
178 {
179 context->textureStage[stage].setSecondArgument(secondArgument);
180 }
181 else ASSERT(false);
182 }
183
184 void PixelProcessor::setThirdArgument(unsigned int stage, TextureStage::SourceArgument thirdArgument)
185 {
186 if(stage < 8)
187 {
188 context->textureStage[stage].setThirdArgument(thirdArgument);
189 }
190 else ASSERT(false);
191 }
192
193 void PixelProcessor::setStageOperationAlpha(unsigned int stage, TextureStage::StageOperation stageOperationAlpha)
194 {
195 if(stage < 8)
196 {
197 context->textureStage[stage].setStageOperationAlpha(stageOperationAlpha);
198 }
199 else ASSERT(false);
200 }
201
202 void PixelProcessor::setFirstArgumentAlpha(unsigned int stage, TextureStage::SourceArgument firstArgumentAlpha)
203 {
204 if(stage < 8)
205 {
206 context->textureStage[stage].setFirstArgumentAlpha(firstArgumentAlpha);
207 }
208 else ASSERT(false);
209 }
210
211 void PixelProcessor::setSecondArgumentAlpha(unsigned int stage, TextureStage::SourceArgument secondArgumentAlpha)
212 {
213 if(stage < 8)
214 {
215 context->textureStage[stage].setSecondArgumentAlpha(secondArgumentAlpha);
216 }
217 else ASSERT(false);
218 }
219
220 void PixelProcessor::setThirdArgumentAlpha(unsigned int stage, TextureStage::SourceArgument thirdArgumentAlpha)
221 {
222 if(stage < 8)
223 {
224 context->textureStage[stage].setThirdArgumentAlpha(thirdArgumentAlpha);
225 }
226 else ASSERT(false);
227 }
228
229 void PixelProcessor::setFirstModifier(unsigned int stage, TextureStage::ArgumentModifier firstModifier)
230 {
231 if(stage < 8)
232 {
233 context->textureStage[stage].setFirstModifier(firstModifier);
234 }
235 else ASSERT(false);
236 }
237
238 void PixelProcessor::setSecondModifier(unsigned int stage, TextureStage::ArgumentModifier secondModifier)
239 {
240 if(stage < 8)
241 {
242 context->textureStage[stage].setSecondModifier(secondModifier);
243 }
244 else ASSERT(false);
245 }
246
247 void PixelProcessor::setThirdModifier(unsigned int stage, TextureStage::ArgumentModifier thirdModifier)
248 {
249 if(stage < 8)
250 {
251 context->textureStage[stage].setThirdModifier(thirdModifier);
252 }
253 else ASSERT(false);
254 }
255
256 void PixelProcessor::setFirstModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier firstModifierAlpha)
257 {
258 if(stage < 8)
259 {
260 context->textureStage[stage].setFirstModifierAlpha(firstModifierAlpha);
261 }
262 else ASSERT(false);
263 }
264
265 void PixelProcessor::setSecondModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier secondModifierAlpha)
266 {
267 if(stage < 8)
268 {
269 context->textureStage[stage].setSecondModifierAlpha(secondModifierAlpha);
270 }
271 else ASSERT(false);
272 }
273
274 void PixelProcessor::setThirdModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier thirdModifierAlpha)
275 {
276 if(stage < 8)
277 {
278 context->textureStage[stage].setThirdModifierAlpha(thirdModifierAlpha);
279 }
280 else ASSERT(false);
281 }
282
283 void PixelProcessor::setDestinationArgument(unsigned int stage, TextureStage::DestinationArgument destinationArgument)
284 {
285 if(stage < 8)
286 {
287 context->textureStage[stage].setDestinationArgument(destinationArgument);
288 }
289 else ASSERT(false);
290 }
291
292 void PixelProcessor::setConstantColor(unsigned int stage, const Color<float> &constantColor)
293 {
294 if(stage < 8)
295 {
296 context->textureStage[stage].setConstantColor(constantColor);
297 }
298 else ASSERT(false);
299 }
300
301 void PixelProcessor::setBumpmapMatrix(unsigned int stage, int element, float value)
302 {
303 if(stage < 8)
304 {
305 context->textureStage[stage].setBumpmapMatrix(element, value);
306 }
307 else ASSERT(false);
308 }
309
310 void PixelProcessor::setLuminanceScale(unsigned int stage, float value)
311 {
312 if(stage < 8)
313 {
314 context->textureStage[stage].setLuminanceScale(value);
315 }
316 else ASSERT(false);
317 }
318
319 void PixelProcessor::setLuminanceOffset(unsigned int stage, float value)
320 {
321 if(stage < 8)
322 {
323 context->textureStage[stage].setLuminanceOffset(value);
324 }
325 else ASSERT(false);
326 }
327
328 void PixelProcessor::setTextureFilter(unsigned int sampler, FilterType textureFilter)
329 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400330 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400331 {
332 context->sampler[sampler].setTextureFilter(textureFilter);
333 }
334 else ASSERT(false);
335 }
336
337 void PixelProcessor::setMipmapFilter(unsigned int sampler, MipmapType mipmapFilter)
338 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400339 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400340 {
341 context->sampler[sampler].setMipmapFilter(mipmapFilter);
342 }
343 else ASSERT(false);
344 }
345
346 void PixelProcessor::setGatherEnable(unsigned int sampler, bool enable)
347 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400348 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400349 {
350 context->sampler[sampler].setGatherEnable(enable);
351 }
352 else ASSERT(false);
353 }
354
355 void PixelProcessor::setAddressingModeU(unsigned int sampler, AddressingMode addressMode)
356 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400357 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400358 {
359 context->sampler[sampler].setAddressingModeU(addressMode);
360 }
361 else ASSERT(false);
362 }
363
364 void PixelProcessor::setAddressingModeV(unsigned int sampler, AddressingMode addressMode)
365 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400366 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400367 {
368 context->sampler[sampler].setAddressingModeV(addressMode);
369 }
370 else ASSERT(false);
371 }
372
373 void PixelProcessor::setAddressingModeW(unsigned int sampler, AddressingMode addressMode)
374 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400375 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400376 {
377 context->sampler[sampler].setAddressingModeW(addressMode);
378 }
379 else ASSERT(false);
380 }
381
382 void PixelProcessor::setReadSRGB(unsigned int sampler, bool sRGB)
383 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400384 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400385 {
386 context->sampler[sampler].setReadSRGB(sRGB);
387 }
388 else ASSERT(false);
389 }
390
391 void PixelProcessor::setMipmapLOD(unsigned int sampler, float bias)
392 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400393 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400394 {
395 context->sampler[sampler].setMipmapLOD(bias);
396 }
397 else ASSERT(false);
398 }
399
400 void PixelProcessor::setBorderColor(unsigned int sampler, const Color<float> &borderColor)
401 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400402 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400403 {
404 context->sampler[sampler].setBorderColor(borderColor);
405 }
406 else ASSERT(false);
407 }
408
Alexis Hetu617a5d52014-11-13 10:56:20 -0500409 void PixelProcessor::setMaxAnisotropy(unsigned int sampler, float maxAnisotropy)
John Bauman89401822014-05-06 15:04:28 -0400410 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400411 if(sampler < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400412 {
413 context->sampler[sampler].setMaxAnisotropy(maxAnisotropy);
414 }
415 else ASSERT(false);
416 }
417
418 void PixelProcessor::setWriteSRGB(bool sRGB)
419 {
420 context->setWriteSRGB(sRGB);
421 }
422
Maxime Grégoired9762742015-07-08 16:43:48 -0400423 void PixelProcessor::setColorLogicOpEnabled(bool colorLogicOpEnabled)
424 {
425 context->setColorLogicOpEnabled(colorLogicOpEnabled);
426 }
427
428 void PixelProcessor::setLogicalOperation(LogicalOperation logicalOperation)
429 {
430 context->setLogicalOperation(logicalOperation);
431 }
432
John Bauman89401822014-05-06 15:04:28 -0400433 void PixelProcessor::setDepthBufferEnable(bool depthBufferEnable)
434 {
435 context->setDepthBufferEnable(depthBufferEnable);
436 }
437
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400438 void PixelProcessor::setDepthCompare(DepthCompareMode depthCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400439 {
440 context->depthCompareMode = depthCompareMode;
441 }
442
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400443 void PixelProcessor::setAlphaCompare(AlphaCompareMode alphaCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400444 {
445 context->alphaCompareMode = alphaCompareMode;
446 }
447
448 void PixelProcessor::setDepthWriteEnable(bool depthWriteEnable)
449 {
450 context->depthWriteEnable = depthWriteEnable;
451 }
452
453 void PixelProcessor::setAlphaTestEnable(bool alphaTestEnable)
454 {
455 context->alphaTestEnable = alphaTestEnable;
456 }
457
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400458 void PixelProcessor::setCullMode(CullMode cullMode)
John Bauman89401822014-05-06 15:04:28 -0400459 {
460 context->cullMode = cullMode;
461 }
462
463 void PixelProcessor::setColorWriteMask(int index, int rgbaMask)
464 {
465 context->setColorWriteMask(index, rgbaMask);
466 }
467
468 void PixelProcessor::setStencilEnable(bool stencilEnable)
469 {
470 context->stencilEnable = stencilEnable;
471 }
472
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400473 void PixelProcessor::setStencilCompare(StencilCompareMode stencilCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400474 {
475 context->stencilCompareMode = stencilCompareMode;
476 }
477
478 void PixelProcessor::setStencilReference(int stencilReference)
479 {
480 context->stencilReference = stencilReference;
481 stencil.set(stencilReference, context->stencilMask, context->stencilWriteMask);
482 }
483
484 void PixelProcessor::setStencilReferenceCCW(int stencilReferenceCCW)
485 {
486 context->stencilReferenceCCW = stencilReferenceCCW;
487 stencilCCW.set(stencilReferenceCCW, context->stencilMaskCCW, context->stencilWriteMaskCCW);
488 }
489
490 void PixelProcessor::setStencilMask(int stencilMask)
491 {
492 context->stencilMask = stencilMask;
493 stencil.set(context->stencilReference, stencilMask, context->stencilWriteMask);
494 }
495
496 void PixelProcessor::setStencilMaskCCW(int stencilMaskCCW)
497 {
498 context->stencilMaskCCW = stencilMaskCCW;
499 stencilCCW.set(context->stencilReferenceCCW, stencilMaskCCW, context->stencilWriteMaskCCW);
500 }
501
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400502 void PixelProcessor::setStencilFailOperation(StencilOperation stencilFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400503 {
504 context->stencilFailOperation = stencilFailOperation;
505 }
506
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400507 void PixelProcessor::setStencilPassOperation(StencilOperation stencilPassOperation)
John Bauman89401822014-05-06 15:04:28 -0400508 {
509 context->stencilPassOperation = stencilPassOperation;
510 }
511
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400512 void PixelProcessor::setStencilZFailOperation(StencilOperation stencilZFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400513 {
514 context->stencilZFailOperation = stencilZFailOperation;
515 }
516
517 void PixelProcessor::setStencilWriteMask(int stencilWriteMask)
518 {
519 context->stencilWriteMask = stencilWriteMask;
520 stencil.set(context->stencilReference, context->stencilMask, stencilWriteMask);
521 }
522
523 void PixelProcessor::setStencilWriteMaskCCW(int stencilWriteMaskCCW)
524 {
525 context->stencilWriteMaskCCW = stencilWriteMaskCCW;
526 stencilCCW.set(context->stencilReferenceCCW, context->stencilMaskCCW, stencilWriteMaskCCW);
527 }
528
529 void PixelProcessor::setTwoSidedStencil(bool enable)
530 {
531 context->twoSidedStencil = enable;
532 }
533
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400534 void PixelProcessor::setStencilCompareCCW(StencilCompareMode stencilCompareMode)
John Bauman89401822014-05-06 15:04:28 -0400535 {
536 context->stencilCompareModeCCW = stencilCompareMode;
537 }
538
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400539 void PixelProcessor::setStencilFailOperationCCW(StencilOperation stencilFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400540 {
541 context->stencilFailOperationCCW = stencilFailOperation;
542 }
543
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400544 void PixelProcessor::setStencilPassOperationCCW(StencilOperation stencilPassOperation)
John Bauman89401822014-05-06 15:04:28 -0400545 {
546 context->stencilPassOperationCCW = stencilPassOperation;
547 }
548
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400549 void PixelProcessor::setStencilZFailOperationCCW(StencilOperation stencilZFailOperation)
John Bauman89401822014-05-06 15:04:28 -0400550 {
551 context->stencilZFailOperationCCW = stencilZFailOperation;
552 }
553
554 void PixelProcessor::setTextureFactor(const Color<float> &textureFactor)
555 {
556 // FIXME: Compact into generic function // FIXME: Clamp
557 short textureFactorR = iround(4095 * textureFactor.r);
558 short textureFactorG = iround(4095 * textureFactor.g);
559 short textureFactorB = iround(4095 * textureFactor.b);
560 short textureFactorA = iround(4095 * textureFactor.a);
561
562 factor.textureFactor4[0][0] = textureFactorR;
563 factor.textureFactor4[0][1] = textureFactorR;
564 factor.textureFactor4[0][2] = textureFactorR;
565 factor.textureFactor4[0][3] = textureFactorR;
566
567 factor.textureFactor4[1][0] = textureFactorG;
568 factor.textureFactor4[1][1] = textureFactorG;
569 factor.textureFactor4[1][2] = textureFactorG;
570 factor.textureFactor4[1][3] = textureFactorG;
571
572 factor.textureFactor4[2][0] = textureFactorB;
573 factor.textureFactor4[2][1] = textureFactorB;
574 factor.textureFactor4[2][2] = textureFactorB;
575 factor.textureFactor4[2][3] = textureFactorB;
576
577 factor.textureFactor4[3][0] = textureFactorA;
578 factor.textureFactor4[3][1] = textureFactorA;
579 factor.textureFactor4[3][2] = textureFactorA;
580 factor.textureFactor4[3][3] = textureFactorA;
581 }
582
583 void PixelProcessor::setBlendConstant(const Color<float> &blendConstant)
584 {
585 // FIXME: Compact into generic function // FIXME: Clamp
586 short blendConstantR = iround(65535 * blendConstant.r);
587 short blendConstantG = iround(65535 * blendConstant.g);
588 short blendConstantB = iround(65535 * blendConstant.b);
589 short blendConstantA = iround(65535 * blendConstant.a);
590
591 factor.blendConstant4W[0][0] = blendConstantR;
592 factor.blendConstant4W[0][1] = blendConstantR;
593 factor.blendConstant4W[0][2] = blendConstantR;
594 factor.blendConstant4W[0][3] = blendConstantR;
595
596 factor.blendConstant4W[1][0] = blendConstantG;
597 factor.blendConstant4W[1][1] = blendConstantG;
598 factor.blendConstant4W[1][2] = blendConstantG;
599 factor.blendConstant4W[1][3] = blendConstantG;
600
601 factor.blendConstant4W[2][0] = blendConstantB;
602 factor.blendConstant4W[2][1] = blendConstantB;
603 factor.blendConstant4W[2][2] = blendConstantB;
604 factor.blendConstant4W[2][3] = blendConstantB;
605
606 factor.blendConstant4W[3][0] = blendConstantA;
607 factor.blendConstant4W[3][1] = blendConstantA;
608 factor.blendConstant4W[3][2] = blendConstantA;
609 factor.blendConstant4W[3][3] = blendConstantA;
610
611 // FIXME: Compact into generic function // FIXME: Clamp
612 short invBlendConstantR = iround(65535 * (1 - blendConstant.r));
613 short invBlendConstantG = iround(65535 * (1 - blendConstant.g));
614 short invBlendConstantB = iround(65535 * (1 - blendConstant.b));
615 short invBlendConstantA = iround(65535 * (1 - blendConstant.a));
616
617 factor.invBlendConstant4W[0][0] = invBlendConstantR;
618 factor.invBlendConstant4W[0][1] = invBlendConstantR;
619 factor.invBlendConstant4W[0][2] = invBlendConstantR;
620 factor.invBlendConstant4W[0][3] = invBlendConstantR;
621
622 factor.invBlendConstant4W[1][0] = invBlendConstantG;
623 factor.invBlendConstant4W[1][1] = invBlendConstantG;
624 factor.invBlendConstant4W[1][2] = invBlendConstantG;
625 factor.invBlendConstant4W[1][3] = invBlendConstantG;
626
627 factor.invBlendConstant4W[2][0] = invBlendConstantB;
628 factor.invBlendConstant4W[2][1] = invBlendConstantB;
629 factor.invBlendConstant4W[2][2] = invBlendConstantB;
630 factor.invBlendConstant4W[2][3] = invBlendConstantB;
631
632 factor.invBlendConstant4W[3][0] = invBlendConstantA;
633 factor.invBlendConstant4W[3][1] = invBlendConstantA;
634 factor.invBlendConstant4W[3][2] = invBlendConstantA;
635 factor.invBlendConstant4W[3][3] = invBlendConstantA;
636
637 factor.blendConstant4F[0][0] = blendConstant.r;
638 factor.blendConstant4F[0][1] = blendConstant.r;
639 factor.blendConstant4F[0][2] = blendConstant.r;
640 factor.blendConstant4F[0][3] = blendConstant.r;
641
642 factor.blendConstant4F[1][0] = blendConstant.g;
643 factor.blendConstant4F[1][1] = blendConstant.g;
644 factor.blendConstant4F[1][2] = blendConstant.g;
645 factor.blendConstant4F[1][3] = blendConstant.g;
646
647 factor.blendConstant4F[2][0] = blendConstant.b;
648 factor.blendConstant4F[2][1] = blendConstant.b;
649 factor.blendConstant4F[2][2] = blendConstant.b;
650 factor.blendConstant4F[2][3] = blendConstant.b;
651
652 factor.blendConstant4F[3][0] = blendConstant.a;
653 factor.blendConstant4F[3][1] = blendConstant.a;
654 factor.blendConstant4F[3][2] = blendConstant.a;
655 factor.blendConstant4F[3][3] = blendConstant.a;
656
657 factor.invBlendConstant4F[0][0] = 1 - blendConstant.r;
658 factor.invBlendConstant4F[0][1] = 1 - blendConstant.r;
659 factor.invBlendConstant4F[0][2] = 1 - blendConstant.r;
660 factor.invBlendConstant4F[0][3] = 1 - blendConstant.r;
661
662 factor.invBlendConstant4F[1][0] = 1 - blendConstant.g;
663 factor.invBlendConstant4F[1][1] = 1 - blendConstant.g;
664 factor.invBlendConstant4F[1][2] = 1 - blendConstant.g;
665 factor.invBlendConstant4F[1][3] = 1 - blendConstant.g;
666
667 factor.invBlendConstant4F[2][0] = 1 - blendConstant.b;
668 factor.invBlendConstant4F[2][1] = 1 - blendConstant.b;
669 factor.invBlendConstant4F[2][2] = 1 - blendConstant.b;
670 factor.invBlendConstant4F[2][3] = 1 - blendConstant.b;
671
672 factor.invBlendConstant4F[3][0] = 1 - blendConstant.a;
673 factor.invBlendConstant4F[3][1] = 1 - blendConstant.a;
674 factor.invBlendConstant4F[3][2] = 1 - blendConstant.a;
675 factor.invBlendConstant4F[3][3] = 1 - blendConstant.a;
676 }
677
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400678 void PixelProcessor::setFillMode(FillMode fillMode)
John Bauman89401822014-05-06 15:04:28 -0400679 {
680 context->fillMode = fillMode;
681 }
682
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400683 void PixelProcessor::setShadingMode(ShadingMode shadingMode)
John Bauman89401822014-05-06 15:04:28 -0400684 {
685 context->shadingMode = shadingMode;
686 }
687
688 void PixelProcessor::setAlphaBlendEnable(bool alphaBlendEnable)
689 {
690 context->setAlphaBlendEnable(alphaBlendEnable);
691 }
692
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400693 void PixelProcessor::setSourceBlendFactor(BlendFactor sourceBlendFactor)
John Bauman89401822014-05-06 15:04:28 -0400694 {
695 context->setSourceBlendFactor(sourceBlendFactor);
696 }
697
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400698 void PixelProcessor::setDestBlendFactor(BlendFactor destBlendFactor)
John Bauman89401822014-05-06 15:04:28 -0400699 {
700 context->setDestBlendFactor(destBlendFactor);
701 }
702
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400703 void PixelProcessor::setBlendOperation(BlendOperation blendOperation)
John Bauman89401822014-05-06 15:04:28 -0400704 {
705 context->setBlendOperation(blendOperation);
706 }
707
708 void PixelProcessor::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)
709 {
710 context->setSeparateAlphaBlendEnable(separateAlphaBlendEnable);
711 }
712
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400713 void PixelProcessor::setSourceBlendFactorAlpha(BlendFactor sourceBlendFactorAlpha)
John Bauman89401822014-05-06 15:04:28 -0400714 {
715 context->setSourceBlendFactorAlpha(sourceBlendFactorAlpha);
716 }
717
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400718 void PixelProcessor::setDestBlendFactorAlpha(BlendFactor destBlendFactorAlpha)
John Bauman89401822014-05-06 15:04:28 -0400719 {
720 context->setDestBlendFactorAlpha(destBlendFactorAlpha);
721 }
722
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400723 void PixelProcessor::setBlendOperationAlpha(BlendOperation blendOperationAlpha)
John Bauman89401822014-05-06 15:04:28 -0400724 {
725 context->setBlendOperationAlpha(blendOperationAlpha);
726 }
727
Alexis Hetua818c452015-06-11 13:06:58 -0400728 void PixelProcessor::setAlphaReference(float alphaReference)
John Bauman89401822014-05-06 15:04:28 -0400729 {
730 context->alphaReference = alphaReference;
731
Alexis Hetua818c452015-06-11 13:06:58 -0400732 factor.alphaReference4[0] = (word)iround(alphaReference * 0x1000 / 0xFF);
733 factor.alphaReference4[1] = (word)iround(alphaReference * 0x1000 / 0xFF);
734 factor.alphaReference4[2] = (word)iround(alphaReference * 0x1000 / 0xFF);
735 factor.alphaReference4[3] = (word)iround(alphaReference * 0x1000 / 0xFF);
John Bauman89401822014-05-06 15:04:28 -0400736 }
737
738 void PixelProcessor::setGlobalMipmapBias(float bias)
739 {
740 context->setGlobalMipmapBias(bias);
741 }
742
743 void PixelProcessor::setFogStart(float start)
744 {
745 setFogRanges(start, context->fogEnd);
746 }
747
748 void PixelProcessor::setFogEnd(float end)
749 {
750 setFogRanges(context->fogStart, end);
751 }
752
753 void PixelProcessor::setFogColor(Color<float> fogColor)
754 {
755 // TODO: Compact into generic function
756 word fogR = (unsigned short)(65535 * fogColor.r);
757 word fogG = (unsigned short)(65535 * fogColor.g);
758 word fogB = (unsigned short)(65535 * fogColor.b);
759
760 fog.color4[0][0] = fogR;
761 fog.color4[0][1] = fogR;
762 fog.color4[0][2] = fogR;
763 fog.color4[0][3] = fogR;
764
765 fog.color4[1][0] = fogG;
766 fog.color4[1][1] = fogG;
767 fog.color4[1][2] = fogG;
768 fog.color4[1][3] = fogG;
769
770 fog.color4[2][0] = fogB;
771 fog.color4[2][1] = fogB;
772 fog.color4[2][2] = fogB;
773 fog.color4[2][3] = fogB;
774
775 fog.colorF[0] = replicate(fogColor.r);
776 fog.colorF[1] = replicate(fogColor.g);
777 fog.colorF[2] = replicate(fogColor.b);
778 }
779
780 void PixelProcessor::setFogDensity(float fogDensity)
781 {
782 fog.densityE = replicate(-fogDensity * 1.442695f); // 1/e^x = 2^(-x*1.44)
783 fog.densityE2 = replicate(fogDensity * 1.201122f); // 1/e^(x^2) = 2^(-(x*1.20)^2)
784 }
785
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400786 void PixelProcessor::setPixelFogMode(FogMode fogMode)
John Bauman89401822014-05-06 15:04:28 -0400787 {
788 context->pixelFogMode = fogMode;
789 }
790
791 void PixelProcessor::setPerspectiveCorrection(bool perspectiveEnable)
792 {
793 perspectiveCorrection = perspectiveEnable;
794 }
795
796 void PixelProcessor::setOcclusionEnabled(bool enable)
797 {
798 context->occlusionEnabled = enable;
799 }
800
801 void PixelProcessor::setRoutineCacheSize(int cacheSize)
802 {
803 delete routineCache;
John Bauman66b8ab22014-05-06 15:57:45 -0400804 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precachePixel ? "sw-pixel" : 0);
John Bauman89401822014-05-06 15:04:28 -0400805 }
806
807 void PixelProcessor::setFogRanges(float start, float end)
808 {
809 context->fogStart = start;
810 context->fogEnd = end;
811
812 if(start == end)
813 {
814 end += 0.001f; // Hack: ensure there is a small range
815 }
816
817 float fogScale = -1.0f / (end - start);
818 float fogOffset = end * -fogScale;
819
820 fog.scale = replicate(fogScale);
821 fog.offset = replicate(fogOffset);
822 }
823
824 const PixelProcessor::State PixelProcessor::update() const
825 {
826 State state;
827
828 if(context->pixelShader)
829 {
John Bauman19bac1e2014-05-06 15:23:49 -0400830 state.shaderID = context->pixelShader->getSerialID();
John Bauman89401822014-05-06 15:04:28 -0400831 }
832 else
833 {
John Bauman19bac1e2014-05-06 15:23:49 -0400834 state.shaderID = 0;
John Bauman89401822014-05-06 15:04:28 -0400835 }
836
837 state.depthOverride = context->pixelShader && context->pixelShader->depthOverride();
John Bauman19bac1e2014-05-06 15:23:49 -0400838 state.shaderContainsKill = context->pixelShader ? context->pixelShader->containsKill() : false;
John Bauman89401822014-05-06 15:04:28 -0400839
840 if(context->alphaTestActive())
841 {
842 state.alphaCompareMode = context->alphaCompareMode;
843
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400844 state.transparencyAntialiasing = context->getMultiSampleCount() > 1 ? transparencyAntialiasing : TRANSPARENCY_NONE;
John Bauman89401822014-05-06 15:04:28 -0400845 }
846
847 state.depthWriteEnable = context->depthWriteActive();
848
849 if(context->stencilActive())
850 {
851 state.stencilActive = true;
852 state.stencilCompareMode = context->stencilCompareMode;
853 state.stencilFailOperation = context->stencilFailOperation;
854 state.stencilPassOperation = context->stencilPassOperation;
855 state.stencilZFailOperation = context->stencilZFailOperation;
856 state.noStencilMask = (context->stencilMask == 0xFF);
857 state.noStencilWriteMask = (context->stencilWriteMask == 0xFF);
858 state.stencilWriteMasked = (context->stencilWriteMask == 0x00);
859
860 state.twoSidedStencil = context->twoSidedStencil;
861 state.stencilCompareModeCCW = context->twoSidedStencil ? context->stencilCompareModeCCW : state.stencilCompareMode;
862 state.stencilFailOperationCCW = context->twoSidedStencil ? context->stencilFailOperationCCW : state.stencilFailOperation;
863 state.stencilPassOperationCCW = context->twoSidedStencil ? context->stencilPassOperationCCW : state.stencilPassOperation;
864 state.stencilZFailOperationCCW = context->twoSidedStencil ? context->stencilZFailOperationCCW : state.stencilZFailOperation;
865 state.noStencilMaskCCW = context->twoSidedStencil ? (context->stencilMaskCCW == 0xFF) : state.noStencilMask;
866 state.noStencilWriteMaskCCW = context->twoSidedStencil ? (context->stencilWriteMaskCCW == 0xFF) : state.noStencilWriteMask;
867 state.stencilWriteMaskedCCW = context->twoSidedStencil ? (context->stencilWriteMaskCCW == 0x00) : state.stencilWriteMasked;
868 }
869
870 if(context->depthBufferActive())
871 {
872 state.depthTestActive = true;
873 state.depthCompareMode = context->depthCompareMode;
874 state.quadLayoutDepthBuffer = context->depthStencil->getInternalFormat() != FORMAT_D32F_LOCKABLE &&
John Bauman66b8ab22014-05-06 15:57:45 -0400875 context->depthStencil->getInternalFormat() != FORMAT_D32FS8_TEXTURE &&
876 context->depthStencil->getInternalFormat() != FORMAT_D32FS8_SHADOW;
John Bauman89401822014-05-06 15:04:28 -0400877 }
878
879 state.occlusionEnabled = context->occlusionEnabled;
880
881 state.fogActive = context->fogActive();
882 state.pixelFogMode = context->pixelFogActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400883 state.wBasedFog = context->wBasedFog && context->pixelFogActive() != FOG_NONE;
John Bauman89401822014-05-06 15:04:28 -0400884 state.perspective = context->perspectiveActive();
885
886 if(context->alphaBlendActive())
887 {
888 state.alphaBlendActive = true;
889 state.sourceBlendFactor = context->sourceBlendFactor();
890 state.destBlendFactor = context->destBlendFactor();
891 state.blendOperation = context->blendOperation();
892 state.sourceBlendFactorAlpha = context->sourceBlendFactorAlpha();
893 state.destBlendFactorAlpha = context->destBlendFactorAlpha();
894 state.blendOperationAlpha = context->blendOperationAlpha();
895 }
Maxime Grégoired9762742015-07-08 16:43:48 -0400896
897 state.logicalOperation = context->colorLogicOp();
898
John Bauman89401822014-05-06 15:04:28 -0400899 state.colorWriteMask = (context->colorWriteActive(0) << 0) |
900 (context->colorWriteActive(1) << 4) |
901 (context->colorWriteActive(2) << 8) |
902 (context->colorWriteActive(3) << 12);
903
904 for(int i = 0; i < 4; i++)
905 {
906 state.targetFormat[i] = context->renderTargetInternalFormat(i);
907 }
908
John Bauman66b8ab22014-05-06 15:57:45 -0400909 state.writeSRGB = context->writeSRGB && context->renderTarget[0] && Surface::isSRGBwritable(context->renderTarget[0]->getExternalFormat());
910 state.multiSample = context->getMultiSampleCount();
John Bauman89401822014-05-06 15:04:28 -0400911 state.multiSampleMask = context->multiSampleMask;
912
913 if(state.multiSample > 1 && context->pixelShader)
914 {
915 state.centroid = context->pixelShader->containsCentroid();
916 }
917
918 if(!context->pixelShader)
919 {
920 for(unsigned int i = 0; i < 8; i++)
921 {
922 state.textureStage[i] = context->textureStage[i].textureStageState();
923 }
924
925 state.specularAdd = context->specularActive() && context->specularEnable;
926 }
927
928 for(unsigned int i = 0; i < 16; i++)
929 {
930 if(context->pixelShader)
931 {
932 if(context->pixelShader->usesSampler(i))
933 {
934 state.sampler[i] = context->sampler[i].samplerState();
935 }
936 }
937 else
938 {
939 if(i < 8 && state.textureStage[i].stageOperation != TextureStage::STAGE_DISABLE)
940 {
941 state.sampler[i] = context->sampler[i].samplerState();
942 }
943 else break;
944 }
945 }
946
947 const bool point = context->isDrawPoint(true);
948 const bool sprite = context->pointSpriteActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400949 const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
John Bauman89401822014-05-06 15:04:28 -0400950
951 if(context->pixelShaderVersion() < 0x0300)
952 {
953 for(int coordinate = 0; coordinate < 8; coordinate++)
954 {
955 for(int component = 0; component < 4; component++)
956 {
957 if(context->textureActive(coordinate, component))
958 {
959 state.texture[coordinate].component |= 1 << component;
960
961 if(point && !sprite)
962 {
963 state.texture[coordinate].flat |= 1 << component;
964 }
965 }
966 }
967
968 if(context->textureTransformProject[coordinate] && context->pixelShaderVersion() <= 0x0103)
969 {
970 if(context->textureTransformCount[coordinate] == 2)
971 {
972 state.texture[coordinate].project = 1;
973 }
974 else if(context->textureTransformCount[coordinate] == 3)
975 {
976 state.texture[coordinate].project = 2;
977 }
978 else if(context->textureTransformCount[coordinate] == 4 || context->textureTransformCount[coordinate] == 0)
979 {
980 state.texture[coordinate].project = 3;
981 }
982 }
983 }
984
985 for(int color = 0; color < 2; color++)
986 {
987 for(int component = 0; component < 4; component++)
988 {
989 if(context->colorActive(color, component))
990 {
991 state.color[color].component |= 1 << component;
992
993 if(point || flatShading)
994 {
995 state.color[color].flat |= 1 << component;
996 }
997 }
998 }
999 }
1000
1001 if(context->fogActive())
1002 {
1003 state.fog.component = true;
1004
1005 if(point)
1006 {
1007 state.fog.flat = true;
1008 }
1009 }
1010 }
1011 else
1012 {
1013 for(int interpolant = 0; interpolant < 10; interpolant++)
1014 {
1015 for(int component = 0; component < 4; component++)
1016 {
1017 if(context->pixelShader->semantic[interpolant][component].active())
1018 {
1019 bool flat = point;
1020
1021 switch(context->pixelShader->semantic[interpolant][component].usage)
1022 {
John Bauman19bac1e2014-05-06 15:23:49 -04001023 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
1024 case Shader::USAGE_COLOR: flat = flatShading; break;
John Bauman89401822014-05-06 15:04:28 -04001025 }
1026
1027 state.interpolant[interpolant].component |= 1 << component;
1028
1029 if(flat)
1030 {
1031 state.interpolant[interpolant].flat |= 1 << component;
1032 }
1033 }
1034 }
1035 }
1036 }
1037
1038 if(state.centroid)
1039 {
1040 for(int interpolant = 0; interpolant < 10; interpolant++)
1041 {
1042 for(int component = 0; component < 4; component++)
1043 {
1044 state.interpolant[interpolant].centroid = context->pixelShader->semantic[interpolant][0].centroid;
1045 }
1046 }
1047 }
1048
1049 state.hash = state.computeHash();
1050
1051 return state;
1052 }
1053
1054 Routine *PixelProcessor::routine(const State &state)
1055 {
1056 Routine *routine = routineCache->query(state);
1057
1058 if(!routine)
1059 {
1060 Rasterizer *generator = new QuadRasterizer(state, context->pixelShader);
1061 generator->generate();
1062 routine = generator->getRoutine();
1063 delete generator;
1064
1065 routineCache->add(state, routine);
1066 }
1067
1068 return routine;
1069 }
1070}