Commit d6c7bac9 by Alexey Knyazev Committed by Commit Bot

Add BlendStateExt helper structure

It provides compact storage and comparison operations for per-drawbuffer blend states. Added BitSetT::Zero() static constexpr. Bug: angleproject:4394 Change-Id: I66d6275facb7b28022fc24ff9cc0d8c3c976c99d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2154669 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 226bba3c
......@@ -132,6 +132,8 @@ class BitSetT final
Iterator begin() const { return Iterator(*this); }
Iterator end() const { return Iterator(BitSetT()); }
constexpr static BitSetT Zero() { return BitSetT(); }
private:
// Produces a mask of ones up to the "x"th bit.
constexpr static BitsT Mask(std::size_t x)
......
......@@ -28,6 +28,8 @@ TYPED_TEST_SUITE(BitSetTest, BitSetTypes);
TYPED_TEST(BitSetTest, Basic)
{
EXPECT_EQ(TypeParam::Zero().bits(), 0u);
TypeParam mBits = this->mBits;
EXPECT_FALSE(mBits.all());
EXPECT_FALSE(mBits.any());
......
......@@ -230,6 +230,237 @@ ImageUnit::ImageUnit(const ImageUnit &other) = default;
ImageUnit::~ImageUnit() = default;
BlendStateExt::BlendStateExt(const size_t drawBuffers)
: mMaxFactorMask(FactorStorage::GetMask(drawBuffers)),
mSrcColor(FactorStorage::GetReplicatedValue(BlendFactorType::One, mMaxFactorMask)),
mDstColor(FactorStorage::GetReplicatedValue(BlendFactorType::Zero, mMaxFactorMask)),
mSrcAlpha(FactorStorage::GetReplicatedValue(BlendFactorType::One, mMaxFactorMask)),
mDstAlpha(FactorStorage::GetReplicatedValue(BlendFactorType::Zero, mMaxFactorMask)),
mMaxEquationMask(EquationStorage::GetMask(drawBuffers)),
mEquationColor(EquationStorage::GetReplicatedValue(BlendEquationType::Add, mMaxEquationMask)),
mEquationAlpha(EquationStorage::GetReplicatedValue(BlendEquationType::Add, mMaxEquationMask)),
mMaxColorMask(ColorMaskStorage::GetMask(drawBuffers)),
mColorMask(ColorMaskStorage::GetReplicatedValue(PackColorMask(true, true, true, true),
mMaxColorMask)),
mMaxEnabledMask(0xFF >> (8 - drawBuffers)),
mEnabledMask(),
mMaxDrawBuffers(drawBuffers)
{}
BlendStateExt &BlendStateExt::operator=(const BlendStateExt &other)
{
memcpy(this, &other, sizeof(BlendStateExt));
return *this;
}
void BlendStateExt::setEnabled(const bool enabled)
{
mEnabledMask = enabled ? mMaxEnabledMask : DrawBufferMask::Zero();
}
void BlendStateExt::setEnabledIndexed(const size_t index, const bool enabled)
{
ASSERT(index < mMaxDrawBuffers);
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), mMaxColorMask);
}
BlendStateExt::ColorMaskStorage::Type BlendStateExt::expandColorMaskIndexed(
const size_t index) const
{
return ColorMaskStorage::GetReplicatedValue(
ColorMaskStorage::GetValueIndexed(index, mColorMask), mMaxColorMask);
}
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 bool red,
const bool green,
const bool blue,
const bool alpha)
{
ASSERT(index < mMaxDrawBuffers);
ColorMaskStorage::SetValueIndexed(index, PackColorMask(red, green, blue, alpha), &mColorMask);
}
void BlendStateExt::getColorMaskIndexed(const size_t index,
bool *red,
bool *green,
bool *blue,
bool *alpha) const
{
ASSERT(index < mMaxDrawBuffers);
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),
mMaxEquationMask);
}
BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationColorIndexed(
const size_t index) const
{
return EquationStorage::GetReplicatedValue(
EquationStorage::GetValueIndexed(index, mEquationColor), mMaxEquationMask);
}
BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationAlphaIndexed(
const size_t index) const
{
return EquationStorage::GetReplicatedValue(
EquationStorage::GetValueIndexed(index, mEquationAlpha), mMaxEquationMask);
}
void BlendStateExt::setEquations(const GLenum modeColor, const GLenum modeAlpha)
{
mEquationColor = expandEquationValue(modeColor);
mEquationAlpha = expandEquationValue(modeAlpha);
}
void BlendStateExt::setEquationsIndexed(const size_t index,
const GLenum modeColor,
const GLenum modeAlpha)
{
ASSERT(index < mMaxDrawBuffers);
EquationStorage::SetValueIndexed(index, FromGLenum<BlendEquationType>(modeColor),
&mEquationColor);
EquationStorage::SetValueIndexed(index, FromGLenum<BlendEquationType>(modeAlpha),
&mEquationAlpha);
}
GLenum BlendStateExt::getEquationColorIndexed(size_t index) const
{
ASSERT(index < mMaxDrawBuffers);
return ToGLenum(EquationStorage::GetValueIndexed(index, mEquationColor));
}
GLenum BlendStateExt::getEquationAlphaIndexed(size_t index) const
{
ASSERT(index < mMaxDrawBuffers);
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), mMaxFactorMask);
}
BlendStateExt::FactorStorage::Type BlendStateExt::expandSrcColorIndexed(const size_t index) const
{
ASSERT(index < mMaxDrawBuffers);
return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mSrcColor),
mMaxFactorMask);
}
BlendStateExt::FactorStorage::Type BlendStateExt::expandDstColorIndexed(const size_t index) const
{
ASSERT(index < mMaxDrawBuffers);
return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mDstColor),
mMaxFactorMask);
}
BlendStateExt::FactorStorage::Type BlendStateExt::expandSrcAlphaIndexed(const size_t index) const
{
ASSERT(index < mMaxDrawBuffers);
return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mSrcAlpha),
mMaxFactorMask);
}
BlendStateExt::FactorStorage::Type BlendStateExt::expandDstAlphaIndexed(const size_t index) const
{
ASSERT(index < mMaxDrawBuffers);
return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mDstAlpha),
mMaxFactorMask);
}
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 < mMaxDrawBuffers);
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);
}
GLenum BlendStateExt::getSrcColorIndexed(size_t index) const
{
ASSERT(index < mMaxDrawBuffers);
return ToGLenum(FactorStorage::GetValueIndexed(index, mSrcColor));
}
GLenum BlendStateExt::getDstColorIndexed(size_t index) const
{
ASSERT(index < mMaxDrawBuffers);
return ToGLenum(FactorStorage::GetValueIndexed(index, mDstColor));
}
GLenum BlendStateExt::getSrcAlphaIndexed(size_t index) const
{
ASSERT(index < mMaxDrawBuffers);
return ToGLenum(FactorStorage::GetValueIndexed(index, mSrcAlpha));
}
GLenum BlendStateExt::getDstAlphaIndexed(size_t index) const
{
ASSERT(index < mMaxDrawBuffers);
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)
......
......@@ -386,6 +386,244 @@ using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER
// Used in Framebuffer / Program
using DrawBufferMask = angle::BitSet<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
class BlendStateExt final
{
static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS == 8, "Only up to 8 draw buffers supported.");
public:
template <typename ElementType, size_t ElementCount>
struct StorageType final
{
static_assert(ElementCount <= 256, "ElementCount cannot exceed 256.");
#if defined(ANGLE_IS_64_BIT_CPU)
// Always use uint64_t on 64-bit systems
static constexpr size_t kBits = 8;
#else
static constexpr size_t kBits = ElementCount > 16 ? 8 : 4;
#endif
using Type = typename std::conditional<kBits == 8, uint64_t, uint32_t>::type;
static constexpr Type kMaxValueMask = (kBits == 8) ? 0xFF : 0xF;
static constexpr Type GetMask(const size_t drawBuffers)
{
ASSERT(drawBuffers <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
return static_cast<Type>(0xFFFFFFFFFFFFFFFFull >> (64 - drawBuffers * kBits));
}
// A multiplier that is used to replicate 4- or 8-bit value 8 times.
static constexpr Type kReplicator = (kBits == 8) ? 0x0101010101010101ull : 0x11111111;
// Extract packed `Bits`-bit value of index `index`. `values` variable contains up to 8
// packed values.
static constexpr ElementType GetValueIndexed(const size_t index, const Type values)
{
ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
return static_cast<ElementType>((values >> (index * kBits)) & kMaxValueMask);
}
// Replicate `Bits`-bit value 8 times and mask the result.
static constexpr Type GetReplicatedValue(const ElementType value, const Type mask)
{
ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
return (static_cast<size_t>(value) * kReplicator) & mask;
}
// Replace `Bits`-bit value of index `index` in `target` with `value`.
static constexpr void SetValueIndexed(const size_t index,
const ElementType value,
Type *target)
{
ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
// Bitmask with set bits that contain the value of index `index`.
const Type selector = kMaxValueMask << (index * kBits);
// Shift the new `value` to its position in the packed value.
const Type builtValue = static_cast<Type>(value) << (index * kBits);
// Mark differing bits of `target` and `builtValue`, then flip the bits on those
// positions in `target`.
// Taken from https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
*target = *target ^ ((*target ^ builtValue) & selector);
}
// Compare two packed sets of eight 4-bit values and return an 8-bit diff mask.
static constexpr DrawBufferMask GetDiffMask(const uint32_t packedValue1,
const uint32_t packedValue2)
{
uint32_t diff = packedValue1 ^ packedValue2;
// For each 4-bit value that is different between inputs, set the msb to 1 and other
// bits to 0.
diff = (diff | ((diff & 0x77777777) + 0x77777777)) & 0x88888888;
// By this point, `diff` looks like a...b...c...d...e...f...g...h... (dots mean zeros).
// To get DrawBufferMask, we need to compress this 32-bit value to 8 bits, i.e. abcdefgh
// Multiplying the lower half of `diff` by 0x249 (0x200 + 0x40 + 0x8 + 0x1) produces:
// ................e...f...g...h... +
// .............e...f...g...h...... +
// ..........e...f...g...h......... +
// .......e...f...g...h............
// ________________________________ =
// .......e..ef.efgefghfgh.gh..h...
// ^^^^
// Similar operation is applied to the upper word.
// This calculation could be replaced with a single PEXT instruction from BMI2 set.
diff = ((((diff & 0xFFFF0000) * 0x249) >> 24) & 0xF0) | (((diff * 0x249) >> 12) & 0xF);
return DrawBufferMask(diff);
}
// Compare two packed sets of eight 8-bit values and return an 8-bit diff mask.
static constexpr DrawBufferMask GetDiffMask(const uint64_t packedValue1,
const uint64_t packedValue2)
{
uint64_t diff = packedValue1 ^ packedValue2;
// For each 8-bit value that is different between inputs, set the msb to 1 and other
// bits to 0.
diff = (diff | ((diff & 0x7F7F7F7F7F7F7F7F) + 0x7F7F7F7F7F7F7F7F)) & 0x8080808080808080;
// By this point, `diff` looks like (dots mean zeros):
// a.......b.......c.......d.......e.......f.......g.......h.......
// To get DrawBufferMask, we need to compress this 64-bit value to 8 bits, i.e. abcdefgh
// Multiplying `diff` by 0x0002040810204081 produces:
// a.......b.......c.......d.......e.......f.......g.......h....... +
// .b.......c.......d.......e.......f.......g.......h.............. +
// ..c.......d.......e.......f.......g.......h..................... +
// ...d.......e.......f.......g.......h............................ +
// ....e.......f.......g.......h................................... +
// .....f.......g.......h.......................................... +
// ......g.......h................................................. +
// .......h........................................................
// ________________________________________________________________ =
// abcdefghbcdefgh.cdefgh..defgh...efgh....fgh.....gh......h.......
// ^^^^^^^^
// This operation could be replaced with a single PEXT instruction from BMI2 set.
diff = 0x0002040810204081 * diff >> 56;
return DrawBufferMask(static_cast<uint32_t>(diff));
}
};
using FactorStorage = StorageType<BlendFactorType, angle::EnumSize<BlendFactorType>()>;
using EquationStorage = StorageType<BlendEquationType, angle::EnumSize<BlendEquationType>()>;
using ColorMaskStorage = StorageType<uint8_t, 16>;
BlendStateExt(const size_t drawBuffers = 1);
BlendStateExt &operator=(const BlendStateExt &other);
///////// Blending Toggle /////////
void setEnabled(const bool enabled);
void setEnabledIndexed(const size_t index, const bool enabled);
///////// Color Write Mask /////////
static constexpr size_t PackColorMask(const bool red,
const bool green,
const bool blue,
const bool alpha)
{
return (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
}
static constexpr void UnpackColorMask(const size_t value,
bool *red,
bool *green,
bool *blue,
bool *alpha)
{
*red = static_cast<bool>(value & 1);
*green = static_cast<bool>(value & 2);
*blue = static_cast<bool>(value & 4);
*alpha = static_cast<bool>(value & 8);
}
ColorMaskStorage::Type expandColorMaskValue(const bool red,
const bool green,
const bool blue,
const bool alpha) const;
ColorMaskStorage::Type expandColorMaskIndexed(const size_t index) const;
void setColorMask(const bool red, const bool green, const bool blue, const bool alpha);
void setColorMaskIndexed(const size_t index,
const bool red,
const bool green,
const bool blue,
const bool alpha);
void getColorMaskIndexed(const size_t index,
bool *red,
bool *green,
bool *blue,
bool *alpha) const;
DrawBufferMask compareColorMask(ColorMaskStorage::Type other) const;
///////// Blend Equation /////////
EquationStorage::Type expandEquationValue(const GLenum mode) const;
EquationStorage::Type expandEquationColorIndexed(const size_t index) const;
EquationStorage::Type expandEquationAlphaIndexed(const size_t index) const;
void setEquations(const GLenum modeColor, const GLenum modeAlpha);
void setEquationsIndexed(const size_t index, const GLenum modeColor, const GLenum modeAlpha);
GLenum getEquationColorIndexed(size_t index) const;
GLenum getEquationAlphaIndexed(size_t index) const;
DrawBufferMask compareEquations(const EquationStorage::Type color,
const EquationStorage::Type alpha) const;
///////// Blend Factors /////////
FactorStorage::Type expandFactorValue(const GLenum func) const;
FactorStorage::Type expandSrcColorIndexed(const size_t index) const;
FactorStorage::Type expandDstColorIndexed(const size_t index) const;
FactorStorage::Type expandSrcAlphaIndexed(const size_t index) const;
FactorStorage::Type expandDstAlphaIndexed(const size_t index) const;
void setFactors(const GLenum srcColor,
const GLenum dstColor,
const GLenum srcAlpha,
const GLenum dstAlpha);
void setFactorsIndexed(const size_t index,
const GLenum srcColor,
const GLenum dstColor,
const GLenum srcAlpha,
const GLenum dstAlpha);
GLenum getSrcColorIndexed(size_t index) const;
GLenum getDstColorIndexed(size_t index) const;
GLenum getSrcAlphaIndexed(size_t index) const;
GLenum getDstAlphaIndexed(size_t index) const;
DrawBufferMask compareFactors(const FactorStorage::Type srcColor,
const FactorStorage::Type dstColor,
const FactorStorage::Type srcAlpha,
const FactorStorage::Type dstAlpha) const;
///////// Data Members /////////
const FactorStorage::Type mMaxFactorMask;
FactorStorage::Type mSrcColor;
FactorStorage::Type mDstColor;
FactorStorage::Type mSrcAlpha;
FactorStorage::Type mDstAlpha;
const EquationStorage::Type mMaxEquationMask;
EquationStorage::Type mEquationColor;
EquationStorage::Type mEquationAlpha;
const ColorMaskStorage::Type mMaxColorMask;
ColorMaskStorage::Type mColorMask;
const DrawBufferMask mMaxEnabledMask;
DrawBufferMask mEnabledMask;
const size_t mMaxDrawBuffers;
};
// Used in StateCache
using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
......
//
// Copyright 2020 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_unittest.cpp: Unit tests of the BlendStateExt class.
#include <gtest/gtest.h>
#include "libANGLE/angletypes.h"
namespace angle
{
#if defined(ANGLE_IS_64_BIT_CPU)
constexpr bool is64Bit = true;
#else
constexpr bool is64Bit = false;
#endif
void checkInitState(const gl::BlendStateExt &blendStateExt)
{
for (size_t i = 0; i < blendStateExt.mMaxDrawBuffers; ++i)
{
ASSERT_FALSE(blendStateExt.mEnabledMask.test(i));
bool r, g, b, a;
blendStateExt.getColorMaskIndexed(i, &r, &g, &b, &a);
ASSERT_TRUE(r);
ASSERT_TRUE(g);
ASSERT_TRUE(b);
ASSERT_TRUE(a);
ASSERT_EQ(blendStateExt.getEquationColorIndexed(i), static_cast<GLenum>(GL_FUNC_ADD));
ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(i), static_cast<GLenum>(GL_FUNC_ADD));
ASSERT_EQ(blendStateExt.getSrcColorIndexed(i), static_cast<GLenum>(GL_ONE));
ASSERT_EQ(blendStateExt.getDstColorIndexed(i), static_cast<GLenum>(GL_ZERO));
ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(i), static_cast<GLenum>(GL_ONE));
ASSERT_EQ(blendStateExt.getDstAlphaIndexed(i), static_cast<GLenum>(GL_ZERO));
}
}
// Test the initial state of BlendStateExt
TEST(BlendStateExt, Init)
{
{
const gl::BlendStateExt blendStateExt = gl::BlendStateExt(1);
ASSERT_EQ(blendStateExt.mMaxDrawBuffers, 1u);
ASSERT_EQ(blendStateExt.mMaxEnabledMask.to_ulong(), 1u);
ASSERT_EQ(blendStateExt.mMaxColorMask, is64Bit ? 0xFFu : 0xFu);
ASSERT_EQ(blendStateExt.mMaxEquationMask, is64Bit ? 0xFFu : 0xFu);
ASSERT_EQ(blendStateExt.mMaxFactorMask, 0xFFu);
checkInitState(blendStateExt);
}
{
const gl::BlendStateExt blendStateExt = gl::BlendStateExt(4);
ASSERT_EQ(blendStateExt.mMaxDrawBuffers, 4u);
ASSERT_EQ(blendStateExt.mMaxEnabledMask.to_ulong(), 0xFu);
ASSERT_EQ(blendStateExt.mMaxColorMask, is64Bit ? 0xFFFFFFFFu : 0xFFFFu);
ASSERT_EQ(blendStateExt.mMaxEquationMask, is64Bit ? 0xFFFFFFFFu : 0xFFFFu);
ASSERT_EQ(blendStateExt.mMaxFactorMask, 0xFFFFFFFFu);
checkInitState(blendStateExt);
}
{
const gl::BlendStateExt blendStateExt = gl::BlendStateExt(8);
ASSERT_EQ(blendStateExt.mMaxDrawBuffers, 8u);
ASSERT_EQ(blendStateExt.mMaxEnabledMask.to_ulong(), 0xFFu);
ASSERT_EQ(blendStateExt.mMaxColorMask, is64Bit ? 0xFFFFFFFFFFFFFFFFu : 0xFFFFFFFFu);
ASSERT_EQ(blendStateExt.mMaxEquationMask, is64Bit ? 0xFFFFFFFFFFFFFFFFu : 0xFFFFFFFFu);
ASSERT_EQ(blendStateExt.mMaxFactorMask, 0xFFFFFFFFFFFFFFFFu);
checkInitState(blendStateExt);
}
}
// Test blend enabled flags
TEST(BlendStateExt, BlendEnabled)
{
gl::BlendStateExt blendStateExt = gl::BlendStateExt(3);
blendStateExt.setEnabled(true);
ASSERT_EQ(blendStateExt.mEnabledMask.to_ulong(), 7u);
blendStateExt.setEnabledIndexed(1, false);
ASSERT_EQ(blendStateExt.mEnabledMask.to_ulong(), 5u);
}
// Test color write mask manipulations
TEST(BlendStateExt, ColorMask)
{
gl::BlendStateExt blendStateExt = gl::BlendStateExt(5);
blendStateExt.setColorMask(true, false, true, false);
ASSERT_EQ(blendStateExt.mColorMask, is64Bit ? 0x0505050505u : 0x55555u);
blendStateExt.setColorMaskIndexed(3, false, true, false, true);
ASSERT_EQ(blendStateExt.mColorMask, is64Bit ? 0x050A050505u : 0x5A555u);
bool r, g, b, a;
blendStateExt.getColorMaskIndexed(3, &r, &g, &b, &a);
ASSERT_FALSE(r);
ASSERT_TRUE(g);
ASSERT_FALSE(b);
ASSERT_TRUE(a);
gl::BlendStateExt::ColorMaskStorage::Type otherColorMask =
blendStateExt.expandColorMaskIndexed(3);
ASSERT_EQ(otherColorMask, is64Bit ? 0x0A0A0A0A0Au : 0xAAAAAu);
const gl::DrawBufferMask diff = blendStateExt.compareColorMask(otherColorMask);
ASSERT_EQ(diff.to_ulong(), 23u);
}
// Test blend equations manipulations
TEST(BlendStateExt, BlendEquations)
{
gl::BlendStateExt blendStateExt = gl::BlendStateExt(7);
blendStateExt.setEquations(GL_MIN, GL_FUNC_SUBTRACT);
ASSERT_EQ(blendStateExt.mEquationColor, is64Bit ? 0x01010101010101u : 0x1111111u);
ASSERT_EQ(blendStateExt.mEquationAlpha, is64Bit ? 0x04040404040404u : 0x4444444u);
blendStateExt.setEquationsIndexed(3, GL_MAX, GL_FUNC_SUBTRACT);
blendStateExt.setEquationsIndexed(5, GL_MIN, GL_FUNC_ADD);
ASSERT_EQ(blendStateExt.mEquationColor, is64Bit ? 0x01010102010101u : 0x1112111u);
ASSERT_EQ(blendStateExt.mEquationAlpha, is64Bit ? 0x04000404040404u : 0x4044444u);
ASSERT_EQ(blendStateExt.getEquationColorIndexed(3), static_cast<GLenum>(GL_MAX));
ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(5), static_cast<GLenum>(GL_FUNC_ADD));
gl::BlendStateExt::EquationStorage::Type otherEquationColor =
blendStateExt.expandEquationColorIndexed(0);
gl::BlendStateExt::EquationStorage::Type otherEquationAlpha =
blendStateExt.expandEquationAlphaIndexed(0);
ASSERT_EQ(otherEquationColor, is64Bit ? 0x01010101010101u : 0x1111111u);
ASSERT_EQ(otherEquationAlpha, is64Bit ? 0x04040404040404u : 0x4444444u);
const gl::DrawBufferMask diff =
blendStateExt.compareEquations(otherEquationColor, otherEquationAlpha);
ASSERT_EQ(diff.to_ulong(), 40u);
}
// Test blend factors manipulations
TEST(BlendStateExt, BlendFactors)
{
gl::BlendStateExt blendStateExt = gl::BlendStateExt(8);
blendStateExt.setFactors(GL_SRC_COLOR, GL_DST_COLOR, GL_SRC_ALPHA, GL_DST_ALPHA);
ASSERT_EQ(blendStateExt.mSrcColor, 0x0202020202020202u);
ASSERT_EQ(blendStateExt.mDstColor, 0x0808080808080808u);
ASSERT_EQ(blendStateExt.mSrcAlpha, 0x0404040404040404u);
ASSERT_EQ(blendStateExt.mDstAlpha, 0x0606060606060606u);
blendStateExt.setFactorsIndexed(0, GL_ONE, GL_DST_COLOR, GL_SRC_ALPHA, GL_DST_ALPHA);
blendStateExt.setFactorsIndexed(3, GL_SRC_COLOR, GL_ONE, GL_SRC_ALPHA, GL_DST_ALPHA);
blendStateExt.setFactorsIndexed(5, GL_SRC_COLOR, GL_DST_COLOR, GL_ONE, GL_DST_ALPHA);
blendStateExt.setFactorsIndexed(7, GL_SRC_COLOR, GL_DST_COLOR, GL_SRC_ALPHA, GL_ONE);
ASSERT_EQ(blendStateExt.mSrcColor, 0x0202020202020201u);
ASSERT_EQ(blendStateExt.mDstColor, 0x0808080801080808u);
ASSERT_EQ(blendStateExt.mSrcAlpha, 0x0404010404040404u);
ASSERT_EQ(blendStateExt.mDstAlpha, 0x0106060606060606u);
ASSERT_EQ(blendStateExt.getSrcColorIndexed(0), static_cast<GLenum>(GL_ONE));
ASSERT_EQ(blendStateExt.getDstColorIndexed(3), static_cast<GLenum>(GL_ONE));
ASSERT_EQ(blendStateExt.getSrcAlphaIndexed(5), static_cast<GLenum>(GL_ONE));
ASSERT_EQ(blendStateExt.getDstAlphaIndexed(7), static_cast<GLenum>(GL_ONE));
gl::BlendStateExt::FactorStorage::Type otherSrcColor = blendStateExt.expandSrcColorIndexed(1);
gl::BlendStateExt::FactorStorage::Type otherDstColor = blendStateExt.expandDstColorIndexed(1);
gl::BlendStateExt::FactorStorage::Type otherSrcAlpha = blendStateExt.expandSrcAlphaIndexed(1);
gl::BlendStateExt::FactorStorage::Type otherDstAlpha = blendStateExt.expandDstAlphaIndexed(1);
ASSERT_EQ(otherSrcColor, 0x0202020202020202u);
ASSERT_EQ(otherDstColor, 0x0808080808080808u);
ASSERT_EQ(otherSrcAlpha, 0x0404040404040404u);
ASSERT_EQ(otherDstAlpha, 0x0606060606060606u);
const gl::DrawBufferMask diff =
blendStateExt.compareFactors(otherSrcColor, otherDstColor, otherSrcAlpha, otherDstAlpha);
ASSERT_EQ(diff.to_ulong(), 169u);
}
} // namespace angle
......@@ -39,6 +39,7 @@ angle_unittests_sources = [
"../libANGLE/VaryingPacking_unittest.cpp",
"../libANGLE/VertexArray_unittest.cpp",
"../libANGLE/WorkerThread_unittest.cpp",
"../libANGLE/angletypes_unittest.cpp",
"../libANGLE/renderer/BufferImpl_mock.h",
"../libANGLE/renderer/FramebufferImpl_mock.h",
"../libANGLE/renderer/ImageImpl_mock.h",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment