blob: f8a302478dd24df5f0472b16ea9cb489b2b1f3ac [file] [log] [blame]
//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// GLES1State.cpp: Implements the GLES1State class, tracking state
// for GLES1 contexts.
#include "libANGLE/GLES1State.h"
#include "libANGLE/Context.h"
#include "libANGLE/GLES1Renderer.h"
namespace gl
{
TextureCoordF::TextureCoordF() = default;
TextureCoordF::TextureCoordF(float _s, float _t, float _r, float _q) : s(_s), t(_t), r(_r), q(_q) {}
bool TextureCoordF::operator==(const TextureCoordF &other) const
{
return s == other.s && t == other.t && r == other.r && q == other.q;
}
MaterialParameters::MaterialParameters() = default;
LightModelParameters::LightModelParameters() = default;
LightParameters::LightParameters() = default;
LightParameters::LightParameters(const LightParameters &other) = default;
FogParameters::FogParameters() = default;
TextureEnvironmentParameters::TextureEnvironmentParameters() = default;
TextureEnvironmentParameters::TextureEnvironmentParameters(
const TextureEnvironmentParameters &other) = default;
PointParameters::PointParameters() = default;
PointParameters::PointParameters(const PointParameters &other) = default;
ClipPlaneParameters::ClipPlaneParameters() = default;
ClipPlaneParameters::ClipPlaneParameters(bool enabled, const angle::Vector4 &equation)
: enabled(enabled), equation(equation)
{}
ClipPlaneParameters::ClipPlaneParameters(const ClipPlaneParameters &other) = default;
GLES1State::GLES1State()
: mGLState(nullptr),
mVertexArrayEnabled(false),
mNormalArrayEnabled(false),
mColorArrayEnabled(false),
mPointSizeArrayEnabled(false),
mLineSmoothEnabled(false),
mPointSmoothEnabled(false),
mPointSpriteEnabled(false),
mAlphaTestEnabled(false),
mLogicOpEnabled(false),
mLightingEnabled(false),
mFogEnabled(false),
mRescaleNormalEnabled(false),
mNormalizeEnabled(false),
mColorMaterialEnabled(false),
mReflectionMapEnabled(false),
mCurrentColor({0.0f, 0.0f, 0.0f, 0.0f}),
mCurrentNormal({0.0f, 0.0f, 0.0f}),
mClientActiveTexture(0),
mMatrixMode(MatrixType::Modelview),
mShadeModel(ShadingModel::Smooth),
mAlphaTestFunc(AlphaTestFunc::AlwaysPass),
mAlphaTestRef(0.0f),
mLogicOp(LogicalOperation::Copy),
mLineSmoothHint(HintSetting::DontCare),
mPointSmoothHint(HintSetting::DontCare),
mPerspectiveCorrectionHint(HintSetting::DontCare),
mFogHint(HintSetting::DontCare)
{}
GLES1State::~GLES1State() = default;
// Taken from the GLES 1.x spec which specifies all initial state values.
void GLES1State::initialize(const Context *context, const State *state)
{
mGLState = state;
const Caps &caps = context->getCaps();
mTexUnitEnables.resize(caps.maxMultitextureUnits);
for (auto &enables : mTexUnitEnables)
{
enables.reset();
}
mVertexArrayEnabled = false;
mNormalArrayEnabled = false;
mColorArrayEnabled = false;
mPointSizeArrayEnabled = false;
mTexCoordArrayEnabled.resize(caps.maxMultitextureUnits, false);
mLineSmoothEnabled = false;
mPointSmoothEnabled = false;
mPointSpriteEnabled = false;
mLogicOpEnabled = false;
mAlphaTestEnabled = false;
mLightingEnabled = false;
mFogEnabled = false;
mRescaleNormalEnabled = false;
mNormalizeEnabled = false;
mColorMaterialEnabled = false;
mReflectionMapEnabled = false;
mMatrixMode = MatrixType::Modelview;
mCurrentColor = {1.0f, 1.0f, 1.0f, 1.0f};
mCurrentNormal = {0.0f, 0.0f, 1.0f};
mCurrentTextureCoords.resize(caps.maxMultitextureUnits);
mClientActiveTexture = 0;
mTextureEnvironments.resize(caps.maxMultitextureUnits);
mModelviewMatrices.push_back(angle::Mat4());
mProjectionMatrices.push_back(angle::Mat4());
mTextureMatrices.resize(caps.maxMultitextureUnits);
for (auto &stack : mTextureMatrices)
{
stack.push_back(angle::Mat4());
}
mMaterial.ambient = {0.2f, 0.2f, 0.2f, 1.0f};
mMaterial.diffuse = {0.8f, 0.8f, 0.8f, 1.0f};
mMaterial.specular = {0.0f, 0.0f, 0.0f, 1.0f};
mMaterial.emissive = {0.0f, 0.0f, 0.0f, 1.0f};
mMaterial.specularExponent = 0.0f;
mLightModel.color = {0.2f, 0.2f, 0.2f, 1.0f};
mLightModel.twoSided = false;
mLights.resize(caps.maxLights);
// GL_LIGHT0 is special and has default state that avoids all-black renderings.
mLights[0].diffuse = {1.0f, 1.0f, 1.0f, 1.0f};
mLights[0].specular = {1.0f, 1.0f, 1.0f, 1.0f};
mFog.mode = FogMode::Exp;
mFog.density = 1.0f;
mFog.start = 0.0f;
mFog.end = 1.0f;
mFog.color = {0.0f, 0.0f, 0.0f, 0.0f};
mShadeModel = ShadingModel::Smooth;
mAlphaTestFunc = AlphaTestFunc::AlwaysPass;
mAlphaTestRef = 0.0f;
mLogicOp = LogicalOperation::Copy;
mClipPlanes.resize(caps.maxClipPlanes,
ClipPlaneParameters(false, angle::Vector4(0.0f, 0.0f, 0.0f, 0.0f)));
mLineSmoothHint = HintSetting::DontCare;
mPointSmoothHint = HintSetting::DontCare;
mPerspectiveCorrectionHint = HintSetting::DontCare;
mFogHint = HintSetting::DontCare;
// The user-specified point size, GL_POINT_SIZE_MAX,
// is initially equal to the implementation maximum.
mPointParameters.pointSizeMax = caps.maxAliasedPointSize;
mDirtyBits.set();
}
void GLES1State::setAlphaFunc(AlphaTestFunc func, GLfloat ref)
{
setDirty(DIRTY_GLES1_ALPHA_TEST);
mAlphaTestFunc = func;
mAlphaTestRef = ref;
}
void GLES1State::setClientTextureUnit(unsigned int unit)
{
setDirty(DIRTY_GLES1_CLIENT_ACTIVE_TEXTURE);
mClientActiveTexture = unit;
}
unsigned int GLES1State::getClientTextureUnit() const
{
return mClientActiveTexture;
}
void GLES1State::setCurrentColor(const ColorF &color)
{
setDirty(DIRTY_GLES1_CURRENT_VECTOR);
mCurrentColor = color;
}
const ColorF &GLES1State::getCurrentColor() const
{
return mCurrentColor;
}
void GLES1State::setCurrentNormal(const angle::Vector3 &normal)
{
setDirty(DIRTY_GLES1_CURRENT_VECTOR);
mCurrentNormal = normal;
}
const angle::Vector3 &GLES1State::getCurrentNormal() const
{
return mCurrentNormal;
}
void GLES1State::setCurrentTextureCoords(unsigned int unit, const TextureCoordF &coords)
{
setDirty(DIRTY_GLES1_CURRENT_VECTOR);
mCurrentTextureCoords[unit] = coords;
}
const TextureCoordF &GLES1State::getCurrentTextureCoords(unsigned int unit) const
{
return mCurrentTextureCoords[unit];
}
void GLES1State::setMatrixMode(MatrixType mode)
{
setDirty(DIRTY_GLES1_MATRICES);
mMatrixMode = mode;
}
MatrixType GLES1State::getMatrixMode() const
{
return mMatrixMode;
}
GLint GLES1State::getCurrentMatrixStackDepth(GLenum queryType) const
{
switch (queryType)
{
case GL_MODELVIEW_STACK_DEPTH:
return clampCast<GLint>(mModelviewMatrices.size());
case GL_PROJECTION_STACK_DEPTH:
return clampCast<GLint>(mProjectionMatrices.size());
case GL_TEXTURE_STACK_DEPTH:
return clampCast<GLint>(mTextureMatrices[mGLState->getActiveSampler()].size());
default:
UNREACHABLE();
return 0;
}
}
void GLES1State::pushMatrix()
{
setDirty(DIRTY_GLES1_MATRICES);
auto &stack = currentMatrixStack();
stack.push_back(stack.back());
}
void GLES1State::popMatrix()
{
setDirty(DIRTY_GLES1_MATRICES);
auto &stack = currentMatrixStack();
stack.pop_back();
}
GLES1State::MatrixStack &GLES1State::currentMatrixStack()
{
setDirty(DIRTY_GLES1_MATRICES);
switch (mMatrixMode)
{
case MatrixType::Modelview:
return mModelviewMatrices;
case MatrixType::Projection:
return mProjectionMatrices;
case MatrixType::Texture:
return mTextureMatrices[mGLState->getActiveSampler()];
default:
UNREACHABLE();
return mModelviewMatrices;
}
}
const angle::Mat4 &GLES1State::getModelviewMatrix() const
{
return mModelviewMatrices.back();
}
const GLES1State::MatrixStack &GLES1State::currentMatrixStack() const
{
switch (mMatrixMode)
{
case MatrixType::Modelview:
return mModelviewMatrices;
case MatrixType::Projection:
return mProjectionMatrices;
case MatrixType::Texture:
return mTextureMatrices[mGLState->getActiveSampler()];
default:
UNREACHABLE();
return mModelviewMatrices;
}
}
void GLES1State::loadMatrix(const angle::Mat4 &m)
{
setDirty(DIRTY_GLES1_MATRICES);
currentMatrixStack().back() = m;
}
void GLES1State::multMatrix(const angle::Mat4 &m)
{
setDirty(DIRTY_GLES1_MATRICES);
angle::Mat4 currentMatrix = currentMatrixStack().back();
currentMatrixStack().back() = currentMatrix.product(m);
}
void GLES1State::setLogicOp(LogicalOperation opcodePacked)
{
setDirty(DIRTY_GLES1_LOGIC_OP);
mLogicOp = opcodePacked;
}
void GLES1State::setClientStateEnabled(ClientVertexArrayType clientState, bool enable)
{
setDirty(DIRTY_GLES1_CLIENT_STATE_ENABLE);
switch (clientState)
{
case ClientVertexArrayType::Vertex:
mVertexArrayEnabled = enable;
break;
case ClientVertexArrayType::Normal:
mNormalArrayEnabled = enable;
break;
case ClientVertexArrayType::Color:
mColorArrayEnabled = enable;
break;
case ClientVertexArrayType::PointSize:
mPointSizeArrayEnabled = enable;
break;
case ClientVertexArrayType::TextureCoord:
mTexCoordArrayEnabled[mClientActiveTexture] = enable;
break;
default:
UNREACHABLE();
break;
}
}
void GLES1State::setTexCoordArrayEnabled(unsigned int unit, bool enable)
{
setDirty(DIRTY_GLES1_CLIENT_STATE_ENABLE);
mTexCoordArrayEnabled[unit] = enable;
}
bool GLES1State::isClientStateEnabled(ClientVertexArrayType clientState) const
{
switch (clientState)
{
case ClientVertexArrayType::Vertex:
return mVertexArrayEnabled;
case ClientVertexArrayType::Normal:
return mNormalArrayEnabled;
case ClientVertexArrayType::Color:
return mColorArrayEnabled;
case ClientVertexArrayType::PointSize:
return mPointSizeArrayEnabled;
case ClientVertexArrayType::TextureCoord:
return mTexCoordArrayEnabled[mClientActiveTexture];
default:
UNREACHABLE();
return false;
}
}
bool GLES1State::isTexCoordArrayEnabled(unsigned int unit) const
{
ASSERT(unit < mTexCoordArrayEnabled.size());
return mTexCoordArrayEnabled[unit];
}
bool GLES1State::isTextureTargetEnabled(unsigned int unit, const TextureType type) const
{
return mTexUnitEnables[unit].test(type);
}
LightModelParameters &GLES1State::lightModelParameters()
{
setDirty(DIRTY_GLES1_LIGHTS);
return mLightModel;
}
const LightModelParameters &GLES1State::lightModelParameters() const
{
return mLightModel;
}
LightParameters &GLES1State::lightParameters(unsigned int light)
{
setDirty(DIRTY_GLES1_LIGHTS);
return mLights[light];
}
const LightParameters &GLES1State::lightParameters(unsigned int light) const
{
return mLights[light];
}
MaterialParameters &GLES1State::materialParameters()
{
setDirty(DIRTY_GLES1_MATERIAL);
return mMaterial;
}
const MaterialParameters &GLES1State::materialParameters() const
{
return mMaterial;
}
bool GLES1State::isColorMaterialEnabled() const
{
return mColorMaterialEnabled;
}
void GLES1State::setShadeModel(ShadingModel model)
{
setDirty(DIRTY_GLES1_SHADE_MODEL);
mShadeModel = model;
}
void GLES1State::setClipPlane(unsigned int plane, const GLfloat *equation)
{
setDirty(DIRTY_GLES1_CLIP_PLANES);
assert(plane < mClipPlanes.size());
mClipPlanes[plane].equation[0] = equation[0];
mClipPlanes[plane].equation[1] = equation[1];
mClipPlanes[plane].equation[2] = equation[2];
mClipPlanes[plane].equation[3] = equation[3];
}
void GLES1State::getClipPlane(unsigned int plane, GLfloat *equation) const
{
assert(plane < mClipPlanes.size());
equation[0] = mClipPlanes[plane].equation[0];
equation[1] = mClipPlanes[plane].equation[1];
equation[2] = mClipPlanes[plane].equation[2];
equation[3] = mClipPlanes[plane].equation[3];
}
FogParameters &GLES1State::fogParameters()
{
setDirty(DIRTY_GLES1_FOG);
return mFog;
}
const FogParameters &GLES1State::fogParameters() const
{
return mFog;
}
TextureEnvironmentParameters &GLES1State::textureEnvironment(unsigned int unit)
{
setDirty(DIRTY_GLES1_TEXTURE_ENVIRONMENT);
assert(unit < mTextureEnvironments.size());
return mTextureEnvironments[unit];
}
const TextureEnvironmentParameters &GLES1State::textureEnvironment(unsigned int unit) const
{
assert(unit < mTextureEnvironments.size());
return mTextureEnvironments[unit];
}
PointParameters &GLES1State::pointParameters()
{
setDirty(DIRTY_GLES1_POINT_PARAMETERS);
return mPointParameters;
}
const PointParameters &GLES1State::pointParameters() const
{
return mPointParameters;
}
AttributesMask GLES1State::getVertexArraysAttributeMask() const
{
AttributesMask attribsMask;
ClientVertexArrayType nonTexcoordArrays[] = {
ClientVertexArrayType::Vertex,
ClientVertexArrayType::Normal,
ClientVertexArrayType::Color,
ClientVertexArrayType::PointSize,
};
for (const ClientVertexArrayType attrib : nonTexcoordArrays)
{
attribsMask.set(GLES1Renderer::VertexArrayIndex(attrib, *this),
isClientStateEnabled(attrib));
}
for (unsigned int i = 0; i < GLES1Renderer::kTexUnitCount; i++)
{
attribsMask.set(GLES1Renderer::TexCoordArrayIndex(i), isTexCoordArrayEnabled(i));
}
return attribsMask;
}
AttributesMask GLES1State::getActiveAttributesMask() const
{
// The program always has 8 attributes enabled.
return AttributesMask(0xFF);
}
void GLES1State::setHint(GLenum target, GLenum mode)
{
setDirty(DIRTY_GLES1_HINT_SETTING);
HintSetting setting = FromGLenum<HintSetting>(mode);
switch (target)
{
case GL_PERSPECTIVE_CORRECTION_HINT:
mPerspectiveCorrectionHint = setting;
break;
case GL_POINT_SMOOTH_HINT:
mPointSmoothHint = setting;
break;
case GL_LINE_SMOOTH_HINT:
mLineSmoothHint = setting;
break;
case GL_FOG_HINT:
mFogHint = setting;
break;
default:
UNREACHABLE();
}
}
GLenum GLES1State::getHint(GLenum target)
{
switch (target)
{
case GL_PERSPECTIVE_CORRECTION_HINT:
return ToGLenum(mPerspectiveCorrectionHint);
case GL_POINT_SMOOTH_HINT:
return ToGLenum(mPointSmoothHint);
case GL_LINE_SMOOTH_HINT:
return ToGLenum(mLineSmoothHint);
case GL_FOG_HINT:
return ToGLenum(mFogHint);
default:
UNREACHABLE();
return 0;
}
}
void GLES1State::setDirty(DirtyGles1Type type)
{
mDirtyBits.set(type);
}
void GLES1State::setAllDirty()
{
mDirtyBits.set();
}
void GLES1State::clearDirty()
{
mDirtyBits.reset();
}
bool GLES1State::isDirty(DirtyGles1Type type) const
{
return mDirtyBits.test(type);
}
} // namespace gl