//
// 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 <limits>

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));
}

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<GLuint>(-1);
    stencilWritemask         = static_cast<GLuint>(-1);
    stencilBackFunc          = GL_ALWAYS;
    stencilBackMask          = static_cast<GLuint>(-1);
    stencilBackWritemask     = static_cast<GLuint>(-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));
}

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<uint8_t>(FromGLenum<FilterMode>(minFilter));
        return true;
    }
    return false;
}

bool SamplerState::setMagFilter(GLenum magFilter)
{
    if (mMagFilter != magFilter)
    {
        mMagFilter                    = magFilter;
        mCompleteness.typed.magFilter = static_cast<uint8_t>(FromGLenum<FilterMode>(magFilter));
        return true;
    }
    return false;
}

bool SamplerState::setWrapS(GLenum wrapS)
{
    if (mWrapS != wrapS)
    {
        mWrapS                    = wrapS;
        mCompleteness.typed.wrapS = static_cast<uint8_t>(FromGLenum<WrapMode>(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<uint8_t>(FromGLenum<WrapMode>(mWrapT));
    uint8_t compare = static_cast<uint8_t>(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<BlendEquationType>(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<BlendEquationType>(modeColor);
    const gl::BlendEquationType alphaEquation = FromGLenum<BlendEquationType>(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<BlendEquationType>(modeColor);
    const gl::BlendEquationType alphaEquation = FromGLenum<BlendEquationType>(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<BlendFactorType>(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<BlendFactorType>(srcColor), &mSrcColor);
    FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(dstColor), &mDstColor);
    FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(srcAlpha), &mSrcAlpha);
    FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(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<int>::empty() const
{
    return width == 0 && height == 0;
}

template <>
bool RectangleImpl<float>::empty() const
{
    return std::abs(width) < std::numeric_limits<float>::epsilon() &&
           std::abs(height) < std::numeric_limits<float>::epsilon();
}

bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection)
{
    angle::CheckedNumeric<int> sourceX2(source.x);
    sourceX2 += source.width;
    if (!sourceX2.IsValid())
    {
        return false;
    }
    angle::CheckedNumeric<int> 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<int> clipX2(clip.x);
    clipX2 += clip.width;
    if (!clipX2.IsValid())
    {
        return false;
    }
    angle::CheckedNumeric<int> 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<int>(rect1.x) + rect1.width).IsValid());
    ASSERT((angle::CheckedNumeric<int>(rect1.y) + rect1.height).IsValid());
    ASSERT((angle::CheckedNumeric<int>(rect2.x) + rect2.width).IsValid());
    ASSERT((angle::CheckedNumeric<int>(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<int>(source.x) + source.width).IsValid());
    ASSERT((angle::CheckedNumeric<int>(source.y) + source.height).IsValid());
    ASSERT((angle::CheckedNumeric<int>(extend.x) + extend.width).IsValid());
    ASSERT((angle::CheckedNumeric<int>(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::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 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<Buffer> &binding)
{
    Buffer *buffer = binding.get();
    if (buffer == nullptr)
    {
        return 0;
    }

    const GLsizeiptr bufferSize = static_cast<GLsizeiptr>(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
