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 {
State()24 	TextureStage::State::State()
25 	{
26 		memset(this, 0, sizeof(State));
27 	}
28 
TextureStage()29 	TextureStage::TextureStage() : sampler(0), previousStage(0)
30 	{
31 	}
32 
~TextureStage()33 	TextureStage::~TextureStage()
34 	{
35 	}
36 
init(int stage,const Sampler * sampler,const TextureStage * previousStage)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 
textureStageState() const62 	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 
setConstantColor(const Color<float> & constantColor)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 
setBumpmapMatrix(int element,float value)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 
setLuminanceScale(float value)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 
setLuminanceOffset(float value)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 
setTexCoordIndex(unsigned int texCoordIndex)133 	void TextureStage::setTexCoordIndex(unsigned int texCoordIndex)
134 	{
135 		ASSERT(texCoordIndex < 8);
136 
137 		this->texCoordIndex = texCoordIndex;
138 	}
139 
setStageOperation(StageOperation stageOperation)140 	void TextureStage::setStageOperation(StageOperation stageOperation)
141 	{
142 		this->stageOperation = stageOperation;
143 	}
144 
setFirstArgument(SourceArgument firstArgument)145 	void TextureStage::setFirstArgument(SourceArgument firstArgument)
146 	{
147 		this->firstArgument = firstArgument;
148 	}
149 
setSecondArgument(SourceArgument secondArgument)150 	void TextureStage::setSecondArgument(SourceArgument secondArgument)
151 	{
152 		this->secondArgument = secondArgument;
153 	}
154 
setThirdArgument(SourceArgument thirdArgument)155 	void TextureStage::setThirdArgument(SourceArgument thirdArgument)
156 	{
157 		this->thirdArgument = thirdArgument;
158 	}
159 
setStageOperationAlpha(StageOperation stageOperationAlpha)160 	void TextureStage::setStageOperationAlpha(StageOperation stageOperationAlpha)
161 	{
162 		this->stageOperationAlpha = stageOperationAlpha;
163 	}
164 
setFirstArgumentAlpha(SourceArgument firstArgumentAlpha)165 	void TextureStage::setFirstArgumentAlpha(SourceArgument firstArgumentAlpha)
166 	{
167 		this->firstArgumentAlpha = firstArgumentAlpha;
168 	}
169 
setSecondArgumentAlpha(SourceArgument secondArgumentAlpha)170 	void TextureStage::setSecondArgumentAlpha(SourceArgument secondArgumentAlpha)
171 	{
172 		this->secondArgumentAlpha = secondArgumentAlpha;
173 	}
174 
setThirdArgumentAlpha(SourceArgument thirdArgumentAlpha)175 	void TextureStage::setThirdArgumentAlpha(SourceArgument thirdArgumentAlpha)
176 	{
177 		this->thirdArgumentAlpha= thirdArgumentAlpha;
178 	}
179 
setFirstModifier(ArgumentModifier firstModifier)180 	void TextureStage::setFirstModifier(ArgumentModifier firstModifier)
181 	{
182 		this->firstModifier = firstModifier;
183 	}
184 
setSecondModifier(ArgumentModifier secondModifier)185 	void TextureStage::setSecondModifier(ArgumentModifier secondModifier)
186 	{
187 		this->secondModifier = secondModifier;
188 	}
189 
setThirdModifier(ArgumentModifier thirdModifier)190 	void TextureStage::setThirdModifier(ArgumentModifier thirdModifier)
191 	{
192 		this->thirdModifier = thirdModifier;
193 	}
194 
setFirstModifierAlpha(ArgumentModifier firstModifierAlpha)195 	void TextureStage::setFirstModifierAlpha(ArgumentModifier firstModifierAlpha)
196 	{
197 		this->firstModifierAlpha = firstModifierAlpha;
198 	}
199 
setSecondModifierAlpha(ArgumentModifier secondModifierAlpha)200 	void TextureStage::setSecondModifierAlpha(ArgumentModifier secondModifierAlpha)
201 	{
202 		this->secondModifierAlpha = secondModifierAlpha;
203 	}
204 
setThirdModifierAlpha(ArgumentModifier thirdModifierAlpha)205 	void TextureStage::setThirdModifierAlpha(ArgumentModifier thirdModifierAlpha)
206 	{
207 		this->thirdModifierAlpha = thirdModifierAlpha;
208 	}
209 
setDestinationArgument(DestinationArgument destinationArgument)210 	void TextureStage::setDestinationArgument(DestinationArgument destinationArgument)
211 	{
212 		this->destinationArgument = destinationArgument;
213 	}
214 
usesColor(SourceArgument source) const215 	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 
usesAlpha(SourceArgument source) const248 	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 
uses(SourceArgument source) const363 	bool TextureStage::uses(SourceArgument source) const
364 	{
365 		return usesColor(source) || usesAlpha(source);
366 	}
367 
usesCurrent() const368 	bool TextureStage::usesCurrent() const
369 	{
370 		return uses(SOURCE_CURRENT) || (stageOperation == STAGE_BLENDCURRENTALPHA || stageOperationAlpha == STAGE_BLENDCURRENTALPHA);
371 	}
372 
usesDiffuse() const373 	bool TextureStage::usesDiffuse() const
374 	{
375 		return uses(SOURCE_DIFFUSE) || (stageOperation == STAGE_BLENDDIFFUSEALPHA || stageOperationAlpha == STAGE_BLENDDIFFUSEALPHA);
376 	}
377 
usesSpecular() const378 	bool TextureStage::usesSpecular() const
379 	{
380 		return uses(SOURCE_SPECULAR);
381 	}
382 
usesTexture() const383 	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 
isStageDisabled() const394 	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 
writesCurrent() const408 	bool TextureStage::writesCurrent() const
409 	{
410 		return !isStageDisabled() && destinationArgument == DESTINATION_CURRENT && stageOperation != STAGE_BUMPENVMAP && stageOperation != STAGE_BUMPENVMAPLUMINANCE;
411 	}
412 }
413