1d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
3d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Licensed under the Apache License, Version 2.0 (the "License");
4d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// you may not use this file except in compliance with the License.
5d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// You may obtain a copy of the License at
6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
7d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//    http://www.apache.org/licenses/LICENSE-2.0
8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
9d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Unless required by applicable law or agreed to in writing, software
10d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// distributed under the License is distributed on an "AS IS" BASIS,
11d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// See the License for the specific language governing permissions and
13d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// limitations under the License.
14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
15894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Renderer.hpp"
16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
17894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Clipper.hpp"
18894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Math.hpp"
19894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "FrameBuffer.hpp"
20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Timer.hpp"
21894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Surface.hpp"
22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Half.hpp"
23894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Primitive.hpp"
24894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Polygon.hpp"
25894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "SwiftConfig.hpp"
26894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "MutexLock.hpp"
27894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "CPUID.hpp"
28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Memory.hpp"
29894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Resource.hpp"
30894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Constants.hpp"
31894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Debug.hpp"
3219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "Reactor/Reactor.hpp"
33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#undef max
35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool disableServer = true;
37894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
38894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#ifndef NDEBUG
39894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanunsigned int minPrimitives = 1;
40894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanunsigned int maxPrimitives = 1 << 21;
41894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
42894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
43894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumannamespace sw
44894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
4519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	extern bool halfIntegerCoordinates;     // Pixel centers are not at integer coordinates
4619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	extern bool symmetricNormalizedDepth;   // [-1, 1] instead of [0, 1]
4719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	extern bool booleanFaceRegister;
4819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	extern bool fullPixelPositionRegister;
4944ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens	extern bool leadingVertexFirst;         // Flat shading uses first vertex, else last
5044ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens	extern bool secondaryColor;             // Specular lighting is applied after texturing
5119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
52894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	extern bool forceWindowed;
53894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	extern bool complementaryDepthBuffer;
54894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	extern bool postBlendSRGB;
55894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	extern bool exactColorRounding;
56a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens	extern TransparencyAntialiasing transparencyAntialiasing;
57894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	extern bool forceClearRegisters;
58894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
5966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	extern bool precacheVertex;
6066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	extern bool precacheSetup;
6166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman	extern bool precachePixel;
6266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	int batchSize = 128;
64894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	int threadCount = 1;
65894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	int unitCount = 1;
66894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	int clusterCount = 1;
67894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
6819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	TranscendentalPrecision logPrecision = ACCURATE;
6919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	TranscendentalPrecision expPrecision = ACCURATE;
7019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	TranscendentalPrecision rcpPrecision = ACCURATE;
7119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	TranscendentalPrecision rsqPrecision = ACCURATE;
7219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	bool perspectiveCorrection = true;
7319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
74894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	struct Parameters
75894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
76894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Renderer *renderer;
77894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int threadIndex;
78894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	};
79894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
80894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	DrawCall::DrawCall()
81894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
82894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		queries = 0;
83894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
8404c967a3f4090bb7b679ae0859d4f2806e1565acAlexis Hetu		vsDirtyConstF = VERTEX_UNIFORM_VECTORS + 1;
85894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		vsDirtyConstI = 16;
86894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		vsDirtyConstB = 16;
87894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
8804c967a3f4090bb7b679ae0859d4f2806e1565acAlexis Hetu		psDirtyConstF = FRAGMENT_UNIFORM_VECTORS;
89894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		psDirtyConstI = 16;
90894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		psDirtyConstB = 16;
91894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
92894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		references = -1;
93894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
94894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		data = (DrawData*)allocate(sizeof(DrawData));
95894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		data->constants = &constants;
96894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
97894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
98894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	DrawCall::~DrawCall()
99894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		delete queries;
101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		deallocate(data);
103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10511997791d9e9b5241be7a1494124121c9c4c79c6Nicolas Capens	Renderer::Renderer(Context *context, Conventions conventions, bool exactColorRounding) : VertexProcessor(context), PixelProcessor(context), SetupProcessor(context), context(context), viewport()
106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1073aa46cbdcb0cc386a53cabe67954a114593c37e5Nicolas Capens		sw::halfIntegerCoordinates = conventions.halfIntegerCoordinates;
1083aa46cbdcb0cc386a53cabe67954a114593c37e5Nicolas Capens		sw::symmetricNormalizedDepth = conventions.symmetricNormalizedDepth;
1093aa46cbdcb0cc386a53cabe67954a114593c37e5Nicolas Capens		sw::booleanFaceRegister = conventions.booleanFaceRegister;
1103aa46cbdcb0cc386a53cabe67954a114593c37e5Nicolas Capens		sw::fullPixelPositionRegister = conventions.fullPixelPositionRegister;
1113aa46cbdcb0cc386a53cabe67954a114593c37e5Nicolas Capens		sw::leadingVertexFirst = conventions.leadingVertexFirst;
11244ffb65ecb2638a3062a13d2fc3beb23a534b40dNicolas Capens		sw::secondaryColor = conventions.secondaryColor;
11319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		sw::exactColorRounding = exactColorRounding;
114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		setRenderTarget(0, 0);
11637525a55597ac1bf4e61e8bb3e54edf8a84c297cNicolas Capens		clipper = new Clipper(symmetricNormalizedDepth);
117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateViewMatrix = true;
119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateBaseMatrix = true;
120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateProjectionMatrix = true;
121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateClipPlanes = true;
122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#if PERF_HUD
124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			resetTimers();
125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#endif
126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < 16; i++)
128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			vertexTask[i] = 0;
130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			worker[i] = 0;
132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			resume[i] = 0;
133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			suspend[i] = 0;
134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		threadsAwake = 0;
137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		resumeApp = new Event();
138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		currentDraw = 0;
140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		nextDraw = 0;
141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		qHead = 0;
143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		qSize = 0;
144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < 16; i++)
146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			triangleBatch[i] = 0;
148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			primitiveBatch[i] = 0;
149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int draw = 0; draw < DRAW_COUNT; draw++)
152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			drawCall[draw] = new DrawCall();
154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			drawList[draw] = drawCall[draw];
155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int unit = 0; unit < 16; unit++)
158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			primitiveProgress[unit].init();
160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int cluster = 0; cluster < 16; cluster++)
163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			pixelProgress[cluster].init();
165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		clipFlags = 0;
168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		swiftConfig = new SwiftConfig(disableServer);
170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateConfiguration(true);
17119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
17219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		sync = new Resource(0);
173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	Renderer::~Renderer()
176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
17719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		sync->destruct();
17819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		delete clipper;
180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		clipper = 0;
181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		terminateThreads();
183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		delete resumeApp;
184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int draw = 0; draw < DRAW_COUNT; draw++)
186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			delete drawCall[draw];
188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		delete swiftConfig;
191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1938b40c3f8ce2f5beff0b0de54b2a22a5b3810984bAlexis Hetu	void Renderer::clear(void *pixel, Format format, Surface *dest, const SliceRect &dRect, unsigned int rgbaMask)
1948b40c3f8ce2f5beff0b0de54b2a22a5b3810984bAlexis Hetu	{
1958b40c3f8ce2f5beff0b0de54b2a22a5b3810984bAlexis Hetu		blitter.clear(pixel, format, dest, dRect, rgbaMask);
1968b40c3f8ce2f5beff0b0de54b2a22a5b3810984bAlexis Hetu	}
1978b40c3f8ce2f5beff0b0de54b2a22a5b3810984bAlexis Hetu
198f7be67f8e9b497e47a1740a27a85886482613679Alexis Hetu	void Renderer::blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter)
199894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
200894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		blitter.blit(source, sRect, dest, dRect, filter);
201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
203f68510dddd0e801b507fd77a108a5f0508c9d4a5Alexis Hetu	void Renderer::blit3D(Surface *source, Surface *dest)
204f68510dddd0e801b507fd77a108a5f0508c9d4a5Alexis Hetu	{
205f68510dddd0e801b507fd77a108a5f0508c9d4a5Alexis Hetu		blitter.blit3D(source, dest);
206f68510dddd0e801b507fd77a108a5f0508c9d4a5Alexis Hetu	}
207f68510dddd0e801b507fd77a108a5f0508c9d4a5Alexis Hetu
208a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens	void Renderer::draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update)
209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#ifndef NDEBUG
211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(count < minPrimitives || count > maxPrimitives)
212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				return;
214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#endif
216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		context->drawType = drawType;
218894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
219894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateConfiguration();
220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateClipper();
221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
22266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		int ss = context->getSuperSampleCount();
22366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		int ms = context->getMultiSampleCount();
224894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
225894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int q = 0; q < ss; q++)
226894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2275767eabd0b3c275c7221f1fceac9ef11ea5ec4e5Nicolas Capens			unsigned int oldMultiSampleMask = context->multiSampleMask;
22819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			context->multiSampleMask = (context->sampleMask >> (ms * q)) & ((unsigned)0xFFFFFFFF >> (32 - ms));
229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(!context->multiSampleMask)
231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
232894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				continue;
233894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
23519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			sync->lock(sw::PRIVATE);
23619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
237235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens			Routine *vertexRoutine;
238235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens			Routine *setupRoutine;
239235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens			Routine *pixelRoutine;
240235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens
241894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(update || oldMultiSampleMask != context->multiSampleMask)
242894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
243ef0505797c620e5115fff2b614d4c6ea017babcdAlexis Hetu				vertexState = VertexProcessor::update(drawType);
244894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				setupState = SetupProcessor::update();
245894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pixelState = PixelProcessor::update();
246894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
247894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				vertexRoutine = VertexProcessor::routine(vertexState);
248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				setupRoutine = SetupProcessor::routine(setupState);
249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pixelRoutine = PixelProcessor::routine(pixelState);
250894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int batch = batchSize / ms;
253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
25421d96b174d4d1153233c4465eb734928778c151aNicolas Capens			int (Renderer::*setupPrimitives)(int batch, int count);
255235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens
256894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(context->isDrawTriangle())
257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
258894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				switch(context->fillMode)
259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
260a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens				case FILL_SOLID:
26121d96b174d4d1153233c4465eb734928778c151aNicolas Capens					setupPrimitives = &Renderer::setupSolidTriangles;
262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
263a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens				case FILL_WIREFRAME:
26421d96b174d4d1153233c4465eb734928778c151aNicolas Capens					setupPrimitives = &Renderer::setupWireframeTriangle;
265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch = 1;
266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
267a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens				case FILL_VERTEX:
26821d96b174d4d1153233c4465eb734928778c151aNicolas Capens					setupPrimitives = &Renderer::setupVertexTriangle;
269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch = 1;
270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					break;
271894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				default: ASSERT(false);
272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
273894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
274894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else if(context->isDrawLine())
275894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
27621d96b174d4d1153233c4465eb734928778c151aNicolas Capens				setupPrimitives = &Renderer::setupLines;
277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
278894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else   // Point draw
279894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
28021d96b174d4d1153233c4465eb734928778c151aNicolas Capens				setupPrimitives = &Renderer::setupPoints;
281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			DrawCall *draw = 0;
284894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			do
286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
287894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int i = 0; i < DRAW_COUNT; i++)
288894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
289894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(drawCall[i]->references == -1)
290894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
291894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						draw = drawCall[i];
292894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						drawList[nextDraw % DRAW_COUNT] = draw;
293894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
294894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						break;
295894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
296894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
297894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
298894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(!draw)
299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
300894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					resumeApp->wait();
301894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
302894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
303894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			while(!draw);
304894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
305894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			DrawData *data = draw->data;
306894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
307894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(queries.size() != 0)
308894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
30920a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu				draw->queries = new std::list<Query*>();
31020a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu				bool includePrimitivesWrittenQueries = vertexState.transformFeedbackQueryEnabled && vertexState.transformFeedbackEnabled;
311894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(std::list<Query*>::iterator query = queries.begin(); query != queries.end(); query++)
312894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
31320a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu					Query* q = *query;
31420a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu					if(includePrimitivesWrittenQueries || (q->type != Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN))
31520a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu					{
31620a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu						atomicIncrement(&(q->reference));
31720a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu						draw->queries->push_back(q);
31820a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu					}
319894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
320894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
321894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
322894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->drawType = drawType;
323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->batchSize = batch;
324894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
325894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			vertexRoutine->bind();
326894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			setupRoutine->bind();
327894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			pixelRoutine->bind();
328894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
329894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->vertexRoutine = vertexRoutine;
330894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->setupRoutine = setupRoutine;
331894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->pixelRoutine = pixelRoutine;
332eb195b6e8d98116d4cd9e6760a6a5621d77370e7Nicolas Capens			draw->vertexPointer = (VertexProcessor::RoutinePointer)vertexRoutine->getEntry();
333894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->setupPointer = (SetupProcessor::RoutinePointer)setupRoutine->getEntry();
334894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->pixelPointer = (PixelProcessor::RoutinePointer)pixelRoutine->getEntry();
335894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->setupPrimitives = setupPrimitives;
336894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->setupState = setupState;
337894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
338502836a8df8985544667325ad0fb44d3ac0f40e3Nicolas Capens			for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
339894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
340894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw->vertexStream[i] = context->input[i].resource;
341894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->input[i] = context->input[i].buffer;
342894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->stride[i] = context->input[i].stride;
343894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
344894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(draw->vertexStream[i])
345894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
346894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw->vertexStream[i]->lock(PUBLIC, PRIVATE);
347894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
348894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
349894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(context->indexBuffer)
351894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
352894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->indices = (unsigned char*)context->indexBuffer->lock(PUBLIC, PRIVATE) + indexOffset;
353894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
354894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->indexBuffer = context->indexBuffer;
356894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3570b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu			for(int sampler = 0; sampler < TOTAL_IMAGE_UNITS; sampler++)
358894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw->texture[sampler] = 0;
360894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
361894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3620b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu			for(int sampler = 0; sampler < TEXTURE_IMAGE_UNITS; sampler++)
363894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
364894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(pixelState.sampler[sampler].textureType != TEXTURE_NULL)
365894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw->texture[sampler] = context->texture[sampler];
367894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw->texture[sampler]->lock(PUBLIC, isReadWriteTexture(sampler) ? MANAGED : PRIVATE);   // If the texure is both read and written, use the same read/write lock as render targets
368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
369894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					data->mipmap[sampler] = context->sampler[sampler].getTextureData();
370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
371894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
373894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(context->pixelShader)
374894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
375894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(draw->psDirtyConstF)
376894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
377894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					memcpy(&data->ps.cW, PixelProcessor::cW, sizeof(word4) * 4 * (draw->psDirtyConstF < 8 ? draw->psDirtyConstF : 8));
378894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					memcpy(&data->ps.c, PixelProcessor::c, sizeof(float4) * draw->psDirtyConstF);
379894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw->psDirtyConstF = 0;
380894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
381894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(draw->psDirtyConstI)
383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					memcpy(&data->ps.i, PixelProcessor::i, sizeof(int4) * draw->psDirtyConstI);
385894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw->psDirtyConstI = 0;
386894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
387894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
388894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(draw->psDirtyConstB)
389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
390894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					memcpy(&data->ps.b, PixelProcessor::b, sizeof(bool) * draw->psDirtyConstB);
391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw->psDirtyConstB = 0;
392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
39308a111aa53596b17f2b405ee28fafe0aad4e6027Alexis Hetu
3946411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				PixelProcessor::lockUniformBuffers(data->ps.u, draw->pUniformBuffers);
3956411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu			}
3966411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu			else
3976411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu			{
3986411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
3996411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				{
4006411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					draw->pUniformBuffers[i] = nullptr;
4016411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				}
402894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
403579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
404894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(context->pixelShaderVersion() <= 0x0104)
405894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
406894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int stage = 0; stage < 8; stage++)
407894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
408894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(pixelState.textureStage[stage].stageOperation != TextureStage::STAGE_DISABLE || context->pixelShader)
409894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
410894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						data->textureStage[stage] = context->textureStage[stage].uniforms;
411894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
412894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else break;
413894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
414894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
415894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
416894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(context->vertexShader)
417894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
418894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(context->vertexShader->getVersion() >= 0x0300)
419894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
4200b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu					for(int sampler = 0; sampler < VERTEX_TEXTURE_IMAGE_UNITS; sampler++)
421894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
422894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						if(vertexState.samplerState[sampler].textureType != TEXTURE_NULL)
423894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
4240b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu							draw->texture[TEXTURE_IMAGE_UNITS + sampler] = context->texture[TEXTURE_IMAGE_UNITS + sampler];
4250b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu							draw->texture[TEXTURE_IMAGE_UNITS + sampler]->lock(PUBLIC, PRIVATE);
426894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
4270b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu							data->mipmap[TEXTURE_IMAGE_UNITS + sampler] = context->sampler[TEXTURE_IMAGE_UNITS + sampler].getTextureData();
428894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
429894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
430894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
431894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
432894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(draw->vsDirtyConstF)
433894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
434894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					memcpy(&data->vs.c, VertexProcessor::c, sizeof(float4) * draw->vsDirtyConstF);
435894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw->vsDirtyConstF = 0;
436894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
437894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
438894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(draw->vsDirtyConstI)
439894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					memcpy(&data->vs.i, VertexProcessor::i, sizeof(int4) * draw->vsDirtyConstI);
441894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw->vsDirtyConstI = 0;
442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
443894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(draw->vsDirtyConstB)
445894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
446894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					memcpy(&data->vs.b, VertexProcessor::b, sizeof(bool) * draw->vsDirtyConstB);
447894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw->vsDirtyConstB = 0;
448894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
449dd8df68e64365aafe91893b11bf7cc4b67599ed4Alexis Hetu
450dd8df68e64365aafe91893b11bf7cc4b67599ed4Alexis Hetu				if(context->vertexShader->instanceIdDeclared)
451dd8df68e64365aafe91893b11bf7cc4b67599ed4Alexis Hetu				{
452dd8df68e64365aafe91893b11bf7cc4b67599ed4Alexis Hetu					data->instanceID = context->instanceID;
453dd8df68e64365aafe91893b11bf7cc4b67599ed4Alexis Hetu				}
45408a111aa53596b17f2b405ee28fafe0aad4e6027Alexis Hetu
4556411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				VertexProcessor::lockUniformBuffers(data->vs.u, draw->vUniformBuffers);
4566411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				VertexProcessor::lockTransformFeedbackBuffers(data->vs.t, data->vs.reg, data->vs.row, data->vs.col, data->vs.str, draw->transformFeedbackBuffers);
457894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else
459894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
460894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->ff = ff;
461894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
46204c967a3f4090bb7b679ae0859d4f2806e1565acAlexis Hetu				draw->vsDirtyConstF = VERTEX_UNIFORM_VECTORS + 1;
463894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw->vsDirtyConstI = 16;
464894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw->vsDirtyConstB = 16;
4656411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu
4666411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
4676411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				{
4686411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					draw->vUniformBuffers[i] = nullptr;
4696411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				}
4706411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu
4716411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
4726411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				{
4736411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					draw->transformFeedbackBuffers[i] = nullptr;
4746411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				}
475894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
476894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(pixelState.stencilActive)
478894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
479894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->stencil[0] = stencil;
480894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->stencil[1] = stencilCCW;
481894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
482894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
483894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(pixelState.fogActive)
484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->fog = fog;
486894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
488894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(setupState.isDrawPoint)
489894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
490894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->point = point;
491894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
492894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
493235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens			data->lineWidth = context->lineWidth;
494235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens
495894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			data->factor = factor;
496894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
497a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			if(pixelState.transparencyAntialiasing == TRANSPARENCY_ALPHA_TO_COVERAGE)
498894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
499a818c45371a81739aeb521dca24ba74ca6a4d38bAlexis Hetu				float ref = context->alphaReference * (1.0f / 255.0f);
500894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				float margin = sw::min(ref, 1.0f - ref);
501894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
502894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(ms == 4)
503894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
504894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					data->a2c0 = replicate(ref - margin * 0.6f);
505894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					data->a2c1 = replicate(ref - margin * 0.2f);
506894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					data->a2c2 = replicate(ref + margin * 0.2f);
507894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					data->a2c3 = replicate(ref + margin * 0.6f);
508894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
509894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				else if(ms == 2)
510894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
511894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					data->a2c0 = replicate(ref - margin * 0.3f);
512894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					data->a2c1 = replicate(ref + margin * 0.3f);
513894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
514894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				else ASSERT(false);
515894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
516894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
517894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(pixelState.occlusionEnabled)
518894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
519894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int cluster = 0; cluster < clusterCount; cluster++)
520894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
521894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					data->occlusion[cluster] = 0;
522894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
523894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
524894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
525894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			#if PERF_PROFILE
526894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int cluster = 0; cluster < clusterCount; cluster++)
527894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
528894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					for(int i = 0; i < PERF_TIMERS; i++)
529894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
530894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						data->cycles[i][cluster] = 0;
531894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
532894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
533894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			#endif
534894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
535894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			// Viewport
536894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
53719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				float W = 0.5f * viewport.width;
53819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				float H = 0.5f * viewport.height;
53919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				float X0 = viewport.x0 + W;
54019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				float Y0 = viewport.y0 + H;
54119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				float N = viewport.minZ;
54219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				float F = viewport.maxZ;
543894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				float Z = F - N;
544894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
545894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(context->isDrawTriangle(false))
546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
547894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					N += depthBias;
548894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
549894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
550894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(complementaryDepthBuffer)
551894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
552894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Z = -Z;
553894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					N = 1 - N;
554894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
555894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
556894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				static const float X[5][16] =   // Fragment offsets
557894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
558894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{+0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 1 sample
559894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{-0.2500f, +0.2500f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 2 samples
560894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{-0.3000f, +0.1000f, +0.3000f, -0.1000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 4 samples
561894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{+0.1875f, -0.3125f, +0.3125f, -0.4375f, -0.0625f, +0.4375f, +0.0625f, -0.1875f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 8 samples
562894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{+0.2553f, -0.1155f, +0.1661f, -0.1828f, +0.2293f, -0.4132f, -0.1773f, -0.0577f, +0.3891f, -0.4656f, +0.4103f, +0.4248f, -0.2109f, +0.3966f, -0.2664f, -0.3872f}    // 16 samples
563894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				};
564894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
565894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				static const float Y[5][16] =   // Fragment offsets
566894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
567894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{+0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 1 sample
568894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{-0.2500f, +0.2500f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 2 samples
569894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{-0.1000f, -0.3000f, +0.1000f, +0.3000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 4 samples
570894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{-0.4375f, -0.3125f, -0.1875f, -0.0625f, +0.0625f, +0.1875f, +0.3125f, +0.4375f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 8 samples
571894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{-0.4503f, +0.1883f, +0.3684f, -0.4668f, -0.0690f, -0.1315f, +0.4999f, +0.0728f, +0.1070f, -0.3086f, +0.3725f, -0.1547f, -0.1102f, -0.3588f, +0.1789f, +0.0269f}    // 16 samples
572894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				};
573894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
574894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int s = sw::log2(ss);
575894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
57619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				data->Wx16 = replicate(W * 16);
57719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				data->Hx16 = replicate(H * 16);
5785491cb48df1edf37f75b36214f0e8aa3a7d6dbc1Nicolas Capens				data->X0x16 = replicate(X0 * 16 - 8);
5795491cb48df1edf37f75b36214f0e8aa3a7d6dbc1Nicolas Capens				data->Y0x16 = replicate(Y0 * 16 - 8);
580894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->XXXX = replicate(X[s][q] / W);
581894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->YYYY = replicate(Y[s][q] / H);
58219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				data->halfPixelX = replicate(0.5f / W);
58319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				data->halfPixelY = replicate(0.5f / H);
58419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				data->viewportHeight = abs(viewport.height);
585894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->slopeDepthBias = slopeDepthBias;
586894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->depthRange = Z;
587894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				data->depthNear = N;
588894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw->clipFlags = clipFlags;
589894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
590894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(clipFlags)
591894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
592894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(clipFlags & Clipper::CLIP_PLANE0) data->clipPlane[0] = clipPlane[0];
593894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(clipFlags & Clipper::CLIP_PLANE1) data->clipPlane[1] = clipPlane[1];
594894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(clipFlags & Clipper::CLIP_PLANE2) data->clipPlane[2] = clipPlane[2];
595894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(clipFlags & Clipper::CLIP_PLANE3) data->clipPlane[3] = clipPlane[3];
596894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(clipFlags & Clipper::CLIP_PLANE4) data->clipPlane[4] = clipPlane[4];
597894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(clipFlags & Clipper::CLIP_PLANE5) data->clipPlane[5] = clipPlane[5];
598894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
599894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
600894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
601894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			// Target
602894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
603fe7a45ceacce06e70a0dc6005873354d1af4c54eAlexis Hetu				for(int index = 0; index < RENDERTARGETS; index++)
604894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
605894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw->renderTarget[index] = context->renderTarget[index];
606894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
607894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(draw->renderTarget[index])
608894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
609894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->lockInternal(0, 0, q * ms, LOCK_READWRITE, MANAGED);
610894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						data->colorPitchB[index] = context->renderTarget[index]->getInternalPitchB();
611894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						data->colorSliceB[index] = context->renderTarget[index]->getInternalSliceB();
612894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
613894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
614894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
61525fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens				draw->depthBuffer = context->depthBuffer;
61625fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens				draw->stencilBuffer = context->stencilBuffer;
617894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
61825fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens				if(draw->depthBuffer)
619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
62025fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens					data->depthBuffer = (float*)context->depthBuffer->lockInternal(0, 0, q * ms, LOCK_READWRITE, MANAGED);
62125fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens					data->depthPitchB = context->depthBuffer->getInternalPitchB();
62225fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens					data->depthSliceB = context->depthBuffer->getInternalSliceB();
62325fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens				}
624894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
62525fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens				if(draw->stencilBuffer)
62625fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens				{
62725fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens					data->stencilBuffer = (unsigned char*)context->stencilBuffer->lockStencil(q * ms, MANAGED);
62825fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens					data->stencilPitchB = context->stencilBuffer->getStencilPitchB();
62925fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens					data->stencilSliceB = context->stencilBuffer->getStencilSliceB();
630894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
631894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
632894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
63319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			// Scissor
63419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			{
63519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				data->scissorX0 = scissor.x0;
63619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				data->scissorX1 = scissor.x1;
63719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				data->scissorY0 = scissor.y0;
63819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				data->scissorY1 = scissor.y1;
63919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			}
64019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
641894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->primitive = 0;
642894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->count = count;
643894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
644894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			draw->references = (count + batch - 1) / batch;
645894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
646ebe676496450066253da95a9e0b2f8885d58be38Nicolas Capens			schedulerMutex.lock();
647894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			nextDraw++;
648ebe676496450066253da95a9e0b2f8885d58be38Nicolas Capens			schedulerMutex.unlock();
649894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
65020248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens			if(threadCount > 1)
651894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
65220248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens				if(!threadsAwake)
65320248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens				{
65420248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens					suspend[0]->wait();
65520248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens
65620248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens					threadsAwake = 1;
65720248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens					task[0].type = Task::RESUME;
658894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
65920248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens					resume[0]->signal();
66020248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens				}
66120248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens			}
66220248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens			else   // Use main thread for draw execution
66320248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens			{
664894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				threadsAwake = 1;
665894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				task[0].type = Task::RESUME;
666894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
66720248ddbef2b78d69d5f1ea3d5df569f9835b94fNicolas Capens				taskLoop(0);
668894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
669894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
670894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
671894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
672894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::threadFunction(void *parameters)
673894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
674894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Renderer *renderer = static_cast<Parameters*>(parameters)->renderer;
675894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int threadIndex = static_cast<Parameters*>(parameters)->threadIndex;
676894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
677894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(logPrecision < IEEE)
678894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
67966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			CPUID::setFlushToZero(true);
68066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			CPUID::setDenormalsAreZero(true);
681894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
682894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
683894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		renderer->threadLoop(threadIndex);
684894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
685894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
686894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::threadLoop(int threadIndex)
687894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
688894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		while(!exitThreads)
689894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
690894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			taskLoop(threadIndex);
691894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
692894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			suspend[threadIndex]->signal();
693894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			resume[threadIndex]->wait();
694894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
695894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
696894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
697894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::taskLoop(int threadIndex)
698894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
699894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		while(task[threadIndex].type != Task::SUSPEND)
700894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
701894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			scheduleTask(threadIndex);
702894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			executeTask(threadIndex);
703894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
704894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
705894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
706894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::findAvailableTasks()
707894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
708894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// Find pixel tasks
709894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int cluster = 0; cluster < clusterCount; cluster++)
710894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
711894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(!pixelProgress[cluster].executing)
712894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
713894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int unit = 0; unit < unitCount; unit++)
714894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
715894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(primitiveProgress[unit].references > 0)   // Contains processed primitives
716894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
717894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						if(pixelProgress[cluster].drawCall == primitiveProgress[unit].drawCall)
718894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
719894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							if(pixelProgress[cluster].processedPrimitives == primitiveProgress[unit].firstPrimitive)   // Previous primitives have been rendered
720894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							{
721894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman								Task &task = taskQueue[qHead];
722894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman								task.type = Task::PIXELS;
723894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman								task.primitiveUnit = unit;
724894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman								task.pixelCluster = cluster;
725894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
726894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman								pixelProgress[cluster].executing = true;
727894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
728894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman								// Commit to the task queue
729894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman								qHead = (qHead + 1) % 32;
730894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman								qSize++;
731894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
732894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman								break;
733894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							}
734894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
735894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
736894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
737894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
738894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
739579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
740894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// Find primitive tasks
741894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(currentDraw == nextDraw)
742894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
743894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return;   // No more primitives to process
744894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
745894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
746894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int unit = 0; unit < unitCount; unit++)
747894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
748894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			DrawCall *draw = drawList[currentDraw % DRAW_COUNT];
749894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
750894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(draw->primitive >= draw->count)
751894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
752894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				currentDraw++;
753894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
754894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(currentDraw == nextDraw)
755894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
756894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					return;   // No more primitives to process
757894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
758894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
759894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw = drawList[currentDraw % DRAW_COUNT];
760894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
761894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
762894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(!primitiveProgress[unit].references)   // Task not already being executed and not still in use by a pixel unit
763894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
764894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int primitive = draw->primitive;
765894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int count = draw->count;
766894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int batch = draw->batchSize;
767894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
768894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitiveProgress[unit].drawCall = currentDraw;
769894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitiveProgress[unit].firstPrimitive = primitive;
770894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitiveProgress[unit].primitiveCount = count - primitive >= batch ? batch : count - primitive;
771894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
772894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw->primitive += batch;
773894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
774894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				Task &task = taskQueue[qHead];
775894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				task.type = Task::PRIMITIVES;
776894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				task.primitiveUnit = unit;
777894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
778894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitiveProgress[unit].references = -1;
779894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
780894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				// Commit to the task queue
781894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				qHead = (qHead + 1) % 32;
782894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				qSize++;
783894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
784894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
785894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
786894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
787894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::scheduleTask(int threadIndex)
788894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
789ebe676496450066253da95a9e0b2f8885d58be38Nicolas Capens		schedulerMutex.lock();
790894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
791894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if((int)qSize < threadCount - threadsAwake + 1)
792894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
793894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			findAvailableTasks();
794894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
795894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
796894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(qSize != 0)
797894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
798894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			task[threadIndex] = taskQueue[(qHead - qSize) % 32];
799894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			qSize--;
800894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
801894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(threadsAwake != threadCount)
802894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
803894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int wakeup = qSize - threadsAwake + 1;
804894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
805894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				for(int i = 0; i < threadCount && wakeup > 0; i++)
806894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
807894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(task[i].type == Task::SUSPEND)
808894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
809894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						suspend[i]->wait();
810894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						task[i].type = Task::RESUME;
811894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						resume[i]->signal();
812894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
813894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						threadsAwake++;
814894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						wakeup--;
815894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
816894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
817894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
818894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
819894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
820894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
821894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			task[threadIndex].type = Task::SUSPEND;
822894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
823894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			threadsAwake--;
824894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
825894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
826ebe676496450066253da95a9e0b2f8885d58be38Nicolas Capens		schedulerMutex.unlock();
827894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
828894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
829894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::executeTask(int threadIndex)
830894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
831894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#if PERF_HUD
832894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int64_t startTick = Timer::ticks();
833894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#endif
834894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
835894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(task[threadIndex].type)
836894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
837894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		case Task::PRIMITIVES:
838894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
839894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int unit = task[threadIndex].primitiveUnit;
840579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
841894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int input = primitiveProgress[unit].firstPrimitive;
842894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int count = primitiveProgress[unit].primitiveCount;
843894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				DrawCall *draw = drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
84421d96b174d4d1153233c4465eb734928778c151aNicolas Capens				int (Renderer::*setupPrimitives)(int batch, int count) = draw->setupPrimitives;
845894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
846894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				processPrimitiveVertices(unit, input, count, draw->count, threadIndex);
847894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
848894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				#if PERF_HUD
849894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					int64_t time = Timer::ticks();
850894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					vertexTime[threadIndex] += time - startTick;
851894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					startTick = time;
852894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				#endif
853894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
85421d96b174d4d1153233c4465eb734928778c151aNicolas Capens				int visible = 0;
85521d96b174d4d1153233c4465eb734928778c151aNicolas Capens
85621d96b174d4d1153233c4465eb734928778c151aNicolas Capens				if(!draw->setupState.rasterizerDiscard)
85721d96b174d4d1153233c4465eb734928778c151aNicolas Capens				{
85821d96b174d4d1153233c4465eb734928778c151aNicolas Capens					visible = (this->*setupPrimitives)(unit, count);
85921d96b174d4d1153233c4465eb734928778c151aNicolas Capens				}
860894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
861894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitiveProgress[unit].visible = visible;
862894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitiveProgress[unit].references = clusterCount;
863894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
864894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				#if PERF_HUD
865894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					setupTime[threadIndex] += Timer::ticks() - startTick;
866894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				#endif
867894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
868894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
869894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		case Task::PIXELS:
870894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
871894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int unit = task[threadIndex].primitiveUnit;
872894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int visible = primitiveProgress[unit].visible;
873894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
874894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(visible > 0)
875894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
876894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					int cluster = task[threadIndex].pixelCluster;
877894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					Primitive *primitive = primitiveBatch[unit];
878894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					DrawCall *draw = drawList[pixelProgress[cluster].drawCall % DRAW_COUNT];
879894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					DrawData *data = draw->data;
880894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					PixelProcessor::RoutinePointer pixelRoutine = draw->pixelPointer;
881894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
882894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					pixelRoutine(primitive, visible, cluster, data);
883894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
884894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
885894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				finishRendering(task[threadIndex]);
886894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
887894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				#if PERF_HUD
888894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					pixelTime[threadIndex] += Timer::ticks() - startTick;
889894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				#endif
890894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
891894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
892894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		case Task::RESUME:
893894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
894894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		case Task::SUSPEND:
895894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
896894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		default:
897894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ASSERT(false);
898894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
899894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
900894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
90119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	void Renderer::synchronize()
90219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
90319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		sync->lock(sw::PUBLIC);
90419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		sync->unlock();
90519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
90619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
907894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::finishRendering(Task &pixelTask)
908894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
909894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int unit = pixelTask.primitiveUnit;
910894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int cluster = pixelTask.pixelCluster;
911894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
912894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
913894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		DrawData &data = *draw.data;
914894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int primitive = primitiveProgress[unit].firstPrimitive;
915894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int count = primitiveProgress[unit].primitiveCount;
91677139bf9734624e893bda673f68853d89f48ccadAlexis Hetu		int processedPrimitives = primitive + count;
917894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
91877139bf9734624e893bda673f68853d89f48ccadAlexis Hetu		pixelProgress[cluster].processedPrimitives = processedPrimitives;
919894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
920540564c79c7e43ec8b2538ddbd8ed9a7fc2ae18eNicolas Capens		if(pixelProgress[cluster].processedPrimitives >= draw.count)
921540564c79c7e43ec8b2538ddbd8ed9a7fc2ae18eNicolas Capens		{
922540564c79c7e43ec8b2538ddbd8ed9a7fc2ae18eNicolas Capens			pixelProgress[cluster].drawCall++;
923540564c79c7e43ec8b2538ddbd8ed9a7fc2ae18eNicolas Capens			pixelProgress[cluster].processedPrimitives = 0;
924540564c79c7e43ec8b2538ddbd8ed9a7fc2ae18eNicolas Capens		}
925540564c79c7e43ec8b2538ddbd8ed9a7fc2ae18eNicolas Capens
92666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman		int ref = atomicDecrement(&primitiveProgress[unit].references);
927894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
928894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(ref == 0)
929894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
93066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			ref = atomicDecrement(&draw.references);
931894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
932894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(ref == 0)
933894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
934894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				#if PERF_PROFILE
935894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					for(int cluster = 0; cluster < clusterCount; cluster++)
936894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
937894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						for(int i = 0; i < PERF_TIMERS; i++)
938894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
939894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman							profiler.cycles[i] += data.cycles[i][cluster];
940894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
941894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
942894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				#endif
943894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
944894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(draw.queries)
945894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
946894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					for(std::list<Query*>::iterator q = draw.queries->begin(); q != draw.queries->end(); q++)
947894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
948894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						Query *query = *q;
949894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
95020a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu						switch(query->type)
951894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						{
95220a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu						case Query::FRAGMENTS_PASSED:
95320a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu							for(int cluster = 0; cluster < clusterCount; cluster++)
95420a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu							{
95520a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu								atomicAdd((volatile int*)&query->data, data.occlusion[cluster]);
95620a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu							}
95720a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu							break;
95820a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu						case Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
95977139bf9734624e893bda673f68853d89f48ccadAlexis Hetu							atomicAdd((volatile int*)&query->data, processedPrimitives);
96020a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu							break;
96120a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu						default:
96220a1d922af662b686afa42a3854d140a1eded72cAlexis Hetu							break;
963894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						}
964894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
96566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman						atomicDecrement(&query->reference);
966894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
967894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
968894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					delete draw.queries;
969894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw.queries = 0;
970894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
971894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
972fe7a45ceacce06e70a0dc6005873354d1af4c54eAlexis Hetu				for(int i = 0; i < RENDERTARGETS; i++)
973894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
974894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(draw.renderTarget[i])
975894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
976894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						draw.renderTarget[i]->unlockInternal();
977894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
978894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
979894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
98025fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens				if(draw.depthBuffer)
98125fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens				{
98225fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens					draw.depthBuffer->unlockInternal();
98325fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens				}
98425fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens
98525fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens				if(draw.stencilBuffer)
986894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
98725fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens					draw.stencilBuffer->unlockStencil();
988894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
989894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
9900b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu				for(int i = 0; i < TOTAL_IMAGE_UNITS; i++)
991894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
992894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(draw.texture[i])
993894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
994894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						draw.texture[i]->unlock();
995894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
996894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
997894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
998502836a8df8985544667325ad0fb44d3ac0f40e3Nicolas Capens				for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
999894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1000894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					if(draw.vertexStream[i])
1001894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
1002894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						draw.vertexStream[i]->unlock();
1003894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
1004894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1005894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1006894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(draw.indexBuffer)
1007894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1008894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					draw.indexBuffer->unlock();
1009894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1010894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
10116411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
10126411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				{
10136411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					if(draw.pUniformBuffers[i])
10146411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					{
10156411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu						draw.pUniformBuffers[i]->unlock();
10166411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					}
10176411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					if(draw.vUniformBuffers[i])
10186411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					{
10196411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu						draw.vUniformBuffers[i]->unlock();
10206411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					}
10216411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				}
10226411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu
10236411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
10246411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				{
10256411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					if(draw.transformFeedbackBuffers[i])
10266411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					{
10276411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu						draw.transformFeedbackBuffers[i]->unlock();
10286411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu					}
10296411e04f9508108af2ec2406d788a31da19e523bAlexis Hetu				}
103008a111aa53596b17f2b405ee28fafe0aad4e6027Alexis Hetu
1031894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw.vertexRoutine->unbind();
1032894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw.setupRoutine->unbind();
1033894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw.pixelRoutine->unbind();
1034894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
103519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				sync->unlock();
103619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1037894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				draw.references = -1;
1038894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				resumeApp->signal();
1039894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1040894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1041894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1042894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		pixelProgress[cluster].executing = false;
1043894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1044894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1045c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens	void Renderer::processPrimitiveVertices(int unit, unsigned int start, unsigned int triangleCount, unsigned int loop, int thread)
1046894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1047894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Triangle *triangle = triangleBatch[unit];
1048894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		DrawCall *draw = drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
1049894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		DrawData *data = draw->data;
1050894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		VertexTask *task = vertexTask[thread];
1051894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1052894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const void *indices = data->indices;
1053894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		VertexProcessor::RoutinePointer vertexRoutine = draw->vertexPointer;
1054894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1055894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(task->vertexCache.drawCall != primitiveProgress[unit].drawCall)
1056894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1057894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			task->vertexCache.clear();
1058894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			task->vertexCache.drawCall = primitiveProgress[unit].drawCall;
1059894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1060894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1061894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		unsigned int batch[128][3];   // FIXME: Adjust to dynamic batch size
1062894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1063894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		switch(draw->drawType)
1064894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1065a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_POINTLIST:
1066894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1067894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				unsigned int index = start;
1068894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1069c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1070894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1071894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index;
1072894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index;
1073894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index;
1074894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1075894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1076894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1077894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1078894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1079a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_LINELIST:
1080894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1081894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				unsigned int index = 2 * start;
1082894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1083c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1084894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1085894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index + 0;
1086894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index + 1;
1087894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index + 1;
1088894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1089894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 2;
1090894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1091894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1092894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1093a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_LINESTRIP:
1094894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1095894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				unsigned int index = start;
1096894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1097c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1098894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1099894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index + 0;
1100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index + 1;
1101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index + 1;
1102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1107a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_LINELOOP:
1108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				unsigned int index = start;
1110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1111c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = (index + 0) % loop;
1114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = (index + 1) % loop;
1115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = (index + 1) % loop;
1116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1121a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_TRIANGLELIST:
1122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				unsigned int index = 3 * start;
1124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1125c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index + 0;
1128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index + 1;
1129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index + 2;
1130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 3;
1132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1135a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_TRIANGLESTRIP:
1136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				unsigned int index = start;
1138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1139c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index + 0;
1142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index + (index & 1) + 1;
1143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index + (~index & 1) + 1;
1144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1149a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_TRIANGLEFAN:
1150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				unsigned int index = start;
1152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1153c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index + 1;
1156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index + 2;
1157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = 0;
1158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1163a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDPOINTLIST8:
1164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned char *index = (const unsigned char*)indices + start;
1166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1167c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = *index;
1170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = *index;
1171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = *index;
1172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1177a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDPOINTLIST16:
1178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned short *index = (const unsigned short*)indices + start;
1180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1181c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = *index;
1184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = *index;
1185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = *index;
1186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1191a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDPOINTLIST32:
1192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned int *index = (const unsigned int*)indices + start;
1194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1195c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = *index;
1198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = *index;
1199894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = *index;
1200894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1205a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDLINELIST8:
1206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned char *index = (const unsigned char*)indices + 2 * start;
1208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1209c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[1];
1213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[1];
1214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 2;
1216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1218894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1219a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDLINELIST16:
1220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned short *index = (const unsigned short*)indices + 2 * start;
1222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1223c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1224894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1225894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1226894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[1];
1227894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[1];
1228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 2;
1230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1232894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1233a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDLINELIST32:
1234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1235894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned int *index = (const unsigned int*)indices + 2 * start;
1236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1237c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1238894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1239894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1240894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[1];
1241894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[1];
1242894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1243894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 2;
1244894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1245894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1246894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1247a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDLINESTRIP8:
1248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned char *index = (const unsigned char*)indices + start;
1250894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1251c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1254894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[1];
1255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[1];
1256894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1258894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1260894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1261a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDLINESTRIP16:
1262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1263894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned short *index = (const unsigned short*)indices + start;
1264894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1265c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1267894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[1];
1269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[1];
1270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1271894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1273894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1274894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1275a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDLINESTRIP32:
1276894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned int *index = (const unsigned int*)indices + start;
1278894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1279c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1280894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[1];
1283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[1];
1284894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1287894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1288894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1289a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDLINELOOP8:
1290894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
129166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman				const unsigned char *index = (const unsigned char*)indices;
1292894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1293c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1294894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
129566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					batch[i][0] = index[(start + i + 0) % loop];
129666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					batch[i][1] = index[(start + i + 1) % loop];
129766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					batch[i][2] = index[(start + i + 1) % loop];
1298894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1300894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1301a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDLINELOOP16:
1302894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
130366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman				const unsigned short *index = (const unsigned short*)indices;
1304894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1305c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1306894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
130766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					batch[i][0] = index[(start + i + 0) % loop];
130866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					batch[i][1] = index[(start + i + 1) % loop];
130966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					batch[i][2] = index[(start + i + 1) % loop];
1310894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1311894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1312894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1313a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDLINELOOP32:
1314894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
131566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman				const unsigned int *index = (const unsigned int*)indices;
1316894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1317c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1318894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
131966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					batch[i][0] = index[(start + i + 0) % loop];
132066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					batch[i][1] = index[(start + i + 1) % loop];
132166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman					batch[i][2] = index[(start + i + 1) % loop];
1322894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1324894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1325a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDTRIANGLELIST8:
1326894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1327894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned char *index = (const unsigned char*)indices + 3 * start;
1328894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1329c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1330894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1331894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1332894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[1];
1333894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[2];
1334894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1335894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 3;
1336894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1337894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1338894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1339a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDTRIANGLELIST16:
1340894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1341894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned short *index = (const unsigned short*)indices + 3 * start;
1342894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1343c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1344894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1345894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1346894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[1];
1347894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[2];
1348894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1349894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 3;
1350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1351894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1352894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1353a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDTRIANGLELIST32:
1354894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned int *index = (const unsigned int*)indices + 3 * start;
1356894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1357c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1358894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1360894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[1];
1361894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[2];
1362894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1363894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 3;
1364894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1365894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1367a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDTRIANGLESTRIP8:
1368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1369894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned char *index = (const unsigned char*)indices + start;
1370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1371c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1373894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1374894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[((start + i) & 1) + 1];
1375894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[(~(start + i) & 1) + 1];
1376894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1377894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1378894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1379894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1380894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1381a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDTRIANGLESTRIP16:
1382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned short *index = (const unsigned short*)indices + start;
1384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1385c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1386894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1387894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1388894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[((start + i) & 1) + 1];
1389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[(~(start + i) & 1) + 1];
1390894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1393894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1394894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1395a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDTRIANGLESTRIP32:
1396894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1397894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned int *index = (const unsigned int*)indices + start;
1398894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1399c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1400894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1401894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[0];
1402894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[((start + i) & 1) + 1];
1403894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[(~(start + i) & 1) + 1];
1404894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1405894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					index += 1;
1406894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1407894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1408894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1409a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDTRIANGLEFAN8:
1410894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1411894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned char *index = (const unsigned char*)indices;
1412894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1413c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1414894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1415894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[start + i + 1];
1416894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[start + i + 2];
1417894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[0];
1418894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1419894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1420894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1421a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDTRIANGLEFAN16:
1422894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1423894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned short *index = (const unsigned short*)indices;
1424894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1425c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1426894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1427894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[start + i + 1];
1428894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[start + i + 2];
1429894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[0];
1430894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1431894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1432894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1433a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		case DRAW_INDEXEDTRIANGLEFAN32:
1434894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1435894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				const unsigned int *index = (const unsigned int*)indices;
1436894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1437c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i++)
1438894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1439894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][0] = index[start + i + 1];
1440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][1] = index[start + i + 2];
1441894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					batch[i][2] = index[0];
1442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1443894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			break;
1445d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		case DRAW_QUADLIST:
1446c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens			{
1447c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				unsigned int index = 4 * start / 2;
1448c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens
1449c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				for(unsigned int i = 0; i < triangleCount; i += 2)
1450c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				{
1451c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens					batch[i+0][0] = index + 0;
1452c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens					batch[i+0][1] = index + 1;
1453c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens					batch[i+0][2] = index + 2;
1454c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens
1455d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens					batch[i+1][0] = index + 0;
1456c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens					batch[i+1][1] = index + 2;
1457c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens					batch[i+1][2] = index + 3;
1458c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens
1459c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens					index += 4;
1460c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens				}
1461c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens			}
1462c50d35d420645b1e0890f50cd4e2587c36e78f96Nicolas Capens			break;
1463894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		default:
1464894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			ASSERT(false);
1465622dca62c556bcfeab005964b0a464db66d473c2Nicolas Capens			return;
1466894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1467894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1468ef0505797c620e5115fff2b614d4c6ea017babcdAlexis Hetu		task->primitiveStart = start;
1469d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens		task->vertexCount = triangleCount * 3;
1470894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		vertexRoutine(&triangle->v0, (unsigned int*)&batch, task, data);
1471894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1472894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
147321d96b174d4d1153233c4465eb734928778c151aNicolas Capens	int Renderer::setupSolidTriangles(int unit, int count)
1474894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
147521d96b174d4d1153233c4465eb734928778c151aNicolas Capens		Triangle *triangle = triangleBatch[unit];
147621d96b174d4d1153233c4465eb734928778c151aNicolas Capens		Primitive *primitive = primitiveBatch[unit];
1477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
147821d96b174d4d1153233c4465eb734928778c151aNicolas Capens		DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
1479894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		SetupProcessor::State &state = draw.setupState;
1480894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
1481894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1482894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int ms = state.multiSample;
1483894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int pos = state.positionRegister;
1484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const DrawData *data = draw.data;
1485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int visible = 0;
1486894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < count; i++, triangle++)
1488894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1489894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Vertex &v0 = triangle->v0;
1490894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Vertex &v1 = triangle->v1;
1491894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Vertex &v2 = triangle->v2;
1492894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1493894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if((v0.clipFlags & v1.clipFlags & v2.clipFlags) == Clipper::CLIP_FINITE)
1494894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1495894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				Polygon polygon(&v0.v[pos], &v1.v[pos], &v2.v[pos]);
1496894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1497894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int clipFlagsOr = v0.clipFlags | v1.clipFlags | v2.clipFlags | draw.clipFlags;
1498894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1499894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(clipFlagsOr != Clipper::CLIP_FINITE)
1500894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
150121d96b174d4d1153233c4465eb734928778c151aNicolas Capens					if(!clipper->clip(polygon, clipFlagsOr, draw))
1502894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
1503894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						continue;
1504894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
1505894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1506894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1507894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(setupRoutine(primitive, triangle, &polygon, data))
1508894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1509894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					primitive += ms;
1510894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					visible++;
1511894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1512894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1513894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1514894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1515894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return visible;
1516894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1517894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
151821d96b174d4d1153233c4465eb734928778c151aNicolas Capens	int Renderer::setupWireframeTriangle(int unit, int count)
1519894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
152021d96b174d4d1153233c4465eb734928778c151aNicolas Capens		Triangle *triangle = triangleBatch[unit];
152121d96b174d4d1153233c4465eb734928778c151aNicolas Capens		Primitive *primitive = primitiveBatch[unit];
1522894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int visible = 0;
1523894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
152421d96b174d4d1153233c4465eb734928778c151aNicolas Capens		DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
1525894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		SetupProcessor::State &state = draw.setupState;
1526894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		SetupProcessor::RoutinePointer setupRoutine = draw.setupPointer;
1527894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1528894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const Vertex &v0 = triangle[0].v0;
1529894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const Vertex &v1 = triangle[0].v1;
1530894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const Vertex &v2 = triangle[0].v2;
1531894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1532894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		float d = (v0.y * v1.x - v0.x * v1.y) * v2.w + (v0.x * v2.y - v0.y * v2.x) * v1.w + (v2.x * v1.y - v1.x * v2.y) * v0.w;
1533894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1534a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		if(state.cullMode == CULL_CLOCKWISE)
1535894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1536894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(d >= 0) return 0;
1537894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1538a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		else if(state.cullMode == CULL_COUNTERCLOCKWISE)
1539894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1540894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(d <= 0) return 0;
1541894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1542894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1543894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// Copy attributes
1544894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		triangle[1].v0 = v1;
1545894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		triangle[1].v1 = v2;
1546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		triangle[2].v0 = v2;
1547894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		triangle[2].v1 = v0;
1548894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1549894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(state.color[0][0].flat)   // FIXME
1550894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1551894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int i = 0; i < 2; i++)
1552894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1553894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				triangle[1].v0.C[i] = triangle[0].v0.C[i];
155466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman				triangle[1].v1.C[i] = triangle[0].v0.C[i];
1555894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				triangle[2].v0.C[i] = triangle[0].v0.C[i];
155666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman				triangle[2].v1.C[i] = triangle[0].v0.C[i];
1557894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1558894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1559894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1560894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < 3; i++)
1561894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
156221d96b174d4d1153233c4465eb734928778c151aNicolas Capens			if(setupLine(*primitive, *triangle, draw))
1563894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1564894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitive->area = 0.5f * d;
1565894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1566894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitive++;
1567894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				visible++;
1568894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1569894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1570894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			triangle++;
1571894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1572894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1573894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return visible;
1574894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1575579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
157621d96b174d4d1153233c4465eb734928778c151aNicolas Capens	int Renderer::setupVertexTriangle(int unit, int count)
1577894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
157821d96b174d4d1153233c4465eb734928778c151aNicolas Capens		Triangle *triangle = triangleBatch[unit];
157921d96b174d4d1153233c4465eb734928778c151aNicolas Capens		Primitive *primitive = primitiveBatch[unit];
1580894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int visible = 0;
1581894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
158221d96b174d4d1153233c4465eb734928778c151aNicolas Capens		DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
1583894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		SetupProcessor::State &state = draw.setupState;
1584894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1585894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const Vertex &v0 = triangle[0].v0;
1586894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const Vertex &v1 = triangle[0].v1;
1587894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const Vertex &v2 = triangle[0].v2;
1588894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1589894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		float d = (v0.y * v1.x - v0.x * v1.y) * v2.w + (v0.x * v2.y - v0.y * v2.x) * v1.w + (v2.x * v1.y - v1.x * v2.y) * v0.w;
1590894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1591a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		if(state.cullMode == CULL_CLOCKWISE)
1592894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1593894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(d >= 0) return 0;
1594894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1595a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens		else if(state.cullMode == CULL_COUNTERCLOCKWISE)
1596894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1597894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(d <= 0) return 0;
1598894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1599894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1600894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		// Copy attributes
1601894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		triangle[1].v0 = v1;
1602894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		triangle[2].v0 = v2;
1603894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1604894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < 3; i++)
1605894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
160621d96b174d4d1153233c4465eb734928778c151aNicolas Capens			if(setupPoint(*primitive, *triangle, draw))
1607894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1608894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitive->area = 0.5f * d;
1609894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1610894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitive++;
1611894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				visible++;
1612894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1613894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1614894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			triangle++;
1615894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1616894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1617894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return visible;
1618894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
162021d96b174d4d1153233c4465eb734928778c151aNicolas Capens	int Renderer::setupLines(int unit, int count)
1621894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
162221d96b174d4d1153233c4465eb734928778c151aNicolas Capens		Triangle *triangle = triangleBatch[unit];
162321d96b174d4d1153233c4465eb734928778c151aNicolas Capens		Primitive *primitive = primitiveBatch[unit];
1624894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int visible = 0;
1625894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
162621d96b174d4d1153233c4465eb734928778c151aNicolas Capens		DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
1627894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		SetupProcessor::State &state = draw.setupState;
1628894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1629894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int ms = state.multiSample;
1630894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1631894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < count; i++)
1632894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
163321d96b174d4d1153233c4465eb734928778c151aNicolas Capens			if(setupLine(*primitive, *triangle, draw))
1634894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1635894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitive += ms;
1636894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				visible++;
1637894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1638894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1639894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			triangle++;
1640894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1641894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1642894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return visible;
1643894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1644894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
164521d96b174d4d1153233c4465eb734928778c151aNicolas Capens	int Renderer::setupPoints(int unit, int count)
1646894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
164721d96b174d4d1153233c4465eb734928778c151aNicolas Capens		Triangle *triangle = triangleBatch[unit];
164821d96b174d4d1153233c4465eb734928778c151aNicolas Capens		Primitive *primitive = primitiveBatch[unit];
1649894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int visible = 0;
1650894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
165121d96b174d4d1153233c4465eb734928778c151aNicolas Capens		DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
1652894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		SetupProcessor::State &state = draw.setupState;
1653894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1654894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int ms = state.multiSample;
1655894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1656894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < count; i++)
1657894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
165821d96b174d4d1153233c4465eb734928778c151aNicolas Capens			if(setupPoint(*primitive, *triangle, draw))
1659894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1660894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				primitive += ms;
1661894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				visible++;
1662894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1663894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1664894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			triangle++;
1665894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1666894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1667894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return visible;
1668894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1669894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
167021d96b174d4d1153233c4465eb734928778c151aNicolas Capens	bool Renderer::setupLine(Primitive &primitive, Triangle &triangle, const DrawCall &draw)
1671894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1672894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
1673894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const SetupProcessor::State &state = draw.setupState;
1674894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const DrawData &data = *draw.data;
1675894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1676235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens		float lineWidth = data.lineWidth;
1677235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens
1678894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Vertex &v0 = triangle.v0;
1679894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Vertex &v1 = triangle.v1;
1680894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1681894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int pos = state.positionRegister;
1682894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1683894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const float4 &P0 = v0.v[pos];
1684894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const float4 &P1 = v1.v[pos];
1685894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1686894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(P0.w <= 0 && P1.w <= 0)
1687894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1688894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return false;
1689894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1690894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
169119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		const float W = data.Wx16[0] * (1.0f / 16.0f);
169219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		const float H = data.Hx16[0] * (1.0f / 16.0f);
1693894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1694894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		float dx = W * (P1.x / P1.w - P0.x / P0.w);
1695894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		float dy = H * (P1.y / P1.w - P0.y / P0.w);
1696894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1697894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(dx == 0 && dy == 0)
1698894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1699894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return false;
1700894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1701894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1702894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(false)   // Rectangle
1703894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1704894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			float4 P[4];
1705894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int C[4];
1706894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1707894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[0] = P0;
1708894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[1] = P1;
1709894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[2] = P1;
1710894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[3] = P0;
1711894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1712235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens			float scale = lineWidth * 0.5f / sqrt(dx*dx + dy*dy);
1713894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1714894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dx *= scale;
1715894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			dy *= scale;
1716894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1717894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			float dx0w = dx * P0.w / W;
1718894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			float dy0h = dy * P0.w / H;
1719894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			float dx0h = dx * P0.w / H;
1720894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			float dy0w = dy * P0.w / W;
1721894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1722894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			float dx1w = dx * P1.w / W;
1723894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			float dy1h = dy * P1.w / H;
1724894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			float dx1h = dx * P1.w / H;
1725894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			float dy1w = dy * P1.w / W;
1726894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
172719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[0].x += -dy0w + -dx0w;
172819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[0].y += -dx0h + +dy0h;
1729ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[0] = clipper->computeClipFlags(P[0]);
1730894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
173119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[1].x += -dy1w + +dx1w;
1732894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[1].y += -dx1h + +dy1h;
1733ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[1] = clipper->computeClipFlags(P[1]);
1734894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
173519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[2].x += +dy1w + +dx1w;
173619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[2].y += +dx1h + -dy1h;
1737ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[2] = clipper->computeClipFlags(P[2]);
1738894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
173919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[3].x += +dy0w + -dx0w;
174019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[3].y += +dx0h + +dy0h;
1741ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[3] = clipper->computeClipFlags(P[3]);
1742894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1743894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
1744894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1745894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				Polygon polygon(P, 4);
1746894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1747894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | draw.clipFlags;
1748894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1749894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(clipFlagsOr != Clipper::CLIP_FINITE)
1750894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
175121d96b174d4d1153233c4465eb734928778c151aNicolas Capens					if(!clipper->clip(polygon, clipFlagsOr, draw))
1752894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
1753894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						return false;
1754894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
1755894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1756894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1757894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				return setupRoutine(&primitive, &triangle, &polygon, &data);
1758894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1759894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1760894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else   // Diamond test convention
1761894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1762894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			float4 P[8];
1763894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int C[8];
1764894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1765894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[0] = P0;
1766894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[1] = P0;
1767894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[2] = P0;
1768894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[3] = P0;
1769894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[4] = P1;
1770894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[5] = P1;
1771894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[6] = P1;
1772894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[7] = P1;
1773894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1774235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens			float dx0 = lineWidth * 0.5f * P0.w / W;
1775235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens			float dy0 = lineWidth * 0.5f * P0.w / H;
1776894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1777235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens			float dx1 = lineWidth * 0.5f * P1.w / W;
1778235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens			float dy1 = lineWidth * 0.5f * P1.w / H;
1779894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1780894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[0].x += -dx0;
1781ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[0] = clipper->computeClipFlags(P[0]);
1782894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
178319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[1].y += +dy0;
1784ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[1] = clipper->computeClipFlags(P[1]);
1785894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1786894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[2].x += +dx0;
1787ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[2] = clipper->computeClipFlags(P[2]);
1788894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
178919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[3].y += -dy0;
1790ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[3] = clipper->computeClipFlags(P[3]);
1791894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1792894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[4].x += -dx1;
1793ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[4] = clipper->computeClipFlags(P[4]);
1794894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
179519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[5].y += +dy1;
1796ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[5] = clipper->computeClipFlags(P[5]);
1797894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1798894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			P[6].x += +dx1;
1799ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[6] = clipper->computeClipFlags(P[6]);
1800894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
180119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			P[7].y += -dy1;
1802ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens			C[7] = clipper->computeClipFlags(P[7]);
1803894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1804894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if((C[0] & C[1] & C[2] & C[3] & C[4] & C[5] & C[6] & C[7]) == Clipper::CLIP_FINITE)
1805894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1806894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				float4 L[6];
1807894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
180819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(dx > -dy)
1809894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
181019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dx > dy)   // Right
1811894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
1812894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[0] = P[0];
1813894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[1] = P[1];
1814894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[2] = P[5];
1815894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[3] = P[6];
1816894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[4] = P[7];
1817894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[5] = P[3];
1818894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
1819894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else   // Down
1820894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
1821894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[0] = P[0];
1822894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[1] = P[4];
1823894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[2] = P[5];
1824894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[3] = P[6];
1825894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[4] = P[2];
1826894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[5] = P[3];
1827894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
1828894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1829894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				else
1830894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
183119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman					if(dx > dy)   // Up
1832894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
1833894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[0] = P[0];
1834894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[1] = P[1];
1835894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[2] = P[2];
1836894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[3] = P[6];
1837894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[4] = P[7];
1838894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[5] = P[4];
1839894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
1840894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					else   // Left
1841894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
1842894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[0] = P[1];
1843894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[1] = P[2];
1844894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[2] = P[3];
1845894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[3] = P[7];
1846894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[4] = P[4];
1847894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						L[5] = P[5];
1848894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
1849894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1850894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1851894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				Polygon polygon(L, 6);
1852894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1853894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | C[4] | C[5] | C[6] | C[7] | draw.clipFlags;
1854894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1855894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(clipFlagsOr != Clipper::CLIP_FINITE)
1856894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
185721d96b174d4d1153233c4465eb734928778c151aNicolas Capens					if(!clipper->clip(polygon, clipFlagsOr, draw))
1858894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					{
1859894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman						return false;
1860894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					}
1861894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1862894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1863894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				return setupRoutine(&primitive, &triangle, &polygon, &data);
1864894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1865894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1866894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1867894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return false;
1868894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1869894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
187021d96b174d4d1153233c4465eb734928778c151aNicolas Capens	bool Renderer::setupPoint(Primitive &primitive, Triangle &triangle, const DrawCall &draw)
1871894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1872894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
1873894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const SetupProcessor::State &state = draw.setupState;
1874894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		const DrawData &data = *draw.data;
1875894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1876894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Vertex &v = triangle.v0;
1877894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1878894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		float pSize;
1879894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1880894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int pts = state.pointSizeRegister;
1881894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1882579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens		if(state.pointSizeRegister != Unused)
1883894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1884894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			pSize = v.v[pts].y;
1885894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1886894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
1887894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1888894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			pSize = data.point.pointSize[0];
1889894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1890894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1891894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		pSize = clamp(pSize, data.point.pointSizeMin, data.point.pointSizeMax);
1892894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1893894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		float4 P[4];
1894894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int C[4];
1895894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1896894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int pos = state.positionRegister;
1897894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1898894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		P[0] = v.v[pos];
1899894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		P[1] = v.v[pos];
1900894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		P[2] = v.v[pos];
1901894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		P[3] = v.v[pos];
1902894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
190319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		const float X = pSize * P[0].w * data.halfPixelX[0];
190419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		const float Y = pSize * P[0].w * data.halfPixelY[0];
1905894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1906894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		P[0].x -= X;
190719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		P[0].y += Y;
1908ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens		C[0] = clipper->computeClipFlags(P[0]);
1909894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1910894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		P[1].x += X;
191119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		P[1].y += Y;
1912ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens		C[1] = clipper->computeClipFlags(P[1]);
1913894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1914894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		P[2].x += X;
191519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		P[2].y -= Y;
1916ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens		C[2] = clipper->computeClipFlags(P[2]);
1917894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1918894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		P[3].x -= X;
191919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		P[3].y -= Y;
1920ce065365a9793bb7f1d39ac98ae0e08d0df58d22Nicolas Capens		C[3] = clipper->computeClipFlags(P[3]);
1921894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1922894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		triangle.v1 = triangle.v0;
1923894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		triangle.v2 = triangle.v0;
1924894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1925894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		triangle.v1.X += iround(16 * 0.5f * pSize);
192619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		triangle.v2.Y -= iround(16 * 0.5f * pSize) * (data.Hx16[0] > 0.0f ? 1 : -1);   // Both Direct3D and OpenGL expect (0, 0) in the top-left corner
1927894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1928894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		Polygon polygon(P, 4);
1929894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1930894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
1931894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1932894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			int clipFlagsOr = C[0] | C[1] | C[2] | C[3] | draw.clipFlags;
1933894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1934894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(clipFlagsOr != Clipper::CLIP_FINITE)
1935894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
193621d96b174d4d1153233c4465eb734928778c151aNicolas Capens				if(!clipper->clip(polygon, clipFlagsOr, draw))
1937894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				{
1938894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman					return false;
1939894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				}
1940894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
1941579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
1942894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return setupRoutine(&primitive, &triangle, &polygon, &data);
1943894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1944894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1945894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return false;
1946894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1947894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
19487381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens	void Renderer::initializeThreads()
1949894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
19507381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens		unitCount = ceilPow2(threadCount);
19517381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens		clusterCount = ceilPow2(threadCount);
1952894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1953894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < unitCount; i++)
1954894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1955894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			triangleBatch[i] = (Triangle*)allocate(batchSize * sizeof(Triangle));
1956894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			primitiveBatch[i] = (Primitive*)allocate(batchSize * sizeof(Primitive));
1957894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1958894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1959894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < threadCount; i++)
1960894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1961894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			vertexTask[i] = (VertexTask*)allocate(sizeof(VertexTask));
1962894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			vertexTask[i]->vertexCache.drawCall = -1;
1963894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1964894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			task[i].type = Task::SUSPEND;
1965894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1966894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			resume[i] = new Event();
1967894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			suspend[i] = new Event();
1968894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1969894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			Parameters parameters;
1970894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			parameters.threadIndex = i;
1971894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			parameters.renderer = this;
1972894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1973894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			exitThreads = false;
1974894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			worker[i] = new Thread(threadFunction, &parameters);
1975894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1976894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			suspend[i]->wait();
1977894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			suspend[i]->signal();
1978894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1979894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
1980894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1981894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::terminateThreads()
1982894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
1983894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		while(threadsAwake != 0)
1984894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
198519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			Thread::sleep(1);
1986894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
1987894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1988894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int thread = 0; thread < threadCount; thread++)
1989894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
1990894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(worker[thread])
1991894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
1992894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				exitThreads = true;
1993894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				resume[thread]->signal();
1994894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				worker[thread]->join();
1995579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
1996894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				delete worker[thread];
1997894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				worker[thread] = 0;
1998894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				delete resume[thread];
1999894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				resume[thread] = 0;
2000894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				delete suspend[thread];
2001894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				suspend[thread] = 0;
2002894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2003579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
2004894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			deallocate(vertexTask[thread]);
2005894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			vertexTask[thread] = 0;
2006894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2007894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2008894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < 16; i++)
2009894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2010894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			deallocate(triangleBatch[i]);
2011894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			triangleBatch[i] = 0;
2012894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2013894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			deallocate(primitiveBatch[i]);
2014894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			primitiveBatch[i] = 0;
2015894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2016894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2017894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2018894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::loadConstants(const VertexShader *vertexShader)
2019894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2020894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!vertexShader) return;
2021894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
20228dcce86d28f3823401ab5137cf38a3a332860940Alexis Hetu		size_t count = vertexShader->getLength();
2023894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2024903e025f6cd8d978f013c741431b87b04ae01fd1Alexis Hetu		for(size_t i = 0; i < count; i++)
2025894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
202619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			const Shader::Instruction *instruction = vertexShader->getInstruction(i);
2027894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
202819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(instruction->opcode == Shader::OPCODE_DEF)
2029894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
203019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				int index = instruction->dst.index;
2031894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				float value[4];
2032894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
203319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				value[0] = instruction->src[0].value[0];
203419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				value[1] = instruction->src[0].value[1];
203519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				value[2] = instruction->src[0].value[2];
203619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				value[3] = instruction->src[0].value[3];
2037894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2038894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				setVertexShaderConstantF(index, value);
2039894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
204019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else if(instruction->opcode == Shader::OPCODE_DEFI)
2041894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
204219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				int index = instruction->dst.index;
2043894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int integer[4];
2044894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
204519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				integer[0] = instruction->src[0].integer[0];
204619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				integer[1] = instruction->src[0].integer[1];
204719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				integer[2] = instruction->src[0].integer[2];
204819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				integer[3] = instruction->src[0].integer[3];
2049894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2050894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				setVertexShaderConstantI(index, integer);
2051894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
205219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else if(instruction->opcode == Shader::OPCODE_DEFB)
2053894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
205419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				int index = instruction->dst.index;
205519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				int boolean = instruction->src[0].boolean[0];
2056894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2057894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				setVertexShaderConstantB(index, &boolean);
2058894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2059894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2060894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2061894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2062894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::loadConstants(const PixelShader *pixelShader)
2063894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2064894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(!pixelShader) return;
2065894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
20668dcce86d28f3823401ab5137cf38a3a332860940Alexis Hetu		size_t count = pixelShader->getLength();
2067894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2068903e025f6cd8d978f013c741431b87b04ae01fd1Alexis Hetu		for(size_t i = 0; i < count; i++)
2069894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
207019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			const Shader::Instruction *instruction = pixelShader->getInstruction(i);
2071894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
207219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			if(instruction->opcode == Shader::OPCODE_DEF)
2073894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
207419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				int index = instruction->dst.index;
2075894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				float value[4];
2076894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
207719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				value[0] = instruction->src[0].value[0];
207819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				value[1] = instruction->src[0].value[1];
207919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				value[2] = instruction->src[0].value[2];
208019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				value[3] = instruction->src[0].value[3];
2081894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2082894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				setPixelShaderConstantF(index, value);
2083894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
208419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else if(instruction->opcode == Shader::OPCODE_DEFI)
2085894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
208619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				int index = instruction->dst.index;
2087894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				int integer[4];
2088894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
208919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				integer[0] = instruction->src[0].integer[0];
209019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				integer[1] = instruction->src[0].integer[1];
209119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				integer[2] = instruction->src[0].integer[2];
209219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				integer[3] = instruction->src[0].integer[3];
2093894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2094894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				setPixelShaderConstantI(index, integer);
2095894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
209619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman			else if(instruction->opcode == Shader::OPCODE_DEFB)
2097894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
209819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				int index = instruction->dst.index;
209919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				int boolean = instruction->src[0].boolean[0];
2100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				setPixelShaderConstantB(index, &boolean);
2102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setIndexBuffer(Resource *indexBuffer)
2107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		context->indexBuffer = indexBuffer;
2109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setMultiSampleMask(unsigned int mask)
2112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		context->sampleMask = mask;
2114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2116a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens	void Renderer::setTransparencyAntialiasing(TransparencyAntialiasing transparencyAntialiasing)
2117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		sw::transparencyAntialiasing = transparencyAntialiasing;
2119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	bool Renderer::isReadWriteTexture(int sampler)
2122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2123fe7a45ceacce06e70a0dc6005873354d1af4c54eAlexis Hetu		for(int index = 0; index < RENDERTARGETS; index++)
2124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(context->renderTarget[index] && context->texture[sampler] == context->renderTarget[index]->getResource())
2126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				return true;
2128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2130579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
213125fed3d8e90b5e1bea814c1f5d94be52834550d4Nicolas Capens		if(context->depthBuffer && context->texture[sampler] == context->depthBuffer->getResource())
2132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return true;
2134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		return false;
2137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2138579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
2139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::updateClipper()
2140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(updateClipPlanes)
2142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(VertexProcessor::isFixedFunction())   // User plane in world space
2144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
214519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				const Matrix &scissorWorld = getViewTransform();
2146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(clipFlags & Clipper::CLIP_PLANE0) clipPlane[0] = scissorWorld * userPlane[0];
2148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(clipFlags & Clipper::CLIP_PLANE1) clipPlane[1] = scissorWorld * userPlane[1];
2149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(clipFlags & Clipper::CLIP_PLANE2) clipPlane[2] = scissorWorld * userPlane[2];
2150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(clipFlags & Clipper::CLIP_PLANE3) clipPlane[3] = scissorWorld * userPlane[3];
2151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(clipFlags & Clipper::CLIP_PLANE4) clipPlane[4] = scissorWorld * userPlane[4];
2152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				if(clipFlags & Clipper::CLIP_PLANE5) clipPlane[5] = scissorWorld * userPlane[5];
2153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			else   // User plane in clip space
2155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
215619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(clipFlags & Clipper::CLIP_PLANE0) clipPlane[0] = userPlane[0];
215719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(clipFlags & Clipper::CLIP_PLANE1) clipPlane[1] = userPlane[1];
215819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(clipFlags & Clipper::CLIP_PLANE2) clipPlane[2] = userPlane[2];
215919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(clipFlags & Clipper::CLIP_PLANE3) clipPlane[3] = userPlane[3];
216019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(clipFlags & Clipper::CLIP_PLANE4) clipPlane[4] = userPlane[4];
216119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman				if(clipFlags & Clipper::CLIP_PLANE5) clipPlane[5] = userPlane[5];
2162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			updateClipPlanes = false;
2165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setTextureResource(unsigned int sampler, Resource *resource)
2169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
21700b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu		ASSERT(sampler < TOTAL_IMAGE_UNITS);
2171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		context->texture[sampler] = resource;
2173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setTextureLevel(unsigned int sampler, unsigned int face, unsigned int level, Surface *surface, TextureType type)
2176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
21770b65c5e3903233839197fd689895ba57b7f61a5bAlexis Hetu		ASSERT(sampler < TOTAL_IMAGE_UNITS && face < 6 && level < MIPMAP_LEVELS);
2178579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
2179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		context->sampler[sampler].setTextureLevel(face, level, surface, type);
2180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setTextureFilter(SamplerType type, int sampler, FilterType textureFilter)
2183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(type == SAMPLER_PIXEL)
2185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setTextureFilter(sampler, textureFilter);
2187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
2189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setTextureFilter(sampler, textureFilter);
2191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setMipmapFilter(SamplerType type, int sampler, MipmapType mipmapFilter)
2195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(type == SAMPLER_PIXEL)
2197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setMipmapFilter(sampler, mipmapFilter);
2199894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2200894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
2201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setMipmapFilter(sampler, mipmapFilter);
2203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2205894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setGatherEnable(SamplerType type, int sampler, bool enable)
2207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(type == SAMPLER_PIXEL)
2209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setGatherEnable(sampler, enable);
2211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
2213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setGatherEnable(sampler, enable);
2215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2218894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setAddressingModeU(SamplerType type, int sampler, AddressingMode addressMode)
2219894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(type == SAMPLER_PIXEL)
2221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setAddressingModeU(sampler, addressMode);
2223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2224894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
2225894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2226894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setAddressingModeU(sampler, addressMode);
2227894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setAddressingModeV(SamplerType type, int sampler, AddressingMode addressMode)
2231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2232894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(type == SAMPLER_PIXEL)
2233894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setAddressingModeV(sampler, addressMode);
2235894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
2237894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2238894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setAddressingModeV(sampler, addressMode);
2239894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2240894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2241894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2242894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setAddressingModeW(SamplerType type, int sampler, AddressingMode addressMode)
2243894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2244894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(type == SAMPLER_PIXEL)
2245894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2246894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setAddressingModeW(sampler, addressMode);
2247894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
2249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2250894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setAddressingModeW(sampler, addressMode);
2251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2254894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setReadSRGB(SamplerType type, int sampler, bool sRGB)
2255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2256894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(type == SAMPLER_PIXEL)
2257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2258894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setReadSRGB(sampler, sRGB);
2259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2260894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
2261894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setReadSRGB(sampler, sRGB);
2263894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2264894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setMipmapLOD(SamplerType type, int sampler, float bias)
2267894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(type == SAMPLER_PIXEL)
2269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setMipmapLOD(sampler, bias);
2271894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
2273894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2274894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setMipmapLOD(sampler, bias);
2275894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2276894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2278894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setBorderColor(SamplerType type, int sampler, const Color<float> &borderColor)
2279894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2280894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(type == SAMPLER_PIXEL)
2281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setBorderColor(sampler, borderColor);
2283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2284894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
2285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setBorderColor(sampler, borderColor);
2287894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2288894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2289894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2290617a5d5e704b17f14304017f263c8f15ee4d4bb5Alexis Hetu	void Renderer::setMaxAnisotropy(SamplerType type, int sampler, float maxAnisotropy)
2291894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2292894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(type == SAMPLER_PIXEL)
2293894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2294894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setMaxAnisotropy(sampler, maxAnisotropy);
2295894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2296894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else
2297894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2298894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setMaxAnisotropy(sampler, maxAnisotropy);
2299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2300894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2301894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
23021d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	void Renderer::setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR)
23031d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	{
23041d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		if(type == SAMPLER_PIXEL)
23051d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		{
23061d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu			PixelProcessor::setSwizzleR(sampler, swizzleR);
23071d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		}
23081d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		else
23091d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		{
23101d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu			VertexProcessor::setSwizzleR(sampler, swizzleR);
23111d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		}
23121d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	}
23131d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu
23141d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	void Renderer::setSwizzleG(SamplerType type, int sampler, SwizzleType swizzleG)
23151d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	{
23161d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		if(type == SAMPLER_PIXEL)
23171d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		{
23181d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu			PixelProcessor::setSwizzleG(sampler, swizzleG);
23191d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		}
23201d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		else
23211d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		{
23221d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu			VertexProcessor::setSwizzleG(sampler, swizzleG);
23231d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		}
23241d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	}
23251d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu
23261d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	void Renderer::setSwizzleB(SamplerType type, int sampler, SwizzleType swizzleB)
23271d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	{
23281d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		if(type == SAMPLER_PIXEL)
23291d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		{
23301d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu			PixelProcessor::setSwizzleB(sampler, swizzleB);
23311d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		}
23321d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		else
23331d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		{
23341d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu			VertexProcessor::setSwizzleB(sampler, swizzleB);
23351d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		}
23361d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	}
23371d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu
23381d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	void Renderer::setSwizzleA(SamplerType type, int sampler, SwizzleType swizzleA)
23391d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	{
23401d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		if(type == SAMPLER_PIXEL)
23411d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		{
23421d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu			PixelProcessor::setSwizzleA(sampler, swizzleA);
23431d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		}
23441d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		else
23451d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		{
23461d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu			VertexProcessor::setSwizzleA(sampler, swizzleA);
23471d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu		}
23481d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu	}
23491d01aa378d060eaca1fe4d7162d3721ed07c69f4Alexis Hetu
2350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setPointSpriteEnable(bool pointSpriteEnable)
2351894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2352894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		context->setPointSpriteEnable(pointSpriteEnable);
2353894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2354894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setPointScaleEnable(bool pointScaleEnable)
2356894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2357894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		context->setPointScaleEnable(pointScaleEnable);
2358894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2360235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens	void Renderer::setLineWidth(float width)
2361235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens	{
2362235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens		context->lineWidth = width;
2363235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens	}
2364235781d1c02eab8fd95b8b75a426837075ecd97aNicolas Capens
2365894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setDepthBias(float bias)
2366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2367894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		depthBias = bias;
2368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2369894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setSlopeDepthBias(float slopeBias)
2371894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		slopeDepthBias = slopeBias;
2373894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2374894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2375cab6414036dfa7ddd5650dbb2de45a640620115fAlexis Hetu	void Renderer::setRasterizerDiscard(bool rasterizerDiscard)
2376cab6414036dfa7ddd5650dbb2de45a640620115fAlexis Hetu	{
2377cab6414036dfa7ddd5650dbb2de45a640620115fAlexis Hetu		context->rasterizerDiscard = rasterizerDiscard;
2378cab6414036dfa7ddd5650dbb2de45a640620115fAlexis Hetu	}
2379cab6414036dfa7ddd5650dbb2de45a640620115fAlexis Hetu
2380894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setPixelShader(const PixelShader *shader)
2381894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		context->pixelShader = shader;
2383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loadConstants(shader);
2385894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2386894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2387894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setVertexShader(const VertexShader *shader)
2388894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		context->vertexShader = shader;
2390894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		loadConstants(shader);
2392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2393894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2394894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setPixelShaderConstantF(int index, const float value[4], int count)
2395894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2396894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < DRAW_COUNT; i++)
2397894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2398894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(drawCall[i]->psDirtyConstF < index + count)
2399894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2400894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				drawCall[i]->psDirtyConstF = index + count;
2401894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2402894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2403894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2404894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < count; i++)
2405894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2406894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setFloatConstant(index + i, value);
2407894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			value += 4;
2408894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2409894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2410894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2411894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setPixelShaderConstantI(int index, const int value[4], int count)
2412894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2413894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < DRAW_COUNT; i++)
2414894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2415894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(drawCall[i]->psDirtyConstI < index + count)
2416894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2417894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				drawCall[i]->psDirtyConstI = index + count;
2418894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2419894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2420894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2421894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < count; i++)
2422894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2423894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setIntegerConstant(index + i, value);
2424894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			value += 4;
2425894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2426894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2427894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2428894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setPixelShaderConstantB(int index, const int *boolean, int count)
2429894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2430894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < DRAW_COUNT; i++)
2431894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2432894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(drawCall[i]->psDirtyConstB < index + count)
2433894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2434894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				drawCall[i]->psDirtyConstB = index + count;
2435894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2436894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2437894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2438894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < count; i++)
2439894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setBooleanConstant(index + i, *boolean);
2441894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			boolean++;
2442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2443894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2445894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setVertexShaderConstantF(int index, const float value[4], int count)
2446894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2447894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < DRAW_COUNT; i++)
2448894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2449894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(drawCall[i]->vsDirtyConstF < index + count)
2450894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2451894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				drawCall[i]->vsDirtyConstF = index + count;
2452894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2453894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2454894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2455894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < count; i++)
2456894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2457894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setFloatConstant(index + i, value);
2458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			value += 4;
2459894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2460894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2461894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2462894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setVertexShaderConstantI(int index, const int value[4], int count)
2463894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2464894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < DRAW_COUNT; i++)
2465894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2466894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(drawCall[i]->vsDirtyConstI < index + count)
2467894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2468894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				drawCall[i]->vsDirtyConstI = index + count;
2469894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2470894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2471894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2472894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < count; i++)
2473894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2474894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setIntegerConstant(index + i, value);
2475894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			value += 4;
2476894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2478894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2479894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setVertexShaderConstantB(int index, const int *boolean, int count)
2480894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2481894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < DRAW_COUNT; i++)
2482894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2483894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			if(drawCall[i]->vsDirtyConstB < index + count)
2484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				drawCall[i]->vsDirtyConstB = index + count;
2486894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2488894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2489894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		for(int i = 0; i < count; i++)
2490894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2491894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setBooleanConstant(index + i, *boolean);
2492894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			boolean++;
2493894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2494894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2495894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2496894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setModelMatrix(const Matrix &M, int i)
2497894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2498894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		VertexProcessor::setModelMatrix(M, i);
2499894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2500894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2501894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setViewMatrix(const Matrix &V)
2502894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2503894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		VertexProcessor::setViewMatrix(V);
2504894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateClipPlanes = true;
2505894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2506894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2507894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setBaseMatrix(const Matrix &B)
2508894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2509894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		VertexProcessor::setBaseMatrix(B);
2510894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateClipPlanes = true;
2511894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2512894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2513894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setProjectionMatrix(const Matrix &P)
2514894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2515894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		VertexProcessor::setProjectionMatrix(P);
2516894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateClipPlanes = true;
2517894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2518894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2519894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::addQuery(Query *query)
2520894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2521894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		queries.push_back(query);
2522894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2523579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
2524894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::removeQuery(Query *query)
2525894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2526894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		queries.remove(query);
2527894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2528894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2529894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#if PERF_HUD
2530894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int Renderer::getThreadCount()
2531894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2532894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return threadCount;
2533894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2534579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
2535894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int64_t Renderer::getVertexTime(int thread)
2536894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2537894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return vertexTime[thread];
2538894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2539894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2540894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int64_t Renderer::getSetupTime(int thread)
2541894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2542894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return setupTime[thread];
2543894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2544579dc4f88eb1891b1d5c19556394df34abf6ff57Nicolas Capens
2545894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		int64_t Renderer::getPixelTime(int thread)
2546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2547894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			return pixelTime[thread];
2548894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2549894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2550894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		void Renderer::resetTimers()
2551894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2552894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int thread = 0; thread < threadCount; thread++)
2553894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2554894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				vertexTime[thread] = 0;
2555894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				setupTime[thread] = 0;
2556894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				pixelTime[thread] = 0;
2557894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2558894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2559894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	#endif
2560894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2561894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setViewport(const Viewport &viewport)
2562894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2563894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		this->viewport = viewport;
2564894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2565894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
256619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	void Renderer::setScissor(const Rect &scissor)
256719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	{
256819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		this->scissor = scissor;
256919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	}
257019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
2571894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setClipFlags(int flags)
2572894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2573894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		clipFlags = flags << 8;   // Bottom 8 bits used by legacy frustum
2574894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2575894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2576894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::setClipPlane(unsigned int index, const float plane[4])
2577894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2578d2264145fee8e92c2de8b5ba0d7f5527e6d555d3Nicolas Capens		if(index < MAX_CLIP_PLANES)
2579894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2580894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			userPlane[index] = plane;
2581894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
2582894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		else ASSERT(false);
2583894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2584894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		updateClipPlanes = true;
2585894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2586894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2587894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	void Renderer::updateConfiguration(bool initialUpdate)
2588894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	{
2589894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		bool newConfiguration = swiftConfig->hasNewConfiguration();
2590894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2591894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		if(newConfiguration || initialUpdate)
2592894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		{
2593894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			terminateThreads();
2594894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2595e14bbd4c4b6fe47908b776f83ead99bec0d13314Nicolas Capens			SwiftConfig::Configuration configuration = {};
2596894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			swiftConfig->getConfiguration(configuration);
2597894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
259866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			precacheVertex = !newConfiguration && configuration.precache;
259966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			precacheSetup = !newConfiguration && configuration.precache;
260066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman			precachePixel = !newConfiguration && configuration.precache;
260166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman
2602894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			VertexProcessor::setRoutineCacheSize(configuration.vertexRoutineCacheSize);
2603894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			PixelProcessor::setRoutineCacheSize(configuration.pixelRoutineCacheSize);
2604894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			SetupProcessor::setRoutineCacheSize(configuration.setupRoutineCacheSize);
2605894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2606894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			switch(configuration.textureSampleQuality)
2607894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
26087381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens			case 0:  Sampler::setFilterQuality(FILTER_POINT);       break;
26097381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens			case 1:  Sampler::setFilterQuality(FILTER_LINEAR);      break;
26107381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens			case 2:  Sampler::setFilterQuality(FILTER_ANISOTROPIC); break;
26117381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens			default: Sampler::setFilterQuality(FILTER_ANISOTROPIC); break;
2612894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2613894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2614894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			switch(configuration.mipmapQuality)
2615894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2616894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 0:  Sampler::setMipmapQuality(MIPMAP_POINT);  break;
2617894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 1:  Sampler::setMipmapQuality(MIPMAP_LINEAR); break;
26187381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens			default: Sampler::setMipmapQuality(MIPMAP_LINEAR); break;
2619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2620894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2621894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			setPerspectiveCorrection(configuration.perspectiveCorrection);
2622894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2623894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			switch(configuration.transcendentalPrecision)
2624894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2625894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 0:
2626894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				logPrecision = APPROXIMATE;
2627894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				expPrecision = APPROXIMATE;
2628894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rcpPrecision = APPROXIMATE;
2629894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rsqPrecision = APPROXIMATE;
2630894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
2631894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 1:
2632894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				logPrecision = PARTIAL;
2633894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				expPrecision = PARTIAL;
2634894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rcpPrecision = PARTIAL;
2635894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rsqPrecision = PARTIAL;
2636894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
2637894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 2:
2638894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				logPrecision = ACCURATE;
2639894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				expPrecision = ACCURATE;
2640894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rcpPrecision = ACCURATE;
2641894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rsqPrecision = ACCURATE;
2642894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
2643894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 3:
2644894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				logPrecision = WHQL;
2645894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				expPrecision = WHQL;
2646894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rcpPrecision = WHQL;
2647894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rsqPrecision = WHQL;
2648894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
2649894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			case 4:
2650894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				logPrecision = IEEE;
2651894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				expPrecision = IEEE;
2652894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rcpPrecision = IEEE;
2653894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rsqPrecision = IEEE;
2654894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
2655894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			default:
2656894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				logPrecision = ACCURATE;
2657894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				expPrecision = ACCURATE;
2658894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rcpPrecision = ACCURATE;
2659894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				rsqPrecision = ACCURATE;
2660894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				break;
2661894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2662894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2663894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			switch(configuration.transparencyAntialiasing)
2664894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2665a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case 0:  transparencyAntialiasing = TRANSPARENCY_NONE;              break;
2666a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			case 1:  transparencyAntialiasing = TRANSPARENCY_ALPHA_TO_COVERAGE; break;
2667a0f4be852b65fe5b1f1b08673eac3761359a114cNicolas Capens			default: transparencyAntialiasing = TRANSPARENCY_NONE;              break;
2668894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2669894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2670894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			switch(configuration.threadCount)
2671894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
26727381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens			case -1: threadCount = CPUID::coreCount();        break;
26737381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens			case 0:  threadCount = CPUID::processAffinity();  break;
26747381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens			default: threadCount = configuration.threadCount; break;
2675894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2676894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2677894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			CPUID::setEnableSSE4_1(configuration.enableSSE4_1);
2678894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			CPUID::setEnableSSSE3(configuration.enableSSSE3);
2679894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			CPUID::setEnableSSE3(configuration.enableSSE3);
2680894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			CPUID::setEnableSSE2(configuration.enableSSE2);
2681894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			CPUID::setEnableSSE(configuration.enableSSE);
2682894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2683894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			for(int pass = 0; pass < 10; pass++)
2684894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			{
2685894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman				optimization[pass] = configuration.optimization[pass];
2686894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			}
2687894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2688894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			forceWindowed = configuration.forceWindowed;
2689894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			complementaryDepthBuffer = configuration.complementaryDepthBuffer;
2690894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			postBlendSRGB = configuration.postBlendSRGB;
2691894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			exactColorRounding = configuration.exactColorRounding;
2692894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			forceClearRegisters = configuration.forceClearRegisters;
2693894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2694894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#ifndef NDEBUG
2695894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			minPrimitives = configuration.minPrimitives;
2696894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman			maxPrimitives = configuration.maxPrimitives;
2697894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		#endif
2698894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman		}
26997381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens
27007381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens		if(!initialUpdate && !worker[0])
27017381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens		{
27027381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens			initializeThreads();
27037381c9940bd3db548cfdee455345c7b100fbe0c6Nicolas Capens		}
2704894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman	}
2705894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2706