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)
......
//
// 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