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 | |
22 | namespace 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 | |