From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- gfx/angle/checkout/src/libANGLE/angletypes.cpp | 1039 ++++++++++++++++++++++++ 1 file changed, 1039 insertions(+) create mode 100644 gfx/angle/checkout/src/libANGLE/angletypes.cpp (limited to 'gfx/angle/checkout/src/libANGLE/angletypes.cpp') diff --git a/gfx/angle/checkout/src/libANGLE/angletypes.cpp b/gfx/angle/checkout/src/libANGLE/angletypes.cpp new file mode 100644 index 0000000000..19f9a25441 --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/angletypes.cpp @@ -0,0 +1,1039 @@ +// +// Copyright 2013 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. +// + +// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 + +#include "libANGLE/angletypes.h" +#include "libANGLE/Program.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/VertexAttribute.h" + +#include + +namespace gl +{ +namespace +{ +bool IsStencilNoOp(GLenum stencilFunc, + GLenum stencilFail, + GLenum stencilPassDepthFail, + GLenum stencilPassDepthPass) +{ + const bool isNeverAndKeep = stencilFunc == GL_NEVER && stencilFail == GL_KEEP; + const bool isAlwaysAndKeepOrAllKeep = (stencilFunc == GL_ALWAYS || stencilFail == GL_KEEP) && + stencilPassDepthFail == GL_KEEP && + stencilPassDepthPass == GL_KEEP; + + return isNeverAndKeep || isAlwaysAndKeepOrAllKeep; +} + +// Calculate whether the range [outsideLow, outsideHigh] encloses the range [insideLow, insideHigh] +bool EnclosesRange(int outsideLow, int outsideHigh, int insideLow, int insideHigh) +{ + return outsideLow <= insideLow && outsideHigh >= insideHigh; +} + +bool IsAdvancedBlendEquation(gl::BlendEquationType blendEquation) +{ + return blendEquation >= gl::BlendEquationType::Multiply && + blendEquation <= gl::BlendEquationType::HslLuminosity; +} +} // anonymous namespace + +RasterizerState::RasterizerState() +{ + memset(this, 0, sizeof(RasterizerState)); + + rasterizerDiscard = false; + cullFace = false; + cullMode = CullFaceMode::Back; + frontFace = GL_CCW; + polygonOffsetFill = false; + polygonOffsetFactor = 0.0f; + polygonOffsetUnits = 0.0f; + pointDrawMode = false; + multiSample = false; + dither = true; +} + +RasterizerState::RasterizerState(const RasterizerState &other) +{ + memcpy(this, &other, sizeof(RasterizerState)); +} + +RasterizerState &RasterizerState::operator=(const RasterizerState &other) +{ + memcpy(this, &other, sizeof(RasterizerState)); + return *this; +} + +bool operator==(const RasterizerState &a, const RasterizerState &b) +{ + return memcmp(&a, &b, sizeof(RasterizerState)) == 0; +} + +bool operator!=(const RasterizerState &a, const RasterizerState &b) +{ + return !(a == b); +} + +BlendState::BlendState() +{ + memset(this, 0, sizeof(BlendState)); + + blend = false; + sourceBlendRGB = GL_ONE; + sourceBlendAlpha = GL_ONE; + destBlendRGB = GL_ZERO; + destBlendAlpha = GL_ZERO; + blendEquationRGB = GL_FUNC_ADD; + blendEquationAlpha = GL_FUNC_ADD; + colorMaskRed = true; + colorMaskGreen = true; + colorMaskBlue = true; + colorMaskAlpha = true; +} + +BlendState::BlendState(const BlendState &other) +{ + memcpy(this, &other, sizeof(BlendState)); +} + +bool operator==(const BlendState &a, const BlendState &b) +{ + return memcmp(&a, &b, sizeof(BlendState)) == 0; +} + +bool operator!=(const BlendState &a, const BlendState &b) +{ + return !(a == b); +} + +DepthStencilState::DepthStencilState() +{ + memset(this, 0, sizeof(DepthStencilState)); + + depthTest = false; + depthFunc = GL_LESS; + depthMask = true; + stencilTest = false; + stencilFunc = GL_ALWAYS; + stencilMask = static_cast(-1); + stencilWritemask = static_cast(-1); + stencilBackFunc = GL_ALWAYS; + stencilBackMask = static_cast(-1); + stencilBackWritemask = static_cast(-1); + stencilFail = GL_KEEP; + stencilPassDepthFail = GL_KEEP; + stencilPassDepthPass = GL_KEEP; + stencilBackFail = GL_KEEP; + stencilBackPassDepthFail = GL_KEEP; + stencilBackPassDepthPass = GL_KEEP; +} + +DepthStencilState::DepthStencilState(const DepthStencilState &other) +{ + memcpy(this, &other, sizeof(DepthStencilState)); +} + +DepthStencilState &DepthStencilState::operator=(const DepthStencilState &other) +{ + memcpy(this, &other, sizeof(DepthStencilState)); + return *this; +} + +bool DepthStencilState::isDepthMaskedOut() const +{ + return !depthMask; +} + +bool DepthStencilState::isStencilMaskedOut() const +{ + return (stencilMask & stencilWritemask) == 0; +} + +bool DepthStencilState::isStencilNoOp() const +{ + return isStencilMaskedOut() || + IsStencilNoOp(stencilFunc, stencilFail, stencilPassDepthFail, stencilPassDepthPass); +} + +bool DepthStencilState::isStencilBackNoOp() const +{ + const bool isStencilBackMaskedOut = (stencilBackMask & stencilBackWritemask) == 0; + return isStencilBackMaskedOut || + IsStencilNoOp(stencilBackFunc, stencilBackFail, stencilBackPassDepthFail, + stencilBackPassDepthPass); +} + +bool operator==(const DepthStencilState &a, const DepthStencilState &b) +{ + return memcmp(&a, &b, sizeof(DepthStencilState)) == 0; +} + +bool operator!=(const DepthStencilState &a, const DepthStencilState &b) +{ + return !(a == b); +} + +SamplerState::SamplerState() +{ + memset(this, 0, sizeof(SamplerState)); + + setMinFilter(GL_NEAREST_MIPMAP_LINEAR); + setMagFilter(GL_LINEAR); + setWrapS(GL_REPEAT); + setWrapT(GL_REPEAT); + setWrapR(GL_REPEAT); + setMaxAnisotropy(1.0f); + setMinLod(-1000.0f); + setMaxLod(1000.0f); + setCompareMode(GL_NONE); + setCompareFunc(GL_LEQUAL); + setSRGBDecode(GL_DECODE_EXT); +} + +SamplerState::SamplerState(const SamplerState &other) = default; + +SamplerState &SamplerState::operator=(const SamplerState &other) = default; + +// static +SamplerState SamplerState::CreateDefaultForTarget(TextureType type) +{ + SamplerState state; + + // According to OES_EGL_image_external and ARB_texture_rectangle: For external textures, the + // default min filter is GL_LINEAR and the default s and t wrap modes are GL_CLAMP_TO_EDGE. + if (type == TextureType::External || type == TextureType::Rectangle) + { + state.mMinFilter = GL_LINEAR; + state.mWrapS = GL_CLAMP_TO_EDGE; + state.mWrapT = GL_CLAMP_TO_EDGE; + } + + return state; +} + +bool SamplerState::setMinFilter(GLenum minFilter) +{ + if (mMinFilter != minFilter) + { + mMinFilter = minFilter; + mCompleteness.typed.minFilter = static_cast(FromGLenum(minFilter)); + return true; + } + return false; +} + +bool SamplerState::setMagFilter(GLenum magFilter) +{ + if (mMagFilter != magFilter) + { + mMagFilter = magFilter; + mCompleteness.typed.magFilter = static_cast(FromGLenum(magFilter)); + return true; + } + return false; +} + +bool SamplerState::setWrapS(GLenum wrapS) +{ + if (mWrapS != wrapS) + { + mWrapS = wrapS; + mCompleteness.typed.wrapS = static_cast(FromGLenum(wrapS)); + return true; + } + return false; +} + +bool SamplerState::setWrapT(GLenum wrapT) +{ + if (mWrapT != wrapT) + { + mWrapT = wrapT; + updateWrapTCompareMode(); + return true; + } + return false; +} + +bool SamplerState::setWrapR(GLenum wrapR) +{ + if (mWrapR != wrapR) + { + mWrapR = wrapR; + return true; + } + return false; +} + +bool SamplerState::setMaxAnisotropy(float maxAnisotropy) +{ + if (mMaxAnisotropy != maxAnisotropy) + { + mMaxAnisotropy = maxAnisotropy; + return true; + } + return false; +} + +bool SamplerState::setMinLod(GLfloat minLod) +{ + if (mMinLod != minLod) + { + mMinLod = minLod; + return true; + } + return false; +} + +bool SamplerState::setMaxLod(GLfloat maxLod) +{ + if (mMaxLod != maxLod) + { + mMaxLod = maxLod; + return true; + } + return false; +} + +bool SamplerState::setCompareMode(GLenum compareMode) +{ + if (mCompareMode != compareMode) + { + mCompareMode = compareMode; + updateWrapTCompareMode(); + return true; + } + return false; +} + +bool SamplerState::setCompareFunc(GLenum compareFunc) +{ + if (mCompareFunc != compareFunc) + { + mCompareFunc = compareFunc; + return true; + } + return false; +} + +bool SamplerState::setSRGBDecode(GLenum sRGBDecode) +{ + if (mSRGBDecode != sRGBDecode) + { + mSRGBDecode = sRGBDecode; + return true; + } + return false; +} + +bool SamplerState::setBorderColor(const ColorGeneric &color) +{ + if (mBorderColor != color) + { + mBorderColor = color; + return true; + } + return false; +} + +void SamplerState::updateWrapTCompareMode() +{ + uint8_t wrap = static_cast(FromGLenum(mWrapT)); + uint8_t compare = static_cast(mCompareMode == GL_NONE ? 0x10 : 0x00); + mCompleteness.typed.wrapTCompareMode = wrap | compare; +} + +ImageUnit::ImageUnit() + : texture(), level(0), layered(false), layer(0), access(GL_READ_ONLY), format(GL_R32UI) +{} + +ImageUnit::ImageUnit(const ImageUnit &other) = default; + +ImageUnit::~ImageUnit() = default; + +BlendStateExt::BlendStateExt(const size_t drawBufferCount) + : mParameterMask(FactorStorage::GetMask(drawBufferCount)), + mSrcColor(FactorStorage::GetReplicatedValue(BlendFactorType::One, mParameterMask)), + mDstColor(FactorStorage::GetReplicatedValue(BlendFactorType::Zero, mParameterMask)), + mSrcAlpha(FactorStorage::GetReplicatedValue(BlendFactorType::One, mParameterMask)), + mDstAlpha(FactorStorage::GetReplicatedValue(BlendFactorType::Zero, mParameterMask)), + mEquationColor(EquationStorage::GetReplicatedValue(BlendEquationType::Add, mParameterMask)), + mEquationAlpha(EquationStorage::GetReplicatedValue(BlendEquationType::Add, mParameterMask)), + mAllColorMask( + ColorMaskStorage::GetReplicatedValue(PackColorMask(true, true, true, true), + ColorMaskStorage::GetMask(drawBufferCount))), + mColorMask(mAllColorMask), + mAllEnabledMask(0xFF >> (8 - drawBufferCount)), + mDrawBufferCount(drawBufferCount) +{} + +BlendStateExt::BlendStateExt(const BlendStateExt &other) = default; + +BlendStateExt &BlendStateExt::operator=(const BlendStateExt &other) = default; + +void BlendStateExt::setEnabled(const bool enabled) +{ + mEnabledMask = enabled ? mAllEnabledMask : DrawBufferMask::Zero(); +} + +void BlendStateExt::setEnabledIndexed(const size_t index, const bool enabled) +{ + ASSERT(index < mDrawBufferCount); + mEnabledMask.set(index, enabled); +} + +BlendStateExt::ColorMaskStorage::Type BlendStateExt::expandColorMaskValue(const bool red, + const bool green, + const bool blue, + const bool alpha) const +{ + return BlendStateExt::ColorMaskStorage::GetReplicatedValue( + PackColorMask(red, green, blue, alpha), mAllColorMask); +} + +BlendStateExt::ColorMaskStorage::Type BlendStateExt::expandColorMaskIndexed( + const size_t index) const +{ + return ColorMaskStorage::GetReplicatedValue( + ColorMaskStorage::GetValueIndexed(index, mColorMask), mAllColorMask); +} + +void BlendStateExt::setColorMask(const bool red, + const bool green, + const bool blue, + const bool alpha) +{ + mColorMask = expandColorMaskValue(red, green, blue, alpha); +} + +void BlendStateExt::setColorMaskIndexed(const size_t index, const uint8_t value) +{ + ASSERT(index < mDrawBufferCount); + ASSERT(value <= 0xF); + ColorMaskStorage::SetValueIndexed(index, value, &mColorMask); +} + +void BlendStateExt::setColorMaskIndexed(const size_t index, + const bool red, + const bool green, + const bool blue, + const bool alpha) +{ + ASSERT(index < mDrawBufferCount); + ColorMaskStorage::SetValueIndexed(index, PackColorMask(red, green, blue, alpha), &mColorMask); +} + +uint8_t BlendStateExt::getColorMaskIndexed(const size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return ColorMaskStorage::GetValueIndexed(index, mColorMask); +} + +void BlendStateExt::getColorMaskIndexed(const size_t index, + bool *red, + bool *green, + bool *blue, + bool *alpha) const +{ + ASSERT(index < mDrawBufferCount); + UnpackColorMask(ColorMaskStorage::GetValueIndexed(index, mColorMask), red, green, blue, alpha); +} + +DrawBufferMask BlendStateExt::compareColorMask(ColorMaskStorage::Type other) const +{ + return ColorMaskStorage::GetDiffMask(mColorMask, other); +} + +BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationValue(const GLenum mode) const +{ + return EquationStorage::GetReplicatedValue(FromGLenum(mode), mParameterMask); +} + +BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationValue( + const gl::BlendEquationType equation) const +{ + return EquationStorage::GetReplicatedValue(equation, mParameterMask); +} + +BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationColorIndexed( + const size_t index) const +{ + return EquationStorage::GetReplicatedValue( + EquationStorage::GetValueIndexed(index, mEquationColor), mParameterMask); +} + +BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationAlphaIndexed( + const size_t index) const +{ + return EquationStorage::GetReplicatedValue( + EquationStorage::GetValueIndexed(index, mEquationAlpha), mParameterMask); +} + +void BlendStateExt::setEquations(const GLenum modeColor, const GLenum modeAlpha) +{ + const gl::BlendEquationType colorEquation = FromGLenum(modeColor); + const gl::BlendEquationType alphaEquation = FromGLenum(modeAlpha); + + mEquationColor = expandEquationValue(colorEquation); + mEquationAlpha = expandEquationValue(alphaEquation); + + // Note that advanced blend equations cannot be independently set for color and alpha, so only + // the color equation can be checked. + if (IsAdvancedBlendEquation(colorEquation)) + { + mUsesAdvancedBlendEquationMask = mAllEnabledMask; + } + else + { + mUsesAdvancedBlendEquationMask.reset(); + } +} + +void BlendStateExt::setEquationsIndexed(const size_t index, + const GLenum modeColor, + const GLenum modeAlpha) +{ + ASSERT(index < mDrawBufferCount); + + const gl::BlendEquationType colorEquation = FromGLenum(modeColor); + const gl::BlendEquationType alphaEquation = FromGLenum(modeAlpha); + + EquationStorage::SetValueIndexed(index, colorEquation, &mEquationColor); + EquationStorage::SetValueIndexed(index, alphaEquation, &mEquationAlpha); + + mUsesAdvancedBlendEquationMask.set(index, IsAdvancedBlendEquation(colorEquation)); +} + +void BlendStateExt::setEquationsIndexed(const size_t index, + const size_t sourceIndex, + const BlendStateExt &source) +{ + ASSERT(index < mDrawBufferCount); + ASSERT(sourceIndex < source.mDrawBufferCount); + + const gl::BlendEquationType colorEquation = + EquationStorage::GetValueIndexed(sourceIndex, source.mEquationColor); + const gl::BlendEquationType alphaEquation = + EquationStorage::GetValueIndexed(sourceIndex, source.mEquationAlpha); + + EquationStorage::SetValueIndexed(index, colorEquation, &mEquationColor); + EquationStorage::SetValueIndexed(index, alphaEquation, &mEquationAlpha); + + mUsesAdvancedBlendEquationMask.set(index, IsAdvancedBlendEquation(colorEquation)); +} + +GLenum BlendStateExt::getEquationColorIndexed(size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return ToGLenum(EquationStorage::GetValueIndexed(index, mEquationColor)); +} + +GLenum BlendStateExt::getEquationAlphaIndexed(size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return ToGLenum(EquationStorage::GetValueIndexed(index, mEquationAlpha)); +} + +DrawBufferMask BlendStateExt::compareEquations(const EquationStorage::Type color, + const EquationStorage::Type alpha) const +{ + return EquationStorage::GetDiffMask(mEquationColor, color) | + EquationStorage::GetDiffMask(mEquationAlpha, alpha); +} + +BlendStateExt::FactorStorage::Type BlendStateExt::expandFactorValue(const GLenum func) const +{ + return FactorStorage::GetReplicatedValue(FromGLenum(func), mParameterMask); +} + +BlendStateExt::FactorStorage::Type BlendStateExt::expandSrcColorIndexed(const size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mSrcColor), + mParameterMask); +} + +BlendStateExt::FactorStorage::Type BlendStateExt::expandDstColorIndexed(const size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mDstColor), + mParameterMask); +} + +BlendStateExt::FactorStorage::Type BlendStateExt::expandSrcAlphaIndexed(const size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mSrcAlpha), + mParameterMask); +} + +BlendStateExt::FactorStorage::Type BlendStateExt::expandDstAlphaIndexed(const size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mDstAlpha), + mParameterMask); +} + +void BlendStateExt::setFactors(const GLenum srcColor, + const GLenum dstColor, + const GLenum srcAlpha, + const GLenum dstAlpha) +{ + mSrcColor = expandFactorValue(srcColor); + mDstColor = expandFactorValue(dstColor); + mSrcAlpha = expandFactorValue(srcAlpha); + mDstAlpha = expandFactorValue(dstAlpha); +} + +void BlendStateExt::setFactorsIndexed(const size_t index, + const GLenum srcColor, + const GLenum dstColor, + const GLenum srcAlpha, + const GLenum dstAlpha) +{ + ASSERT(index < mDrawBufferCount); + FactorStorage::SetValueIndexed(index, FromGLenum(srcColor), &mSrcColor); + FactorStorage::SetValueIndexed(index, FromGLenum(dstColor), &mDstColor); + FactorStorage::SetValueIndexed(index, FromGLenum(srcAlpha), &mSrcAlpha); + FactorStorage::SetValueIndexed(index, FromGLenum(dstAlpha), &mDstAlpha); +} + +void BlendStateExt::setFactorsIndexed(const size_t index, + const size_t sourceIndex, + const BlendStateExt &source) +{ + ASSERT(index < mDrawBufferCount); + ASSERT(sourceIndex < source.mDrawBufferCount); + FactorStorage::SetValueIndexed( + index, FactorStorage::GetValueIndexed(sourceIndex, source.mSrcColor), &mSrcColor); + FactorStorage::SetValueIndexed( + index, FactorStorage::GetValueIndexed(sourceIndex, source.mDstColor), &mDstColor); + FactorStorage::SetValueIndexed( + index, FactorStorage::GetValueIndexed(sourceIndex, source.mSrcAlpha), &mSrcAlpha); + FactorStorage::SetValueIndexed( + index, FactorStorage::GetValueIndexed(sourceIndex, source.mDstAlpha), &mDstAlpha); +} + +GLenum BlendStateExt::getSrcColorIndexed(size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return ToGLenum(FactorStorage::GetValueIndexed(index, mSrcColor)); +} + +GLenum BlendStateExt::getDstColorIndexed(size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return ToGLenum(FactorStorage::GetValueIndexed(index, mDstColor)); +} + +GLenum BlendStateExt::getSrcAlphaIndexed(size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return ToGLenum(FactorStorage::GetValueIndexed(index, mSrcAlpha)); +} + +GLenum BlendStateExt::getDstAlphaIndexed(size_t index) const +{ + ASSERT(index < mDrawBufferCount); + return ToGLenum(FactorStorage::GetValueIndexed(index, mDstAlpha)); +} + +DrawBufferMask BlendStateExt::compareFactors(const FactorStorage::Type srcColor, + const FactorStorage::Type dstColor, + const FactorStorage::Type srcAlpha, + const FactorStorage::Type dstAlpha) const +{ + return FactorStorage::GetDiffMask(mSrcColor, srcColor) | + FactorStorage::GetDiffMask(mDstColor, dstColor) | + FactorStorage::GetDiffMask(mSrcAlpha, srcAlpha) | + FactorStorage::GetDiffMask(mDstAlpha, dstAlpha); +} + +static void MinMax(int a, int b, int *minimum, int *maximum) +{ + if (a < b) + { + *minimum = a; + *maximum = b; + } + else + { + *minimum = b; + *maximum = a; + } +} + +template <> +bool RectangleImpl::empty() const +{ + return width == 0 && height == 0; +} + +template <> +bool RectangleImpl::empty() const +{ + return std::abs(width) < std::numeric_limits::epsilon() && + std::abs(height) < std::numeric_limits::epsilon(); +} + +bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection) +{ + angle::CheckedNumeric sourceX2(source.x); + sourceX2 += source.width; + if (!sourceX2.IsValid()) + { + return false; + } + angle::CheckedNumeric sourceY2(source.y); + sourceY2 += source.height; + if (!sourceY2.IsValid()) + { + return false; + } + + int minSourceX, maxSourceX, minSourceY, maxSourceY; + MinMax(source.x, sourceX2.ValueOrDie(), &minSourceX, &maxSourceX); + MinMax(source.y, sourceY2.ValueOrDie(), &minSourceY, &maxSourceY); + + angle::CheckedNumeric clipX2(clip.x); + clipX2 += clip.width; + if (!clipX2.IsValid()) + { + return false; + } + angle::CheckedNumeric clipY2(clip.y); + clipY2 += clip.height; + if (!clipY2.IsValid()) + { + return false; + } + + int minClipX, maxClipX, minClipY, maxClipY; + MinMax(clip.x, clipX2.ValueOrDie(), &minClipX, &maxClipX); + MinMax(clip.y, clipY2.ValueOrDie(), &minClipY, &maxClipY); + + if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY || + maxSourceY <= minClipY) + { + return false; + } + + int x = std::max(minSourceX, minClipX); + int y = std::max(minSourceY, minClipY); + int width = std::min(maxSourceX, maxClipX) - x; + int height = std::min(maxSourceY, maxClipY) - y; + + if (intersection) + { + intersection->x = x; + intersection->y = y; + intersection->width = width; + intersection->height = height; + } + return width != 0 && height != 0; +} + +void GetEnclosingRectangle(const Rectangle &rect1, const Rectangle &rect2, Rectangle *rectUnion) +{ + // All callers use non-flipped framebuffer-size-clipped rectangles, so both flip and overflow + // are impossible. + ASSERT(!rect1.isReversedX() && !rect1.isReversedY()); + ASSERT(!rect2.isReversedX() && !rect2.isReversedY()); + ASSERT((angle::CheckedNumeric(rect1.x) + rect1.width).IsValid()); + ASSERT((angle::CheckedNumeric(rect1.y) + rect1.height).IsValid()); + ASSERT((angle::CheckedNumeric(rect2.x) + rect2.width).IsValid()); + ASSERT((angle::CheckedNumeric(rect2.y) + rect2.height).IsValid()); + + // This function calculates a rectangle that covers both input rectangles: + // + // +---------+ + // rect1 --> | | + // | +---+-----+ + // | | | | <-- rect2 + // +-----+---+ | + // | | + // +---------+ + // + // xy0 = min(rect1.xy0, rect2.xy0) + // \ + // +---------+-----+ + // union --> | . | + // | + . + . . + + // | . . | + // + . . + . + | + // | . | + // +-----+---------+ + // / + // xy1 = max(rect1.xy1, rect2.xy1) + + int x0 = std::min(rect1.x0(), rect2.x0()); + int y0 = std::min(rect1.y0(), rect2.y0()); + + int x1 = std::max(rect1.x1(), rect2.x1()); + int y1 = std::max(rect1.y1(), rect2.y1()); + + rectUnion->x = x0; + rectUnion->y = y0; + rectUnion->width = x1 - x0; + rectUnion->height = y1 - y0; +} + +void ExtendRectangle(const Rectangle &source, const Rectangle &extend, Rectangle *extended) +{ + // All callers use non-flipped framebuffer-size-clipped rectangles, so both flip and overflow + // are impossible. + ASSERT(!source.isReversedX() && !source.isReversedY()); + ASSERT(!extend.isReversedX() && !extend.isReversedY()); + ASSERT((angle::CheckedNumeric(source.x) + source.width).IsValid()); + ASSERT((angle::CheckedNumeric(source.y) + source.height).IsValid()); + ASSERT((angle::CheckedNumeric(extend.x) + extend.width).IsValid()); + ASSERT((angle::CheckedNumeric(extend.y) + extend.height).IsValid()); + + int x0 = source.x0(); + int x1 = source.x1(); + int y0 = source.y0(); + int y1 = source.y1(); + + const int extendX0 = extend.x0(); + const int extendX1 = extend.x1(); + const int extendY0 = extend.y0(); + const int extendY1 = extend.y1(); + + // For each side of the rectangle, calculate whether it can be extended by the second rectangle. + // If so, extend it and continue for the next side with the new dimensions. + + // Left: Reduce x0 if the second rectangle's vertical edge covers the source's: + // + // +--- - - - +--- - - - + // | | + // | +--------------+ +-----------------+ + // | | source | --> | source | + // | +--------------+ +-----------------+ + // | | + // +--- - - - +--- - - - + // + const bool enclosesHeight = EnclosesRange(extendY0, extendY1, y0, y1); + if (extendX0 < x0 && extendX1 >= x0 && enclosesHeight) + { + x0 = extendX0; + } + + // Right: Increase x1 simiarly. + if (extendX0 <= x1 && extendX1 > x1 && enclosesHeight) + { + x1 = extendX1; + } + + // Top: Reduce y0 if the second rectangle's horizontal edge covers the source's potentially + // extended edge. + const bool enclosesWidth = EnclosesRange(extendX0, extendX1, x0, x1); + if (extendY0 < y0 && extendY1 >= y0 && enclosesWidth) + { + y0 = extendY0; + } + + // Right: Increase y1 simiarly. + if (extendY0 <= y1 && extendY1 > y1 && enclosesWidth) + { + y1 = extendY1; + } + + extended->x = x0; + extended->y = y0; + extended->width = x1 - x0; + extended->height = y1 - y0; +} + +bool Box::valid() const +{ + return width != 0 && height != 0 && depth != 0; +} + +bool Box::operator==(const Box &other) const +{ + return (x == other.x && y == other.y && z == other.z && width == other.width && + height == other.height && depth == other.depth); +} + +bool Box::operator!=(const Box &other) const +{ + return !(*this == other); +} + +Rectangle Box::toRect() const +{ + ASSERT(z == 0 && depth == 1); + return Rectangle(x, y, width, height); +} + +bool Box::coversSameExtent(const Extents &size) const +{ + return x == 0 && y == 0 && z == 0 && width == size.width && height == size.height && + depth == size.depth; +} + +bool Box::contains(const Box &other) const +{ + return x <= other.x && y <= other.y && z <= other.z && x + width >= other.x + other.width && + y + height >= other.y + other.height && z + depth >= other.z + other.depth; +} + +size_t Box::volume() const +{ + return width * height * depth; +} + +void Box::extend(const Box &other) +{ + // This extends the logic of "ExtendRectangle" to 3 dimensions + + int x0 = x; + int x1 = x + width; + int y0 = y; + int y1 = y + height; + int z0 = z; + int z1 = z + depth; + + const int otherx0 = other.x; + const int otherx1 = other.x + other.width; + const int othery0 = other.y; + const int othery1 = other.y + other.height; + const int otherz0 = other.z; + const int otherz1 = other.z + other.depth; + + // For each side of the box, calculate whether it can be extended by the other box. + // If so, extend it and continue to the next side with the new dimensions. + + const bool enclosesWidth = EnclosesRange(otherx0, otherx1, x0, x1); + const bool enclosesHeight = EnclosesRange(othery0, othery1, y0, y1); + const bool enclosesDepth = EnclosesRange(otherz0, otherz1, z0, z1); + + // Left: Reduce x0 if the other box's Y and Z plane encloses the source + if (otherx0 < x0 && otherx1 >= x0 && enclosesHeight && enclosesDepth) + { + x0 = otherx0; + } + + // Right: Increase x1 simiarly. + if (otherx0 <= x1 && otherx1 > x1 && enclosesHeight && enclosesDepth) + { + x1 = otherx1; + } + + // Bottom: Reduce y0 if the other box's X and Z plane encloses the source + if (othery0 < y0 && othery1 >= y0 && enclosesWidth && enclosesDepth) + { + y0 = othery0; + } + + // Top: Increase y1 simiarly. + if (othery0 <= y1 && othery1 > y1 && enclosesWidth && enclosesDepth) + { + y1 = othery1; + } + + // Front: Reduce z0 if the other box's X and Y plane encloses the source + if (otherz0 < z0 && otherz1 >= z0 && enclosesWidth && enclosesHeight) + { + z0 = otherz0; + } + + // Back: Increase z1 simiarly. + if (otherz0 <= z1 && otherz1 > z1 && enclosesWidth && enclosesHeight) + { + z1 = otherz1; + } + + // Update member var with new dimensions + x = x0; + width = x1 - x0; + y = y0; + height = y1 - y0; + z = z0; + depth = z1 - z0; +} + +bool operator==(const Offset &a, const Offset &b) +{ + return a.x == b.x && a.y == b.y && a.z == b.z; +} + +bool operator!=(const Offset &a, const Offset &b) +{ + return !(a == b); +} + +bool operator==(const Extents &lhs, const Extents &rhs) +{ + return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depth == rhs.depth; +} + +bool operator!=(const Extents &lhs, const Extents &rhs) +{ + return !(lhs == rhs); +} + +bool ValidateComponentTypeMasks(unsigned long outputTypes, + unsigned long inputTypes, + unsigned long outputMask, + unsigned long inputMask) +{ + static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS <= kMaxComponentTypeMaskIndex, + "Output/input masks should fit into 16 bits - 1 bit per draw buffer. The " + "corresponding type masks should fit into 32 bits - 2 bits per draw buffer."); + static_assert(MAX_VERTEX_ATTRIBS <= kMaxComponentTypeMaskIndex, + "Output/input masks should fit into 16 bits - 1 bit per attrib. The " + "corresponding type masks should fit into 32 bits - 2 bits per attrib."); + + // For performance reasons, draw buffer and attribute type validation is done using bit masks. + // We store two bits representing the type split, with the low bit in the lower 16 bits of the + // variable, and the high bit in the upper 16 bits of the variable. This is done so we can AND + // with the elswewhere used DrawBufferMask or AttributeMask. + + // OR the masks with themselves, shifted 16 bits. This is to match our split type bits. + outputMask |= (outputMask << kMaxComponentTypeMaskIndex); + inputMask |= (inputMask << kMaxComponentTypeMaskIndex); + + // To validate: + // 1. Remove any indexes that are not enabled in the input (& inputMask) + // 2. Remove any indexes that exist in output, but not in input (& outputMask) + // 3. Use == to verify equality + return (outputTypes & inputMask) == ((inputTypes & outputMask) & inputMask); +} + +GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer &binding) +{ + Buffer *buffer = binding.get(); + if (buffer == nullptr) + { + return 0; + } + + const GLsizeiptr bufferSize = static_cast(buffer->getSize()); + + if (binding.getSize() == 0) + { + return bufferSize; + } + + const GLintptr offset = binding.getOffset(); + const GLsizeiptr size = binding.getSize(); + + ASSERT(offset >= 0 && bufferSize >= 0); + + if (bufferSize <= offset) + { + return 0; + } + + return std::min(size, bufferSize - offset); +} + +} // namespace gl -- cgit v1.2.3