blob: a309ea431727d180bae1a718f6db0451fd6f0baf [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001// SwiftShader Software Renderer
2//
John Bauman66b8ab22014-05-06 15:57:45 -04003// Copyright(c) 2005-2012 TransGaming Inc.
John Bauman89401822014-05-06 15:04:28 -04004//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#include "TextureStage.hpp"
13
14#include "Sampler.hpp"
15#include "Debug.hpp"
16
John Bauman66b8ab22014-05-06 15:57:45 -040017#include <string.h>
18
John Bauman89401822014-05-06 15:04:28 -040019namespace sw
20{
21 TextureStage::State::State()
22 {
23 memset(this, 0, sizeof(State));
24 }
25
26 TextureStage::TextureStage() : sampler(0), previousStage(0)
27 {
28 }
29
30 TextureStage::~TextureStage()
31 {
32 }
33
34 void TextureStage::init(int stage, const Sampler *sampler, const TextureStage *previousStage)
35 {
36 this->stage = stage;
37
38 stageOperation = (stage == 0 ? STAGE_MODULATE : STAGE_DISABLE);
39 firstArgument = SOURCE_TEXTURE;
40 secondArgument = SOURCE_CURRENT;
41 thirdArgument = SOURCE_CURRENT;
42 stageOperationAlpha = (stage == 0 ? STAGE_SELECTARG1 : STAGE_DISABLE);
43 firstArgumentAlpha = SOURCE_DIFFUSE;
44 secondArgumentAlpha = SOURCE_CURRENT;
45 thirdArgumentAlpha = SOURCE_CURRENT;
46 firstModifier = MODIFIER_COLOR;
47 secondModifier = MODIFIER_COLOR;
48 thirdModifier = MODIFIER_COLOR;
49 destinationArgument = DESTINATION_CURRENT;
50
51 texCoordIndex = stage;
52 this->sampler = sampler;
53 this->previousStage = previousStage;
54 }
55
56 TextureStage::State TextureStage::textureStageState() const
57 {
58 State state;
59
60 if(!isStageDisabled())
61 {
62 state.stageOperation = stageOperation;
63 state.firstArgument = firstArgument;
64 state.secondArgument = secondArgument;
65 state.thirdArgument = thirdArgument;
66 state.stageOperationAlpha = stageOperationAlpha;
67 state.firstArgumentAlpha = firstArgumentAlpha;
68 state.secondArgumentAlpha = secondArgumentAlpha;
69 state.thirdArgumentAlpha = thirdArgumentAlpha;
70 state.firstModifier = firstModifier;
71 state.secondModifier = secondModifier;
72 state.thirdModifier = thirdModifier;
73 state.firstModifierAlpha = firstModifierAlpha;
74 state.secondModifierAlpha = secondModifierAlpha;
75 state.thirdModifierAlpha = thirdModifierAlpha;
76 state.destinationArgument = destinationArgument;
77 state.texCoordIndex = texCoordIndex;
78
79 state.cantUnderflow = sampler->hasUnsignedTexture() || !usesTexture();
80 state.usesTexture = usesTexture();
81 }
82
83 return state;
84 }
85
86 void TextureStage::setConstantColor(const Color<float> &constantColor)
87 {
88 // FIXME: Compact into generic function // FIXME: Clamp
89 short r = iround(4095 * constantColor.r);
90 short g = iround(4095 * constantColor.g);
91 short b = iround(4095 * constantColor.b);
92 short a = iround(4095 * constantColor.a);
93
94 uniforms.constantColor4[0][0] = uniforms.constantColor4[0][1] = uniforms.constantColor4[0][2] = uniforms.constantColor4[0][3] = r;
95 uniforms.constantColor4[1][0] = uniforms.constantColor4[1][1] = uniforms.constantColor4[1][2] = uniforms.constantColor4[1][3] = g;
96 uniforms.constantColor4[2][0] = uniforms.constantColor4[2][1] = uniforms.constantColor4[2][2] = uniforms.constantColor4[2][3] = b;
97 uniforms.constantColor4[3][0] = uniforms.constantColor4[3][1] = uniforms.constantColor4[3][2] = uniforms.constantColor4[3][3] = a;
98 }
99
100 void TextureStage::setBumpmapMatrix(int element, float value)
101 {
102 uniforms.bumpmapMatrix4F[element / 2][element % 2][0] = value;
103 uniforms.bumpmapMatrix4F[element / 2][element % 2][1] = value;
104 uniforms.bumpmapMatrix4F[element / 2][element % 2][2] = value;
105 uniforms.bumpmapMatrix4F[element / 2][element % 2][3] = value;
106
107 uniforms.bumpmapMatrix4W[element / 2][element % 2][0] = iround(4095 * value);
108 uniforms.bumpmapMatrix4W[element / 2][element % 2][1] = iround(4095 * value);
109 uniforms.bumpmapMatrix4W[element / 2][element % 2][2] = iround(4095 * value);
110 uniforms.bumpmapMatrix4W[element / 2][element % 2][3] = iround(4095 * value);
111 }
112
113 void TextureStage::setLuminanceScale(float value)
114 {
115 short scale = iround(4095 * value);
116
117 uniforms.luminanceScale4[0] = uniforms.luminanceScale4[1] = uniforms.luminanceScale4[2] = uniforms.luminanceScale4[3] = scale;
118 }
119
120 void TextureStage::setLuminanceOffset(float value)
121 {
122 short offset = iround(4095 * value);
123
124 uniforms.luminanceOffset4[0] = uniforms.luminanceOffset4[1] = uniforms.luminanceOffset4[2] = uniforms.luminanceOffset4[3] = offset;
125 }
126
127 void TextureStage::setTexCoordIndex(unsigned int texCoordIndex)
128 {
129 ASSERT(texCoordIndex < 8);
130
131 this->texCoordIndex = texCoordIndex;
132 }
133
134 void TextureStage::setStageOperation(StageOperation stageOperation)
135 {
136 this->stageOperation = stageOperation;
137 }
138
139 void TextureStage::setFirstArgument(SourceArgument firstArgument)
140 {
141 this->firstArgument = firstArgument;
142 }
143
144 void TextureStage::setSecondArgument(SourceArgument secondArgument)
145 {
146 this->secondArgument = secondArgument;
147 }
148
149 void TextureStage::setThirdArgument(SourceArgument thirdArgument)
150 {
151 this->thirdArgument = thirdArgument;
152 }
153
154 void TextureStage::setStageOperationAlpha(StageOperation stageOperationAlpha)
155 {
156 this->stageOperationAlpha = stageOperationAlpha;
157 }
158
159 void TextureStage::setFirstArgumentAlpha(SourceArgument firstArgumentAlpha)
160 {
161 this->firstArgumentAlpha = firstArgumentAlpha;
162 }
163
164 void TextureStage::setSecondArgumentAlpha(SourceArgument secondArgumentAlpha)
165 {
166 this->secondArgumentAlpha = secondArgumentAlpha;
167 }
168
169 void TextureStage::setThirdArgumentAlpha(SourceArgument thirdArgumentAlpha)
170 {
171 this->thirdArgumentAlpha= thirdArgumentAlpha;
172 }
173
174 void TextureStage::setFirstModifier(ArgumentModifier firstModifier)
175 {
176 this->firstModifier = firstModifier;
177 }
178
179 void TextureStage::setSecondModifier(ArgumentModifier secondModifier)
180 {
181 this->secondModifier = secondModifier;
182 }
183
184 void TextureStage::setThirdModifier(ArgumentModifier thirdModifier)
185 {
186 this->thirdModifier = thirdModifier;
187 }
188
189 void TextureStage::setFirstModifierAlpha(ArgumentModifier firstModifierAlpha)
190 {
191 this->firstModifierAlpha = firstModifierAlpha;
192 }
193
194 void TextureStage::setSecondModifierAlpha(ArgumentModifier secondModifierAlpha)
195 {
196 this->secondModifierAlpha = secondModifierAlpha;
197 }
198
199 void TextureStage::setThirdModifierAlpha(ArgumentModifier thirdModifierAlpha)
200 {
201 this->thirdModifierAlpha = thirdModifierAlpha;
202 }
203
204 void TextureStage::setDestinationArgument(DestinationArgument destinationArgument)
205 {
206 this->destinationArgument = destinationArgument;
207 }
208
209 bool TextureStage::usesColor(SourceArgument source) const
210 {
211 // One argument
212 if(stageOperation == STAGE_SELECTARG1 || stageOperation == STAGE_PREMODULATE)
213 {
214 return firstArgument == source;
215 }
216 else if(stageOperation == STAGE_SELECTARG2)
217 {
218 return secondArgument == source;
219 }
220 else if(stageOperation == STAGE_SELECTARG3)
221 {
222 return thirdArgument == source;
223 }
224 else
225 {
226 // Two arguments or more
227 if(firstArgument == source || secondArgument == source)
228 {
229 return true;
230 }
231
232 // Three arguments
233 if(stageOperation == STAGE_MULTIPLYADD || stageOperation == STAGE_LERP)
234 {
235 return thirdArgument == source;
236 }
237 }
238
239 return false;
240 }
241
242 bool TextureStage::usesAlpha(SourceArgument source) const
243 {
244 if(stageOperationAlpha == STAGE_DISABLE)
245 {
246 return false;
247 }
248
249 if(source == SOURCE_TEXTURE)
250 {
251 if(stageOperation == STAGE_BLENDTEXTUREALPHA || stageOperation == STAGE_BLENDTEXTUREALPHAPM)
252 {
253 return true;
254 }
255 }
256 else if(source == SOURCE_CURRENT)
257 {
258 if(stageOperation == STAGE_BLENDCURRENTALPHA)
259 {
260 return true;
261 }
262 }
263 else if(source == SOURCE_DIFFUSE)
264 {
265 if(stageOperation == STAGE_BLENDDIFFUSEALPHA)
266 {
267 return true;
268 }
269 }
270 else if(source == SOURCE_TFACTOR)
271 {
272 if(stageOperation == STAGE_BLENDFACTORALPHA)
273 {
274 return true;
275 }
276 }
277
278 // One argument
279 if(stageOperation == STAGE_SELECTARG1 || stageOperation == STAGE_PREMODULATE)
280 {
281 if(firstArgument == source && (firstModifier == MODIFIER_ALPHA || firstModifier == MODIFIER_INVALPHA))
282 {
283 return true;
284 }
285 }
286 else if(stageOperation == STAGE_SELECTARG2)
287 {
288 if(secondArgument == source && (secondModifier == MODIFIER_ALPHA || secondModifier == MODIFIER_INVALPHA))
289 {
290 return true;
291 }
292 }
293 else if(stageOperation == STAGE_SELECTARG3)
294 {
295 if(thirdArgument == source && (thirdModifier == MODIFIER_ALPHA || thirdModifier == MODIFIER_INVALPHA))
296 {
297 return true;
298 }
299 }
300 else
301 {
302 // Two arguments or more
303 if(firstArgument == source || secondArgument == source)
304 {
305 if(firstArgument == source && (firstModifier == MODIFIER_ALPHA || firstModifier == MODIFIER_INVALPHA))
306 {
307 return true;
308 }
309
310 if(secondArgument == source && (secondModifier == MODIFIER_ALPHA || secondModifier == MODIFIER_INVALPHA))
311 {
312 return true;
313 }
314 }
315
316 // Three arguments
317 if(stageOperation == STAGE_MULTIPLYADD || stageOperation == STAGE_LERP)
318 {
319 if(thirdArgument == source && (thirdModifier == MODIFIER_ALPHA || thirdModifier == MODIFIER_INVALPHA))
320 {
321 return true;
322 }
323 }
324 }
325
326 // One argument
327 if(stageOperationAlpha == STAGE_SELECTARG1 || stageOperationAlpha == STAGE_PREMODULATE)
328 {
329 return firstArgumentAlpha == source;
330 }
331 else if(stageOperationAlpha == STAGE_SELECTARG2)
332 {
333 return secondArgumentAlpha == source;
334 }
335 else if(stageOperationAlpha == STAGE_SELECTARG3)
336 {
337 return thirdArgumentAlpha == source;
338 }
339 else
340 {
341 // Two arguments or more
342 if(firstArgumentAlpha == source || secondArgumentAlpha == source)
343 {
344 return true;
345 }
346
347 // Three arguments
348 if(stageOperationAlpha == STAGE_MULTIPLYADD || stageOperationAlpha == STAGE_LERP)
349 {
350 return thirdArgumentAlpha == source;
351 }
352 }
353
354 return false;
355 }
356
357 bool TextureStage::uses(SourceArgument source) const
358 {
359 return usesColor(source) || usesAlpha(source);
360 }
361
362 bool TextureStage::usesCurrent() const
363 {
364 return uses(SOURCE_CURRENT) || (stageOperation == STAGE_BLENDCURRENTALPHA || stageOperationAlpha == STAGE_BLENDCURRENTALPHA);
365 }
366
367 bool TextureStage::usesDiffuse() const
368 {
369 return uses(SOURCE_DIFFUSE) || (stageOperation == STAGE_BLENDDIFFUSEALPHA || stageOperationAlpha == STAGE_BLENDDIFFUSEALPHA);
370 }
371
372 bool TextureStage::usesSpecular() const
373 {
374 return uses(SOURCE_SPECULAR);
375 }
376
377 bool TextureStage::usesTexture() const
378 {
379 return uses(SOURCE_TEXTURE) ||
380 stageOperation == STAGE_BLENDTEXTUREALPHA ||
381 stageOperationAlpha == STAGE_BLENDTEXTUREALPHA ||
382 stageOperation == STAGE_BLENDTEXTUREALPHAPM ||
383 stageOperationAlpha == STAGE_BLENDTEXTUREALPHAPM ||
384 (previousStage && previousStage->stageOperation == STAGE_PREMODULATE) ||
385 (previousStage && previousStage->stageOperationAlpha == STAGE_PREMODULATE);
386 }
387
388 bool TextureStage::isStageDisabled() const
389 {
390 bool disabled = (stageOperation == STAGE_DISABLE) || (!sampler->hasTexture() && usesTexture());
391
392 if(!previousStage || disabled)
393 {
394 return disabled;
395 }
396 else
397 {
398 return previousStage->isStageDisabled();
399 }
400 }
401
402 bool TextureStage::writesCurrent() const
403 {
404 return !isStageDisabled() && destinationArgument == DESTINATION_CURRENT && stageOperation != STAGE_BUMPENVMAP && stageOperation != STAGE_BUMPENVMAPLUMINANCE;
405 }
406}