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