// // 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; ClipPlaneParameters &ClipPlaneParameters::operator=(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; // > When enabled, both the ambient (acm) and diffuse (dcm) properties of both the front and // > back material are immediately set to the value of the current color, and will track changes // > to the current color resulting from either the Color commands or drawing vertex arrays with // > the color array enabled. // > The replacements made to material properties are permanent; the replaced values remain // > until changed by either sending a new color or by setting a new material value when // > COLOR_MATERIAL is not currently enabled, to override that particular value. if (isColorMaterialEnabled()) { mMaterial.ambient = color; mMaterial.diffuse = 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; } bool GLES1State::shouldHandleDirtyProgram() { bool ret = isDirty(DIRTY_GLES1_PROGRAM); clearDirtyBits(DIRTY_GLES1_PROGRAM); return ret; } 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(mModelviewMatrices.size()); case GL_PROJECTION_STACK_DEPTH: return clampCast(mProjectionMatrices.size()); case GL_TEXTURE_STACK_DEPTH: return clampCast(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::getMatrixStack(MatrixType mode) const { switch (mode) { case MatrixType::Modelview: return mModelviewMatrices; case MatrixType::Projection: return mProjectionMatrices; case MatrixType::Texture: return mTextureMatrices[mGLState->getActiveSampler()]; default: UNREACHABLE(); return mModelviewMatrices; } } const GLES1State::MatrixStack &GLES1State::currentMatrixStack() const { return getMatrixStack(mMatrixMode); } 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::setLogicOpEnabled(bool enabled) { setDirty(DIRTY_GLES1_LOGIC_OP); mLogicOpEnabled = enabled; } 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 { if (mTexUnitEnables.empty()) { return false; } 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]; } bool operator==(const TextureEnvironmentParameters &a, const TextureEnvironmentParameters &b) { return a.tie() == b.tie(); } bool operator!=(const TextureEnvironmentParameters &a, const TextureEnvironmentParameters &b) { return !(a == b); } 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 < 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(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) const { 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; } } } // namespace gl