blob: a1a752ca3a508b5953041cf7ac571c4c4a83e98d [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 "PixelRoutine.hpp"
13
14#include "Renderer.hpp"
John Bauman89401822014-05-06 15:04:28 -040015#include "QuadRasterizer.hpp"
16#include "Surface.hpp"
17#include "Primitive.hpp"
18#include "CPUID.hpp"
19#include "SamplerCore.hpp"
20#include "Constants.hpp"
21#include "Debug.hpp"
22
John Bauman89401822014-05-06 15:04:28 -040023namespace sw
24{
25 extern bool complementaryDepthBuffer;
26 extern bool postBlendSRGB;
27 extern bool exactColorRounding;
Alexis Hetuf2a8c372015-07-13 11:08:41 -040028 extern bool forceClearRegisters;
John Bauman89401822014-05-06 15:04:28 -040029
Nicolas Capens4f172c72016-01-13 08:34:30 -050030 PixelRoutine::PixelRoutine(const PixelProcessor::State &state, const PixelShader *shader) : QuadRasterizer(state, shader), v(shader && shader->dynamicallyIndexedInput)
John Bauman89401822014-05-06 15:04:28 -040031 {
Alexis Hetuf2a8c372015-07-13 11:08:41 -040032 if(!shader || shader->getVersion() < 0x0200 || forceClearRegisters)
John Bauman89401822014-05-06 15:04:28 -040033 {
Alexis Hetuf2a8c372015-07-13 11:08:41 -040034 for(int i = 0; i < 10; i++)
35 {
Alexis Hetu3e1fd3a2015-08-11 10:15:34 -040036 v[i].x = Float4(0.0f);
37 v[i].y = Float4(0.0f);
38 v[i].z = Float4(0.0f);
39 v[i].w = Float4(0.0f);
Alexis Hetuf2a8c372015-07-13 11:08:41 -040040 }
John Bauman89401822014-05-06 15:04:28 -040041 }
42 }
43
44 PixelRoutine::~PixelRoutine()
45 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -040046 for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++)
John Bauman89401822014-05-06 15:04:28 -040047 {
48 delete sampler[i];
49 }
50 }
51
Nicolas Capens4f172c72016-01-13 08:34:30 -050052 void PixelRoutine::quad(Pointer<Byte> cBuffer[RENDERTARGETS], Pointer<Byte> &zBuffer, Pointer<Byte> &sBuffer, Int cMask[4], Int &x, Int &y)
John Bauman89401822014-05-06 15:04:28 -040053 {
54 #if PERF_PROFILE
55 Long pipeTime = Ticks();
56 #endif
57
Alexis Hetu0b65c5e2015-03-31 11:48:57 -040058 for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++)
John Bauman89401822014-05-06 15:04:28 -040059 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050060 sampler[i] = new SamplerCore(constants, state.sampler[i]);
John Bauman89401822014-05-06 15:04:28 -040061 }
62
63 const bool earlyDepthTest = !state.depthOverride && !state.alphaTestActive();
John Bauman89401822014-05-06 15:04:28 -040064
65 Int zMask[4]; // Depth mask
66 Int sMask[4]; // Stencil mask
67
68 for(unsigned int q = 0; q < state.multiSample; q++)
69 {
70 zMask[q] = cMask[q];
71 sMask[q] = cMask[q];
72 }
73
74 for(unsigned int q = 0; q < state.multiSample; q++)
75 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050076 stencilTest(sBuffer, q, x, sMask[q], cMask[q]);
John Bauman89401822014-05-06 15:04:28 -040077 }
78
79 Float4 f;
John Bauman89401822014-05-06 15:04:28 -040080 Float4 rhwCentroid;
81
Nicolas Capens4f172c72016-01-13 08:34:30 -050082 Float4 xxxx = Float4(Float(x)) + *Pointer<Float4>(primitive + OFFSET(Primitive,xQuad), 16);
John Bauman89401822014-05-06 15:04:28 -040083
John Bauman19bac1e2014-05-06 15:23:49 -040084 if(interpolateZ())
John Bauman89401822014-05-06 15:04:28 -040085 {
86 for(unsigned int q = 0; q < state.multiSample; q++)
87 {
88 Float4 x = xxxx;
Nicolas Capens4f172c72016-01-13 08:34:30 -050089
John Bauman89401822014-05-06 15:04:28 -040090 if(state.multiSample > 1)
91 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050092 x -= *Pointer<Float4>(constants + OFFSET(Constants,X) + q * sizeof(float4));
John Bauman89401822014-05-06 15:04:28 -040093 }
94
Nicolas Capens4f172c72016-01-13 08:34:30 -050095 z[q] = interpolate(x, Dz[q], z[q], primitive + OFFSET(Primitive,z), false, false);
John Bauman89401822014-05-06 15:04:28 -040096 }
97 }
98
99 Bool depthPass = false;
100
101 if(earlyDepthTest)
102 {
103 for(unsigned int q = 0; q < state.multiSample; q++)
104 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500105 depthPass = depthPass || depthTest(zBuffer, q, x, z[q], sMask[q], zMask[q], cMask[q]);
John Bauman89401822014-05-06 15:04:28 -0400106 }
107 }
108
109 If(depthPass || Bool(!earlyDepthTest))
110 {
111 #if PERF_PROFILE
112 Long interpTime = Ticks();
113 #endif
114
Nicolas Capens4f172c72016-01-13 08:34:30 -0500115 Float4 yyyy = Float4(Float(y)) + *Pointer<Float4>(primitive + OFFSET(Primitive,yQuad), 16);
Nicolas Capenscbefe532014-10-16 00:16:01 -0400116
John Bauman89401822014-05-06 15:04:28 -0400117 // Centroid locations
118 Float4 XXXX = Float4(0.0f);
119 Float4 YYYY = Float4(0.0f);
120
121 if(state.centroid)
122 {
123 Float4 WWWW(1.0e-9f);
124
125 for(unsigned int q = 0; q < state.multiSample; q++)
126 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500127 XXXX += *Pointer<Float4>(constants + OFFSET(Constants,sampleX[q]) + 16 * cMask[q]);
128 YYYY += *Pointer<Float4>(constants + OFFSET(Constants,sampleY[q]) + 16 * cMask[q]);
129 WWWW += *Pointer<Float4>(constants + OFFSET(Constants,weight) + 16 * cMask[q]);
John Bauman89401822014-05-06 15:04:28 -0400130 }
131
132 WWWW = Rcp_pp(WWWW);
133 XXXX *= WWWW;
134 YYYY *= WWWW;
135
136 XXXX += xxxx;
137 YYYY += yyyy;
138 }
139
John Bauman19bac1e2014-05-06 15:23:49 -0400140 if(interpolateW())
John Bauman89401822014-05-06 15:04:28 -0400141 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500142 w = interpolate(xxxx, Dw, rhw, primitive + OFFSET(Primitive,w), false, false);
Nicolas Capens05b3d662016-02-25 23:58:33 -0500143 rhw = reciprocal(w, false, false, true);
John Bauman89401822014-05-06 15:04:28 -0400144
145 if(state.centroid)
146 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500147 rhwCentroid = reciprocal(interpolateCentroid(XXXX, YYYY, rhwCentroid, primitive + OFFSET(Primitive,w), false, false));
John Bauman89401822014-05-06 15:04:28 -0400148 }
149 }
150
151 for(int interpolant = 0; interpolant < 10; interpolant++)
152 {
153 for(int component = 0; component < 4; component++)
154 {
John Bauman89401822014-05-06 15:04:28 -0400155 if(state.interpolant[interpolant].component & (1 << component))
156 {
157 if(!state.interpolant[interpolant].centroid)
158 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500159 v[interpolant][component] = interpolate(xxxx, Dv[interpolant][component], rhw, primitive + OFFSET(Primitive, V[interpolant][component]), (state.interpolant[interpolant].flat & (1 << component)) != 0, state.perspective);
John Bauman89401822014-05-06 15:04:28 -0400160 }
161 else
162 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500163 v[interpolant][component] = interpolateCentroid(XXXX, YYYY, rhwCentroid, primitive + OFFSET(Primitive, V[interpolant][component]), (state.interpolant[interpolant].flat & (1 << component)) != 0, state.perspective);
John Bauman89401822014-05-06 15:04:28 -0400164 }
165 }
166 }
167
168 Float4 rcp;
169
170 switch(state.interpolant[interpolant].project)
171 {
172 case 0:
173 break;
174 case 1:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500175 rcp = reciprocal(v[interpolant].y);
176 v[interpolant].x = v[interpolant].x * rcp;
John Bauman89401822014-05-06 15:04:28 -0400177 break;
178 case 2:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500179 rcp = reciprocal(v[interpolant].z);
180 v[interpolant].x = v[interpolant].x * rcp;
181 v[interpolant].y = v[interpolant].y * rcp;
John Bauman89401822014-05-06 15:04:28 -0400182 break;
183 case 3:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500184 rcp = reciprocal(v[interpolant].w);
185 v[interpolant].x = v[interpolant].x * rcp;
186 v[interpolant].y = v[interpolant].y * rcp;
187 v[interpolant].z = v[interpolant].z * rcp;
John Bauman89401822014-05-06 15:04:28 -0400188 break;
189 }
190 }
191
192 if(state.fog.component)
193 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500194 f = interpolate(xxxx, Df, rhw, primitive + OFFSET(Primitive,f), state.fog.flat & 0x01, state.perspective);
John Bauman89401822014-05-06 15:04:28 -0400195 }
196
Nicolas Capens4f172c72016-01-13 08:34:30 -0500197 setBuiltins(x, y, z, w);
John Bauman89401822014-05-06 15:04:28 -0400198
199 #if PERF_PROFILE
Nicolas Capens4f172c72016-01-13 08:34:30 -0500200 cycles[PERF_INTERP] += Ticks() - interpTime;
John Bauman89401822014-05-06 15:04:28 -0400201 #endif
202
203 Bool alphaPass = true;
204
205 if(colorUsed())
206 {
207 #if PERF_PROFILE
208 Long shaderTime = Ticks();
209 #endif
210
Nicolas Capens4f172c72016-01-13 08:34:30 -0500211 applyShader(cMask);
John Bauman89401822014-05-06 15:04:28 -0400212
213 #if PERF_PROFILE
Nicolas Capens4f172c72016-01-13 08:34:30 -0500214 cycles[PERF_SHADER] += Ticks() - shaderTime;
John Bauman89401822014-05-06 15:04:28 -0400215 #endif
216
Nicolas Capens4f172c72016-01-13 08:34:30 -0500217 alphaPass = alphaTest(cMask);
John Bauman89401822014-05-06 15:04:28 -0400218
John Bauman19bac1e2014-05-06 15:23:49 -0400219 if((shader && shader->containsKill()) || state.alphaTestActive())
John Bauman89401822014-05-06 15:04:28 -0400220 {
221 for(unsigned int q = 0; q < state.multiSample; q++)
222 {
223 zMask[q] &= cMask[q];
224 sMask[q] &= cMask[q];
225 }
226 }
227 }
228
229 If(alphaPass)
230 {
231 if(!earlyDepthTest)
232 {
233 for(unsigned int q = 0; q < state.multiSample; q++)
234 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500235 depthPass = depthPass || depthTest(zBuffer, q, x, z[q], sMask[q], zMask[q], cMask[q]);
John Bauman89401822014-05-06 15:04:28 -0400236 }
237 }
238
239 #if PERF_PROFILE
240 Long ropTime = Ticks();
241 #endif
242
243 If(depthPass || Bool(earlyDepthTest))
244 {
245 for(unsigned int q = 0; q < state.multiSample; q++)
246 {
247 if(state.multiSampleMask & (1 << q))
248 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500249 writeDepth(zBuffer, q, x, z[q], zMask[q]);
John Bauman89401822014-05-06 15:04:28 -0400250
251 if(state.occlusionEnabled)
252 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500253 occlusion += *Pointer<UInt>(constants + OFFSET(Constants,occlusionCount) + 4 * (zMask[q] & sMask[q]));
John Bauman89401822014-05-06 15:04:28 -0400254 }
255 }
256 }
257
258 if(colorUsed())
259 {
260 #if PERF_PROFILE
John Bauman66b8ab22014-05-06 15:57:45 -0400261 AddAtomic(Pointer<Long>(&profiler.ropOperations), 4);
John Bauman89401822014-05-06 15:04:28 -0400262 #endif
263
Nicolas Capens4f172c72016-01-13 08:34:30 -0500264 rasterOperation(f, cBuffer, x, sMask, zMask, cMask);
John Bauman89401822014-05-06 15:04:28 -0400265 }
266 }
267
268 #if PERF_PROFILE
Nicolas Capens4f172c72016-01-13 08:34:30 -0500269 cycles[PERF_ROP] += Ticks() - ropTime;
John Bauman89401822014-05-06 15:04:28 -0400270 #endif
271 }
272 }
273
274 for(unsigned int q = 0; q < state.multiSample; q++)
275 {
276 if(state.multiSampleMask & (1 << q))
277 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500278 writeStencil(sBuffer, q, x, sMask[q], zMask[q], cMask[q]);
John Bauman89401822014-05-06 15:04:28 -0400279 }
280 }
281
282 #if PERF_PROFILE
Nicolas Capens4f172c72016-01-13 08:34:30 -0500283 cycles[PERF_PIPE] += Ticks() - pipeTime;
John Bauman89401822014-05-06 15:04:28 -0400284 #endif
285 }
286
John Bauman89401822014-05-06 15:04:28 -0400287 Float4 PixelRoutine::interpolateCentroid(Float4 &x, Float4 &y, Float4 &rhw, Pointer<Byte> planeEquation, bool flat, bool perspective)
288 {
289 Float4 interpolant = *Pointer<Float4>(planeEquation + OFFSET(PlaneEquation,C), 16);
290
291 if(!flat)
292 {
293 interpolant += x * *Pointer<Float4>(planeEquation + OFFSET(PlaneEquation,A), 16) +
294 y * *Pointer<Float4>(planeEquation + OFFSET(PlaneEquation,B), 16);
295
296 if(perspective)
297 {
298 interpolant *= rhw;
299 }
300 }
301
302 return interpolant;
303 }
304
Nicolas Capens4f172c72016-01-13 08:34:30 -0500305 void PixelRoutine::stencilTest(Pointer<Byte> &sBuffer, int q, Int &x, Int &sMask, Int &cMask)
John Bauman89401822014-05-06 15:04:28 -0400306 {
307 if(!state.stencilActive)
308 {
309 return;
310 }
311
312 // (StencilRef & StencilMask) CompFunc (StencilBufferValue & StencilMask)
313
314 Pointer<Byte> buffer = sBuffer + 2 * x;
315
316 if(q > 0)
317 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500318 buffer += q * *Pointer<Int>(data + OFFSET(DrawData,stencilSliceB));
John Bauman89401822014-05-06 15:04:28 -0400319 }
320
321 Byte8 value = As<Byte8>(Long1(*Pointer<UInt>(buffer)));
322 Byte8 valueCCW = value;
323
324 if(!state.noStencilMask)
325 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500326 value &= *Pointer<Byte8>(data + OFFSET(DrawData,stencil[0].testMaskQ));
John Bauman89401822014-05-06 15:04:28 -0400327 }
328
Nicolas Capens4f172c72016-01-13 08:34:30 -0500329 stencilTest(value, state.stencilCompareMode, false);
John Bauman89401822014-05-06 15:04:28 -0400330
331 if(state.twoSidedStencil)
332 {
333 if(!state.noStencilMaskCCW)
334 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500335 valueCCW &= *Pointer<Byte8>(data + OFFSET(DrawData,stencil[1].testMaskQ));
John Bauman89401822014-05-06 15:04:28 -0400336 }
337
Nicolas Capens4f172c72016-01-13 08:34:30 -0500338 stencilTest(valueCCW, state.stencilCompareModeCCW, true);
John Bauman89401822014-05-06 15:04:28 -0400339
Nicolas Capens4f172c72016-01-13 08:34:30 -0500340 value &= *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask));
341 valueCCW &= *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask));
John Bauman89401822014-05-06 15:04:28 -0400342 value |= valueCCW;
343 }
344
345 sMask = SignMask(value) & cMask;
346 }
347
Nicolas Capens4f172c72016-01-13 08:34:30 -0500348 void PixelRoutine::stencilTest(Byte8 &value, StencilCompareMode stencilCompareMode, bool CCW)
John Bauman89401822014-05-06 15:04:28 -0400349 {
350 Byte8 equal;
351
352 switch(stencilCompareMode)
353 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400354 case STENCIL_ALWAYS:
John Bauman89401822014-05-06 15:04:28 -0400355 value = Byte8(0xFFFFFFFFFFFFFFFF);
356 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400357 case STENCIL_NEVER:
John Bauman89401822014-05-06 15:04:28 -0400358 value = Byte8(0x0000000000000000);
359 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400360 case STENCIL_LESS: // a < b ~ b > a
John Bauman89401822014-05-06 15:04:28 -0400361 value += Byte8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
Nicolas Capens4f172c72016-01-13 08:34:30 -0500362 value = CmpGT(As<SByte8>(value), *Pointer<SByte8>(data + OFFSET(DrawData,stencil[CCW].referenceMaskedSignedQ)));
John Bauman89401822014-05-06 15:04:28 -0400363 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400364 case STENCIL_EQUAL:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500365 value = CmpEQ(value, *Pointer<Byte8>(data + OFFSET(DrawData,stencil[CCW].referenceMaskedQ)));
John Bauman89401822014-05-06 15:04:28 -0400366 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400367 case STENCIL_NOTEQUAL: // a != b ~ !(a == b)
Nicolas Capens4f172c72016-01-13 08:34:30 -0500368 value = CmpEQ(value, *Pointer<Byte8>(data + OFFSET(DrawData,stencil[CCW].referenceMaskedQ)));
John Bauman89401822014-05-06 15:04:28 -0400369 value ^= Byte8(0xFFFFFFFFFFFFFFFF);
370 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400371 case STENCIL_LESSEQUAL: // a <= b ~ (b > a) || (a == b)
John Bauman89401822014-05-06 15:04:28 -0400372 equal = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500373 equal = CmpEQ(equal, *Pointer<Byte8>(data + OFFSET(DrawData,stencil[CCW].referenceMaskedQ)));
John Bauman89401822014-05-06 15:04:28 -0400374 value += Byte8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
Nicolas Capens4f172c72016-01-13 08:34:30 -0500375 value = CmpGT(As<SByte8>(value), *Pointer<SByte8>(data + OFFSET(DrawData,stencil[CCW].referenceMaskedSignedQ)));
John Bauman89401822014-05-06 15:04:28 -0400376 value |= equal;
377 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400378 case STENCIL_GREATER: // a > b
Nicolas Capens4f172c72016-01-13 08:34:30 -0500379 equal = *Pointer<Byte8>(data + OFFSET(DrawData,stencil[CCW].referenceMaskedSignedQ));
John Bauman89401822014-05-06 15:04:28 -0400380 value += Byte8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
381 equal = CmpGT(As<SByte8>(equal), As<SByte8>(value));
382 value = equal;
383 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400384 case STENCIL_GREATEREQUAL: // a >= b ~ !(a < b) ~ !(b > a)
John Bauman89401822014-05-06 15:04:28 -0400385 value += Byte8(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80);
Nicolas Capens4f172c72016-01-13 08:34:30 -0500386 value = CmpGT(As<SByte8>(value), *Pointer<SByte8>(data + OFFSET(DrawData,stencil[CCW].referenceMaskedSignedQ)));
John Bauman89401822014-05-06 15:04:28 -0400387 value ^= Byte8(0xFFFFFFFFFFFFFFFF);
388 break;
389 default:
390 ASSERT(false);
391 }
392 }
393
Nicolas Capens4f172c72016-01-13 08:34:30 -0500394 Bool PixelRoutine::depthTest(Pointer<Byte> &zBuffer, int q, Int &x, Float4 &z, Int &sMask, Int &zMask, Int &cMask)
John Bauman89401822014-05-06 15:04:28 -0400395 {
396 if(!state.depthTestActive)
397 {
398 return true;
399 }
400
401 Float4 Z = z;
402
John Bauman19bac1e2014-05-06 15:23:49 -0400403 if(shader && shader->depthOverride())
John Bauman89401822014-05-06 15:04:28 -0400404 {
405 if(complementaryDepthBuffer)
406 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500407 Z = Float4(1.0f) - oDepth;
John Bauman89401822014-05-06 15:04:28 -0400408 }
409 else
410 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500411 Z = oDepth;
John Bauman89401822014-05-06 15:04:28 -0400412 }
413 }
414
415 Pointer<Byte> buffer;
416 Int pitch;
417
418 if(!state.quadLayoutDepthBuffer)
419 {
420 buffer = zBuffer + 4 * x;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500421 pitch = *Pointer<Int>(data + OFFSET(DrawData,depthPitchB));
John Bauman89401822014-05-06 15:04:28 -0400422 }
423 else
424 {
425 buffer = zBuffer + 8 * x;
426 }
427
428 if(q > 0)
429 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500430 buffer += q * *Pointer<Int>(data + OFFSET(DrawData,depthSliceB));
John Bauman89401822014-05-06 15:04:28 -0400431 }
432
433 Float4 zValue;
434
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400435 if(state.depthCompareMode != DEPTH_NEVER || (state.depthCompareMode != DEPTH_ALWAYS && !state.depthWriteEnable))
John Bauman89401822014-05-06 15:04:28 -0400436 {
437 if(!state.quadLayoutDepthBuffer)
438 {
439 // FIXME: Properly optimizes?
440 zValue.xy = *Pointer<Float4>(buffer);
441 zValue.zw = *Pointer<Float4>(buffer + pitch - 8);
442 }
443 else
444 {
445 zValue = *Pointer<Float4>(buffer, 16);
446 }
447 }
448
449 Int4 zTest;
450
451 switch(state.depthCompareMode)
452 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400453 case DEPTH_ALWAYS:
John Bauman89401822014-05-06 15:04:28 -0400454 // Optimized
455 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400456 case DEPTH_NEVER:
John Bauman89401822014-05-06 15:04:28 -0400457 // Optimized
458 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400459 case DEPTH_EQUAL:
John Bauman89401822014-05-06 15:04:28 -0400460 zTest = CmpEQ(zValue, Z);
461 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400462 case DEPTH_NOTEQUAL:
John Bauman89401822014-05-06 15:04:28 -0400463 zTest = CmpNEQ(zValue, Z);
464 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400465 case DEPTH_LESS:
John Bauman89401822014-05-06 15:04:28 -0400466 if(complementaryDepthBuffer)
467 {
468 zTest = CmpLT(zValue, Z);
469 }
470 else
471 {
472 zTest = CmpNLE(zValue, Z);
473 }
474 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400475 case DEPTH_GREATEREQUAL:
John Bauman89401822014-05-06 15:04:28 -0400476 if(complementaryDepthBuffer)
477 {
478 zTest = CmpNLT(zValue, Z);
479 }
480 else
481 {
482 zTest = CmpLE(zValue, Z);
483 }
484 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400485 case DEPTH_LESSEQUAL:
John Bauman89401822014-05-06 15:04:28 -0400486 if(complementaryDepthBuffer)
487 {
488 zTest = CmpLE(zValue, Z);
489 }
490 else
491 {
492 zTest = CmpNLT(zValue, Z);
493 }
494 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400495 case DEPTH_GREATER:
John Bauman89401822014-05-06 15:04:28 -0400496 if(complementaryDepthBuffer)
497 {
498 zTest = CmpNLE(zValue, Z);
499 }
500 else
501 {
502 zTest = CmpLT(zValue, Z);
503 }
504 break;
505 default:
506 ASSERT(false);
507 }
508
509 switch(state.depthCompareMode)
510 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400511 case DEPTH_ALWAYS:
John Bauman89401822014-05-06 15:04:28 -0400512 zMask = cMask;
513 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400514 case DEPTH_NEVER:
John Bauman89401822014-05-06 15:04:28 -0400515 zMask = 0x0;
516 break;
517 default:
518 zMask = SignMask(zTest) & cMask;
519 break;
520 }
Nicolas Capens05b3d662016-02-25 23:58:33 -0500521
John Bauman89401822014-05-06 15:04:28 -0400522 if(state.stencilActive)
523 {
524 zMask &= sMask;
525 }
526
527 return zMask != 0;
528 }
529
Nicolas Capens4f172c72016-01-13 08:34:30 -0500530 void PixelRoutine::alphaTest(Int &aMask, Short4 &alpha)
John Bauman89401822014-05-06 15:04:28 -0400531 {
532 Short4 cmp;
533 Short4 equal;
534
535 switch(state.alphaCompareMode)
536 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400537 case ALPHA_ALWAYS:
John Bauman89401822014-05-06 15:04:28 -0400538 aMask = 0xF;
539 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400540 case ALPHA_NEVER:
John Bauman89401822014-05-06 15:04:28 -0400541 aMask = 0x0;
542 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400543 case ALPHA_EQUAL:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500544 cmp = CmpEQ(alpha, *Pointer<Short4>(data + OFFSET(DrawData,factor.alphaReference4)));
John Bauman89401822014-05-06 15:04:28 -0400545 aMask = SignMask(Pack(cmp, Short4(0x0000, 0x0000, 0x0000, 0x0000)));
546 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400547 case ALPHA_NOTEQUAL: // a != b ~ !(a == b)
Nicolas Capens4f172c72016-01-13 08:34:30 -0500548 cmp = CmpEQ(alpha, *Pointer<Short4>(data + OFFSET(DrawData,factor.alphaReference4))) ^ Short4((short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF); // FIXME
John Bauman89401822014-05-06 15:04:28 -0400549 aMask = SignMask(Pack(cmp, Short4(0x0000, 0x0000, 0x0000, 0x0000)));
550 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400551 case ALPHA_LESS: // a < b ~ b > a
Nicolas Capens4f172c72016-01-13 08:34:30 -0500552 cmp = CmpGT(*Pointer<Short4>(data + OFFSET(DrawData,factor.alphaReference4)), alpha);
John Bauman89401822014-05-06 15:04:28 -0400553 aMask = SignMask(Pack(cmp, Short4(0x0000, 0x0000, 0x0000, 0x0000)));
554 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400555 case ALPHA_GREATEREQUAL: // a >= b ~ (a > b) || (a == b) ~ !(b > a) // TODO: Approximate
Nicolas Capens4f172c72016-01-13 08:34:30 -0500556 equal = CmpEQ(alpha, *Pointer<Short4>(data + OFFSET(DrawData,factor.alphaReference4)));
557 cmp = CmpGT(alpha, *Pointer<Short4>(data + OFFSET(DrawData,factor.alphaReference4)));
John Bauman89401822014-05-06 15:04:28 -0400558 cmp |= equal;
559 aMask = SignMask(Pack(cmp, Short4(0x0000, 0x0000, 0x0000, 0x0000)));
560 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400561 case ALPHA_LESSEQUAL: // a <= b ~ !(a > b)
Nicolas Capens4f172c72016-01-13 08:34:30 -0500562 cmp = CmpGT(alpha, *Pointer<Short4>(data + OFFSET(DrawData,factor.alphaReference4))) ^ Short4((short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF); // FIXME
John Bauman89401822014-05-06 15:04:28 -0400563 aMask = SignMask(Pack(cmp, Short4(0x0000, 0x0000, 0x0000, 0x0000)));
564 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400565 case ALPHA_GREATER: // a > b
Nicolas Capens4f172c72016-01-13 08:34:30 -0500566 cmp = CmpGT(alpha, *Pointer<Short4>(data + OFFSET(DrawData,factor.alphaReference4)));
John Bauman89401822014-05-06 15:04:28 -0400567 aMask = SignMask(Pack(cmp, Short4(0x0000, 0x0000, 0x0000, 0x0000)));
568 break;
569 default:
570 ASSERT(false);
571 }
572 }
573
Nicolas Capens4f172c72016-01-13 08:34:30 -0500574 void PixelRoutine::alphaToCoverage(Int cMask[4], Float4 &alpha)
John Bauman89401822014-05-06 15:04:28 -0400575 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500576 Int4 coverage0 = CmpNLT(alpha, *Pointer<Float4>(data + OFFSET(DrawData,a2c0)));
577 Int4 coverage1 = CmpNLT(alpha, *Pointer<Float4>(data + OFFSET(DrawData,a2c1)));
578 Int4 coverage2 = CmpNLT(alpha, *Pointer<Float4>(data + OFFSET(DrawData,a2c2)));
579 Int4 coverage3 = CmpNLT(alpha, *Pointer<Float4>(data + OFFSET(DrawData,a2c3)));
John Bauman89401822014-05-06 15:04:28 -0400580
581 Int aMask0 = SignMask(coverage0);
582 Int aMask1 = SignMask(coverage1);
583 Int aMask2 = SignMask(coverage2);
584 Int aMask3 = SignMask(coverage3);
585
586 cMask[0] &= aMask0;
587 cMask[1] &= aMask1;
588 cMask[2] &= aMask2;
589 cMask[3] &= aMask3;
590 }
591
Nicolas Capens4f172c72016-01-13 08:34:30 -0500592 void PixelRoutine::fogBlend(Vector4f &c0, Float4 &fog)
John Bauman89401822014-05-06 15:04:28 -0400593 {
594 if(!state.fogActive)
595 {
596 return;
597 }
598
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400599 if(state.pixelFogMode != FOG_NONE)
John Bauman89401822014-05-06 15:04:28 -0400600 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500601 pixelFog(fog);
John Bauman89401822014-05-06 15:04:28 -0400602
John Bauman19bac1e2014-05-06 15:23:49 -0400603 fog = Min(fog, Float4(1.0f));
604 fog = Max(fog, Float4(0.0f));
John Bauman89401822014-05-06 15:04:28 -0400605 }
606
Nicolas Capens4f172c72016-01-13 08:34:30 -0500607 c0.x -= *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[0]));
608 c0.y -= *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[1]));
609 c0.z -= *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[2]));
John Bauman89401822014-05-06 15:04:28 -0400610
John Bauman19bac1e2014-05-06 15:23:49 -0400611 c0.x *= fog;
612 c0.y *= fog;
613 c0.z *= fog;
John Bauman89401822014-05-06 15:04:28 -0400614
Nicolas Capens4f172c72016-01-13 08:34:30 -0500615 c0.x += *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[0]));
616 c0.y += *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[1]));
617 c0.z += *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[2]));
John Bauman89401822014-05-06 15:04:28 -0400618 }
619
Nicolas Capens4f172c72016-01-13 08:34:30 -0500620 void PixelRoutine::pixelFog(Float4 &visibility)
John Bauman89401822014-05-06 15:04:28 -0400621 {
622 Float4 &zw = visibility;
623
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400624 if(state.pixelFogMode != FOG_NONE)
John Bauman89401822014-05-06 15:04:28 -0400625 {
626 if(state.wBasedFog)
627 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500628 zw = rhw;
John Bauman89401822014-05-06 15:04:28 -0400629 }
630 else
631 {
632 if(complementaryDepthBuffer)
633 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500634 zw = Float4(1.0f) - z[0];
John Bauman89401822014-05-06 15:04:28 -0400635 }
636 else
637 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500638 zw = z[0];
John Bauman89401822014-05-06 15:04:28 -0400639 }
640 }
641 }
642
643 switch(state.pixelFogMode)
644 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400645 case FOG_NONE:
John Bauman89401822014-05-06 15:04:28 -0400646 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400647 case FOG_LINEAR:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500648 zw *= *Pointer<Float4>(data + OFFSET(DrawData,fog.scale));
649 zw += *Pointer<Float4>(data + OFFSET(DrawData,fog.offset));
John Bauman89401822014-05-06 15:04:28 -0400650 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400651 case FOG_EXP:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500652 zw *= *Pointer<Float4>(data + OFFSET(DrawData,fog.densityE));
John Bauman19bac1e2014-05-06 15:23:49 -0400653 zw = exponential2(zw, true);
John Bauman89401822014-05-06 15:04:28 -0400654 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400655 case FOG_EXP2:
John Bauman89401822014-05-06 15:04:28 -0400656 zw *= zw;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500657 zw *= *Pointer<Float4>(data + OFFSET(DrawData,fog.density2E));
John Bauman19bac1e2014-05-06 15:23:49 -0400658 zw = exponential2(zw, true);
John Bauman89401822014-05-06 15:04:28 -0400659 break;
660 default:
661 ASSERT(false);
662 }
663 }
664
Nicolas Capens4f172c72016-01-13 08:34:30 -0500665 void PixelRoutine::writeDepth(Pointer<Byte> &zBuffer, int q, Int &x, Float4 &z, Int &zMask)
John Bauman89401822014-05-06 15:04:28 -0400666 {
667 if(!state.depthWriteEnable)
668 {
669 return;
670 }
671
672 Float4 Z = z;
673
John Bauman19bac1e2014-05-06 15:23:49 -0400674 if(shader && shader->depthOverride())
John Bauman89401822014-05-06 15:04:28 -0400675 {
676 if(complementaryDepthBuffer)
677 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500678 Z = Float4(1.0f) - oDepth;
John Bauman89401822014-05-06 15:04:28 -0400679 }
680 else
681 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500682 Z = oDepth;
John Bauman89401822014-05-06 15:04:28 -0400683 }
684 }
685
686 Pointer<Byte> buffer;
687 Int pitch;
688
689 if(!state.quadLayoutDepthBuffer)
Nicolas Capens05b3d662016-02-25 23:58:33 -0500690 {
John Bauman89401822014-05-06 15:04:28 -0400691 buffer = zBuffer + 4 * x;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500692 pitch = *Pointer<Int>(data + OFFSET(DrawData,depthPitchB));
John Bauman89401822014-05-06 15:04:28 -0400693 }
694 else
Nicolas Capens05b3d662016-02-25 23:58:33 -0500695 {
John Bauman89401822014-05-06 15:04:28 -0400696 buffer = zBuffer + 8 * x;
697 }
698
699 if(q > 0)
700 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500701 buffer += q * *Pointer<Int>(data + OFFSET(DrawData,depthSliceB));
John Bauman89401822014-05-06 15:04:28 -0400702 }
703
704 Float4 zValue;
705
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400706 if(state.depthCompareMode != DEPTH_NEVER || (state.depthCompareMode != DEPTH_ALWAYS && !state.depthWriteEnable))
John Bauman89401822014-05-06 15:04:28 -0400707 {
708 if(!state.quadLayoutDepthBuffer)
709 {
710 // FIXME: Properly optimizes?
711 zValue.xy = *Pointer<Float4>(buffer);
712 zValue.zw = *Pointer<Float4>(buffer + pitch - 8);
713 }
714 else
715 {
716 zValue = *Pointer<Float4>(buffer, 16);
717 }
718 }
719
Nicolas Capens4f172c72016-01-13 08:34:30 -0500720 Z = As<Float4>(As<Int4>(Z) & *Pointer<Int4>(constants + OFFSET(Constants,maskD4X) + zMask * 16, 16));
721 zValue = As<Float4>(As<Int4>(zValue) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskD4X) + zMask * 16, 16));
John Bauman89401822014-05-06 15:04:28 -0400722 Z = As<Float4>(As<Int4>(Z) | As<Int4>(zValue));
723
724 if(!state.quadLayoutDepthBuffer)
725 {
726 // FIXME: Properly optimizes?
727 *Pointer<Float2>(buffer) = Float2(Z.xy);
728 *Pointer<Float2>(buffer + pitch) = Float2(Z.zw);
729 }
730 else
731 {
732 *Pointer<Float4>(buffer, 16) = Z;
733 }
734 }
735
Nicolas Capens4f172c72016-01-13 08:34:30 -0500736 void PixelRoutine::writeStencil(Pointer<Byte> &sBuffer, int q, Int &x, Int &sMask, Int &zMask, Int &cMask)
John Bauman89401822014-05-06 15:04:28 -0400737 {
738 if(!state.stencilActive)
739 {
740 return;
741 }
742
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400743 if(state.stencilPassOperation == OPERATION_KEEP && state.stencilZFailOperation == OPERATION_KEEP && state.stencilFailOperation == OPERATION_KEEP)
John Bauman89401822014-05-06 15:04:28 -0400744 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400745 if(!state.twoSidedStencil || (state.stencilPassOperationCCW == OPERATION_KEEP && state.stencilZFailOperationCCW == OPERATION_KEEP && state.stencilFailOperationCCW == OPERATION_KEEP))
John Bauman89401822014-05-06 15:04:28 -0400746 {
747 return;
748 }
749 }
750
751 if(state.stencilWriteMasked && (!state.twoSidedStencil || state.stencilWriteMaskedCCW))
752 {
753 return;
754 }
755
756 Pointer<Byte> buffer = sBuffer + 2 * x;
757
758 if(q > 0)
759 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500760 buffer += q * *Pointer<Int>(data + OFFSET(DrawData,stencilSliceB));
John Bauman89401822014-05-06 15:04:28 -0400761 }
762
763 Byte8 bufferValue = As<Byte8>(Long1(*Pointer<UInt>(buffer)));
Nicolas Capens05b3d662016-02-25 23:58:33 -0500764
John Bauman89401822014-05-06 15:04:28 -0400765 Byte8 newValue;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500766 stencilOperation(newValue, bufferValue, state.stencilPassOperation, state.stencilZFailOperation, state.stencilFailOperation, false, zMask, sMask);
John Bauman89401822014-05-06 15:04:28 -0400767
768 if(!state.noStencilWriteMask)
769 {
770 Byte8 maskedValue = bufferValue;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500771 newValue &= *Pointer<Byte8>(data + OFFSET(DrawData,stencil[0].writeMaskQ));
772 maskedValue &= *Pointer<Byte8>(data + OFFSET(DrawData,stencil[0].invWriteMaskQ));
John Bauman89401822014-05-06 15:04:28 -0400773 newValue |= maskedValue;
774 }
775
776 if(state.twoSidedStencil)
777 {
778 Byte8 newValueCCW;
779
Nicolas Capens4f172c72016-01-13 08:34:30 -0500780 stencilOperation(newValueCCW, bufferValue, state.stencilPassOperationCCW, state.stencilZFailOperationCCW, state.stencilFailOperationCCW, true, zMask, sMask);
John Bauman89401822014-05-06 15:04:28 -0400781
782 if(!state.noStencilWriteMaskCCW)
783 {
784 Byte8 maskedValue = bufferValue;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500785 newValueCCW &= *Pointer<Byte8>(data + OFFSET(DrawData,stencil[1].writeMaskQ));
786 maskedValue &= *Pointer<Byte8>(data + OFFSET(DrawData,stencil[1].invWriteMaskQ));
John Bauman89401822014-05-06 15:04:28 -0400787 newValueCCW |= maskedValue;
788 }
789
Nicolas Capens4f172c72016-01-13 08:34:30 -0500790 newValue &= *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask));
791 newValueCCW &= *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask));
John Bauman89401822014-05-06 15:04:28 -0400792 newValue |= newValueCCW;
793 }
794
Nicolas Capens4f172c72016-01-13 08:34:30 -0500795 newValue &= *Pointer<Byte8>(constants + OFFSET(Constants,maskB4Q) + 8 * cMask);
796 bufferValue &= *Pointer<Byte8>(constants + OFFSET(Constants,invMaskB4Q) + 8 * cMask);
John Bauman89401822014-05-06 15:04:28 -0400797 newValue |= bufferValue;
798
799 *Pointer<UInt>(buffer) = UInt(As<Long>(newValue));
800 }
801
Nicolas Capens4f172c72016-01-13 08:34:30 -0500802 void PixelRoutine::stencilOperation(Byte8 &newValue, Byte8 &bufferValue, StencilOperation stencilPassOperation, StencilOperation stencilZFailOperation, StencilOperation stencilFailOperation, bool CCW, Int &zMask, Int &sMask)
John Bauman89401822014-05-06 15:04:28 -0400803 {
804 Byte8 &pass = newValue;
805 Byte8 fail;
806 Byte8 zFail;
807
Nicolas Capens4f172c72016-01-13 08:34:30 -0500808 stencilOperation(pass, bufferValue, stencilPassOperation, CCW);
John Bauman89401822014-05-06 15:04:28 -0400809
810 if(stencilZFailOperation != stencilPassOperation)
811 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500812 stencilOperation(zFail, bufferValue, stencilZFailOperation, CCW);
John Bauman89401822014-05-06 15:04:28 -0400813 }
814
815 if(stencilFailOperation != stencilPassOperation || stencilFailOperation != stencilZFailOperation)
816 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500817 stencilOperation(fail, bufferValue, stencilFailOperation, CCW);
John Bauman89401822014-05-06 15:04:28 -0400818 }
819
820 if(stencilFailOperation != stencilPassOperation || stencilFailOperation != stencilZFailOperation)
821 {
822 if(state.depthTestActive && stencilZFailOperation != stencilPassOperation) // zMask valid and values not the same
823 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500824 pass &= *Pointer<Byte8>(constants + OFFSET(Constants,maskB4Q) + 8 * zMask);
825 zFail &= *Pointer<Byte8>(constants + OFFSET(Constants,invMaskB4Q) + 8 * zMask);
John Bauman89401822014-05-06 15:04:28 -0400826 pass |= zFail;
827 }
828
Nicolas Capens4f172c72016-01-13 08:34:30 -0500829 pass &= *Pointer<Byte8>(constants + OFFSET(Constants,maskB4Q) + 8 * sMask);
830 fail &= *Pointer<Byte8>(constants + OFFSET(Constants,invMaskB4Q) + 8 * sMask);
John Bauman89401822014-05-06 15:04:28 -0400831 pass |= fail;
832 }
833 }
834
Nicolas Capens4f172c72016-01-13 08:34:30 -0500835 void PixelRoutine::stencilOperation(Byte8 &output, Byte8 &bufferValue, StencilOperation operation, bool CCW)
John Bauman89401822014-05-06 15:04:28 -0400836 {
837 switch(operation)
838 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400839 case OPERATION_KEEP:
John Bauman89401822014-05-06 15:04:28 -0400840 output = bufferValue;
841 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400842 case OPERATION_ZERO:
John Bauman89401822014-05-06 15:04:28 -0400843 output = Byte8(0x0000000000000000);
844 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400845 case OPERATION_REPLACE:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500846 output = *Pointer<Byte8>(data + OFFSET(DrawData,stencil[CCW].referenceQ));
John Bauman89401822014-05-06 15:04:28 -0400847 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400848 case OPERATION_INCRSAT:
John Bauman89401822014-05-06 15:04:28 -0400849 output = AddSat(bufferValue, Byte8(1, 1, 1, 1, 1, 1, 1, 1));
850 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400851 case OPERATION_DECRSAT:
John Bauman89401822014-05-06 15:04:28 -0400852 output = SubSat(bufferValue, Byte8(1, 1, 1, 1, 1, 1, 1, 1));
853 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400854 case OPERATION_INVERT:
John Bauman89401822014-05-06 15:04:28 -0400855 output = bufferValue ^ Byte8(0xFFFFFFFFFFFFFFFF);
856 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400857 case OPERATION_INCR:
John Bauman89401822014-05-06 15:04:28 -0400858 output = bufferValue + Byte8(1, 1, 1, 1, 1, 1, 1, 1);
859 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400860 case OPERATION_DECR:
John Bauman89401822014-05-06 15:04:28 -0400861 output = bufferValue - Byte8(1, 1, 1, 1, 1, 1, 1, 1);
862 break;
863 default:
864 ASSERT(false);
865 }
866 }
867
Nicolas Capens4f172c72016-01-13 08:34:30 -0500868 void PixelRoutine::blendFactor(const Vector4s &blendFactor, const Vector4s &current, const Vector4s &pixel, BlendFactor blendFactorActive)
John Bauman89401822014-05-06 15:04:28 -0400869 {
870 switch(blendFactorActive)
871 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400872 case BLEND_ZERO:
John Bauman89401822014-05-06 15:04:28 -0400873 // Optimized
874 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400875 case BLEND_ONE:
John Bauman89401822014-05-06 15:04:28 -0400876 // Optimized
877 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400878 case BLEND_SOURCE:
John Bauman19bac1e2014-05-06 15:23:49 -0400879 blendFactor.x = current.x;
880 blendFactor.y = current.y;
881 blendFactor.z = current.z;
John Bauman89401822014-05-06 15:04:28 -0400882 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400883 case BLEND_INVSOURCE:
John Bauman19bac1e2014-05-06 15:23:49 -0400884 blendFactor.x = Short4(0xFFFFu) - current.x;
885 blendFactor.y = Short4(0xFFFFu) - current.y;
886 blendFactor.z = Short4(0xFFFFu) - current.z;
John Bauman89401822014-05-06 15:04:28 -0400887 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400888 case BLEND_DEST:
John Bauman19bac1e2014-05-06 15:23:49 -0400889 blendFactor.x = pixel.x;
890 blendFactor.y = pixel.y;
891 blendFactor.z = pixel.z;
John Bauman89401822014-05-06 15:04:28 -0400892 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400893 case BLEND_INVDEST:
John Bauman19bac1e2014-05-06 15:23:49 -0400894 blendFactor.x = Short4(0xFFFFu) - pixel.x;
895 blendFactor.y = Short4(0xFFFFu) - pixel.y;
896 blendFactor.z = Short4(0xFFFFu) - pixel.z;
John Bauman89401822014-05-06 15:04:28 -0400897 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400898 case BLEND_SOURCEALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -0400899 blendFactor.x = current.w;
900 blendFactor.y = current.w;
901 blendFactor.z = current.w;
John Bauman89401822014-05-06 15:04:28 -0400902 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400903 case BLEND_INVSOURCEALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -0400904 blendFactor.x = Short4(0xFFFFu) - current.w;
905 blendFactor.y = Short4(0xFFFFu) - current.w;
906 blendFactor.z = Short4(0xFFFFu) - current.w;
John Bauman89401822014-05-06 15:04:28 -0400907 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400908 case BLEND_DESTALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -0400909 blendFactor.x = pixel.w;
910 blendFactor.y = pixel.w;
911 blendFactor.z = pixel.w;
John Bauman89401822014-05-06 15:04:28 -0400912 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400913 case BLEND_INVDESTALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -0400914 blendFactor.x = Short4(0xFFFFu) - pixel.w;
915 blendFactor.y = Short4(0xFFFFu) - pixel.w;
916 blendFactor.z = Short4(0xFFFFu) - pixel.w;
John Bauman89401822014-05-06 15:04:28 -0400917 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400918 case BLEND_SRCALPHASAT:
John Bauman19bac1e2014-05-06 15:23:49 -0400919 blendFactor.x = Short4(0xFFFFu) - pixel.w;
920 blendFactor.x = Min(As<UShort4>(blendFactor.x), As<UShort4>(current.w));
921 blendFactor.y = blendFactor.x;
922 blendFactor.z = blendFactor.x;
John Bauman89401822014-05-06 15:04:28 -0400923 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400924 case BLEND_CONSTANT:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500925 blendFactor.x = *Pointer<Short4>(data + OFFSET(DrawData,factor.blendConstant4W[0]));
926 blendFactor.y = *Pointer<Short4>(data + OFFSET(DrawData,factor.blendConstant4W[1]));
927 blendFactor.z = *Pointer<Short4>(data + OFFSET(DrawData,factor.blendConstant4W[2]));
John Bauman89401822014-05-06 15:04:28 -0400928 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400929 case BLEND_INVCONSTANT:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500930 blendFactor.x = *Pointer<Short4>(data + OFFSET(DrawData,factor.invBlendConstant4W[0]));
931 blendFactor.y = *Pointer<Short4>(data + OFFSET(DrawData,factor.invBlendConstant4W[1]));
932 blendFactor.z = *Pointer<Short4>(data + OFFSET(DrawData,factor.invBlendConstant4W[2]));
John Bauman89401822014-05-06 15:04:28 -0400933 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400934 case BLEND_CONSTANTALPHA:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500935 blendFactor.x = *Pointer<Short4>(data + OFFSET(DrawData,factor.blendConstant4W[3]));
936 blendFactor.y = *Pointer<Short4>(data + OFFSET(DrawData,factor.blendConstant4W[3]));
937 blendFactor.z = *Pointer<Short4>(data + OFFSET(DrawData,factor.blendConstant4W[3]));
John Bauman89401822014-05-06 15:04:28 -0400938 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400939 case BLEND_INVCONSTANTALPHA:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500940 blendFactor.x = *Pointer<Short4>(data + OFFSET(DrawData,factor.invBlendConstant4W[3]));
941 blendFactor.y = *Pointer<Short4>(data + OFFSET(DrawData,factor.invBlendConstant4W[3]));
942 blendFactor.z = *Pointer<Short4>(data + OFFSET(DrawData,factor.invBlendConstant4W[3]));
John Bauman89401822014-05-06 15:04:28 -0400943 break;
944 default:
945 ASSERT(false);
946 }
947 }
Nicolas Capens05b3d662016-02-25 23:58:33 -0500948
Nicolas Capens4f172c72016-01-13 08:34:30 -0500949 void PixelRoutine::blendFactorAlpha(const Vector4s &blendFactor, const Vector4s &current, const Vector4s &pixel, BlendFactor blendFactorAlphaActive)
John Bauman89401822014-05-06 15:04:28 -0400950 {
951 switch(blendFactorAlphaActive)
952 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400953 case BLEND_ZERO:
John Bauman89401822014-05-06 15:04:28 -0400954 // Optimized
955 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400956 case BLEND_ONE:
John Bauman89401822014-05-06 15:04:28 -0400957 // Optimized
958 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400959 case BLEND_SOURCE:
John Bauman19bac1e2014-05-06 15:23:49 -0400960 blendFactor.w = current.w;
John Bauman89401822014-05-06 15:04:28 -0400961 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400962 case BLEND_INVSOURCE:
John Bauman19bac1e2014-05-06 15:23:49 -0400963 blendFactor.w = Short4(0xFFFFu) - current.w;
John Bauman89401822014-05-06 15:04:28 -0400964 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400965 case BLEND_DEST:
John Bauman19bac1e2014-05-06 15:23:49 -0400966 blendFactor.w = pixel.w;
John Bauman89401822014-05-06 15:04:28 -0400967 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400968 case BLEND_INVDEST:
John Bauman19bac1e2014-05-06 15:23:49 -0400969 blendFactor.w = Short4(0xFFFFu) - pixel.w;
John Bauman89401822014-05-06 15:04:28 -0400970 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400971 case BLEND_SOURCEALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -0400972 blendFactor.w = current.w;
John Bauman89401822014-05-06 15:04:28 -0400973 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400974 case BLEND_INVSOURCEALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -0400975 blendFactor.w = Short4(0xFFFFu) - current.w;
John Bauman89401822014-05-06 15:04:28 -0400976 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400977 case BLEND_DESTALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -0400978 blendFactor.w = pixel.w;
John Bauman89401822014-05-06 15:04:28 -0400979 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400980 case BLEND_INVDESTALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -0400981 blendFactor.w = Short4(0xFFFFu) - pixel.w;
John Bauman89401822014-05-06 15:04:28 -0400982 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400983 case BLEND_SRCALPHASAT:
John Bauman19bac1e2014-05-06 15:23:49 -0400984 blendFactor.w = Short4(0xFFFFu);
John Bauman89401822014-05-06 15:04:28 -0400985 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400986 case BLEND_CONSTANT:
987 case BLEND_CONSTANTALPHA:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500988 blendFactor.w = *Pointer<Short4>(data + OFFSET(DrawData,factor.blendConstant4W[3]));
John Bauman89401822014-05-06 15:04:28 -0400989 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400990 case BLEND_INVCONSTANT:
991 case BLEND_INVCONSTANTALPHA:
Nicolas Capens4f172c72016-01-13 08:34:30 -0500992 blendFactor.w = *Pointer<Short4>(data + OFFSET(DrawData,factor.invBlendConstant4W[3]));
John Bauman89401822014-05-06 15:04:28 -0400993 break;
994 default:
995 ASSERT(false);
996 }
997 }
998
Alexis Hetu049a1872016-04-25 16:59:58 -0400999 bool PixelRoutine::isSRGB(int index) const
1000 {
1001 return state.targetFormat[index] == FORMAT_SRGB8_A8 || state.targetFormat[index] == FORMAT_SRGB8_X8;
1002 }
1003
Nicolas Capens4f172c72016-01-13 08:34:30 -05001004 void PixelRoutine::readPixel(int index, Pointer<Byte> &cBuffer, Int &x, Vector4s &pixel)
John Bauman89401822014-05-06 15:04:28 -04001005 {
John Bauman89401822014-05-06 15:04:28 -04001006 Short4 c01;
1007 Short4 c23;
Maxime Grégoired9762742015-07-08 16:43:48 -04001008 Pointer<Byte> buffer;
Nicolas Capensb40a2562016-01-05 00:08:45 -05001009 Pointer<Byte> buffer2;
John Bauman89401822014-05-06 15:04:28 -04001010
John Bauman89401822014-05-06 15:04:28 -04001011 switch(state.targetFormat[index])
1012 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001013 case FORMAT_R5G6B5:
1014 buffer = cBuffer + 2 * x;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001015 buffer2 = buffer + *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
Nicolas Capensb40a2562016-01-05 00:08:45 -05001016 c01 = As<Short4>(Int2(*Pointer<Int>(buffer), *Pointer<Int>(buffer2)));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001017
1018 pixel.x = c01 & Short4(0xF800u);
1019 pixel.y = (c01 & Short4(0x07E0u)) << 5;
1020 pixel.z = (c01 & Short4(0x001Fu)) << 11;
1021 pixel.w = Short4(0xFFFFu);
1022 break;
John Bauman89401822014-05-06 15:04:28 -04001023 case FORMAT_A8R8G8B8:
1024 buffer = cBuffer + 4 * x;
1025 c01 = *Pointer<Short4>(buffer);
Nicolas Capens4f172c72016-01-13 08:34:30 -05001026 buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
John Bauman89401822014-05-06 15:04:28 -04001027 c23 = *Pointer<Short4>(buffer);
John Bauman19bac1e2014-05-06 15:23:49 -04001028 pixel.z = c01;
1029 pixel.y = c01;
1030 pixel.z = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(c23));
1031 pixel.y = UnpackHigh(As<Byte8>(pixel.y), As<Byte8>(c23));
1032 pixel.x = pixel.z;
1033 pixel.z = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(pixel.y));
1034 pixel.x = UnpackHigh(As<Byte8>(pixel.x), As<Byte8>(pixel.y));
1035 pixel.y = pixel.z;
1036 pixel.w = pixel.x;
1037 pixel.x = UnpackLow(As<Byte8>(pixel.x), As<Byte8>(pixel.x));
1038 pixel.y = UnpackHigh(As<Byte8>(pixel.y), As<Byte8>(pixel.y));
1039 pixel.z = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(pixel.z));
1040 pixel.w = UnpackHigh(As<Byte8>(pixel.w), As<Byte8>(pixel.w));
John Bauman89401822014-05-06 15:04:28 -04001041 break;
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001042 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04001043 case FORMAT_SRGB8_A8:
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001044 buffer = cBuffer + 4 * x;
1045 c01 = *Pointer<Short4>(buffer);
Nicolas Capens4f172c72016-01-13 08:34:30 -05001046 buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001047 c23 = *Pointer<Short4>(buffer);
1048 pixel.z = c01;
1049 pixel.y = c01;
1050 pixel.z = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(c23));
1051 pixel.y = UnpackHigh(As<Byte8>(pixel.y), As<Byte8>(c23));
1052 pixel.x = pixel.z;
1053 pixel.z = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(pixel.y));
1054 pixel.x = UnpackHigh(As<Byte8>(pixel.x), As<Byte8>(pixel.y));
1055 pixel.y = pixel.z;
1056 pixel.w = pixel.x;
1057 pixel.x = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(pixel.z));
1058 pixel.y = UnpackHigh(As<Byte8>(pixel.y), As<Byte8>(pixel.y));
1059 pixel.z = UnpackLow(As<Byte8>(pixel.w), As<Byte8>(pixel.w));
1060 pixel.w = UnpackHigh(As<Byte8>(pixel.w), As<Byte8>(pixel.w));
1061 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001062 case FORMAT_A8:
1063 buffer = cBuffer + 1 * x;
1064 pixel.w = Insert(pixel.w, *Pointer<Short>(buffer), 0);
Nicolas Capens4f172c72016-01-13 08:34:30 -05001065 buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
John Bauman66b8ab22014-05-06 15:57:45 -04001066 pixel.w = Insert(pixel.w, *Pointer<Short>(buffer), 1);
1067 pixel.w = UnpackLow(As<Byte8>(pixel.w), As<Byte8>(pixel.w));
1068 pixel.x = Short4(0x0000);
1069 pixel.y = Short4(0x0000);
1070 pixel.z = Short4(0x0000);
1071 break;
John Bauman89401822014-05-06 15:04:28 -04001072 case FORMAT_X8R8G8B8:
1073 buffer = cBuffer + 4 * x;
1074 c01 = *Pointer<Short4>(buffer);
Nicolas Capens4f172c72016-01-13 08:34:30 -05001075 buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
John Bauman89401822014-05-06 15:04:28 -04001076 c23 = *Pointer<Short4>(buffer);
John Bauman19bac1e2014-05-06 15:23:49 -04001077 pixel.z = c01;
1078 pixel.y = c01;
1079 pixel.z = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(c23));
1080 pixel.y = UnpackHigh(As<Byte8>(pixel.y), As<Byte8>(c23));
1081 pixel.x = pixel.z;
1082 pixel.z = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(pixel.y));
1083 pixel.x = UnpackHigh(As<Byte8>(pixel.x), As<Byte8>(pixel.y));
1084 pixel.y = pixel.z;
1085 pixel.x = UnpackLow(As<Byte8>(pixel.x), As<Byte8>(pixel.x));
1086 pixel.y = UnpackHigh(As<Byte8>(pixel.y), As<Byte8>(pixel.y));
1087 pixel.z = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(pixel.z));
1088 pixel.w = Short4(0xFFFFu);
John Bauman89401822014-05-06 15:04:28 -04001089 break;
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001090 case FORMAT_X8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04001091 case FORMAT_SRGB8_X8:
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001092 buffer = cBuffer + 4 * x;
1093 c01 = *Pointer<Short4>(buffer);
Nicolas Capens4f172c72016-01-13 08:34:30 -05001094 buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001095 c23 = *Pointer<Short4>(buffer);
1096 pixel.z = c01;
1097 pixel.y = c01;
1098 pixel.z = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(c23));
1099 pixel.y = UnpackHigh(As<Byte8>(pixel.y), As<Byte8>(c23));
1100 pixel.x = pixel.z;
1101 pixel.z = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(pixel.y));
1102 pixel.x = UnpackHigh(As<Byte8>(pixel.x), As<Byte8>(pixel.y));
1103 pixel.y = pixel.z;
1104 pixel.w = pixel.x;
1105 pixel.x = UnpackLow(As<Byte8>(pixel.z), As<Byte8>(pixel.z));
1106 pixel.y = UnpackHigh(As<Byte8>(pixel.y), As<Byte8>(pixel.y));
1107 pixel.z = UnpackLow(As<Byte8>(pixel.w), As<Byte8>(pixel.w));
1108 pixel.w = Short4(0xFFFFu);
1109 break;
John Bauman89401822014-05-06 15:04:28 -04001110 case FORMAT_A8G8R8B8Q:
1111 UNIMPLEMENTED();
Nicolas Capens64750b52015-09-22 10:11:00 -04001112 // pixel.z = UnpackLow(As<Byte8>(pixel.z), *Pointer<Byte8>(cBuffer + 8 * x + 0));
1113 // pixel.x = UnpackHigh(As<Byte8>(pixel.x), *Pointer<Byte8>(cBuffer + 8 * x + 0));
1114 // pixel.y = UnpackLow(As<Byte8>(pixel.y), *Pointer<Byte8>(cBuffer + 8 * x + 8));
1115 // pixel.w = UnpackHigh(As<Byte8>(pixel.w), *Pointer<Byte8>(cBuffer + 8 * x + 8));
John Bauman89401822014-05-06 15:04:28 -04001116 break;
1117 case FORMAT_X8G8R8B8Q:
1118 UNIMPLEMENTED();
Nicolas Capens64750b52015-09-22 10:11:00 -04001119 // pixel.z = UnpackLow(As<Byte8>(pixel.z), *Pointer<Byte8>(cBuffer + 8 * x + 0));
1120 // pixel.x = UnpackHigh(As<Byte8>(pixel.x), *Pointer<Byte8>(cBuffer + 8 * x + 0));
1121 // pixel.y = UnpackLow(As<Byte8>(pixel.y), *Pointer<Byte8>(cBuffer + 8 * x + 8));
1122 // pixel.w = Short4(0xFFFFu);
John Bauman89401822014-05-06 15:04:28 -04001123 break;
1124 case FORMAT_A16B16G16R16:
Maxime Grégoired9762742015-07-08 16:43:48 -04001125 buffer = cBuffer;
John Bauman19bac1e2014-05-06 15:23:49 -04001126 pixel.x = *Pointer<Short4>(buffer + 8 * x);
1127 pixel.y = *Pointer<Short4>(buffer + 8 * x + 8);
Nicolas Capens4f172c72016-01-13 08:34:30 -05001128 buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
John Bauman19bac1e2014-05-06 15:23:49 -04001129 pixel.z = *Pointer<Short4>(buffer + 8 * x);
1130 pixel.w = *Pointer<Short4>(buffer + 8 * x + 8);
1131 transpose4x4(pixel.x, pixel.y, pixel.z, pixel.w);
John Bauman89401822014-05-06 15:04:28 -04001132 break;
1133 case FORMAT_G16R16:
1134 buffer = cBuffer;
Maxime Grégoired9762742015-07-08 16:43:48 -04001135 pixel.x = *Pointer<Short4>(buffer + 4 * x);
Nicolas Capens4f172c72016-01-13 08:34:30 -05001136 buffer += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
Maxime Grégoired9762742015-07-08 16:43:48 -04001137 pixel.y = *Pointer<Short4>(buffer + 4 * x);
John Bauman19bac1e2014-05-06 15:23:49 -04001138 pixel.z = pixel.x;
1139 pixel.x = As<Short4>(UnpackLow(pixel.x, pixel.y));
1140 pixel.z = As<Short4>(UnpackHigh(pixel.z, pixel.y));
1141 pixel.y = pixel.z;
1142 pixel.x = As<Short4>(UnpackLow(pixel.x, pixel.z));
1143 pixel.y = As<Short4>(UnpackHigh(pixel.y, pixel.z));
1144 pixel.z = Short4(0xFFFFu);
1145 pixel.w = Short4(0xFFFFu);
John Bauman89401822014-05-06 15:04:28 -04001146 break;
1147 default:
1148 ASSERT(false);
1149 }
1150
Alexis Hetu049a1872016-04-25 16:59:58 -04001151 if((postBlendSRGB && state.writeSRGB) || isSRGB(index))
John Bauman89401822014-05-06 15:04:28 -04001152 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001153 sRGBtoLinear16_12_16(pixel);
John Bauman89401822014-05-06 15:04:28 -04001154 }
Maxime Grégoired9762742015-07-08 16:43:48 -04001155 }
1156
Nicolas Capens4f172c72016-01-13 08:34:30 -05001157 void PixelRoutine::alphaBlend(int index, Pointer<Byte> &cBuffer, Vector4s &current, Int &x)
Maxime Grégoired9762742015-07-08 16:43:48 -04001158 {
1159 if(!state.alphaBlendActive)
1160 {
1161 return;
1162 }
1163
1164 Vector4s pixel;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001165 readPixel(index, cBuffer, x, pixel);
John Bauman89401822014-05-06 15:04:28 -04001166
1167 // Final Color = ObjectColor * SourceBlendFactor + PixelColor * DestinationBlendFactor
Alexis Hetu96517182015-04-15 10:30:23 -04001168 Vector4s sourceFactor;
1169 Vector4s destFactor;
John Bauman89401822014-05-06 15:04:28 -04001170
Nicolas Capens4f172c72016-01-13 08:34:30 -05001171 blendFactor(sourceFactor, current, pixel, state.sourceBlendFactor);
1172 blendFactor(destFactor, current, pixel, state.destBlendFactor);
John Bauman89401822014-05-06 15:04:28 -04001173
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001174 if(state.sourceBlendFactor != BLEND_ONE && state.sourceBlendFactor != BLEND_ZERO)
John Bauman89401822014-05-06 15:04:28 -04001175 {
John Bauman19bac1e2014-05-06 15:23:49 -04001176 current.x = MulHigh(As<UShort4>(current.x), As<UShort4>(sourceFactor.x));
1177 current.y = MulHigh(As<UShort4>(current.y), As<UShort4>(sourceFactor.y));
1178 current.z = MulHigh(As<UShort4>(current.z), As<UShort4>(sourceFactor.z));
John Bauman89401822014-05-06 15:04:28 -04001179 }
Nicolas Capens05b3d662016-02-25 23:58:33 -05001180
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001181 if(state.destBlendFactor != BLEND_ONE && state.destBlendFactor != BLEND_ZERO)
John Bauman89401822014-05-06 15:04:28 -04001182 {
John Bauman19bac1e2014-05-06 15:23:49 -04001183 pixel.x = MulHigh(As<UShort4>(pixel.x), As<UShort4>(destFactor.x));
1184 pixel.y = MulHigh(As<UShort4>(pixel.y), As<UShort4>(destFactor.y));
1185 pixel.z = MulHigh(As<UShort4>(pixel.z), As<UShort4>(destFactor.z));
John Bauman89401822014-05-06 15:04:28 -04001186 }
1187
1188 switch(state.blendOperation)
1189 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001190 case BLENDOP_ADD:
John Bauman19bac1e2014-05-06 15:23:49 -04001191 current.x = AddSat(As<UShort4>(current.x), As<UShort4>(pixel.x));
1192 current.y = AddSat(As<UShort4>(current.y), As<UShort4>(pixel.y));
1193 current.z = AddSat(As<UShort4>(current.z), As<UShort4>(pixel.z));
John Bauman89401822014-05-06 15:04:28 -04001194 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001195 case BLENDOP_SUB:
John Bauman19bac1e2014-05-06 15:23:49 -04001196 current.x = SubSat(As<UShort4>(current.x), As<UShort4>(pixel.x));
1197 current.y = SubSat(As<UShort4>(current.y), As<UShort4>(pixel.y));
1198 current.z = SubSat(As<UShort4>(current.z), As<UShort4>(pixel.z));
John Bauman89401822014-05-06 15:04:28 -04001199 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001200 case BLENDOP_INVSUB:
John Bauman19bac1e2014-05-06 15:23:49 -04001201 current.x = SubSat(As<UShort4>(pixel.x), As<UShort4>(current.x));
1202 current.y = SubSat(As<UShort4>(pixel.y), As<UShort4>(current.y));
1203 current.z = SubSat(As<UShort4>(pixel.z), As<UShort4>(current.z));
John Bauman89401822014-05-06 15:04:28 -04001204 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001205 case BLENDOP_MIN:
John Bauman19bac1e2014-05-06 15:23:49 -04001206 current.x = Min(As<UShort4>(current.x), As<UShort4>(pixel.x));
1207 current.y = Min(As<UShort4>(current.y), As<UShort4>(pixel.y));
1208 current.z = Min(As<UShort4>(current.z), As<UShort4>(pixel.z));
John Bauman89401822014-05-06 15:04:28 -04001209 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001210 case BLENDOP_MAX:
John Bauman19bac1e2014-05-06 15:23:49 -04001211 current.x = Max(As<UShort4>(current.x), As<UShort4>(pixel.x));
1212 current.y = Max(As<UShort4>(current.y), As<UShort4>(pixel.y));
1213 current.z = Max(As<UShort4>(current.z), As<UShort4>(pixel.z));
John Bauman89401822014-05-06 15:04:28 -04001214 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001215 case BLENDOP_SOURCE:
John Bauman89401822014-05-06 15:04:28 -04001216 // No operation
1217 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001218 case BLENDOP_DEST:
John Bauman19bac1e2014-05-06 15:23:49 -04001219 current.x = pixel.x;
1220 current.y = pixel.y;
1221 current.z = pixel.z;
John Bauman89401822014-05-06 15:04:28 -04001222 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001223 case BLENDOP_NULL:
John Bauman19bac1e2014-05-06 15:23:49 -04001224 current.x = Short4(0x0000, 0x0000, 0x0000, 0x0000);
1225 current.y = Short4(0x0000, 0x0000, 0x0000, 0x0000);
1226 current.z = Short4(0x0000, 0x0000, 0x0000, 0x0000);
John Bauman89401822014-05-06 15:04:28 -04001227 break;
1228 default:
1229 ASSERT(false);
1230 }
1231
Nicolas Capens4f172c72016-01-13 08:34:30 -05001232 blendFactorAlpha(sourceFactor, current, pixel, state.sourceBlendFactorAlpha);
1233 blendFactorAlpha(destFactor, current, pixel, state.destBlendFactorAlpha);
John Bauman89401822014-05-06 15:04:28 -04001234
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001235 if(state.sourceBlendFactorAlpha != BLEND_ONE && state.sourceBlendFactorAlpha != BLEND_ZERO)
John Bauman89401822014-05-06 15:04:28 -04001236 {
John Bauman19bac1e2014-05-06 15:23:49 -04001237 current.w = MulHigh(As<UShort4>(current.w), As<UShort4>(sourceFactor.w));
John Bauman89401822014-05-06 15:04:28 -04001238 }
Nicolas Capens05b3d662016-02-25 23:58:33 -05001239
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001240 if(state.destBlendFactorAlpha != BLEND_ONE && state.destBlendFactorAlpha != BLEND_ZERO)
John Bauman89401822014-05-06 15:04:28 -04001241 {
John Bauman19bac1e2014-05-06 15:23:49 -04001242 pixel.w = MulHigh(As<UShort4>(pixel.w), As<UShort4>(destFactor.w));
John Bauman89401822014-05-06 15:04:28 -04001243 }
1244
1245 switch(state.blendOperationAlpha)
1246 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001247 case BLENDOP_ADD:
John Bauman19bac1e2014-05-06 15:23:49 -04001248 current.w = AddSat(As<UShort4>(current.w), As<UShort4>(pixel.w));
John Bauman89401822014-05-06 15:04:28 -04001249 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001250 case BLENDOP_SUB:
John Bauman19bac1e2014-05-06 15:23:49 -04001251 current.w = SubSat(As<UShort4>(current.w), As<UShort4>(pixel.w));
John Bauman89401822014-05-06 15:04:28 -04001252 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001253 case BLENDOP_INVSUB:
John Bauman19bac1e2014-05-06 15:23:49 -04001254 current.w = SubSat(As<UShort4>(pixel.w), As<UShort4>(current.w));
John Bauman89401822014-05-06 15:04:28 -04001255 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001256 case BLENDOP_MIN:
John Bauman19bac1e2014-05-06 15:23:49 -04001257 current.w = Min(As<UShort4>(current.w), As<UShort4>(pixel.w));
John Bauman89401822014-05-06 15:04:28 -04001258 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001259 case BLENDOP_MAX:
John Bauman19bac1e2014-05-06 15:23:49 -04001260 current.w = Max(As<UShort4>(current.w), As<UShort4>(pixel.w));
John Bauman89401822014-05-06 15:04:28 -04001261 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001262 case BLENDOP_SOURCE:
John Bauman89401822014-05-06 15:04:28 -04001263 // No operation
1264 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001265 case BLENDOP_DEST:
John Bauman19bac1e2014-05-06 15:23:49 -04001266 current.w = pixel.w;
John Bauman89401822014-05-06 15:04:28 -04001267 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001268 case BLENDOP_NULL:
John Bauman19bac1e2014-05-06 15:23:49 -04001269 current.w = Short4(0x0000, 0x0000, 0x0000, 0x0000);
John Bauman89401822014-05-06 15:04:28 -04001270 break;
1271 default:
1272 ASSERT(false);
1273 }
1274 }
1275
Nicolas Capens4f172c72016-01-13 08:34:30 -05001276 void PixelRoutine::logicOperation(int index, Pointer<Byte> &cBuffer, Vector4s &current, Int &x)
Maxime Grégoired9762742015-07-08 16:43:48 -04001277 {
Nicolas Capens2afcc802015-08-04 10:34:43 -04001278 if(state.logicalOperation == LOGICALOP_COPY)
Maxime Grégoired9762742015-07-08 16:43:48 -04001279 {
1280 return;
1281 }
1282
1283 Vector4s pixel;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001284 readPixel(index, cBuffer, x, pixel);
Maxime Grégoired9762742015-07-08 16:43:48 -04001285
1286 switch(state.logicalOperation)
1287 {
1288 case LOGICALOP_CLEAR:
1289 current.x = 0;
1290 current.y = 0;
1291 current.z = 0;
1292 break;
1293 case LOGICALOP_SET:
Nicolas Capens2afcc802015-08-04 10:34:43 -04001294 current.x = 0xFFFFu;
1295 current.y = 0xFFFFu;
1296 current.z = 0xFFFFu;
Maxime Grégoired9762742015-07-08 16:43:48 -04001297 break;
1298 case LOGICALOP_COPY:
1299 ASSERT(false); // Optimized out
1300 break;
1301 case LOGICALOP_COPY_INVERTED:
1302 current.x = ~current.x;
1303 current.y = ~current.y;
1304 current.z = ~current.z;
1305 break;
1306 case LOGICALOP_NOOP:
1307 current.x = pixel.x;
1308 current.y = pixel.y;
1309 current.z = pixel.z;
1310 break;
1311 case LOGICALOP_INVERT:
1312 current.x = ~pixel.x;
1313 current.y = ~pixel.y;
1314 current.z = ~pixel.z;
1315 break;
1316 case LOGICALOP_AND:
1317 current.x = pixel.x & current.x;
1318 current.y = pixel.y & current.y;
1319 current.z = pixel.z & current.z;
1320 break;
1321 case LOGICALOP_NAND:
1322 current.x = ~(pixel.x & current.x);
1323 current.y = ~(pixel.y & current.y);
1324 current.z = ~(pixel.z & current.z);
1325 break;
1326 case LOGICALOP_OR:
1327 current.x = pixel.x | current.x;
1328 current.y = pixel.y | current.y;
1329 current.z = pixel.z | current.z;
1330 break;
1331 case LOGICALOP_NOR:
1332 current.x = ~(pixel.x | current.x);
1333 current.y = ~(pixel.y | current.y);
1334 current.z = ~(pixel.z | current.z);
1335 break;
1336 case LOGICALOP_XOR:
1337 current.x = pixel.x ^ current.x;
1338 current.y = pixel.y ^ current.y;
1339 current.z = pixel.z ^ current.z;
1340 break;
1341 case LOGICALOP_EQUIV:
1342 current.x = ~(pixel.x ^ current.x);
1343 current.y = ~(pixel.y ^ current.y);
1344 current.z = ~(pixel.z ^ current.z);
1345 break;
1346 case LOGICALOP_AND_REVERSE:
1347 current.x = ~pixel.x & current.x;
1348 current.y = ~pixel.y & current.y;
1349 current.z = ~pixel.z & current.z;
1350 break;
1351 case LOGICALOP_AND_INVERTED:
1352 current.x = pixel.x & ~current.x;
1353 current.y = pixel.y & ~current.y;
1354 current.z = pixel.z & ~current.z;
1355 break;
1356 case LOGICALOP_OR_REVERSE:
1357 current.x = ~pixel.x | current.x;
1358 current.y = ~pixel.y | current.y;
1359 current.z = ~pixel.z | current.z;
1360 break;
1361 case LOGICALOP_OR_INVERTED:
1362 current.x = pixel.x | ~current.x;
1363 current.y = pixel.y | ~current.y;
1364 current.z = pixel.z | ~current.z;
1365 break;
1366 default:
1367 ASSERT(false);
1368 }
1369 }
1370
Nicolas Capens4f172c72016-01-13 08:34:30 -05001371 void PixelRoutine::writeColor(int index, Pointer<Byte> &cBuffer, Int &x, Vector4s &current, Int &sMask, Int &zMask, Int &cMask)
John Bauman89401822014-05-06 15:04:28 -04001372 {
Alexis Hetu049a1872016-04-25 16:59:58 -04001373 if((postBlendSRGB && state.writeSRGB) || isSRGB(index))
John Bauman89401822014-05-06 15:04:28 -04001374 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05001375 linearToSRGB16_12_16(current);
John Bauman89401822014-05-06 15:04:28 -04001376 }
1377
1378 if(exactColorRounding)
1379 {
1380 switch(state.targetFormat[index])
1381 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001382 case FORMAT_R5G6B5:
Nicolas Capens26f37222015-09-22 09:53:45 -04001383 current.x = AddSat(As<UShort4>(current.x), UShort4(0x0400));
1384 current.y = AddSat(As<UShort4>(current.y), UShort4(0x0200));
1385 current.z = AddSat(As<UShort4>(current.z), UShort4(0x0400));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001386 break;
John Bauman89401822014-05-06 15:04:28 -04001387 case FORMAT_X8G8R8B8Q:
1388 case FORMAT_A8G8R8B8Q:
1389 case FORMAT_X8R8G8B8:
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001390 case FORMAT_X8B8G8R8:
John Bauman89401822014-05-06 15:04:28 -04001391 case FORMAT_A8R8G8B8:
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001392 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04001393 case FORMAT_SRGB8_X8:
1394 case FORMAT_SRGB8_A8:
Nicolas Capens26f37222015-09-22 09:53:45 -04001395 current.x = current.x - As<Short4>(As<UShort4>(current.x) >> 8) + Short4(0x0080, 0x0080, 0x0080, 0x0080);
1396 current.y = current.y - As<Short4>(As<UShort4>(current.y) >> 8) + Short4(0x0080, 0x0080, 0x0080, 0x0080);
1397 current.z = current.z - As<Short4>(As<UShort4>(current.z) >> 8) + Short4(0x0080, 0x0080, 0x0080, 0x0080);
1398 current.w = current.w - As<Short4>(As<UShort4>(current.w) >> 8) + Short4(0x0080, 0x0080, 0x0080, 0x0080);
John Bauman89401822014-05-06 15:04:28 -04001399 break;
Nicolas Capensb69aa272016-01-02 00:06:41 -05001400 default:
1401 break;
John Bauman89401822014-05-06 15:04:28 -04001402 }
1403 }
1404
1405 int rgbaWriteMask = state.colorWriteActive(index);
Nicolas Capens3b396462016-01-02 00:23:53 -05001406 int bgraWriteMask = (rgbaWriteMask & 0x0000000A) | (rgbaWriteMask & 0x00000001) << 2 | (rgbaWriteMask & 0x00000004) >> 2;
1407 int brgaWriteMask = (rgbaWriteMask & 0x00000008) | (rgbaWriteMask & 0x00000001) << 1 | (rgbaWriteMask & 0x00000002) << 1 | (rgbaWriteMask & 0x00000004) >> 2;
John Bauman89401822014-05-06 15:04:28 -04001408
1409 switch(state.targetFormat[index])
1410 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001411 case FORMAT_R5G6B5:
1412 {
1413 current.x = current.x & Short4(0xF800u);
1414 current.y = As<UShort4>(current.y & Short4(0xFC00u)) >> 5;
1415 current.z = As<UShort4>(current.z) >> 11;
1416
1417 current.x = current.x | current.y | current.z;
1418 }
1419 break;
John Bauman89401822014-05-06 15:04:28 -04001420 case FORMAT_X8G8R8B8Q:
1421 UNIMPLEMENTED();
John Bauman19bac1e2014-05-06 15:23:49 -04001422 // current.x = As<Short4>(As<UShort4>(current.x) >> 8);
1423 // current.y = As<Short4>(As<UShort4>(current.y) >> 8);
1424 // current.z = As<Short4>(As<UShort4>(current.z) >> 8);
John Bauman89401822014-05-06 15:04:28 -04001425
John Bauman19bac1e2014-05-06 15:23:49 -04001426 // current.z = As<Short4>(Pack(As<UShort4>(current.z), As<UShort4>(current.x)));
1427 // current.y = As<Short4>(Pack(As<UShort4>(current.y), As<UShort4>(current.y)));
John Bauman89401822014-05-06 15:04:28 -04001428 break;
1429 case FORMAT_A8G8R8B8Q:
1430 UNIMPLEMENTED();
John Bauman19bac1e2014-05-06 15:23:49 -04001431 // current.x = As<Short4>(As<UShort4>(current.x) >> 8);
1432 // current.y = As<Short4>(As<UShort4>(current.y) >> 8);
1433 // current.z = As<Short4>(As<UShort4>(current.z) >> 8);
1434 // current.w = As<Short4>(As<UShort4>(current.w) >> 8);
John Bauman89401822014-05-06 15:04:28 -04001435
John Bauman19bac1e2014-05-06 15:23:49 -04001436 // current.z = As<Short4>(Pack(As<UShort4>(current.z), As<UShort4>(current.x)));
1437 // current.y = As<Short4>(Pack(As<UShort4>(current.y), As<UShort4>(current.w)));
John Bauman89401822014-05-06 15:04:28 -04001438 break;
1439 case FORMAT_X8R8G8B8:
1440 case FORMAT_A8R8G8B8:
1441 if(state.targetFormat[index] == FORMAT_X8R8G8B8 || rgbaWriteMask == 0x7)
1442 {
John Bauman19bac1e2014-05-06 15:23:49 -04001443 current.x = As<Short4>(As<UShort4>(current.x) >> 8);
1444 current.y = As<Short4>(As<UShort4>(current.y) >> 8);
1445 current.z = As<Short4>(As<UShort4>(current.z) >> 8);
John Bauman89401822014-05-06 15:04:28 -04001446
John Bauman19bac1e2014-05-06 15:23:49 -04001447 current.z = As<Short4>(Pack(As<UShort4>(current.z), As<UShort4>(current.x)));
1448 current.y = As<Short4>(Pack(As<UShort4>(current.y), As<UShort4>(current.y)));
John Bauman89401822014-05-06 15:04:28 -04001449
John Bauman19bac1e2014-05-06 15:23:49 -04001450 current.x = current.z;
1451 current.z = UnpackLow(As<Byte8>(current.z), As<Byte8>(current.y));
1452 current.x = UnpackHigh(As<Byte8>(current.x), As<Byte8>(current.y));
1453 current.y = current.z;
1454 current.z = As<Short4>(UnpackLow(current.z, current.x));
1455 current.y = As<Short4>(UnpackHigh(current.y, current.x));
John Bauman89401822014-05-06 15:04:28 -04001456 }
1457 else
1458 {
John Bauman19bac1e2014-05-06 15:23:49 -04001459 current.x = As<Short4>(As<UShort4>(current.x) >> 8);
1460 current.y = As<Short4>(As<UShort4>(current.y) >> 8);
1461 current.z = As<Short4>(As<UShort4>(current.z) >> 8);
1462 current.w = As<Short4>(As<UShort4>(current.w) >> 8);
John Bauman89401822014-05-06 15:04:28 -04001463
John Bauman19bac1e2014-05-06 15:23:49 -04001464 current.z = As<Short4>(Pack(As<UShort4>(current.z), As<UShort4>(current.x)));
1465 current.y = As<Short4>(Pack(As<UShort4>(current.y), As<UShort4>(current.w)));
John Bauman89401822014-05-06 15:04:28 -04001466
John Bauman19bac1e2014-05-06 15:23:49 -04001467 current.x = current.z;
1468 current.z = UnpackLow(As<Byte8>(current.z), As<Byte8>(current.y));
1469 current.x = UnpackHigh(As<Byte8>(current.x), As<Byte8>(current.y));
1470 current.y = current.z;
1471 current.z = As<Short4>(UnpackLow(current.z, current.x));
1472 current.y = As<Short4>(UnpackHigh(current.y, current.x));
John Bauman89401822014-05-06 15:04:28 -04001473 }
1474 break;
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001475 case FORMAT_X8B8G8R8:
1476 case FORMAT_A8B8G8R8:
Alexis Hetu049a1872016-04-25 16:59:58 -04001477 case FORMAT_SRGB8_X8:
1478 case FORMAT_SRGB8_A8:
1479 if(state.targetFormat[index] == FORMAT_X8B8G8R8 || state.targetFormat[index] == FORMAT_SRGB8_X8 || rgbaWriteMask == 0x7)
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001480 {
1481 current.x = As<Short4>(As<UShort4>(current.x) >> 8);
1482 current.y = As<Short4>(As<UShort4>(current.y) >> 8);
1483 current.z = As<Short4>(As<UShort4>(current.z) >> 8);
1484
1485 current.z = As<Short4>(Pack(As<UShort4>(current.x), As<UShort4>(current.z)));
1486 current.y = As<Short4>(Pack(As<UShort4>(current.y), As<UShort4>(current.y)));
1487
1488 current.x = current.z;
1489 current.z = UnpackLow(As<Byte8>(current.z), As<Byte8>(current.y));
1490 current.x = UnpackHigh(As<Byte8>(current.x), As<Byte8>(current.y));
1491 current.y = current.z;
1492 current.z = As<Short4>(UnpackLow(current.z, current.x));
1493 current.y = As<Short4>(UnpackHigh(current.y, current.x));
1494 }
1495 else
1496 {
1497 current.x = As<Short4>(As<UShort4>(current.x) >> 8);
1498 current.y = As<Short4>(As<UShort4>(current.y) >> 8);
1499 current.z = As<Short4>(As<UShort4>(current.z) >> 8);
1500 current.w = As<Short4>(As<UShort4>(current.w) >> 8);
1501
1502 current.z = As<Short4>(Pack(As<UShort4>(current.x), As<UShort4>(current.z)));
1503 current.y = As<Short4>(Pack(As<UShort4>(current.y), As<UShort4>(current.w)));
1504
1505 current.x = current.z;
1506 current.z = UnpackLow(As<Byte8>(current.z), As<Byte8>(current.y));
1507 current.x = UnpackHigh(As<Byte8>(current.x), As<Byte8>(current.y));
1508 current.y = current.z;
1509 current.z = As<Short4>(UnpackLow(current.z, current.x));
1510 current.y = As<Short4>(UnpackHigh(current.y, current.x));
1511 }
1512 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001513 case FORMAT_A8:
1514 current.w = As<Short4>(As<UShort4>(current.w) >> 8);
1515 current.w = As<Short4>(Pack(As<UShort4>(current.w), As<UShort4>(current.w)));
1516 break;
John Bauman89401822014-05-06 15:04:28 -04001517 case FORMAT_G16R16:
John Bauman19bac1e2014-05-06 15:23:49 -04001518 current.z = current.x;
1519 current.x = As<Short4>(UnpackLow(current.x, current.y));
1520 current.z = As<Short4>(UnpackHigh(current.z, current.y));
1521 current.y = current.z;
John Bauman89401822014-05-06 15:04:28 -04001522 break;
1523 case FORMAT_A16B16G16R16:
John Bauman19bac1e2014-05-06 15:23:49 -04001524 transpose4x4(current.x, current.y, current.z, current.w);
John Bauman89401822014-05-06 15:04:28 -04001525 break;
John Bauman89401822014-05-06 15:04:28 -04001526 default:
1527 ASSERT(false);
1528 }
1529
John Bauman19bac1e2014-05-06 15:23:49 -04001530 Short4 c01 = current.z;
1531 Short4 c23 = current.y;
John Bauman89401822014-05-06 15:04:28 -04001532
1533 Int xMask; // Combination of all masks
1534
1535 if(state.depthTestActive)
1536 {
1537 xMask = zMask;
1538 }
1539 else
1540 {
1541 xMask = cMask;
1542 }
1543
1544 if(state.stencilActive)
1545 {
1546 xMask &= sMask;
1547 }
1548
John Bauman89401822014-05-06 15:04:28 -04001549 switch(state.targetFormat[index])
1550 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001551 case FORMAT_R5G6B5:
1552 {
1553 Pointer<Byte> buffer = cBuffer + 2 * x;
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001554 Int value = *Pointer<Int>(buffer);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001555
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001556 Int c01 = Extract(As<Int2>(current.x), 0);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001557
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001558 if((bgraWriteMask & 0x00000007) != 0x00000007)
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001559 {
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001560 Int masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001561 c01 &= *Pointer<Int>(constants + OFFSET(Constants,mask565Q[bgraWriteMask & 0x7][0]));
1562 masked &= *Pointer<Int>(constants + OFFSET(Constants,invMask565Q[bgraWriteMask & 0x7][0]));
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001563 c01 |= masked;
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001564 }
1565
Nicolas Capens4f172c72016-01-13 08:34:30 -05001566 c01 &= *Pointer<Int>(constants + OFFSET(Constants,maskW4Q[0][0]) + xMask * 8);
1567 value &= *Pointer<Int>(constants + OFFSET(Constants,invMaskW4Q[0][0]) + xMask * 8);
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001568 c01 |= value;
1569 *Pointer<Int>(buffer) = c01;
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001570
Nicolas Capens4f172c72016-01-13 08:34:30 -05001571 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001572 value = *Pointer<Int>(buffer);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001573
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001574 Int c23 = Extract(As<Int2>(current.x), 1);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001575
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001576 if((bgraWriteMask & 0x00000007) != 0x00000007)
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001577 {
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001578 Int masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001579 c23 &= *Pointer<Int>(constants + OFFSET(Constants,mask565Q[bgraWriteMask & 0x7][0]));
1580 masked &= *Pointer<Int>(constants + OFFSET(Constants,invMask565Q[bgraWriteMask & 0x7][0]));
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001581 c23 |= masked;
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001582 }
1583
Nicolas Capens4f172c72016-01-13 08:34:30 -05001584 c23 &= *Pointer<Int>(constants + OFFSET(Constants,maskW4Q[0][2]) + xMask * 8);
1585 value &= *Pointer<Int>(constants + OFFSET(Constants,invMaskW4Q[0][2]) + xMask * 8);
Nicolas Capens9919b6c2015-05-26 01:11:26 -04001586 c23 |= value;
1587 *Pointer<Int>(buffer) = c23;
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001588 }
1589 break;
John Bauman89401822014-05-06 15:04:28 -04001590 case FORMAT_A8G8R8B8Q:
1591 case FORMAT_X8G8R8B8Q: // FIXME: Don't touch alpha?
1592 UNIMPLEMENTED();
1593 // value = *Pointer<Short4>(cBuffer + 8 * x + 0);
1594
1595 // if((state.targetFormat[index] == FORMAT_A8G8R8B8Q && bgraWriteMask != 0x0000000F) ||
1596 // ((state.targetFormat[index] == FORMAT_X8G8R8B8Q && bgraWriteMask != 0x00000007) &&
1597 // (state.targetFormat[index] == FORMAT_X8G8R8B8Q && bgraWriteMask != 0x0000000F))) // FIXME: Need for masking when XRGB && Fh?
1598 // {
1599 // Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001600 // c01 &= *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q[bgraWriteMask][0]));
1601 // masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskB4Q[bgraWriteMask][0]));
John Bauman89401822014-05-06 15:04:28 -04001602 // c01 |= masked;
1603 // }
1604
Nicolas Capens4f172c72016-01-13 08:34:30 -05001605 // c01 &= *Pointer<Short4>(constants + OFFSET(Constants,maskD01Q) + xMask * 8);
1606 // value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskD01Q) + xMask * 8);
John Bauman89401822014-05-06 15:04:28 -04001607 // c01 |= value;
1608 // *Pointer<Short4>(cBuffer + 8 * x + 0) = c01;
1609
1610 // value = *Pointer<Short4>(cBuffer + 8 * x + 8);
1611
1612 // if((state.targetFormat[index] == FORMAT_A8G8R8B8Q && bgraWriteMask != 0x0000000F) ||
1613 // ((state.targetFormat[index] == FORMAT_X8G8R8B8Q && bgraWriteMask != 0x00000007) &&
1614 // (state.targetFormat[index] == FORMAT_X8G8R8B8Q && bgraWriteMask != 0x0000000F))) // FIXME: Need for masking when XRGB && Fh?
1615 // {
1616 // Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001617 // c23 &= *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q[bgraWriteMask][0]));
1618 // masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskB4Q[bgraWriteMask][0]));
John Bauman89401822014-05-06 15:04:28 -04001619 // c23 |= masked;
1620 // }
1621
Nicolas Capens4f172c72016-01-13 08:34:30 -05001622 // c23 &= *Pointer<Short4>(constants + OFFSET(Constants,maskD23Q) + xMask * 8);
1623 // value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskD23Q) + xMask * 8);
John Bauman89401822014-05-06 15:04:28 -04001624 // c23 |= value;
1625 // *Pointer<Short4>(cBuffer + 8 * x + 8) = c23;
1626 break;
1627 case FORMAT_A8R8G8B8:
1628 case FORMAT_X8R8G8B8: // FIXME: Don't touch alpha?
John Bauman89401822014-05-06 15:04:28 -04001629 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001630 Pointer<Byte> buffer = cBuffer + x * 4;
1631 Short4 value = *Pointer<Short4>(buffer);
1632
1633 if((state.targetFormat[index] == FORMAT_A8R8G8B8 && bgraWriteMask != 0x0000000F) ||
1634 ((state.targetFormat[index] == FORMAT_X8R8G8B8 && bgraWriteMask != 0x00000007) &&
1635 (state.targetFormat[index] == FORMAT_X8R8G8B8 && bgraWriteMask != 0x0000000F))) // FIXME: Need for masking when XRGB && Fh?
1636 {
1637 Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001638 c01 &= *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q[bgraWriteMask][0]));
1639 masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskB4Q[bgraWriteMask][0]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001640 c01 |= masked;
1641 }
1642
Nicolas Capens4f172c72016-01-13 08:34:30 -05001643 c01 &= *Pointer<Short4>(constants + OFFSET(Constants,maskD01Q) + xMask * 8);
1644 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskD01Q) + xMask * 8);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001645 c01 |= value;
1646 *Pointer<Short4>(buffer) = c01;
1647
Nicolas Capens4f172c72016-01-13 08:34:30 -05001648 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001649 value = *Pointer<Short4>(buffer);
1650
1651 if((state.targetFormat[index] == FORMAT_A8R8G8B8 && bgraWriteMask != 0x0000000F) ||
1652 ((state.targetFormat[index] == FORMAT_X8R8G8B8 && bgraWriteMask != 0x00000007) &&
1653 (state.targetFormat[index] == FORMAT_X8R8G8B8 && bgraWriteMask != 0x0000000F))) // FIXME: Need for masking when XRGB && Fh?
1654 {
1655 Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001656 c23 &= *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q[bgraWriteMask][0]));
1657 masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskB4Q[bgraWriteMask][0]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001658 c23 |= masked;
1659 }
1660
Nicolas Capens4f172c72016-01-13 08:34:30 -05001661 c23 &= *Pointer<Short4>(constants + OFFSET(Constants,maskD23Q) + xMask * 8);
1662 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskD23Q) + xMask * 8);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001663 c23 |= value;
1664 *Pointer<Short4>(buffer) = c23;
John Bauman89401822014-05-06 15:04:28 -04001665 }
John Bauman89401822014-05-06 15:04:28 -04001666 break;
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001667 case FORMAT_A8B8G8R8:
1668 case FORMAT_X8B8G8R8: // FIXME: Don't touch alpha?
Alexis Hetu049a1872016-04-25 16:59:58 -04001669 case FORMAT_SRGB8_X8:
1670 case FORMAT_SRGB8_A8:
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001671 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001672 Pointer<Byte> buffer = cBuffer + x * 4;
1673 Short4 value = *Pointer<Short4>(buffer);
1674
Alexis Hetu049a1872016-04-25 16:59:58 -04001675 bool masked = (((state.targetFormat[index] == FORMAT_A8B8G8R8 || state.targetFormat[index] == FORMAT_SRGB8_A8) && rgbaWriteMask != 0x0000000F) ||
1676 (((state.targetFormat[index] == FORMAT_X8B8G8R8 || state.targetFormat[index] == FORMAT_SRGB8_X8) && rgbaWriteMask != 0x00000007) &&
1677 ((state.targetFormat[index] == FORMAT_X8B8G8R8 || state.targetFormat[index] == FORMAT_SRGB8_X8) && rgbaWriteMask != 0x0000000F))); // FIXME: Need for masking when XBGR && Fh?
1678
1679 if(masked)
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001680 {
1681 Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001682 c01 &= *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q[rgbaWriteMask][0]));
1683 masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskB4Q[rgbaWriteMask][0]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001684 c01 |= masked;
1685 }
1686
Nicolas Capens4f172c72016-01-13 08:34:30 -05001687 c01 &= *Pointer<Short4>(constants + OFFSET(Constants,maskD01Q) + xMask * 8);
1688 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskD01Q) + xMask * 8);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001689 c01 |= value;
1690 *Pointer<Short4>(buffer) = c01;
1691
Nicolas Capens4f172c72016-01-13 08:34:30 -05001692 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001693 value = *Pointer<Short4>(buffer);
1694
Alexis Hetu049a1872016-04-25 16:59:58 -04001695 if(masked)
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001696 {
1697 Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001698 c23 &= *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q[rgbaWriteMask][0]));
1699 masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskB4Q[rgbaWriteMask][0]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001700 c23 |= masked;
1701 }
1702
Nicolas Capens4f172c72016-01-13 08:34:30 -05001703 c23 &= *Pointer<Short4>(constants + OFFSET(Constants,maskD23Q) + xMask * 8);
1704 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskD23Q) + xMask * 8);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001705 c23 |= value;
1706 *Pointer<Short4>(buffer) = c23;
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001707 }
Nicolas Capens0c42ee12015-03-28 18:54:07 -04001708 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001709 case FORMAT_A8:
1710 if(rgbaWriteMask & 0x00000008)
1711 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001712 Pointer<Byte> buffer = cBuffer + 1 * x;
1713 Short4 value;
John Bauman66b8ab22014-05-06 15:57:45 -04001714 Insert(value, *Pointer<Short>(buffer), 0);
Nicolas Capens4f172c72016-01-13 08:34:30 -05001715 Int pitch = *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
John Bauman66b8ab22014-05-06 15:57:45 -04001716 Insert(value, *Pointer<Short>(buffer + pitch), 1);
1717 value = UnpackLow(As<Byte8>(value), As<Byte8>(value));
1718
Nicolas Capens4f172c72016-01-13 08:34:30 -05001719 current.w &= *Pointer<Short4>(constants + OFFSET(Constants,maskB4Q) + 8 * xMask);
1720 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskB4Q) + 8 * xMask);
John Bauman66b8ab22014-05-06 15:57:45 -04001721 current.w |= value;
1722
1723 *Pointer<Short>(buffer) = Extract(current.w, 0);
1724 *Pointer<Short>(buffer + pitch) = Extract(current.w, 1);
1725 }
1726 break;
John Bauman89401822014-05-06 15:04:28 -04001727 case FORMAT_G16R16:
John Bauman89401822014-05-06 15:04:28 -04001728 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001729 Pointer<Byte> buffer = cBuffer + 4 * x;
John Bauman89401822014-05-06 15:04:28 -04001730
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001731 Short4 value = *Pointer<Short4>(buffer);
John Bauman89401822014-05-06 15:04:28 -04001732
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001733 if((rgbaWriteMask & 0x00000003) != 0x00000003)
John Bauman89401822014-05-06 15:04:28 -04001734 {
1735 Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001736 current.x &= *Pointer<Short4>(constants + OFFSET(Constants,maskW01Q[rgbaWriteMask & 0x3][0]));
1737 masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskW01Q[rgbaWriteMask & 0x3][0]));
John Bauman19bac1e2014-05-06 15:23:49 -04001738 current.x |= masked;
John Bauman89401822014-05-06 15:04:28 -04001739 }
1740
Nicolas Capens4f172c72016-01-13 08:34:30 -05001741 current.x &= *Pointer<Short4>(constants + OFFSET(Constants,maskD01Q) + xMask * 8);
1742 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskD01Q) + xMask * 8);
John Bauman19bac1e2014-05-06 15:23:49 -04001743 current.x |= value;
1744 *Pointer<Short4>(buffer) = current.x;
John Bauman89401822014-05-06 15:04:28 -04001745
Nicolas Capens4f172c72016-01-13 08:34:30 -05001746 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
John Bauman89401822014-05-06 15:04:28 -04001747
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001748 value = *Pointer<Short4>(buffer);
1749
1750 if((rgbaWriteMask & 0x00000003) != 0x00000003)
John Bauman89401822014-05-06 15:04:28 -04001751 {
1752 Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001753 current.y &= *Pointer<Short4>(constants + OFFSET(Constants,maskW01Q[rgbaWriteMask & 0x3][0]));
1754 masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskW01Q[rgbaWriteMask & 0x3][0]));
John Bauman19bac1e2014-05-06 15:23:49 -04001755 current.y |= masked;
John Bauman89401822014-05-06 15:04:28 -04001756 }
1757
Nicolas Capens4f172c72016-01-13 08:34:30 -05001758 current.y &= *Pointer<Short4>(constants + OFFSET(Constants,maskD23Q) + xMask * 8);
1759 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskD23Q) + xMask * 8);
John Bauman19bac1e2014-05-06 15:23:49 -04001760 current.y |= value;
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001761 *Pointer<Short4>(buffer) = current.y;
John Bauman89401822014-05-06 15:04:28 -04001762 }
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001763 break;
1764 case FORMAT_A16B16G16R16:
John Bauman89401822014-05-06 15:04:28 -04001765 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001766 Pointer<Byte> buffer = cBuffer + 8 * x;
John Bauman89401822014-05-06 15:04:28 -04001767
John Bauman89401822014-05-06 15:04:28 -04001768 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001769 Short4 value = *Pointer<Short4>(buffer);
1770
1771 if(rgbaWriteMask != 0x0000000F)
1772 {
1773 Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001774 current.x &= *Pointer<Short4>(constants + OFFSET(Constants,maskW4Q[rgbaWriteMask][0]));
1775 masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskW4Q[rgbaWriteMask][0]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001776 current.x |= masked;
1777 }
1778
Nicolas Capens4f172c72016-01-13 08:34:30 -05001779 current.x &= *Pointer<Short4>(constants + OFFSET(Constants,maskQ0Q) + xMask * 8);
1780 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskQ0Q) + xMask * 8);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001781 current.x |= value;
1782 *Pointer<Short4>(buffer) = current.x;
John Bauman89401822014-05-06 15:04:28 -04001783 }
1784
John Bauman89401822014-05-06 15:04:28 -04001785 {
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001786 Short4 value = *Pointer<Short4>(buffer + 8);
1787
1788 if(rgbaWriteMask != 0x0000000F)
1789 {
1790 Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001791 current.y &= *Pointer<Short4>(constants + OFFSET(Constants,maskW4Q[rgbaWriteMask][0]));
1792 masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskW4Q[rgbaWriteMask][0]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001793 current.y |= masked;
1794 }
1795
Nicolas Capens4f172c72016-01-13 08:34:30 -05001796 current.y &= *Pointer<Short4>(constants + OFFSET(Constants,maskQ1Q) + xMask * 8);
1797 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskQ1Q) + xMask * 8);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001798 current.y |= value;
1799 *Pointer<Short4>(buffer + 8) = current.y;
John Bauman89401822014-05-06 15:04:28 -04001800 }
1801
Nicolas Capens4f172c72016-01-13 08:34:30 -05001802 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001803
1804 {
1805 Short4 value = *Pointer<Short4>(buffer);
1806
1807 if(rgbaWriteMask != 0x0000000F)
1808 {
1809 Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001810 current.z &= *Pointer<Short4>(constants + OFFSET(Constants,maskW4Q[rgbaWriteMask][0]));
1811 masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskW4Q[rgbaWriteMask][0]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001812 current.z |= masked;
1813 }
1814
Nicolas Capens4f172c72016-01-13 08:34:30 -05001815 current.z &= *Pointer<Short4>(constants + OFFSET(Constants,maskQ2Q) + xMask * 8);
1816 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskQ2Q) + xMask * 8);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001817 current.z |= value;
1818 *Pointer<Short4>(buffer) = current.z;
1819 }
1820
1821 {
1822 Short4 value = *Pointer<Short4>(buffer + 8);
1823
1824 if(rgbaWriteMask != 0x0000000F)
1825 {
1826 Short4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05001827 current.w &= *Pointer<Short4>(constants + OFFSET(Constants,maskW4Q[rgbaWriteMask][0]));
1828 masked &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskW4Q[rgbaWriteMask][0]));
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001829 current.w |= masked;
1830 }
1831
Nicolas Capens4f172c72016-01-13 08:34:30 -05001832 current.w &= *Pointer<Short4>(constants + OFFSET(Constants,maskQ3Q) + xMask * 8);
1833 value &= *Pointer<Short4>(constants + OFFSET(Constants,invMaskQ3Q) + xMask * 8);
Nicolas Capensd5f0a6c2015-05-26 00:18:01 -04001834 current.w |= value;
1835 *Pointer<Short4>(buffer + 8) = current.w;
1836 }
John Bauman89401822014-05-06 15:04:28 -04001837 }
1838 break;
1839 default:
1840 ASSERT(false);
1841 }
1842 }
1843
Nicolas Capens05b3d662016-02-25 23:58:33 -05001844 void PixelRoutine::blendFactor(const Vector4f &blendFactor, const Vector4f &oC, const Vector4f &pixel, BlendFactor blendFactorActive)
John Bauman89401822014-05-06 15:04:28 -04001845 {
1846 switch(blendFactorActive)
1847 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001848 case BLEND_ZERO:
John Bauman89401822014-05-06 15:04:28 -04001849 // Optimized
1850 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001851 case BLEND_ONE:
John Bauman89401822014-05-06 15:04:28 -04001852 // Optimized
1853 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001854 case BLEND_SOURCE:
John Bauman19bac1e2014-05-06 15:23:49 -04001855 blendFactor.x = oC.x;
1856 blendFactor.y = oC.y;
1857 blendFactor.z = oC.z;
John Bauman89401822014-05-06 15:04:28 -04001858 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001859 case BLEND_INVSOURCE:
John Bauman19bac1e2014-05-06 15:23:49 -04001860 blendFactor.x = Float4(1.0f) - oC.x;
1861 blendFactor.y = Float4(1.0f) - oC.y;
1862 blendFactor.z = Float4(1.0f) - oC.z;
John Bauman89401822014-05-06 15:04:28 -04001863 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001864 case BLEND_DEST:
John Bauman19bac1e2014-05-06 15:23:49 -04001865 blendFactor.x = pixel.x;
1866 blendFactor.y = pixel.y;
1867 blendFactor.z = pixel.z;
John Bauman89401822014-05-06 15:04:28 -04001868 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001869 case BLEND_INVDEST:
John Bauman19bac1e2014-05-06 15:23:49 -04001870 blendFactor.x = Float4(1.0f) - pixel.x;
1871 blendFactor.y = Float4(1.0f) - pixel.y;
1872 blendFactor.z = Float4(1.0f) - pixel.z;
John Bauman89401822014-05-06 15:04:28 -04001873 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001874 case BLEND_SOURCEALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -04001875 blendFactor.x = oC.w;
1876 blendFactor.y = oC.w;
1877 blendFactor.z = oC.w;
John Bauman89401822014-05-06 15:04:28 -04001878 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001879 case BLEND_INVSOURCEALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -04001880 blendFactor.x = Float4(1.0f) - oC.w;
1881 blendFactor.y = Float4(1.0f) - oC.w;
1882 blendFactor.z = Float4(1.0f) - oC.w;
John Bauman89401822014-05-06 15:04:28 -04001883 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001884 case BLEND_DESTALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -04001885 blendFactor.x = pixel.w;
1886 blendFactor.y = pixel.w;
1887 blendFactor.z = pixel.w;
John Bauman89401822014-05-06 15:04:28 -04001888 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001889 case BLEND_INVDESTALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -04001890 blendFactor.x = Float4(1.0f) - pixel.w;
1891 blendFactor.y = Float4(1.0f) - pixel.w;
1892 blendFactor.z = Float4(1.0f) - pixel.w;
John Bauman89401822014-05-06 15:04:28 -04001893 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001894 case BLEND_SRCALPHASAT:
John Bauman19bac1e2014-05-06 15:23:49 -04001895 blendFactor.x = Float4(1.0f) - pixel.w;
1896 blendFactor.x = Min(blendFactor.x, oC.w);
1897 blendFactor.y = blendFactor.x;
1898 blendFactor.z = blendFactor.x;
John Bauman89401822014-05-06 15:04:28 -04001899 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001900 case BLEND_CONSTANT:
Nicolas Capens4f172c72016-01-13 08:34:30 -05001901 blendFactor.x = *Pointer<Float4>(data + OFFSET(DrawData,factor.blendConstant4F[0]));
1902 blendFactor.y = *Pointer<Float4>(data + OFFSET(DrawData,factor.blendConstant4F[1]));
1903 blendFactor.z = *Pointer<Float4>(data + OFFSET(DrawData,factor.blendConstant4F[2]));
John Bauman89401822014-05-06 15:04:28 -04001904 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001905 case BLEND_INVCONSTANT:
Nicolas Capens4f172c72016-01-13 08:34:30 -05001906 blendFactor.x = *Pointer<Float4>(data + OFFSET(DrawData,factor.invBlendConstant4F[0]));
1907 blendFactor.y = *Pointer<Float4>(data + OFFSET(DrawData,factor.invBlendConstant4F[1]));
1908 blendFactor.z = *Pointer<Float4>(data + OFFSET(DrawData,factor.invBlendConstant4F[2]));
John Bauman89401822014-05-06 15:04:28 -04001909 break;
1910 default:
1911 ASSERT(false);
1912 }
1913 }
1914
Nicolas Capens05b3d662016-02-25 23:58:33 -05001915 void PixelRoutine::blendFactorAlpha(const Vector4f &blendFactor, const Vector4f &oC, const Vector4f &pixel, BlendFactor blendFactorAlphaActive)
John Bauman89401822014-05-06 15:04:28 -04001916 {
1917 switch(blendFactorAlphaActive)
1918 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001919 case BLEND_ZERO:
John Bauman89401822014-05-06 15:04:28 -04001920 // Optimized
1921 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001922 case BLEND_ONE:
John Bauman89401822014-05-06 15:04:28 -04001923 // Optimized
1924 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001925 case BLEND_SOURCE:
John Bauman19bac1e2014-05-06 15:23:49 -04001926 blendFactor.w = oC.w;
John Bauman89401822014-05-06 15:04:28 -04001927 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001928 case BLEND_INVSOURCE:
John Bauman19bac1e2014-05-06 15:23:49 -04001929 blendFactor.w = Float4(1.0f) - oC.w;
John Bauman89401822014-05-06 15:04:28 -04001930 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001931 case BLEND_DEST:
John Bauman19bac1e2014-05-06 15:23:49 -04001932 blendFactor.w = pixel.w;
John Bauman89401822014-05-06 15:04:28 -04001933 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001934 case BLEND_INVDEST:
John Bauman19bac1e2014-05-06 15:23:49 -04001935 blendFactor.w = Float4(1.0f) - pixel.w;
John Bauman89401822014-05-06 15:04:28 -04001936 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001937 case BLEND_SOURCEALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -04001938 blendFactor.w = oC.w;
John Bauman89401822014-05-06 15:04:28 -04001939 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001940 case BLEND_INVSOURCEALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -04001941 blendFactor.w = Float4(1.0f) - oC.w;
John Bauman89401822014-05-06 15:04:28 -04001942 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001943 case BLEND_DESTALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -04001944 blendFactor.w = pixel.w;
John Bauman89401822014-05-06 15:04:28 -04001945 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001946 case BLEND_INVDESTALPHA:
John Bauman19bac1e2014-05-06 15:23:49 -04001947 blendFactor.w = Float4(1.0f) - pixel.w;
John Bauman89401822014-05-06 15:04:28 -04001948 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001949 case BLEND_SRCALPHASAT:
John Bauman19bac1e2014-05-06 15:23:49 -04001950 blendFactor.w = Float4(1.0f);
John Bauman89401822014-05-06 15:04:28 -04001951 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001952 case BLEND_CONSTANT:
Nicolas Capens4f172c72016-01-13 08:34:30 -05001953 blendFactor.w = *Pointer<Float4>(data + OFFSET(DrawData,factor.blendConstant4F[3]));
John Bauman89401822014-05-06 15:04:28 -04001954 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04001955 case BLEND_INVCONSTANT:
Nicolas Capens4f172c72016-01-13 08:34:30 -05001956 blendFactor.w = *Pointer<Float4>(data + OFFSET(DrawData,factor.invBlendConstant4F[3]));
John Bauman89401822014-05-06 15:04:28 -04001957 break;
1958 default:
1959 ASSERT(false);
1960 }
1961 }
1962
Nicolas Capens4f172c72016-01-13 08:34:30 -05001963 void PixelRoutine::alphaBlend(int index, Pointer<Byte> &cBuffer, Vector4f &oC, Int &x)
John Bauman89401822014-05-06 15:04:28 -04001964 {
1965 if(!state.alphaBlendActive)
1966 {
1967 return;
1968 }
1969
1970 Pointer<Byte> buffer;
John Bauman19bac1e2014-05-06 15:23:49 -04001971 Vector4f pixel;
John Bauman89401822014-05-06 15:04:28 -04001972
Alexis Hetu96517182015-04-15 10:30:23 -04001973 Vector4s color;
John Bauman89401822014-05-06 15:04:28 -04001974 Short4 c01;
1975 Short4 c23;
1976
Alexis Hetu1abb6382016-02-08 11:21:16 -05001977 Float4 one;
John Bauman89401822014-05-06 15:04:28 -04001978 switch(state.targetFormat[index])
1979 {
Alexis Hetu1abb6382016-02-08 11:21:16 -05001980 case FORMAT_R32I:
1981 case FORMAT_G32R32I:
1982 one = As<Float4>(Int4(0x7FFFFFFF));
1983 break;
1984 case FORMAT_R32UI:
1985 case FORMAT_G32R32UI:
1986 one = As<Float4>(Int4(0xFFFFFFFF));
1987 break;
1988 case FORMAT_R32F:
1989 case FORMAT_G32R32F:
1990 one = Float4(1.0f);
1991 break;
1992 }
1993
1994 switch(state.targetFormat[index])
1995 {
1996 case FORMAT_R32I:
1997 case FORMAT_R32UI:
John Bauman89401822014-05-06 15:04:28 -04001998 case FORMAT_R32F:
1999 buffer = cBuffer;
2000 // FIXME: movlps
John Bauman19bac1e2014-05-06 15:23:49 -04002001 pixel.x.x = *Pointer<Float>(buffer + 4 * x + 0);
2002 pixel.x.y = *Pointer<Float>(buffer + 4 * x + 4);
Nicolas Capens4f172c72016-01-13 08:34:30 -05002003 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
John Bauman89401822014-05-06 15:04:28 -04002004 // FIXME: movhps
John Bauman19bac1e2014-05-06 15:23:49 -04002005 pixel.x.z = *Pointer<Float>(buffer + 4 * x + 0);
2006 pixel.x.w = *Pointer<Float>(buffer + 4 * x + 4);
Alexis Hetu1abb6382016-02-08 11:21:16 -05002007 pixel.y = pixel.z = pixel.w = one;
John Bauman89401822014-05-06 15:04:28 -04002008 break;
Alexis Hetu1abb6382016-02-08 11:21:16 -05002009 case FORMAT_G32R32I:
2010 case FORMAT_G32R32UI:
John Bauman89401822014-05-06 15:04:28 -04002011 case FORMAT_G32R32F:
2012 buffer = cBuffer;
John Bauman19bac1e2014-05-06 15:23:49 -04002013 pixel.x = *Pointer<Float4>(buffer + 8 * x, 16);
Nicolas Capens4f172c72016-01-13 08:34:30 -05002014 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
John Bauman19bac1e2014-05-06 15:23:49 -04002015 pixel.y = *Pointer<Float4>(buffer + 8 * x, 16);
2016 pixel.z = pixel.x;
2017 pixel.x = ShuffleLowHigh(pixel.x, pixel.y, 0x88);
2018 pixel.z = ShuffleLowHigh(pixel.z, pixel.y, 0xDD);
2019 pixel.y = pixel.z;
Alexis Hetu1abb6382016-02-08 11:21:16 -05002020 pixel.z = pixel.w = one;
John Bauman89401822014-05-06 15:04:28 -04002021 break;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002022 case FORMAT_X32B32G32R32F:
John Bauman89401822014-05-06 15:04:28 -04002023 case FORMAT_A32B32G32R32F:
Alexis Hetu1abb6382016-02-08 11:21:16 -05002024 case FORMAT_A32B32G32R32I:
2025 case FORMAT_A32B32G32R32UI:
John Bauman89401822014-05-06 15:04:28 -04002026 buffer = cBuffer;
John Bauman19bac1e2014-05-06 15:23:49 -04002027 pixel.x = *Pointer<Float4>(buffer + 16 * x, 16);
2028 pixel.y = *Pointer<Float4>(buffer + 16 * x + 16, 16);
Nicolas Capens4f172c72016-01-13 08:34:30 -05002029 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
John Bauman19bac1e2014-05-06 15:23:49 -04002030 pixel.z = *Pointer<Float4>(buffer + 16 * x, 16);
2031 pixel.w = *Pointer<Float4>(buffer + 16 * x + 16, 16);
2032 transpose4x4(pixel.x, pixel.y, pixel.z, pixel.w);
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002033 if(state.targetFormat[index] == FORMAT_X32B32G32R32F)
2034 {
2035 pixel.w = Float4(1.0f);
2036 }
John Bauman89401822014-05-06 15:04:28 -04002037 break;
2038 default:
2039 ASSERT(false);
2040 }
2041
Alexis Hetu049a1872016-04-25 16:59:58 -04002042 if((postBlendSRGB && state.writeSRGB) || isSRGB(index))
John Bauman89401822014-05-06 15:04:28 -04002043 {
John Bauman19bac1e2014-05-06 15:23:49 -04002044 sRGBtoLinear(pixel.x);
2045 sRGBtoLinear(pixel.y);
2046 sRGBtoLinear(pixel.z);
John Bauman89401822014-05-06 15:04:28 -04002047 }
2048
2049 // Final Color = ObjectColor * SourceBlendFactor + PixelColor * DestinationBlendFactor
John Bauman19bac1e2014-05-06 15:23:49 -04002050 Vector4f sourceFactor;
2051 Vector4f destFactor;
John Bauman89401822014-05-06 15:04:28 -04002052
Nicolas Capens4f172c72016-01-13 08:34:30 -05002053 blendFactor(sourceFactor, oC, pixel, state.sourceBlendFactor);
2054 blendFactor(destFactor, oC, pixel, state.destBlendFactor);
John Bauman89401822014-05-06 15:04:28 -04002055
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002056 if(state.sourceBlendFactor != BLEND_ONE && state.sourceBlendFactor != BLEND_ZERO)
John Bauman89401822014-05-06 15:04:28 -04002057 {
John Bauman19bac1e2014-05-06 15:23:49 -04002058 oC.x *= sourceFactor.x;
2059 oC.y *= sourceFactor.y;
2060 oC.z *= sourceFactor.z;
John Bauman89401822014-05-06 15:04:28 -04002061 }
Nicolas Capens05b3d662016-02-25 23:58:33 -05002062
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002063 if(state.destBlendFactor != BLEND_ONE && state.destBlendFactor != BLEND_ZERO)
John Bauman89401822014-05-06 15:04:28 -04002064 {
John Bauman19bac1e2014-05-06 15:23:49 -04002065 pixel.x *= destFactor.x;
2066 pixel.y *= destFactor.y;
2067 pixel.z *= destFactor.z;
John Bauman89401822014-05-06 15:04:28 -04002068 }
2069
2070 switch(state.blendOperation)
2071 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002072 case BLENDOP_ADD:
John Bauman19bac1e2014-05-06 15:23:49 -04002073 oC.x += pixel.x;
2074 oC.y += pixel.y;
2075 oC.z += pixel.z;
John Bauman89401822014-05-06 15:04:28 -04002076 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002077 case BLENDOP_SUB:
John Bauman19bac1e2014-05-06 15:23:49 -04002078 oC.x -= pixel.x;
2079 oC.y -= pixel.y;
2080 oC.z -= pixel.z;
John Bauman89401822014-05-06 15:04:28 -04002081 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002082 case BLENDOP_INVSUB:
John Bauman19bac1e2014-05-06 15:23:49 -04002083 oC.x = pixel.x - oC.x;
2084 oC.y = pixel.y - oC.y;
2085 oC.z = pixel.z - oC.z;
John Bauman89401822014-05-06 15:04:28 -04002086 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002087 case BLENDOP_MIN:
John Bauman19bac1e2014-05-06 15:23:49 -04002088 oC.x = Min(oC.x, pixel.x);
2089 oC.y = Min(oC.y, pixel.y);
2090 oC.z = Min(oC.z, pixel.z);
John Bauman89401822014-05-06 15:04:28 -04002091 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002092 case BLENDOP_MAX:
John Bauman19bac1e2014-05-06 15:23:49 -04002093 oC.x = Max(oC.x, pixel.x);
2094 oC.y = Max(oC.y, pixel.y);
2095 oC.z = Max(oC.z, pixel.z);
John Bauman89401822014-05-06 15:04:28 -04002096 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002097 case BLENDOP_SOURCE:
John Bauman89401822014-05-06 15:04:28 -04002098 // No operation
2099 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002100 case BLENDOP_DEST:
John Bauman19bac1e2014-05-06 15:23:49 -04002101 oC.x = pixel.x;
2102 oC.y = pixel.y;
2103 oC.z = pixel.z;
John Bauman89401822014-05-06 15:04:28 -04002104 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002105 case BLENDOP_NULL:
John Bauman19bac1e2014-05-06 15:23:49 -04002106 oC.x = Float4(0.0f);
2107 oC.y = Float4(0.0f);
2108 oC.z = Float4(0.0f);
John Bauman89401822014-05-06 15:04:28 -04002109 break;
2110 default:
2111 ASSERT(false);
2112 }
2113
Nicolas Capens4f172c72016-01-13 08:34:30 -05002114 blendFactorAlpha(sourceFactor, oC, pixel, state.sourceBlendFactorAlpha);
2115 blendFactorAlpha(destFactor, oC, pixel, state.destBlendFactorAlpha);
John Bauman89401822014-05-06 15:04:28 -04002116
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002117 if(state.sourceBlendFactorAlpha != BLEND_ONE && state.sourceBlendFactorAlpha != BLEND_ZERO)
John Bauman89401822014-05-06 15:04:28 -04002118 {
John Bauman19bac1e2014-05-06 15:23:49 -04002119 oC.w *= sourceFactor.w;
John Bauman89401822014-05-06 15:04:28 -04002120 }
Nicolas Capens05b3d662016-02-25 23:58:33 -05002121
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002122 if(state.destBlendFactorAlpha != BLEND_ONE && state.destBlendFactorAlpha != BLEND_ZERO)
John Bauman89401822014-05-06 15:04:28 -04002123 {
John Bauman19bac1e2014-05-06 15:23:49 -04002124 pixel.w *= destFactor.w;
John Bauman89401822014-05-06 15:04:28 -04002125 }
2126
2127 switch(state.blendOperationAlpha)
2128 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002129 case BLENDOP_ADD:
John Bauman19bac1e2014-05-06 15:23:49 -04002130 oC.w += pixel.w;
John Bauman89401822014-05-06 15:04:28 -04002131 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002132 case BLENDOP_SUB:
John Bauman19bac1e2014-05-06 15:23:49 -04002133 oC.w -= pixel.w;
John Bauman89401822014-05-06 15:04:28 -04002134 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002135 case BLENDOP_INVSUB:
John Bauman19bac1e2014-05-06 15:23:49 -04002136 pixel.w -= oC.w;
2137 oC.w = pixel.w;
John Bauman89401822014-05-06 15:04:28 -04002138 break;
Nicolas Capens05b3d662016-02-25 23:58:33 -05002139 case BLENDOP_MIN:
John Bauman19bac1e2014-05-06 15:23:49 -04002140 oC.w = Min(oC.w, pixel.w);
John Bauman89401822014-05-06 15:04:28 -04002141 break;
Nicolas Capens05b3d662016-02-25 23:58:33 -05002142 case BLENDOP_MAX:
John Bauman19bac1e2014-05-06 15:23:49 -04002143 oC.w = Max(oC.w, pixel.w);
John Bauman89401822014-05-06 15:04:28 -04002144 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002145 case BLENDOP_SOURCE:
John Bauman89401822014-05-06 15:04:28 -04002146 // No operation
2147 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002148 case BLENDOP_DEST:
John Bauman19bac1e2014-05-06 15:23:49 -04002149 oC.w = pixel.w;
John Bauman89401822014-05-06 15:04:28 -04002150 break;
Nicolas Capensa0f4be82014-10-22 14:35:30 -04002151 case BLENDOP_NULL:
John Bauman19bac1e2014-05-06 15:23:49 -04002152 oC.w = Float4(0.0f);
John Bauman89401822014-05-06 15:04:28 -04002153 break;
2154 default:
2155 ASSERT(false);
2156 }
2157 }
2158
Nicolas Capens4f172c72016-01-13 08:34:30 -05002159 void PixelRoutine::writeColor(int index, Pointer<Byte> &cBuffer, Int &x, Vector4f &oC, Int &sMask, Int &zMask, Int &cMask)
John Bauman89401822014-05-06 15:04:28 -04002160 {
John Bauman89401822014-05-06 15:04:28 -04002161 switch(state.targetFormat[index])
2162 {
John Bauman89401822014-05-06 15:04:28 -04002163 case FORMAT_R32F:
Alexis Hetu1abb6382016-02-08 11:21:16 -05002164 case FORMAT_R32I:
2165 case FORMAT_R32UI:
John Bauman89401822014-05-06 15:04:28 -04002166 break;
2167 case FORMAT_G32R32F:
Alexis Hetu1abb6382016-02-08 11:21:16 -05002168 case FORMAT_G32R32I:
2169 case FORMAT_G32R32UI:
John Bauman19bac1e2014-05-06 15:23:49 -04002170 oC.z = oC.x;
2171 oC.x = UnpackLow(oC.x, oC.y);
2172 oC.z = UnpackHigh(oC.z, oC.y);
2173 oC.y = oC.z;
John Bauman89401822014-05-06 15:04:28 -04002174 break;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002175 case FORMAT_X32B32G32R32F:
John Bauman89401822014-05-06 15:04:28 -04002176 case FORMAT_A32B32G32R32F:
Alexis Hetu1abb6382016-02-08 11:21:16 -05002177 case FORMAT_A32B32G32R32I:
2178 case FORMAT_A32B32G32R32UI:
John Bauman19bac1e2014-05-06 15:23:49 -04002179 transpose4x4(oC.x, oC.y, oC.z, oC.w);
John Bauman89401822014-05-06 15:04:28 -04002180 break;
2181 default:
2182 ASSERT(false);
2183 }
2184
2185 int rgbaWriteMask = state.colorWriteActive(index);
2186
2187 Int xMask; // Combination of all masks
2188
2189 if(state.depthTestActive)
2190 {
2191 xMask = zMask;
2192 }
2193 else
2194 {
2195 xMask = cMask;
2196 }
2197
2198 if(state.stencilActive)
2199 {
2200 xMask &= sMask;
2201 }
2202
2203 Pointer<Byte> buffer;
2204 Float4 value;
2205
2206 switch(state.targetFormat[index])
2207 {
2208 case FORMAT_R32F:
Alexis Hetu1abb6382016-02-08 11:21:16 -05002209 case FORMAT_R32I:
2210 case FORMAT_R32UI:
John Bauman89401822014-05-06 15:04:28 -04002211 if(rgbaWriteMask & 0x00000001)
2212 {
2213 buffer = cBuffer + 4 * x;
2214
2215 // FIXME: movlps
2216 value.x = *Pointer<Float>(buffer + 0);
2217 value.y = *Pointer<Float>(buffer + 4);
2218
Nicolas Capens4f172c72016-01-13 08:34:30 -05002219 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
John Bauman89401822014-05-06 15:04:28 -04002220
2221 // FIXME: movhps
2222 value.z = *Pointer<Float>(buffer + 0);
2223 value.w = *Pointer<Float>(buffer + 4);
2224
Nicolas Capens4f172c72016-01-13 08:34:30 -05002225 oC.x = As<Float4>(As<Int4>(oC.x) & *Pointer<Int4>(constants + OFFSET(Constants,maskD4X) + xMask * 16, 16));
2226 value = As<Float4>(As<Int4>(value) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskD4X) + xMask * 16, 16));
John Bauman19bac1e2014-05-06 15:23:49 -04002227 oC.x = As<Float4>(As<Int4>(oC.x) | As<Int4>(value));
John Bauman89401822014-05-06 15:04:28 -04002228
2229 // FIXME: movhps
John Bauman19bac1e2014-05-06 15:23:49 -04002230 *Pointer<Float>(buffer + 0) = oC.x.z;
2231 *Pointer<Float>(buffer + 4) = oC.x.w;
John Bauman89401822014-05-06 15:04:28 -04002232
Nicolas Capens4f172c72016-01-13 08:34:30 -05002233 buffer -= *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
John Bauman89401822014-05-06 15:04:28 -04002234
2235 // FIXME: movlps
John Bauman19bac1e2014-05-06 15:23:49 -04002236 *Pointer<Float>(buffer + 0) = oC.x.x;
2237 *Pointer<Float>(buffer + 4) = oC.x.y;
John Bauman89401822014-05-06 15:04:28 -04002238 }
2239 break;
2240 case FORMAT_G32R32F:
Alexis Hetu1abb6382016-02-08 11:21:16 -05002241 case FORMAT_G32R32I:
2242 case FORMAT_G32R32UI:
John Bauman89401822014-05-06 15:04:28 -04002243 buffer = cBuffer + 8 * x;
2244
2245 value = *Pointer<Float4>(buffer);
2246
2247 if((rgbaWriteMask & 0x00000003) != 0x00000003)
2248 {
2249 Float4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05002250 oC.x = As<Float4>(As<Int4>(oC.x) & *Pointer<Int4>(constants + OFFSET(Constants,maskD01X[rgbaWriteMask & 0x3][0])));
2251 masked = As<Float4>(As<Int4>(masked) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskD01X[rgbaWriteMask & 0x3][0])));
John Bauman19bac1e2014-05-06 15:23:49 -04002252 oC.x = As<Float4>(As<Int4>(oC.x) | As<Int4>(masked));
John Bauman89401822014-05-06 15:04:28 -04002253 }
2254
Nicolas Capens4f172c72016-01-13 08:34:30 -05002255 oC.x = As<Float4>(As<Int4>(oC.x) & *Pointer<Int4>(constants + OFFSET(Constants,maskQ01X) + xMask * 16, 16));
2256 value = As<Float4>(As<Int4>(value) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskQ01X) + xMask * 16, 16));
John Bauman19bac1e2014-05-06 15:23:49 -04002257 oC.x = As<Float4>(As<Int4>(oC.x) | As<Int4>(value));
2258 *Pointer<Float4>(buffer) = oC.x;
John Bauman89401822014-05-06 15:04:28 -04002259
Nicolas Capens4f172c72016-01-13 08:34:30 -05002260 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
John Bauman89401822014-05-06 15:04:28 -04002261
2262 value = *Pointer<Float4>(buffer);
2263
2264 if((rgbaWriteMask & 0x00000003) != 0x00000003)
2265 {
2266 Float4 masked;
2267
2268 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05002269 oC.y = As<Float4>(As<Int4>(oC.y) & *Pointer<Int4>(constants + OFFSET(Constants,maskD01X[rgbaWriteMask & 0x3][0])));
2270 masked = As<Float4>(As<Int4>(masked) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskD01X[rgbaWriteMask & 0x3][0])));
John Bauman19bac1e2014-05-06 15:23:49 -04002271 oC.y = As<Float4>(As<Int4>(oC.y) | As<Int4>(masked));
John Bauman89401822014-05-06 15:04:28 -04002272 }
2273
Nicolas Capens4f172c72016-01-13 08:34:30 -05002274 oC.y = As<Float4>(As<Int4>(oC.y) & *Pointer<Int4>(constants + OFFSET(Constants,maskQ23X) + xMask * 16, 16));
2275 value = As<Float4>(As<Int4>(value) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskQ23X) + xMask * 16, 16));
John Bauman19bac1e2014-05-06 15:23:49 -04002276 oC.y = As<Float4>(As<Int4>(oC.y) | As<Int4>(value));
2277 *Pointer<Float4>(buffer) = oC.y;
John Bauman89401822014-05-06 15:04:28 -04002278 break;
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002279 case FORMAT_X32B32G32R32F:
John Bauman89401822014-05-06 15:04:28 -04002280 case FORMAT_A32B32G32R32F:
Alexis Hetu1abb6382016-02-08 11:21:16 -05002281 case FORMAT_A32B32G32R32I:
2282 case FORMAT_A32B32G32R32UI:
John Bauman89401822014-05-06 15:04:28 -04002283 buffer = cBuffer + 16 * x;
2284
2285 {
2286 value = *Pointer<Float4>(buffer, 16);
2287
2288 if(rgbaWriteMask != 0x0000000F)
2289 {
2290 Float4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05002291 oC.x = As<Float4>(As<Int4>(oC.x) & *Pointer<Int4>(constants + OFFSET(Constants,maskD4X[rgbaWriteMask][0])));
2292 masked = As<Float4>(As<Int4>(masked) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskD4X[rgbaWriteMask][0])));
John Bauman19bac1e2014-05-06 15:23:49 -04002293 oC.x = As<Float4>(As<Int4>(oC.x) | As<Int4>(masked));
John Bauman89401822014-05-06 15:04:28 -04002294 }
Nicolas Capens05b3d662016-02-25 23:58:33 -05002295
Nicolas Capens4f172c72016-01-13 08:34:30 -05002296 oC.x = As<Float4>(As<Int4>(oC.x) & *Pointer<Int4>(constants + OFFSET(Constants,maskX0X) + xMask * 16, 16));
2297 value = As<Float4>(As<Int4>(value) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskX0X) + xMask * 16, 16));
John Bauman19bac1e2014-05-06 15:23:49 -04002298 oC.x = As<Float4>(As<Int4>(oC.x) | As<Int4>(value));
2299 *Pointer<Float4>(buffer, 16) = oC.x;
John Bauman89401822014-05-06 15:04:28 -04002300 }
2301
2302 {
2303 value = *Pointer<Float4>(buffer + 16, 16);
2304
2305 if(rgbaWriteMask != 0x0000000F)
Nicolas Capens05b3d662016-02-25 23:58:33 -05002306 {
John Bauman89401822014-05-06 15:04:28 -04002307 Float4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05002308 oC.y = As<Float4>(As<Int4>(oC.y) & *Pointer<Int4>(constants + OFFSET(Constants,maskD4X[rgbaWriteMask][0])));
2309 masked = As<Float4>(As<Int4>(masked) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskD4X[rgbaWriteMask][0])));
John Bauman19bac1e2014-05-06 15:23:49 -04002310 oC.y = As<Float4>(As<Int4>(oC.y) | As<Int4>(masked));
John Bauman89401822014-05-06 15:04:28 -04002311 }
2312
Nicolas Capens4f172c72016-01-13 08:34:30 -05002313 oC.y = As<Float4>(As<Int4>(oC.y) & *Pointer<Int4>(constants + OFFSET(Constants,maskX1X) + xMask * 16, 16));
2314 value = As<Float4>(As<Int4>(value) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskX1X) + xMask * 16, 16));
John Bauman19bac1e2014-05-06 15:23:49 -04002315 oC.y = As<Float4>(As<Int4>(oC.y) | As<Int4>(value));
2316 *Pointer<Float4>(buffer + 16, 16) = oC.y;
John Bauman89401822014-05-06 15:04:28 -04002317 }
2318
Nicolas Capens4f172c72016-01-13 08:34:30 -05002319 buffer += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
John Bauman89401822014-05-06 15:04:28 -04002320
2321 {
2322 value = *Pointer<Float4>(buffer, 16);
2323
2324 if(rgbaWriteMask != 0x0000000F)
2325 {
2326 Float4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05002327 oC.z = As<Float4>(As<Int4>(oC.z) & *Pointer<Int4>(constants + OFFSET(Constants,maskD4X[rgbaWriteMask][0])));
2328 masked = As<Float4>(As<Int4>(masked) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskD4X[rgbaWriteMask][0])));
John Bauman19bac1e2014-05-06 15:23:49 -04002329 oC.z = As<Float4>(As<Int4>(oC.z) | As<Int4>(masked));
John Bauman89401822014-05-06 15:04:28 -04002330 }
2331
Nicolas Capens4f172c72016-01-13 08:34:30 -05002332 oC.z = As<Float4>(As<Int4>(oC.z) & *Pointer<Int4>(constants + OFFSET(Constants,maskX2X) + xMask * 16, 16));
2333 value = As<Float4>(As<Int4>(value) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskX2X) + xMask * 16, 16));
John Bauman19bac1e2014-05-06 15:23:49 -04002334 oC.z = As<Float4>(As<Int4>(oC.z) | As<Int4>(value));
2335 *Pointer<Float4>(buffer, 16) = oC.z;
John Bauman89401822014-05-06 15:04:28 -04002336 }
2337
2338 {
Alexis Hetudbd1a8e2016-04-13 11:40:30 -04002339 value = (state.targetFormat[index] == FORMAT_X32B32G32R32F) ? Float4(1.0f) : *Pointer<Float4>(buffer + 16, 16);
John Bauman89401822014-05-06 15:04:28 -04002340
2341 if(rgbaWriteMask != 0x0000000F)
2342 {
2343 Float4 masked = value;
Nicolas Capens4f172c72016-01-13 08:34:30 -05002344 oC.w = As<Float4>(As<Int4>(oC.w) & *Pointer<Int4>(constants + OFFSET(Constants,maskD4X[rgbaWriteMask][0])));
2345 masked = As<Float4>(As<Int4>(masked) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskD4X[rgbaWriteMask][0])));
John Bauman19bac1e2014-05-06 15:23:49 -04002346 oC.w = As<Float4>(As<Int4>(oC.w) | As<Int4>(masked));
John Bauman89401822014-05-06 15:04:28 -04002347 }
2348
Nicolas Capens4f172c72016-01-13 08:34:30 -05002349 oC.w = As<Float4>(As<Int4>(oC.w) & *Pointer<Int4>(constants + OFFSET(Constants,maskX3X) + xMask * 16, 16));
2350 value = As<Float4>(As<Int4>(value) & *Pointer<Int4>(constants + OFFSET(Constants,invMaskX3X) + xMask * 16, 16));
John Bauman19bac1e2014-05-06 15:23:49 -04002351 oC.w = As<Float4>(As<Int4>(oC.w) | As<Int4>(value));
2352 *Pointer<Float4>(buffer + 16, 16) = oC.w;
John Bauman89401822014-05-06 15:04:28 -04002353 }
2354 break;
2355 default:
2356 ASSERT(false);
2357 }
2358 }
2359
John Bauman89401822014-05-06 15:04:28 -04002360 UShort4 PixelRoutine::convertFixed16(Float4 &cf, bool saturate)
2361 {
John Bauman19bac1e2014-05-06 15:23:49 -04002362 return UShort4(cf * Float4(0xFFFF), saturate);
John Bauman89401822014-05-06 15:04:28 -04002363 }
2364
Nicolas Capens4f172c72016-01-13 08:34:30 -05002365 void PixelRoutine::sRGBtoLinear16_12_16(Vector4s &c)
John Bauman89401822014-05-06 15:04:28 -04002366 {
John Bauman19bac1e2014-05-06 15:23:49 -04002367 c.x = As<UShort4>(c.x) >> 4;
2368 c.y = As<UShort4>(c.y) >> 4;
2369 c.z = As<UShort4>(c.z) >> 4;
John Bauman89401822014-05-06 15:04:28 -04002370
Nicolas Capens4f172c72016-01-13 08:34:30 -05002371 sRGBtoLinear12_16(c);
John Bauman89401822014-05-06 15:04:28 -04002372 }
2373
Nicolas Capens4f172c72016-01-13 08:34:30 -05002374 void PixelRoutine::sRGBtoLinear12_16(Vector4s &c)
John Bauman89401822014-05-06 15:04:28 -04002375 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05002376 Pointer<Byte> LUT = constants + OFFSET(Constants,sRGBtoLinear12_16);
John Bauman89401822014-05-06 15:04:28 -04002377
John Bauman19bac1e2014-05-06 15:23:49 -04002378 c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 0))), 0);
2379 c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 1))), 1);
2380 c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 2))), 2);
2381 c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 3))), 3);
John Bauman89401822014-05-06 15:04:28 -04002382
John Bauman19bac1e2014-05-06 15:23:49 -04002383 c.y = Insert(c.y, *Pointer<Short>(LUT + 2 * Int(Extract(c.y, 0))), 0);
2384 c.y = Insert(c.y, *Pointer<Short>(LUT + 2 * Int(Extract(c.y, 1))), 1);
2385 c.y = Insert(c.y, *Pointer<Short>(LUT + 2 * Int(Extract(c.y, 2))), 2);
2386 c.y = Insert(c.y, *Pointer<Short>(LUT + 2 * Int(Extract(c.y, 3))), 3);
John Bauman89401822014-05-06 15:04:28 -04002387
John Bauman19bac1e2014-05-06 15:23:49 -04002388 c.z = Insert(c.z, *Pointer<Short>(LUT + 2 * Int(Extract(c.z, 0))), 0);
2389 c.z = Insert(c.z, *Pointer<Short>(LUT + 2 * Int(Extract(c.z, 1))), 1);
2390 c.z = Insert(c.z, *Pointer<Short>(LUT + 2 * Int(Extract(c.z, 2))), 2);
2391 c.z = Insert(c.z, *Pointer<Short>(LUT + 2 * Int(Extract(c.z, 3))), 3);
John Bauman89401822014-05-06 15:04:28 -04002392 }
2393
Nicolas Capens4f172c72016-01-13 08:34:30 -05002394 void PixelRoutine::linearToSRGB16_12_16(Vector4s &c)
John Bauman89401822014-05-06 15:04:28 -04002395 {
John Bauman19bac1e2014-05-06 15:23:49 -04002396 c.x = As<UShort4>(c.x) >> 4;
2397 c.y = As<UShort4>(c.y) >> 4;
2398 c.z = As<UShort4>(c.z) >> 4;
John Bauman89401822014-05-06 15:04:28 -04002399
Nicolas Capens4f172c72016-01-13 08:34:30 -05002400 linearToSRGB12_16(c);
John Bauman89401822014-05-06 15:04:28 -04002401 }
2402
Nicolas Capens4f172c72016-01-13 08:34:30 -05002403 void PixelRoutine::linearToSRGB12_16(Vector4s &c)
John Bauman89401822014-05-06 15:04:28 -04002404 {
Nicolas Capens4f172c72016-01-13 08:34:30 -05002405 Pointer<Byte> LUT = constants + OFFSET(Constants,linearToSRGB12_16);
John Bauman89401822014-05-06 15:04:28 -04002406
John Bauman19bac1e2014-05-06 15:23:49 -04002407 c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 0))), 0);
2408 c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 1))), 1);
2409 c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 2))), 2);
2410 c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 3))), 3);
John Bauman89401822014-05-06 15:04:28 -04002411
John Bauman19bac1e2014-05-06 15:23:49 -04002412 c.y = Insert(c.y, *Pointer<Short>(LUT + 2 * Int(Extract(c.y, 0))), 0);
2413 c.y = Insert(c.y, *Pointer<Short>(LUT + 2 * Int(Extract(c.y, 1))), 1);
2414 c.y = Insert(c.y, *Pointer<Short>(LUT + 2 * Int(Extract(c.y, 2))), 2);
2415 c.y = Insert(c.y, *Pointer<Short>(LUT + 2 * Int(Extract(c.y, 3))), 3);
John Bauman89401822014-05-06 15:04:28 -04002416
John Bauman19bac1e2014-05-06 15:23:49 -04002417 c.z = Insert(c.z, *Pointer<Short>(LUT + 2 * Int(Extract(c.z, 0))), 0);
2418 c.z = Insert(c.z, *Pointer<Short>(LUT + 2 * Int(Extract(c.z, 1))), 1);
2419 c.z = Insert(c.z, *Pointer<Short>(LUT + 2 * Int(Extract(c.z, 2))), 2);
2420 c.z = Insert(c.z, *Pointer<Short>(LUT + 2 * Int(Extract(c.z, 3))), 3);
John Bauman89401822014-05-06 15:04:28 -04002421 }
2422
John Bauman89401822014-05-06 15:04:28 -04002423 Float4 PixelRoutine::sRGBtoLinear(const Float4 &x) // Approximates x^2.2
2424 {
2425 Float4 linear = x * x;
2426 linear = linear * Float4(0.73f) + linear * x * Float4(0.27f);
2427
2428 return Min(Max(linear, Float4(0.0f)), Float4(1.0f));
2429 }
2430
John Bauman19bac1e2014-05-06 15:23:49 -04002431 bool PixelRoutine::colorUsed()
2432 {
2433 return state.colorWriteMask || state.alphaTestActive() || state.shaderContainsKill;
2434 }
John Bauman89401822014-05-06 15:04:28 -04002435}