1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include "TextureStage.hpp"
17 #include "Sampler.hpp"
24 TextureStage::State::State()
26 memset(this, 0, sizeof(State));
29 TextureStage::TextureStage() : sampler(0), previousStage(0)
33 TextureStage::~TextureStage()
37 void TextureStage::init(int stage, const Sampler *sampler, const TextureStage *previousStage)
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;
57 texCoordIndex = stage;
58 this->sampler = sampler;
59 this->previousStage = previousStage;
62 TextureStage::State TextureStage::textureStageState() const
66 if(!isStageDisabled())
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;
85 state.cantUnderflow = sampler->hasUnsignedTexture() || !usesTexture();
86 state.usesTexture = usesTexture();
92 void TextureStage::setConstantColor(const Color<float> &constantColor)
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);
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;
106 void TextureStage::setBumpmapMatrix(int element, float value)
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;
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);
119 void TextureStage::setLuminanceScale(float value)
121 short scale = iround(4095 * value);
123 uniforms.luminanceScale4[0] = uniforms.luminanceScale4[1] = uniforms.luminanceScale4[2] = uniforms.luminanceScale4[3] = scale;
126 void TextureStage::setLuminanceOffset(float value)
128 short offset = iround(4095 * value);
130 uniforms.luminanceOffset4[0] = uniforms.luminanceOffset4[1] = uniforms.luminanceOffset4[2] = uniforms.luminanceOffset4[3] = offset;
133 void TextureStage::setTexCoordIndex(unsigned int texCoordIndex)
135 ASSERT(texCoordIndex < 8);
137 this->texCoordIndex = texCoordIndex;
140 void TextureStage::setStageOperation(StageOperation stageOperation)
142 this->stageOperation = stageOperation;
145 void TextureStage::setFirstArgument(SourceArgument firstArgument)
147 this->firstArgument = firstArgument;
150 void TextureStage::setSecondArgument(SourceArgument secondArgument)
152 this->secondArgument = secondArgument;
155 void TextureStage::setThirdArgument(SourceArgument thirdArgument)
157 this->thirdArgument = thirdArgument;
160 void TextureStage::setStageOperationAlpha(StageOperation stageOperationAlpha)
162 this->stageOperationAlpha = stageOperationAlpha;
165 void TextureStage::setFirstArgumentAlpha(SourceArgument firstArgumentAlpha)
167 this->firstArgumentAlpha = firstArgumentAlpha;
170 void TextureStage::setSecondArgumentAlpha(SourceArgument secondArgumentAlpha)
172 this->secondArgumentAlpha = secondArgumentAlpha;
175 void TextureStage::setThirdArgumentAlpha(SourceArgument thirdArgumentAlpha)
177 this->thirdArgumentAlpha= thirdArgumentAlpha;
180 void TextureStage::setFirstModifier(ArgumentModifier firstModifier)
182 this->firstModifier = firstModifier;
185 void TextureStage::setSecondModifier(ArgumentModifier secondModifier)
187 this->secondModifier = secondModifier;
190 void TextureStage::setThirdModifier(ArgumentModifier thirdModifier)
192 this->thirdModifier = thirdModifier;
195 void TextureStage::setFirstModifierAlpha(ArgumentModifier firstModifierAlpha)
197 this->firstModifierAlpha = firstModifierAlpha;
200 void TextureStage::setSecondModifierAlpha(ArgumentModifier secondModifierAlpha)
202 this->secondModifierAlpha = secondModifierAlpha;
205 void TextureStage::setThirdModifierAlpha(ArgumentModifier thirdModifierAlpha)
207 this->thirdModifierAlpha = thirdModifierAlpha;
210 void TextureStage::setDestinationArgument(DestinationArgument destinationArgument)
212 this->destinationArgument = destinationArgument;
215 bool TextureStage::usesColor(SourceArgument source) const
218 if(stageOperation == STAGE_SELECTARG1 || stageOperation == STAGE_PREMODULATE)
220 return firstArgument == source;
222 else if(stageOperation == STAGE_SELECTARG2)
224 return secondArgument == source;
226 else if(stageOperation == STAGE_SELECTARG3)
228 return thirdArgument == source;
232 // Two arguments or more
233 if(firstArgument == source || secondArgument == source)
239 if(stageOperation == STAGE_MULTIPLYADD || stageOperation == STAGE_LERP)
241 return thirdArgument == source;
248 bool TextureStage::usesAlpha(SourceArgument source) const
250 if(stageOperationAlpha == STAGE_DISABLE)
255 if(source == SOURCE_TEXTURE)
257 if(stageOperation == STAGE_BLENDTEXTUREALPHA || stageOperation == STAGE_BLENDTEXTUREALPHAPM)
262 else if(source == SOURCE_CURRENT)
264 if(stageOperation == STAGE_BLENDCURRENTALPHA)
269 else if(source == SOURCE_DIFFUSE)
271 if(stageOperation == STAGE_BLENDDIFFUSEALPHA)
276 else if(source == SOURCE_TFACTOR)
278 if(stageOperation == STAGE_BLENDFACTORALPHA)
285 if(stageOperation == STAGE_SELECTARG1 || stageOperation == STAGE_PREMODULATE)
287 if(firstArgument == source && (firstModifier == MODIFIER_ALPHA || firstModifier == MODIFIER_INVALPHA))
292 else if(stageOperation == STAGE_SELECTARG2)
294 if(secondArgument == source && (secondModifier == MODIFIER_ALPHA || secondModifier == MODIFIER_INVALPHA))
299 else if(stageOperation == STAGE_SELECTARG3)
301 if(thirdArgument == source && (thirdModifier == MODIFIER_ALPHA || thirdModifier == MODIFIER_INVALPHA))
308 // Two arguments or more
309 if(firstArgument == source || secondArgument == source)
311 if(firstArgument == source && (firstModifier == MODIFIER_ALPHA || firstModifier == MODIFIER_INVALPHA))
316 if(secondArgument == source && (secondModifier == MODIFIER_ALPHA || secondModifier == MODIFIER_INVALPHA))
323 if(stageOperation == STAGE_MULTIPLYADD || stageOperation == STAGE_LERP)
325 if(thirdArgument == source && (thirdModifier == MODIFIER_ALPHA || thirdModifier == MODIFIER_INVALPHA))
333 if(stageOperationAlpha == STAGE_SELECTARG1 || stageOperationAlpha == STAGE_PREMODULATE)
335 return firstArgumentAlpha == source;
337 else if(stageOperationAlpha == STAGE_SELECTARG2)
339 return secondArgumentAlpha == source;
341 else if(stageOperationAlpha == STAGE_SELECTARG3)
343 return thirdArgumentAlpha == source;
347 // Two arguments or more
348 if(firstArgumentAlpha == source || secondArgumentAlpha == source)
354 if(stageOperationAlpha == STAGE_MULTIPLYADD || stageOperationAlpha == STAGE_LERP)
356 return thirdArgumentAlpha == source;
363 bool TextureStage::uses(SourceArgument source) const
365 return usesColor(source) || usesAlpha(source);
368 bool TextureStage::usesCurrent() const
370 return uses(SOURCE_CURRENT) || (stageOperation == STAGE_BLENDCURRENTALPHA || stageOperationAlpha == STAGE_BLENDCURRENTALPHA);
373 bool TextureStage::usesDiffuse() const
375 return uses(SOURCE_DIFFUSE) || (stageOperation == STAGE_BLENDDIFFUSEALPHA || stageOperationAlpha == STAGE_BLENDDIFFUSEALPHA);
378 bool TextureStage::usesSpecular() const
380 return uses(SOURCE_SPECULAR);
383 bool TextureStage::usesTexture() const
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);
394 bool TextureStage::isStageDisabled() const
396 bool disabled = (stageOperation == STAGE_DISABLE) || (!sampler->hasTexture() && usesTexture());
398 if(!previousStage || disabled)
404 return previousStage->isStageDisabled();
408 bool TextureStage::writesCurrent() const
410 return !isStageDisabled() && destinationArgument == DESTINATION_CURRENT && stageOperation != STAGE_BUMPENVMAP && stageOperation != STAGE_BUMPENVMAPLUMINANCE;