Commit 6193fd69 by Alexey Knyazev Committed by Commit Bot

OpenGL: Implement OES_draw_buffers_indexed

OpenGL state sync issues as few GL commands as possible to update the blend state regardless of an application input. Enhanced ClearTestES3.MaskedIndexedClearMultipleAttachments regression test. Disabled OES_draw_buffers_indexed on Windows/AMD/OpenGL. Bug: angleproject:4394 Change-Id: I244ac2975678bc559634152cf4eb997d9dbe83d0 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2145874 Commit-Queue: Kenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 6e7d7296
......@@ -426,6 +426,12 @@ struct FeaturesGL : FeatureSetBase
"avoid_dxt1_srgb_texture_format", FeatureCategory::OpenGLWorkarounds,
"Replaces DXT1 sRGB with DXT1 sRGB Alpha as a driver bug workaround.", &members};
// Bugs exist in OpenGL AMD drivers on Windows that produce incorrect pipeline state for
// colorMaski calls.
Feature disableDrawBuffersIndexed = {"disable_draw_buffers_indexed",
FeatureCategory::OpenGLWorkarounds,
"Disable OES_draw_buffers_indexed extension.", &members};
// GL_EXT_semaphore_fd doesn't work properly with Mesa 19.3.4 and earlier versions.
Feature disableSemaphoreFd = {"disable_semaphore_fd", FeatureCategory::OpenGLWorkarounds,
"Disable GL_EXT_semaphore_fd extension", &members,
......
......@@ -388,6 +388,7 @@ void State::initialize(Context *context)
const Version &clientVersion = context->getClientVersion();
mMaxDrawBuffers = static_cast<GLuint>(caps.maxDrawBuffers);
mBlendStateExt = BlendStateExt(mMaxDrawBuffers);
mMaxCombinedTextureImageUnits = static_cast<GLuint>(caps.maxCombinedTextureImageUnits);
setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f);
......@@ -706,6 +707,8 @@ void State::setColorMask(bool red, bool green, bool blue, bool alpha)
blendState.colorMaskBlue = blue;
blendState.colorMaskAlpha = alpha;
}
mBlendStateExt.setColorMask(red, green, blue, alpha);
mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
}
......@@ -716,6 +719,8 @@ void State::setColorMaskIndexed(bool red, bool green, bool blue, bool alpha, GLu
mBlendStateArray[index].colorMaskGreen = green;
mBlendStateArray[index].colorMaskBlue = blue;
mBlendStateArray[index].colorMaskAlpha = alpha;
mBlendStateExt.setColorMaskIndexed(index, red, green, blue, alpha);
mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
}
......@@ -814,7 +819,7 @@ void State::setBlend(bool enabled)
{
blendState.blend = enabled;
}
enabled ? mBlendEnabledDrawBuffers.set() : mBlendEnabledDrawBuffers.reset();
mBlendStateExt.setEnabled(enabled);
mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
}
......@@ -822,7 +827,7 @@ void State::setBlendIndexed(bool enabled, GLuint index)
{
ASSERT(index < mBlendStateArray.size());
mBlendStateArray[index].blend = enabled;
mBlendEnabledDrawBuffers.set(index, enabled);
mBlendStateExt.setEnabledIndexed(index, enabled);
mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
}
......@@ -856,6 +861,8 @@ void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha
mBlendFuncConstantAlphaDrawBuffers.reset();
}
}
mBlendStateExt.setFactors(sourceRGB, destRGB, sourceAlpha, destAlpha);
mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS);
}
......@@ -876,6 +883,8 @@ void State::setBlendFactorsIndexed(GLenum sourceRGB,
mBlendFuncConstantColorDrawBuffers.set(index, hasConstantColor(sourceRGB, destRGB));
mBlendFuncConstantAlphaDrawBuffers.set(index, hasConstantAlpha(sourceRGB, destRGB));
}
mBlendStateExt.setFactorsIndexed(index, sourceRGB, destRGB, sourceAlpha, destAlpha);
mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS);
}
......@@ -909,6 +918,8 @@ void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
blendState.blendEquationRGB = rgbEquation;
blendState.blendEquationAlpha = alphaEquation;
}
mBlendStateExt.setEquations(rgbEquation, alphaEquation);
mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS);
}
......@@ -917,6 +928,8 @@ void State::setBlendEquationIndexed(GLenum rgbEquation, GLenum alphaEquation, GL
ASSERT(index < mBlendStateArray.size());
mBlendStateArray[index].blendEquationRGB = rgbEquation;
mBlendStateArray[index].blendEquationAlpha = alphaEquation;
mBlendStateExt.setEquationsIndexed(index, rgbEquation, alphaEquation);
mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS);
}
......
......@@ -172,7 +172,7 @@ class State : angle::NonCopyable
ASSERT(index < mBlendStateArray.size());
return mBlendStateArray[index].blend;
}
DrawBufferMask getBlendEnabledDrawBufferMask() const { return mBlendEnabledDrawBuffers; }
DrawBufferMask getBlendEnabledDrawBufferMask() const { return mBlendStateExt.mEnabledMask; }
void setBlend(bool enabled);
void setBlendIndexed(bool enabled, GLuint index);
void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
......@@ -764,12 +764,12 @@ class State : angle::NonCopyable
bool hasConstantAlphaBlendFunc() const
{
return (mBlendFuncConstantAlphaDrawBuffers & mBlendEnabledDrawBuffers).any();
return (mBlendFuncConstantAlphaDrawBuffers & mBlendStateExt.mEnabledMask).any();
}
bool hasSimultaneousConstantColorAndAlphaBlendFunc() const
{
return (mBlendFuncConstantColorDrawBuffers & mBlendEnabledDrawBuffers).any() &&
return (mBlendFuncConstantColorDrawBuffers & mBlendStateExt.mEnabledMask).any() &&
hasConstantAlphaBlendFunc();
}
......@@ -780,6 +780,8 @@ class State : angle::NonCopyable
bool isEarlyFragmentTestsOptimizationAllowed() const { return isSampleCoverageEnabled(); }
const BlendStateExt &getBlendStateExt() const { return mBlendStateExt; }
private:
friend class Context;
......@@ -875,6 +877,7 @@ class State : angle::NonCopyable
Rectangle mScissor;
BlendStateArray mBlendStateArray;
BlendStateExt mBlendStateExt;
ColorF mBlendColor;
bool mSampleAlphaToCoverage;
bool mSampleCoverage;
......@@ -1002,7 +1005,6 @@ class State : angle::NonCopyable
const OverlayType *mOverlay;
// OES_draw_buffers_indexed
DrawBufferMask mBlendEnabledDrawBuffers;
DrawBufferMask mBlendFuncConstantAlphaDrawBuffers;
DrawBufferMask mBlendFuncConstantColorDrawBuffers;
bool mNoSimultaneousConstantColorAndAlphaBlendFunc;
......
......@@ -94,18 +94,9 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mViewport(0, 0, 0, 0),
mNear(0.0f),
mFar(1.0f),
mBlendEnabled(false),
mBlendColor(0, 0, 0, 0),
mSourceBlendRGB(GL_ONE),
mDestBlendRGB(GL_ZERO),
mSourceBlendAlpha(GL_ONE),
mDestBlendAlpha(GL_ZERO),
mBlendEquationRGB(GL_FUNC_ADD),
mBlendEquationAlpha(GL_FUNC_ADD),
mColorMaskRed(true),
mColorMaskGreen(true),
mColorMaskBlue(true),
mColorMaskAlpha(true),
mBlendStateExt(rendererCaps.maxDrawBuffers),
mIndependentBlendStates(extensions.drawBuffersIndexedAny()),
mSampleAlphaToCoverageEnabled(false),
mSampleCoverageEnabled(false),
mSampleCoverageValue(1.0f),
......@@ -1062,20 +1053,75 @@ void StateManagerGL::setDepthRange(float near, float far)
void StateManagerGL::setBlendEnabled(bool enabled)
{
if (mBlendEnabled != enabled)
const gl::DrawBufferMask mask =
enabled ? mBlendStateExt.mMaxEnabledMask : gl::DrawBufferMask::Zero();
if (mBlendStateExt.mEnabledMask == mask)
{
mBlendEnabled = enabled;
if (mBlendEnabled)
return;
}
if (enabled)
{
mFunctions->enable(GL_BLEND);
}
else
{
mFunctions->disable(GL_BLEND);
}
mBlendStateExt.setEnabled(enabled);
mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
}
void StateManagerGL::setBlendEnabledIndexed(const gl::DrawBufferMask enabledMask)
{
if (mBlendStateExt.mEnabledMask == enabledMask)
{
return;
}
// Get DrawBufferMask of buffers with different blend enable state
gl::DrawBufferMask diffMask = mBlendStateExt.mEnabledMask ^ enabledMask;
const size_t diffCount = diffMask.count();
// Check if enabling or disabling blending for all buffers reduces the number of subsequent
// indexed commands. Implicitly handles the case when the new blend enable state is the same for
// all buffers.
if (diffCount > 1)
{
// The number of indexed blend enable commands in case a mass disable is used.
const size_t enabledCount = enabledMask.count();
// The mask and the number of indexed blend disable commands in case a mass enable is used.
const gl::DrawBufferMask disabledMask = enabledMask ^ mBlendStateExt.mMaxEnabledMask;
const size_t disabledCount = disabledMask.count();
if (enabledCount < diffCount && enabledCount <= disabledCount)
{
diffMask = enabledMask;
mFunctions->disable(GL_BLEND);
}
else if (disabledCount < diffCount && disabledCount <= enabledCount)
{
diffMask = disabledMask;
mFunctions->enable(GL_BLEND);
}
}
for (size_t drawBufferIndex : diffMask)
{
if (enabledMask.test(drawBufferIndex))
{
mFunctions->enablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
}
else
{
mFunctions->disable(GL_BLEND);
mFunctions->disablei(GL_BLEND, static_cast<GLuint>(drawBufferIndex));
}
mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
}
mBlendStateExt.mEnabledMask = enabledMask;
mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED);
}
void StateManagerGL::setBlendColor(const gl::ColorF &blendColor)
......@@ -1090,50 +1136,179 @@ void StateManagerGL::setBlendColor(const gl::ColorF &blendColor)
}
}
void StateManagerGL::setBlendFuncs(GLenum sourceBlendRGB,
GLenum destBlendRGB,
GLenum sourceBlendAlpha,
GLenum destBlendAlpha)
void StateManagerGL::setBlendFuncs(const gl::BlendStateExt &blendStateExt)
{
if (mSourceBlendRGB != sourceBlendRGB || mDestBlendRGB != destBlendRGB ||
mSourceBlendAlpha != sourceBlendAlpha || mDestBlendAlpha != destBlendAlpha)
if (mBlendStateExt.mSrcColor == blendStateExt.mSrcColor &&
mBlendStateExt.mDstColor == blendStateExt.mDstColor &&
mBlendStateExt.mSrcAlpha == blendStateExt.mSrcAlpha &&
mBlendStateExt.mDstAlpha == blendStateExt.mDstAlpha)
{
mSourceBlendRGB = sourceBlendRGB;
mDestBlendRGB = destBlendRGB;
mSourceBlendAlpha = sourceBlendAlpha;
mDestBlendAlpha = destBlendAlpha;
return;
}
mFunctions->blendFuncSeparate(mSourceBlendRGB, mDestBlendRGB, mSourceBlendAlpha,
mDestBlendAlpha);
if (!mIndependentBlendStates)
{
mFunctions->blendFuncSeparate(
blendStateExt.getSrcColorIndexed(0), blendStateExt.getDstColorIndexed(0),
blendStateExt.getSrcAlphaIndexed(0), blendStateExt.getDstAlphaIndexed(0));
}
else
{
// Get DrawBufferMask of buffers with different blend factors
gl::DrawBufferMask diffMask =
mBlendStateExt.compareFactors(blendStateExt.mSrcColor, blendStateExt.mDstColor,
blendStateExt.mSrcAlpha, blendStateExt.mDstAlpha);
size_t diffCount = diffMask.count();
// Check if setting all buffers to the same value reduces the number of subsequent indexed
// commands. Implicitly handles the case when the new blend function state is the same for
// all buffers.
if (diffCount > 1)
{
bool found = false;
gl::BlendStateExt::FactorStorage::Type commonSrcColor = 0;
gl::BlendStateExt::FactorStorage::Type commonDstColor = 0;
gl::BlendStateExt::FactorStorage::Type commonSrcAlpha = 0;
gl::BlendStateExt::FactorStorage::Type commonDstAlpha = 0;
for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
{
const gl::BlendStateExt::FactorStorage::Type tempCommonSrcColor =
blendStateExt.expandSrcColorIndexed(i);
const gl::BlendStateExt::FactorStorage::Type tempCommonDstColor =
blendStateExt.expandDstColorIndexed(i);
const gl::BlendStateExt::FactorStorage::Type tempCommonSrcAlpha =
blendStateExt.expandSrcAlphaIndexed(i);
const gl::BlendStateExt::FactorStorage::Type tempCommonDstAlpha =
blendStateExt.expandDstAlphaIndexed(i);
const gl::DrawBufferMask tempDiffMask = blendStateExt.compareFactors(
tempCommonSrcColor, tempCommonDstColor, tempCommonSrcAlpha, tempCommonDstAlpha);
const size_t tempDiffCount = tempDiffMask.count();
if (tempDiffCount < diffCount)
{
found = true;
diffMask = tempDiffMask;
diffCount = tempDiffCount;
commonSrcColor = tempCommonSrcColor;
commonDstColor = tempCommonDstColor;
commonSrcAlpha = tempCommonSrcAlpha;
commonDstAlpha = tempCommonDstAlpha;
if (tempDiffCount == 0)
{
break; // the blend factors are the same for all buffers
}
}
}
if (found)
{
mFunctions->blendFuncSeparate(
ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcColor)),
ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstColor)),
ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonSrcAlpha)),
ToGLenum(gl::BlendStateExt::FactorStorage::GetValueIndexed(0, commonDstAlpha)));
}
}
mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
for (size_t drawBufferIndex : diffMask)
{
mFunctions->blendFuncSeparatei(static_cast<GLuint>(drawBufferIndex),
blendStateExt.getSrcColorIndexed(drawBufferIndex),
blendStateExt.getDstColorIndexed(drawBufferIndex),
blendStateExt.getSrcAlphaIndexed(drawBufferIndex),
blendStateExt.getDstAlphaIndexed(drawBufferIndex));
}
}
mBlendStateExt.mSrcColor = blendStateExt.mSrcColor;
mBlendStateExt.mDstColor = blendStateExt.mDstColor;
mBlendStateExt.mSrcAlpha = blendStateExt.mSrcAlpha;
mBlendStateExt.mDstAlpha = blendStateExt.mDstAlpha;
mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_FUNCS);
}
void StateManagerGL::setBlendEquations(GLenum blendEquationRGB, GLenum blendEquationAlpha)
void StateManagerGL::setBlendEquations(const gl::BlendStateExt &blendStateExt)
{
if (mBlendEquationRGB != blendEquationRGB || mBlendEquationAlpha != blendEquationAlpha)
if (mBlendStateExt.mEquationColor == blendStateExt.mEquationColor &&
mBlendStateExt.mEquationAlpha == blendStateExt.mEquationAlpha)
{
mBlendEquationRGB = blendEquationRGB;
mBlendEquationAlpha = blendEquationAlpha;
return;
}
if (!mIndependentBlendStates)
{
mFunctions->blendEquationSeparate(blendStateExt.getEquationColorIndexed(0),
blendStateExt.getEquationAlphaIndexed(0));
}
else
{
// Get DrawBufferMask of buffers with different blend equations
gl::DrawBufferMask diffMask = mBlendStateExt.compareEquations(blendStateExt.mEquationColor,
blendStateExt.mEquationAlpha);
size_t diffCount = diffMask.count();
// Check if setting all buffers to the same value reduces the number of subsequent indexed
// commands. Implicitly handles the case when the new blend equation state is the same for
// all buffers.
if (diffCount > 1)
{
bool found = false;
gl::BlendStateExt::EquationStorage::Type commonEquationColor = 0;
gl::BlendStateExt::EquationStorage::Type commonEquationAlpha = 0;
for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
{
const gl::BlendStateExt::EquationStorage::Type tempCommonEquationColor =
blendStateExt.expandEquationColorIndexed(i);
const gl::BlendStateExt::EquationStorage::Type tempCommonEquationAlpha =
blendStateExt.expandEquationAlphaIndexed(i);
const gl::DrawBufferMask tempDiffMask = blendStateExt.compareEquations(
tempCommonEquationColor, tempCommonEquationAlpha);
mFunctions->blendEquationSeparate(mBlendEquationRGB, mBlendEquationAlpha);
const size_t tempDiffCount = tempDiffMask.count();
if (tempDiffCount < diffCount)
{
found = true;
diffMask = tempDiffMask;
diffCount = tempDiffCount;
commonEquationColor = tempCommonEquationColor;
commonEquationAlpha = tempCommonEquationAlpha;
if (tempDiffCount == 0)
{
break; // the new blend equations are the same for all buffers
}
}
}
if (found)
{
mFunctions->blendEquationSeparate(
ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
0, commonEquationColor)),
ToGLenum(gl::BlendStateExt::EquationStorage::GetValueIndexed(
0, commonEquationAlpha)));
}
}
mLocalDirtyBits.set(gl::State::DIRTY_BIT_BLEND_EQUATIONS);
for (size_t drawBufferIndex : diffMask)
{
mFunctions->blendEquationSeparatei(
static_cast<GLuint>(drawBufferIndex),
blendStateExt.getEquationColorIndexed(drawBufferIndex),
blendStateExt.getEquationAlphaIndexed(drawBufferIndex));
}
}
mBlendStateExt.mEquationColor = blendStateExt.mEquationColor;
mBlendStateExt.mEquationAlpha = blendStateExt.mEquationAlpha;
mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
}
void StateManagerGL::setColorMask(bool red, bool green, bool blue, bool alpha)
{
if (mColorMaskRed != red || mColorMaskGreen != green || mColorMaskBlue != blue ||
mColorMaskAlpha != alpha)
const gl::BlendStateExt::ColorMaskStorage::Type mask =
mBlendStateExt.expandColorMaskValue(red, green, blue, alpha);
if (mBlendStateExt.mColorMask != mask)
{
mColorMaskRed = red;
mColorMaskGreen = green;
mColorMaskBlue = blue;
mColorMaskAlpha = alpha;
mFunctions->colorMask(mColorMaskRed, mColorMaskGreen, mColorMaskBlue, mColorMaskAlpha);
mFunctions->colorMask(red, green, blue, alpha);
mBlendStateExt.mColorMask = mask;
mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
}
}
......@@ -1562,33 +1737,36 @@ angle::Result StateManagerGL::syncState(const gl::Context *context,
setDepthRange(state.getNearPlane(), state.getFarPlane());
break;
case gl::State::DIRTY_BIT_BLEND_ENABLED:
setBlendEnabled(state.isBlendEnabled());
if (mIndependentBlendStates)
{
setBlendEnabledIndexed(state.getBlendEnabledDrawBufferMask());
}
else
{
setBlendEnabled(state.isBlendEnabled());
}
break;
case gl::State::DIRTY_BIT_BLEND_COLOR:
setBlendColor(state.getBlendColor());
break;
case gl::State::DIRTY_BIT_BLEND_FUNCS:
{
const auto &blendState = state.getBlendState();
setBlendFuncs(blendState.sourceBlendRGB, blendState.destBlendRGB,
blendState.sourceBlendAlpha, blendState.destBlendAlpha);
setBlendFuncs(state.getBlendStateExt());
break;
}
case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
{
const auto &blendState = state.getBlendState();
setBlendEquations(blendState.blendEquationRGB, blendState.blendEquationAlpha);
setBlendEquations(state.getBlendStateExt());
break;
}
case gl::State::DIRTY_BIT_COLOR_MASK:
{
gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
const gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
const bool disableAlphaWrite =
framebufferGL->hasEmulatedAlphaChannelTextureAttachment();
const auto &blendState = state.getBlendState();
setColorMaskForFramebuffer(blendState.colorMaskRed, blendState.colorMaskGreen,
blendState.colorMaskBlue, blendState.colorMaskAlpha,
framebufferGL);
setColorMaskForFramebuffer(state.getBlendStateExt(), disableAlphaWrite);
break;
}
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
......@@ -1932,18 +2110,75 @@ void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::Context *
}
}
void StateManagerGL::setColorMaskForFramebuffer(bool red,
bool green,
bool blue,
bool alpha,
const FramebufferGL *framebuffer)
void StateManagerGL::setColorMaskForFramebuffer(const gl::BlendStateExt &blendStateExt,
const bool disableAlpha)
{
bool modifiedAlphaMask = alpha;
if (framebuffer->hasEmulatedAlphaChannelTextureAttachment())
bool r, g, b, a;
// Given that disableAlpha can be true only on macOS backbuffers and color mask is re-synced on
// bound draw framebuffer change, switch all draw buffers color masks to avoid special case
// later.
if (!mIndependentBlendStates || disableAlpha)
{
blendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
setColorMask(r, g, b, disableAlpha ? false : a);
return;
}
// Check if the current mask already matches the new state
if (mBlendStateExt.mColorMask == blendStateExt.mColorMask)
{
modifiedAlphaMask = false;
return;
}
setColorMask(red, green, blue, modifiedAlphaMask);
// Get DrawBufferMask of buffers with different color masks
gl::DrawBufferMask diffMask = mBlendStateExt.compareColorMask(blendStateExt.mColorMask);
size_t diffCount = diffMask.count();
// Check if setting all buffers to the same value reduces the number of subsequent indexed
// commands. Implicitly handles the case when the new mask is the same for all buffers.
// For instance, let's say that previously synced mask is ccccff00 and the new state is
// ffeeeeee. Instead of calling colorMaski 8 times, ANGLE can set all buffers to `e` and then
// use colorMaski only twice. On the other hand, if the new state is cceeee00, a non-indexed
// call will increase the total number of GL commands.
if (diffCount > 1)
{
bool found = false;
gl::BlendStateExt::ColorMaskStorage::Type commonColorMask = 0;
for (size_t i = 0; i < mBlendStateExt.mMaxDrawBuffers - 1; i++)
{
const gl::BlendStateExt::ColorMaskStorage::Type tempCommonColorMask =
blendStateExt.expandColorMaskIndexed(i);
const gl::DrawBufferMask tempDiffMask =
blendStateExt.compareColorMask(tempCommonColorMask);
const size_t tempDiffCount = tempDiffMask.count();
if (tempDiffCount < diffCount)
{
found = true;
diffMask = tempDiffMask;
diffCount = tempDiffCount;
commonColorMask = tempCommonColorMask;
if (tempDiffCount == 0)
{
break; // the new mask is the same for all buffers
}
}
}
if (found)
{
gl::BlendStateExt::UnpackColorMask(commonColorMask, &r, &g, &b, &a);
mFunctions->colorMask(r, g, b, a);
}
}
for (size_t drawBufferIndex : diffMask)
{
blendStateExt.getColorMaskIndexed(drawBufferIndex, &r, &g, &b, &a);
mFunctions->colorMaski(static_cast<GLuint>(drawBufferIndex), r, g, b, a);
}
mBlendStateExt.mColorMask = blendStateExt.mColorMask;
mLocalDirtyBits.set(gl::State::DIRTY_BIT_COLOR_MASK);
}
void StateManagerGL::setDitherEnabled(bool enabled)
......
......@@ -89,12 +89,10 @@ class StateManagerGL final : angle::NonCopyable
void setDepthRange(float near, float far);
void setBlendEnabled(bool enabled);
void setBlendEnabledIndexed(const gl::DrawBufferMask blendEnabledMask);
void setBlendColor(const gl::ColorF &blendColor);
void setBlendFuncs(GLenum sourceBlendRGB,
GLenum destBlendRGB,
GLenum sourceBlendAlpha,
GLenum destBlendAlpha);
void setBlendEquations(GLenum blendEquationRGB, GLenum blendEquationAlpha);
void setBlendFuncs(const gl::BlendStateExt &blendStateExt);
void setBlendEquations(const gl::BlendStateExt &blendStateExt);
void setColorMask(bool red, bool green, bool blue, bool alpha);
void setSampleAlphaToCoverageEnabled(bool enabled);
void setSampleCoverageEnabled(bool enabled);
......@@ -137,11 +135,8 @@ class StateManagerGL final : angle::NonCopyable
void setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
bool enabled,
const FramebufferGL *framebuffer);
void setColorMaskForFramebuffer(bool red,
bool green,
bool blue,
bool alpha,
const FramebufferGL *framebuffer);
void setColorMaskForFramebuffer(const gl::BlendStateExt &blendStateExt,
const bool disableAlpha);
void setDitherEnabled(bool enabled);
......@@ -279,18 +274,10 @@ class StateManagerGL final : angle::NonCopyable
float mNear;
float mFar;
bool mBlendEnabled;
gl::ColorF mBlendColor;
GLenum mSourceBlendRGB;
GLenum mDestBlendRGB;
GLenum mSourceBlendAlpha;
GLenum mDestBlendAlpha;
GLenum mBlendEquationRGB;
GLenum mBlendEquationAlpha;
bool mColorMaskRed;
bool mColorMaskGreen;
bool mColorMaskBlue;
bool mColorMaskAlpha;
gl::BlendStateExt mBlendStateExt;
const bool mIndependentBlendStates;
bool mSampleAlphaToCoverageEnabled;
bool mSampleCoverageEnabled;
float mSampleCoverageValue;
......
......@@ -1162,7 +1162,16 @@ void GenerateCaps(const FunctionsGL *functions,
extensions->drawBuffers = functions->isAtLeastGL(gl::Version(2, 0)) ||
functions->hasGLExtension("ARB_draw_buffers") ||
functions->hasGLESExtension("GL_EXT_draw_buffers");
extensions->textureStorage = functions->standard == STANDARD_GL_DESKTOP ||
extensions->drawBuffersIndexedEXT =
!features.disableDrawBuffersIndexed.enabled &&
(functions->isAtLeastGL(gl::Version(4, 0)) ||
(functions->hasGLExtension("GL_EXT_draw_buffers2") &&
functions->hasGLExtension("GL_ARB_draw_buffers_blend")) ||
functions->isAtLeastGLES(gl::Version(3, 2)) ||
functions->hasGLESExtension("GL_OES_draw_buffers_indexed") ||
functions->hasGLESExtension("GL_EXT_draw_buffers_indexed"));
extensions->drawBuffersIndexedOES = extensions->drawBuffersIndexedEXT;
extensions->textureStorage = functions->standard == STANDARD_GL_DESKTOP ||
functions->hasGLESExtension("GL_EXT_texture_storage");
extensions->textureFilterAnisotropic =
functions->hasGLExtension("GL_EXT_texture_filter_anisotropic") ||
......@@ -1705,6 +1714,8 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature
// Workaround for incorrect sampling from DXT1 sRGB textures in Intel OpenGL on Windows.
ANGLE_FEATURE_CONDITION(features, avoidDXT1sRGBTextureFormat, IsWindows() && isIntel);
ANGLE_FEATURE_CONDITION(features, disableDrawBuffersIndexed, IsWindows() && isAMD);
ANGLE_FEATURE_CONDITION(
features, disableSemaphoreFd,
IsLinux() && isAMD && isMesa && mesaVersion < (std::array<int, 3>{19, 3, 5}));
......
......@@ -852,7 +852,7 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments)
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"));
constexpr uint32_t kSize = 16;
constexpr uint32_t kAttachmentCount = 2;
constexpr uint32_t kAttachmentCount = 4;
std::vector<unsigned char> pixelData(kSize * kSize * 4, 255);
glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
......@@ -882,7 +882,8 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments)
// Block blue channel for all attachements
glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE);
// Unblock blue channel for attachement 1
// Unblock blue channel for attachments 0 and 1
glColorMaskiOES(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glColorMaskiOES(1, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
......@@ -895,12 +896,12 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments)
glReadBuffer(GL_COLOR_ATTACHMENT0 + i);
ASSERT_GL_NO_ERROR();
const GLColor attachementColor = (i == 1) ? clearColor : clearColorMasked;
EXPECT_PIXEL_COLOR_EQ(0, 0, attachementColor);
EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, attachementColor);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, attachementColor);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, attachementColor);
EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, attachementColor);
const GLColor attachmentColor = (i > 1) ? clearColorMasked : clearColor;
EXPECT_PIXEL_COLOR_EQ(0, 0, attachmentColor);
EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, attachmentColor);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, attachmentColor);
EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, attachmentColor);
EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, attachmentColor);
}
}
......
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