// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
|
//
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
// you may not use this file except in compliance with the License.
|
// You may obtain a copy of the License at
|
//
|
// http://www.apache.org/licenses/LICENSE-2.0
|
//
|
// Unless required by applicable law or agreed to in writing, software
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// See the License for the specific language governing permissions and
|
// limitations under the License.
|
|
#include "TextureStage.hpp"
|
|
#include "Sampler.hpp"
|
#include "Common/Debug.hpp"
|
|
#include <string.h>
|
|
namespace sw
|
{
|
TextureStage::State::State()
|
{
|
memset(this, 0, sizeof(State));
|
}
|
|
TextureStage::TextureStage() : sampler(0), previousStage(0)
|
{
|
}
|
|
TextureStage::~TextureStage()
|
{
|
}
|
|
void TextureStage::init(int stage, const Sampler *sampler, const TextureStage *previousStage)
|
{
|
this->stage = stage;
|
|
stageOperation = (stage == 0 ? STAGE_MODULATE : STAGE_DISABLE);
|
firstArgument = SOURCE_TEXTURE;
|
secondArgument = SOURCE_CURRENT;
|
thirdArgument = SOURCE_CURRENT;
|
stageOperationAlpha = (stage == 0 ? STAGE_SELECTARG1 : STAGE_DISABLE);
|
firstArgumentAlpha = SOURCE_DIFFUSE;
|
secondArgumentAlpha = SOURCE_CURRENT;
|
thirdArgumentAlpha = SOURCE_CURRENT;
|
firstModifier = MODIFIER_COLOR;
|
secondModifier = MODIFIER_COLOR;
|
thirdModifier = MODIFIER_COLOR;
|
firstModifierAlpha = MODIFIER_COLOR;
|
secondModifierAlpha = MODIFIER_COLOR;
|
thirdModifierAlpha = MODIFIER_COLOR;
|
destinationArgument = DESTINATION_CURRENT;
|
|
texCoordIndex = stage;
|
this->sampler = sampler;
|
this->previousStage = previousStage;
|
}
|
|
TextureStage::State TextureStage::textureStageState() const
|
{
|
State state;
|
|
if(!isStageDisabled())
|
{
|
state.stageOperation = stageOperation;
|
state.firstArgument = firstArgument;
|
state.secondArgument = secondArgument;
|
state.thirdArgument = thirdArgument;
|
state.stageOperationAlpha = stageOperationAlpha;
|
state.firstArgumentAlpha = firstArgumentAlpha;
|
state.secondArgumentAlpha = secondArgumentAlpha;
|
state.thirdArgumentAlpha = thirdArgumentAlpha;
|
state.firstModifier = firstModifier;
|
state.secondModifier = secondModifier;
|
state.thirdModifier = thirdModifier;
|
state.firstModifierAlpha = firstModifierAlpha;
|
state.secondModifierAlpha = secondModifierAlpha;
|
state.thirdModifierAlpha = thirdModifierAlpha;
|
state.destinationArgument = destinationArgument;
|
state.texCoordIndex = texCoordIndex;
|
|
state.cantUnderflow = sampler->hasUnsignedTexture() || !usesTexture();
|
state.usesTexture = usesTexture();
|
}
|
|
return state;
|
}
|
|
void TextureStage::setConstantColor(const Color<float> &constantColor)
|
{
|
// FIXME: Compact into generic function // FIXME: Clamp
|
short r = iround(4095 * constantColor.r);
|
short g = iround(4095 * constantColor.g);
|
short b = iround(4095 * constantColor.b);
|
short a = iround(4095 * constantColor.a);
|
|
uniforms.constantColor4[0][0] = uniforms.constantColor4[0][1] = uniforms.constantColor4[0][2] = uniforms.constantColor4[0][3] = r;
|
uniforms.constantColor4[1][0] = uniforms.constantColor4[1][1] = uniforms.constantColor4[1][2] = uniforms.constantColor4[1][3] = g;
|
uniforms.constantColor4[2][0] = uniforms.constantColor4[2][1] = uniforms.constantColor4[2][2] = uniforms.constantColor4[2][3] = b;
|
uniforms.constantColor4[3][0] = uniforms.constantColor4[3][1] = uniforms.constantColor4[3][2] = uniforms.constantColor4[3][3] = a;
|
}
|
|
void TextureStage::setBumpmapMatrix(int element, float value)
|
{
|
uniforms.bumpmapMatrix4F[element / 2][element % 2][0] = value;
|
uniforms.bumpmapMatrix4F[element / 2][element % 2][1] = value;
|
uniforms.bumpmapMatrix4F[element / 2][element % 2][2] = value;
|
uniforms.bumpmapMatrix4F[element / 2][element % 2][3] = value;
|
|
uniforms.bumpmapMatrix4W[element / 2][element % 2][0] = iround(4095 * value);
|
uniforms.bumpmapMatrix4W[element / 2][element % 2][1] = iround(4095 * value);
|
uniforms.bumpmapMatrix4W[element / 2][element % 2][2] = iround(4095 * value);
|
uniforms.bumpmapMatrix4W[element / 2][element % 2][3] = iround(4095 * value);
|
}
|
|
void TextureStage::setLuminanceScale(float value)
|
{
|
short scale = iround(4095 * value);
|
|
uniforms.luminanceScale4[0] = uniforms.luminanceScale4[1] = uniforms.luminanceScale4[2] = uniforms.luminanceScale4[3] = scale;
|
}
|
|
void TextureStage::setLuminanceOffset(float value)
|
{
|
short offset = iround(4095 * value);
|
|
uniforms.luminanceOffset4[0] = uniforms.luminanceOffset4[1] = uniforms.luminanceOffset4[2] = uniforms.luminanceOffset4[3] = offset;
|
}
|
|
void TextureStage::setTexCoordIndex(unsigned int texCoordIndex)
|
{
|
ASSERT(texCoordIndex < 8);
|
|
this->texCoordIndex = texCoordIndex;
|
}
|
|
void TextureStage::setStageOperation(StageOperation stageOperation)
|
{
|
this->stageOperation = stageOperation;
|
}
|
|
void TextureStage::setFirstArgument(SourceArgument firstArgument)
|
{
|
this->firstArgument = firstArgument;
|
}
|
|
void TextureStage::setSecondArgument(SourceArgument secondArgument)
|
{
|
this->secondArgument = secondArgument;
|
}
|
|
void TextureStage::setThirdArgument(SourceArgument thirdArgument)
|
{
|
this->thirdArgument = thirdArgument;
|
}
|
|
void TextureStage::setStageOperationAlpha(StageOperation stageOperationAlpha)
|
{
|
this->stageOperationAlpha = stageOperationAlpha;
|
}
|
|
void TextureStage::setFirstArgumentAlpha(SourceArgument firstArgumentAlpha)
|
{
|
this->firstArgumentAlpha = firstArgumentAlpha;
|
}
|
|
void TextureStage::setSecondArgumentAlpha(SourceArgument secondArgumentAlpha)
|
{
|
this->secondArgumentAlpha = secondArgumentAlpha;
|
}
|
|
void TextureStage::setThirdArgumentAlpha(SourceArgument thirdArgumentAlpha)
|
{
|
this->thirdArgumentAlpha= thirdArgumentAlpha;
|
}
|
|
void TextureStage::setFirstModifier(ArgumentModifier firstModifier)
|
{
|
this->firstModifier = firstModifier;
|
}
|
|
void TextureStage::setSecondModifier(ArgumentModifier secondModifier)
|
{
|
this->secondModifier = secondModifier;
|
}
|
|
void TextureStage::setThirdModifier(ArgumentModifier thirdModifier)
|
{
|
this->thirdModifier = thirdModifier;
|
}
|
|
void TextureStage::setFirstModifierAlpha(ArgumentModifier firstModifierAlpha)
|
{
|
this->firstModifierAlpha = firstModifierAlpha;
|
}
|
|
void TextureStage::setSecondModifierAlpha(ArgumentModifier secondModifierAlpha)
|
{
|
this->secondModifierAlpha = secondModifierAlpha;
|
}
|
|
void TextureStage::setThirdModifierAlpha(ArgumentModifier thirdModifierAlpha)
|
{
|
this->thirdModifierAlpha = thirdModifierAlpha;
|
}
|
|
void TextureStage::setDestinationArgument(DestinationArgument destinationArgument)
|
{
|
this->destinationArgument = destinationArgument;
|
}
|
|
bool TextureStage::usesColor(SourceArgument source) const
|
{
|
// One argument
|
if(stageOperation == STAGE_SELECTARG1 || stageOperation == STAGE_PREMODULATE)
|
{
|
return firstArgument == source;
|
}
|
else if(stageOperation == STAGE_SELECTARG2)
|
{
|
return secondArgument == source;
|
}
|
else if(stageOperation == STAGE_SELECTARG3)
|
{
|
return thirdArgument == source;
|
}
|
else
|
{
|
// Two arguments or more
|
if(firstArgument == source || secondArgument == source)
|
{
|
return true;
|
}
|
|
// Three arguments
|
if(stageOperation == STAGE_MULTIPLYADD || stageOperation == STAGE_LERP)
|
{
|
return thirdArgument == source;
|
}
|
}
|
|
return false;
|
}
|
|
bool TextureStage::usesAlpha(SourceArgument source) const
|
{
|
if(stageOperationAlpha == STAGE_DISABLE)
|
{
|
return false;
|
}
|
|
if(source == SOURCE_TEXTURE)
|
{
|
if(stageOperation == STAGE_BLENDTEXTUREALPHA || stageOperation == STAGE_BLENDTEXTUREALPHAPM)
|
{
|
return true;
|
}
|
}
|
else if(source == SOURCE_CURRENT)
|
{
|
if(stageOperation == STAGE_BLENDCURRENTALPHA)
|
{
|
return true;
|
}
|
}
|
else if(source == SOURCE_DIFFUSE)
|
{
|
if(stageOperation == STAGE_BLENDDIFFUSEALPHA)
|
{
|
return true;
|
}
|
}
|
else if(source == SOURCE_TFACTOR)
|
{
|
if(stageOperation == STAGE_BLENDFACTORALPHA)
|
{
|
return true;
|
}
|
}
|
|
// One argument
|
if(stageOperation == STAGE_SELECTARG1 || stageOperation == STAGE_PREMODULATE)
|
{
|
if(firstArgument == source && (firstModifier == MODIFIER_ALPHA || firstModifier == MODIFIER_INVALPHA))
|
{
|
return true;
|
}
|
}
|
else if(stageOperation == STAGE_SELECTARG2)
|
{
|
if(secondArgument == source && (secondModifier == MODIFIER_ALPHA || secondModifier == MODIFIER_INVALPHA))
|
{
|
return true;
|
}
|
}
|
else if(stageOperation == STAGE_SELECTARG3)
|
{
|
if(thirdArgument == source && (thirdModifier == MODIFIER_ALPHA || thirdModifier == MODIFIER_INVALPHA))
|
{
|
return true;
|
}
|
}
|
else
|
{
|
// Two arguments or more
|
if(firstArgument == source || secondArgument == source)
|
{
|
if(firstArgument == source && (firstModifier == MODIFIER_ALPHA || firstModifier == MODIFIER_INVALPHA))
|
{
|
return true;
|
}
|
|
if(secondArgument == source && (secondModifier == MODIFIER_ALPHA || secondModifier == MODIFIER_INVALPHA))
|
{
|
return true;
|
}
|
}
|
|
// Three arguments
|
if(stageOperation == STAGE_MULTIPLYADD || stageOperation == STAGE_LERP)
|
{
|
if(thirdArgument == source && (thirdModifier == MODIFIER_ALPHA || thirdModifier == MODIFIER_INVALPHA))
|
{
|
return true;
|
}
|
}
|
}
|
|
// One argument
|
if(stageOperationAlpha == STAGE_SELECTARG1 || stageOperationAlpha == STAGE_PREMODULATE)
|
{
|
return firstArgumentAlpha == source;
|
}
|
else if(stageOperationAlpha == STAGE_SELECTARG2)
|
{
|
return secondArgumentAlpha == source;
|
}
|
else if(stageOperationAlpha == STAGE_SELECTARG3)
|
{
|
return thirdArgumentAlpha == source;
|
}
|
else
|
{
|
// Two arguments or more
|
if(firstArgumentAlpha == source || secondArgumentAlpha == source)
|
{
|
return true;
|
}
|
|
// Three arguments
|
if(stageOperationAlpha == STAGE_MULTIPLYADD || stageOperationAlpha == STAGE_LERP)
|
{
|
return thirdArgumentAlpha == source;
|
}
|
}
|
|
return false;
|
}
|
|
bool TextureStage::uses(SourceArgument source) const
|
{
|
return usesColor(source) || usesAlpha(source);
|
}
|
|
bool TextureStage::usesCurrent() const
|
{
|
return uses(SOURCE_CURRENT) || (stageOperation == STAGE_BLENDCURRENTALPHA || stageOperationAlpha == STAGE_BLENDCURRENTALPHA);
|
}
|
|
bool TextureStage::usesDiffuse() const
|
{
|
return uses(SOURCE_DIFFUSE) || (stageOperation == STAGE_BLENDDIFFUSEALPHA || stageOperationAlpha == STAGE_BLENDDIFFUSEALPHA);
|
}
|
|
bool TextureStage::usesSpecular() const
|
{
|
return uses(SOURCE_SPECULAR);
|
}
|
|
bool TextureStage::usesTexture() const
|
{
|
return uses(SOURCE_TEXTURE) ||
|
stageOperation == STAGE_BLENDTEXTUREALPHA ||
|
stageOperationAlpha == STAGE_BLENDTEXTUREALPHA ||
|
stageOperation == STAGE_BLENDTEXTUREALPHAPM ||
|
stageOperationAlpha == STAGE_BLENDTEXTUREALPHAPM ||
|
(previousStage && previousStage->stageOperation == STAGE_PREMODULATE) ||
|
(previousStage && previousStage->stageOperationAlpha == STAGE_PREMODULATE);
|
}
|
|
bool TextureStage::isStageDisabled() const
|
{
|
bool disabled = (stageOperation == STAGE_DISABLE) || (!sampler->hasTexture() && usesTexture());
|
|
if(!previousStage || disabled)
|
{
|
return disabled;
|
}
|
else
|
{
|
return previousStage->isStageDisabled();
|
}
|
}
|
|
bool TextureStage::writesCurrent() const
|
{
|
return !isStageDisabled() && destinationArgument == DESTINATION_CURRENT && stageOperation != STAGE_BUMPENVMAP && stageOperation != STAGE_BUMPENVMAPLUMINANCE;
|
}
|
}
|