You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1676 lines
58 KiB
1676 lines
58 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL ES 3.1 Module
|
|
* -------------------------------------------------
|
|
*
|
|
* Copyright 2015 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Indexed blend operation tests (GL_EXT_draw_buffers_indexed)
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es31fDrawBuffersIndexedTests.hpp"
|
|
|
|
#include "gluContextInfo.hpp"
|
|
#include "gluDrawUtil.hpp"
|
|
#include "gluObjectWrapper.hpp"
|
|
#include "gluPixelTransfer.hpp"
|
|
#include "gluShaderProgram.hpp"
|
|
#include "gluStrUtil.hpp"
|
|
#include "gluTextureUtil.hpp"
|
|
|
|
#include "sglrReferenceUtils.hpp"
|
|
|
|
#include "rrMultisamplePixelBufferAccess.hpp"
|
|
#include "rrRenderer.hpp"
|
|
|
|
#include "glwEnums.hpp"
|
|
#include "glwFunctions.hpp"
|
|
|
|
#include "tcuEither.hpp"
|
|
#include "tcuImageCompare.hpp"
|
|
#include "tcuMaybe.hpp"
|
|
#include "tcuResultCollector.hpp"
|
|
#include "tcuStringTemplate.hpp"
|
|
#include "tcuTestLog.hpp"
|
|
#include "tcuTexture.hpp"
|
|
#include "tcuTextureUtil.hpp"
|
|
#include "tcuVector.hpp"
|
|
#include "tcuVectorUtil.hpp"
|
|
#include "tcuFloat.hpp"
|
|
|
|
#include "deRandom.hpp"
|
|
#include "deArrayUtil.hpp"
|
|
#include "deStringUtil.hpp"
|
|
#include "deUniquePtr.hpp"
|
|
|
|
#include "deInt32.h"
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
using tcu::BVec4;
|
|
using tcu::Either;
|
|
using tcu::IVec2;
|
|
using tcu::IVec4;
|
|
using tcu::Maybe;
|
|
using tcu::TestLog;
|
|
using tcu::TextureFormat;
|
|
using tcu::TextureLevel;
|
|
using tcu::UVec4;
|
|
using tcu::Vec2;
|
|
using tcu::Vec4;
|
|
using tcu::just;
|
|
|
|
using std::string;
|
|
using std::vector;
|
|
using std::map;
|
|
|
|
using sglr::rr_util::mapGLBlendEquation;
|
|
using sglr::rr_util::mapGLBlendFunc;
|
|
using sglr::rr_util::mapGLBlendEquationAdvanced;
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gles31
|
|
{
|
|
namespace Functional
|
|
{
|
|
namespace
|
|
{
|
|
|
|
typedef deUint32 BlendEq;
|
|
|
|
bool isAdvancedBlendEq (BlendEq eq)
|
|
{
|
|
switch (eq)
|
|
{
|
|
case GL_MULTIPLY: return true;
|
|
case GL_SCREEN: return true;
|
|
case GL_OVERLAY: return true;
|
|
case GL_DARKEN: return true;
|
|
case GL_LIGHTEN: return true;
|
|
case GL_COLORDODGE: return true;
|
|
case GL_COLORBURN: return true;
|
|
case GL_HARDLIGHT: return true;
|
|
case GL_SOFTLIGHT: return true;
|
|
case GL_DIFFERENCE: return true;
|
|
case GL_EXCLUSION: return true;
|
|
case GL_HSL_HUE: return true;
|
|
case GL_HSL_SATURATION: return true;
|
|
case GL_HSL_COLOR: return true;
|
|
case GL_HSL_LUMINOSITY: return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
struct SeparateBlendEq
|
|
{
|
|
SeparateBlendEq (BlendEq rgb_, BlendEq alpha_)
|
|
: rgb (rgb_)
|
|
, alpha (alpha_)
|
|
{
|
|
}
|
|
|
|
BlendEq rgb;
|
|
BlendEq alpha;
|
|
};
|
|
|
|
struct BlendFunc
|
|
{
|
|
BlendFunc (deUint32 src_, deUint32 dst_)
|
|
: src (src_)
|
|
, dst (dst_)
|
|
{
|
|
}
|
|
|
|
deUint32 src;
|
|
deUint32 dst;
|
|
};
|
|
|
|
struct SeparateBlendFunc
|
|
{
|
|
SeparateBlendFunc (BlendFunc rgb_, BlendFunc alpha_)
|
|
: rgb (rgb_)
|
|
, alpha (alpha_)
|
|
{
|
|
}
|
|
|
|
BlendFunc rgb;
|
|
BlendFunc alpha;
|
|
};
|
|
|
|
typedef deUint32 DrawBuffer;
|
|
|
|
struct BlendState
|
|
{
|
|
BlendState (void) {}
|
|
|
|
BlendState (const Maybe<bool>& enableBlend_,
|
|
const Maybe<Either<BlendEq, SeparateBlendEq> >& blendEq_,
|
|
const Maybe<Either<BlendFunc, SeparateBlendFunc> >& blendFunc_,
|
|
const Maybe<BVec4>& colorMask_)
|
|
: enableBlend (enableBlend_)
|
|
, blendEq (blendEq_)
|
|
, blendFunc (blendFunc_)
|
|
, colorMask (colorMask_)
|
|
{
|
|
}
|
|
|
|
bool isEmpty (void) const
|
|
{
|
|
return (!enableBlend) && (!blendEq) && (!blendFunc) && (!colorMask);
|
|
}
|
|
|
|
Maybe<bool> enableBlend;
|
|
Maybe<Either<BlendEq, SeparateBlendEq> > blendEq;
|
|
Maybe<Either<BlendFunc, SeparateBlendFunc> > blendFunc;
|
|
Maybe<BVec4> colorMask;
|
|
};
|
|
|
|
static bool checkES32orGL45Support(Context& ctx)
|
|
{
|
|
auto ctxType = ctx.getRenderContext().getType();
|
|
return contextSupports(ctxType, glu::ApiType::es(3, 2)) ||
|
|
contextSupports(ctxType, glu::ApiType::core(4, 5));
|
|
}
|
|
|
|
void setCommonBlendState (const glw::Functions& gl, const BlendState& blend)
|
|
{
|
|
if (blend.enableBlend)
|
|
{
|
|
if (*blend.enableBlend)
|
|
gl.enable(GL_BLEND);
|
|
else
|
|
gl.disable(GL_BLEND);
|
|
}
|
|
|
|
if (blend.colorMask)
|
|
{
|
|
const BVec4& mask = *blend.colorMask;
|
|
|
|
gl.colorMask(mask.x(), mask.y(), mask.z(), mask.w());
|
|
}
|
|
|
|
if (blend.blendEq)
|
|
{
|
|
const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
|
|
|
|
if (blendEq.is<BlendEq>())
|
|
gl.blendEquation(blendEq.get<BlendEq>());
|
|
else if (blendEq.is<SeparateBlendEq>())
|
|
gl.blendEquationSeparate(blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha);
|
|
else
|
|
DE_ASSERT(false);
|
|
}
|
|
|
|
if (blend.blendFunc)
|
|
{
|
|
const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
|
|
|
|
if (blendFunc.is<BlendFunc>())
|
|
gl.blendFunc(blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst);
|
|
else if (blendFunc.is<SeparateBlendFunc>())
|
|
gl.blendFuncSeparate(blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst);
|
|
else
|
|
DE_ASSERT(false);
|
|
}
|
|
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set common blend state.");
|
|
}
|
|
|
|
void setIndexedBlendState (const glw::Functions& gl, const BlendState& blend, deUint32 index)
|
|
{
|
|
if (blend.enableBlend)
|
|
{
|
|
if (*blend.enableBlend)
|
|
gl.enablei(GL_BLEND, index);
|
|
else
|
|
gl.disablei(GL_BLEND, index);
|
|
}
|
|
|
|
if (blend.colorMask)
|
|
{
|
|
const BVec4 mask = *blend.colorMask;
|
|
|
|
gl.colorMaski(index, mask.x(), mask.y(), mask.z(), mask.w());
|
|
}
|
|
|
|
if (blend.blendEq)
|
|
{
|
|
const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
|
|
|
|
if (blendEq.is<BlendEq>())
|
|
gl.blendEquationi(index, blendEq.get<BlendEq>());
|
|
else if (blendEq.is<SeparateBlendEq>())
|
|
gl.blendEquationSeparatei(index, blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha);
|
|
else
|
|
DE_ASSERT(false);
|
|
}
|
|
|
|
if (blend.blendFunc)
|
|
{
|
|
const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
|
|
|
|
if (blendFunc.is<BlendFunc>())
|
|
gl.blendFunci(index, blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst);
|
|
else if (blendFunc.is<SeparateBlendFunc>())
|
|
gl.blendFuncSeparatei(index, blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst);
|
|
else
|
|
DE_ASSERT(false);
|
|
}
|
|
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set draw buffer specifig blend state.");
|
|
}
|
|
|
|
class DrawBufferInfo
|
|
{
|
|
public:
|
|
DrawBufferInfo (bool render,
|
|
const IVec2& size,
|
|
const BlendState& blendState,
|
|
const TextureFormat& format);
|
|
|
|
const TextureFormat& getFormat (void) const { return m_format; }
|
|
const IVec2& getSize (void) const { return m_size; }
|
|
const BlendState& getBlendState (void) const { return m_blendState; }
|
|
bool getRender (void) const { return m_render; }
|
|
|
|
private:
|
|
bool m_render;
|
|
IVec2 m_size;
|
|
TextureFormat m_format;
|
|
BlendState m_blendState;
|
|
};
|
|
|
|
DrawBufferInfo::DrawBufferInfo (bool render, const IVec2& size, const BlendState& blendState, const TextureFormat& format)
|
|
: m_render (render)
|
|
, m_size (size)
|
|
, m_format (format)
|
|
, m_blendState (blendState)
|
|
{
|
|
}
|
|
|
|
void clearRenderbuffer (const glw::Functions& gl,
|
|
const tcu::TextureFormat& format,
|
|
int renderbufferNdx,
|
|
int renderbufferCount,
|
|
tcu::TextureLevel& refRenderbuffer)
|
|
{
|
|
const tcu::TextureFormatInfo info = tcu::getTextureFormatInfo(format);
|
|
|
|
// Clear each buffer to different color
|
|
const float redScale = float(renderbufferNdx + 1) / float(renderbufferCount);
|
|
const float blueScale = float(renderbufferCount - renderbufferNdx) / float(renderbufferCount);
|
|
const float greenScale = float(((renderbufferCount/2) + renderbufferNdx) % renderbufferCount) / float(renderbufferCount);
|
|
// Alpha should never be zero as advanced blend equations assume premultiplied alpha.
|
|
const float alphaScale = float(1 + (((renderbufferCount/2) + renderbufferCount - renderbufferNdx) % renderbufferCount)) / float(renderbufferCount);
|
|
|
|
switch (tcu::getTextureChannelClass(format.type))
|
|
{
|
|
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
|
|
{
|
|
const float red = -1000.0f + 2000.0f * redScale;
|
|
const float green = -1000.0f + 2000.0f * greenScale;
|
|
const float blue = -1000.0f + 2000.0f * blueScale;
|
|
const float alpha = -1000.0f + 2000.0f * alphaScale;
|
|
const Vec4 color (red, green, blue, alpha);
|
|
|
|
tcu::clear(refRenderbuffer, color);
|
|
gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
|
|
break;
|
|
}
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
|
|
{
|
|
const deInt32 red = deInt32(info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale);
|
|
const deInt32 green = deInt32(info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale);
|
|
const deInt32 blue = deInt32(info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale);
|
|
const deInt32 alpha = deInt32(info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale);
|
|
const IVec4 color (red, green, blue, alpha);
|
|
|
|
tcu::clear(refRenderbuffer, color);
|
|
gl.clearBufferiv(GL_COLOR, renderbufferNdx, color.getPtr());
|
|
break;
|
|
}
|
|
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
|
|
{
|
|
const deUint32 red = deUint32(info.valueMax.x() * redScale);
|
|
const deUint32 green = deUint32(info.valueMax.y() * greenScale);
|
|
const deUint32 blue = deUint32(info.valueMax.z() * blueScale);
|
|
const deUint32 alpha = deUint32(info.valueMax.w() * alphaScale);
|
|
const UVec4 color (red, green, blue, alpha);
|
|
|
|
tcu::clear(refRenderbuffer, color);
|
|
gl.clearBufferuiv(GL_COLOR, renderbufferNdx, color.getPtr());
|
|
break;
|
|
}
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
|
|
{
|
|
const float red = info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale;
|
|
const float green = info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale;
|
|
const float blue = info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale;
|
|
const float alpha = info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale;
|
|
const Vec4 color (red, green, blue, alpha);
|
|
|
|
tcu::clear(refRenderbuffer, color);
|
|
gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
|
|
break;
|
|
}
|
|
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
|
|
{
|
|
const float red = info.valueMax.x() * redScale;
|
|
const float green = info.valueMax.y() * greenScale;
|
|
const float blue = info.valueMax.z() * blueScale;
|
|
const float alpha = info.valueMax.w() * alphaScale;
|
|
const Vec4 color (red, green, blue, alpha);
|
|
|
|
tcu::clear(refRenderbuffer, color);
|
|
gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
|
|
break;
|
|
}
|
|
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear renderbuffer.");
|
|
}
|
|
|
|
void genRenderbuffers (const glw::Functions& gl,
|
|
const vector<DrawBufferInfo>& drawBuffers,
|
|
const glu::Framebuffer& framebuffer,
|
|
const glu::RenderbufferVector& renderbuffers,
|
|
vector<TextureLevel>& refRenderbuffers)
|
|
{
|
|
vector<deUint32> bufs;
|
|
|
|
bufs.resize(drawBuffers.size());
|
|
|
|
DE_ASSERT(drawBuffers.size() == renderbuffers.size());
|
|
DE_ASSERT(drawBuffers.size() == refRenderbuffers.size());
|
|
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
|
|
|
|
for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
|
|
{
|
|
const DrawBufferInfo& drawBuffer = drawBuffers[renderbufferNdx];
|
|
const TextureFormat& format = drawBuffer.getFormat();
|
|
const IVec2& size = drawBuffer.getSize();
|
|
const deUint32 glFormat = glu::getInternalFormat(format);
|
|
|
|
bufs[renderbufferNdx] = GL_COLOR_ATTACHMENT0 + renderbufferNdx;
|
|
refRenderbuffers[renderbufferNdx] = TextureLevel(drawBuffer.getFormat(), size.x(), size.y());
|
|
|
|
gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffers[renderbufferNdx]);
|
|
gl.renderbufferStorage(GL_RENDERBUFFER, glFormat, size.x(), size.y());
|
|
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + renderbufferNdx, GL_RENDERBUFFER, renderbuffers[renderbufferNdx]);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create renderbuffer.");
|
|
}
|
|
|
|
gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));
|
|
|
|
for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
|
|
{
|
|
const DrawBufferInfo& drawBuffer = drawBuffers[renderbufferNdx];
|
|
const TextureFormat& format = drawBuffer.getFormat();
|
|
|
|
clearRenderbuffer(gl, format, renderbufferNdx, (int)refRenderbuffers.size(), refRenderbuffers[renderbufferNdx]);
|
|
}
|
|
|
|
gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
Vec4 getFixedPointFormatThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
|
|
{
|
|
DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
|
|
DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
|
|
|
|
DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
|
|
DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
|
|
|
|
DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
|
|
DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
|
|
|
|
const tcu::IVec4 srcBits = tcu::getTextureFormatBitDepth(sourceFormat);
|
|
const tcu::IVec4 readBits = tcu::getTextureFormatBitDepth(readPixelsFormat);
|
|
|
|
return Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>();
|
|
}
|
|
|
|
UVec4 getFloatULPThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
|
|
{
|
|
const tcu::IVec4 srcMantissaBits = tcu::getTextureFormatMantissaBitDepth(sourceFormat);
|
|
const tcu::IVec4 readMantissaBits = tcu::getTextureFormatMantissaBitDepth(readPixelsFormat);
|
|
tcu::IVec4 ULPDiff(0);
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
if (readMantissaBits[i] >= srcMantissaBits[i])
|
|
ULPDiff[i] = readMantissaBits[i] - srcMantissaBits[i];
|
|
|
|
return UVec4(4) * (UVec4(1) << (ULPDiff.cast<deUint32>()));
|
|
}
|
|
|
|
void verifyRenderbuffer (TestLog& log,
|
|
tcu::ResultCollector& results,
|
|
const tcu::TextureFormat& format,
|
|
int renderbufferNdx,
|
|
const tcu::TextureLevel& refRenderbuffer,
|
|
const tcu::TextureLevel& result)
|
|
{
|
|
switch (tcu::getTextureChannelClass(format.type))
|
|
{
|
|
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
|
|
{
|
|
const string name = "Renderbuffer" + de::toString(renderbufferNdx);
|
|
const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
|
|
const UVec4 threshold = getFloatULPThreshold(format, result.getFormat());
|
|
|
|
if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
|
|
results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
|
|
|
|
break;
|
|
}
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
|
|
{
|
|
const string name = "Renderbuffer" + de::toString(renderbufferNdx);
|
|
const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
|
|
const UVec4 threshold (1, 1, 1, 1);
|
|
|
|
if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
|
|
results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
|
|
|
|
break;
|
|
}
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
|
|
{
|
|
const string name = "Renderbuffer" + de::toString(renderbufferNdx);
|
|
const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx);
|
|
const Vec4 threshold = getFixedPointFormatThreshold(format, result.getFormat());
|
|
|
|
if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
|
|
results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
}
|
|
|
|
TextureFormat getReadPixelFormat (const TextureFormat& format)
|
|
{
|
|
switch (tcu::getTextureChannelClass(format.type))
|
|
{
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
|
|
return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32);
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
|
|
return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT32);
|
|
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
|
|
return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
|
|
|
|
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
|
|
return TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT);
|
|
|
|
default:
|
|
DE_ASSERT(false);
|
|
return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
|
|
}
|
|
}
|
|
|
|
void verifyRenderbuffers (TestLog& log,
|
|
tcu::ResultCollector& results,
|
|
glu::RenderContext& renderContext,
|
|
const glu::RenderbufferVector& renderbuffers,
|
|
const glu::Framebuffer& framebuffer,
|
|
const vector<TextureLevel>& refRenderbuffers)
|
|
{
|
|
const glw::Functions& gl = renderContext.getFunctions();
|
|
|
|
DE_ASSERT(renderbuffers.size() == refRenderbuffers.size());
|
|
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
|
|
|
|
for (int renderbufferNdx = 0; renderbufferNdx < (int)renderbuffers.size(); renderbufferNdx++)
|
|
{
|
|
const TextureLevel& refRenderbuffer = refRenderbuffers[renderbufferNdx];
|
|
const int width = refRenderbuffer.getWidth();
|
|
const int height = refRenderbuffer.getHeight();
|
|
const TextureFormat format = refRenderbuffer.getFormat();
|
|
|
|
tcu::TextureLevel result (getReadPixelFormat(format), width, height);
|
|
|
|
gl.readBuffer(GL_COLOR_ATTACHMENT0 + renderbufferNdx);
|
|
glu::readPixels(renderContext, 0, 0, result.getAccess());
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels from renderbuffer failed.");
|
|
|
|
verifyRenderbuffer(log, results, format, renderbufferNdx, refRenderbuffer, result);
|
|
}
|
|
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
static const float s_quadCoords[] =
|
|
{
|
|
-0.5f, -0.5f,
|
|
0.5f, -0.5f,
|
|
0.5f, 0.5f,
|
|
|
|
0.5f, 0.5f,
|
|
-0.5f, 0.5f,
|
|
-0.5f, -0.5f
|
|
};
|
|
|
|
void setBlendState (rr::FragmentOperationState& fragOps, const BlendState& state)
|
|
{
|
|
if (state.blendEq)
|
|
{
|
|
if (state.blendEq->is<BlendEq>())
|
|
{
|
|
if (isAdvancedBlendEq(state.blendEq->get<BlendEq>()))
|
|
{
|
|
const rr::BlendEquationAdvanced equation = mapGLBlendEquationAdvanced(state.blendEq->get<BlendEq>());
|
|
|
|
fragOps.blendMode = rr::BLENDMODE_ADVANCED;
|
|
fragOps.blendEquationAdvaced = equation;
|
|
}
|
|
else
|
|
{
|
|
const rr::BlendEquation equation = mapGLBlendEquation(state.blendEq->get<BlendEq>());
|
|
|
|
fragOps.blendMode = rr::BLENDMODE_STANDARD;
|
|
fragOps.blendRGBState.equation = equation;
|
|
fragOps.blendAState.equation = equation;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DE_ASSERT(state.blendEq->is<SeparateBlendEq>());
|
|
|
|
fragOps.blendMode = rr::BLENDMODE_STANDARD;
|
|
fragOps.blendRGBState.equation = mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().rgb);
|
|
fragOps.blendAState.equation = mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().alpha);
|
|
}
|
|
}
|
|
|
|
if (state.blendFunc)
|
|
{
|
|
if (state.blendFunc->is<BlendFunc>())
|
|
{
|
|
const rr::BlendFunc srcFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().src);
|
|
const rr::BlendFunc dstFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().dst);
|
|
|
|
fragOps.blendRGBState.srcFunc = srcFunction;
|
|
fragOps.blendRGBState.dstFunc = dstFunction;
|
|
|
|
fragOps.blendAState.srcFunc = srcFunction;
|
|
fragOps.blendAState.dstFunc = dstFunction;
|
|
}
|
|
else
|
|
{
|
|
DE_ASSERT(state.blendFunc->is<SeparateBlendFunc>());
|
|
|
|
fragOps.blendRGBState.srcFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.src);
|
|
fragOps.blendRGBState.dstFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.dst);
|
|
|
|
fragOps.blendAState.srcFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.src);
|
|
fragOps.blendAState.dstFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.dst);
|
|
}
|
|
}
|
|
|
|
if (state.colorMask)
|
|
fragOps.colorMask = *state.colorMask;
|
|
}
|
|
|
|
rr::RenderState createRenderState (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const DrawBufferInfo& info, int subpixelBits)
|
|
{
|
|
const IVec2 size = info.getSize();
|
|
rr::RenderState state (rr::ViewportState(rr::WindowRectangle(0, 0, size.x(), size.y())), subpixelBits);
|
|
|
|
state.fragOps.blendMode = rr::BLENDMODE_STANDARD;
|
|
|
|
setBlendState(state.fragOps, preCommonBlendState);
|
|
setBlendState(state.fragOps, info.getBlendState());
|
|
setBlendState(state.fragOps, postCommonBlendState);
|
|
|
|
if (postCommonBlendState.enableBlend)
|
|
state.fragOps.blendMode = (*(postCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
|
|
else if (info.getBlendState().enableBlend)
|
|
state.fragOps.blendMode = (*(info.getBlendState().enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
|
|
else if (preCommonBlendState.enableBlend)
|
|
state.fragOps.blendMode = (*(preCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
|
|
else
|
|
state.fragOps.blendMode = rr::BLENDMODE_NONE;
|
|
|
|
if (tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
|
|
&& tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
|
|
&& tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
|
|
state.fragOps.blendMode = rr::BLENDMODE_NONE;
|
|
|
|
return state;
|
|
}
|
|
|
|
class VertexShader : public rr::VertexShader
|
|
{
|
|
public:
|
|
VertexShader (void);
|
|
virtual void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
|
|
};
|
|
|
|
VertexShader::VertexShader (void)
|
|
: rr::VertexShader (1, 1)
|
|
{
|
|
m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
}
|
|
|
|
void VertexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
rr::VertexPacket& packet = *packets[packetNdx];
|
|
|
|
packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
|
|
packet.outputs[0] = 0.5f * (Vec4(1.0f) + rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx));
|
|
}
|
|
}
|
|
|
|
class FragmentShader : public rr::FragmentShader
|
|
{
|
|
public:
|
|
FragmentShader (int drawBufferNdx, const DrawBufferInfo& info);
|
|
void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
|
|
|
|
private:
|
|
const int m_drawBufferNdx;
|
|
const DrawBufferInfo m_info;
|
|
};
|
|
|
|
FragmentShader::FragmentShader (int drawBufferNdx, const DrawBufferInfo& info)
|
|
: rr::FragmentShader (1, 1)
|
|
, m_drawBufferNdx (drawBufferNdx)
|
|
, m_info (info)
|
|
{
|
|
m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
|
|
switch (tcu::getTextureChannelClass(m_info.getFormat().type))
|
|
{
|
|
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
|
|
m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
break;
|
|
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
|
|
m_outputs[0].type = rr::GENERICVECTYPE_UINT32;
|
|
break;
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
|
|
m_outputs[0].type = rr::GENERICVECTYPE_INT32;
|
|
break;
|
|
|
|
default:
|
|
DE_ASSERT(false);
|
|
};
|
|
}
|
|
|
|
void FragmentShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
rr::FragmentPacket& packet = packets[packetNdx];
|
|
|
|
DE_ASSERT(m_drawBufferNdx >= 0);
|
|
DE_UNREF(m_info);
|
|
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const Vec2 vColor = rr::readVarying<float>(packet, context, 0, fragNdx).xy();
|
|
const float values[] =
|
|
{
|
|
vColor.x(),
|
|
vColor.y(),
|
|
(1.0f - vColor.x()),
|
|
(1.0f - vColor.y())
|
|
};
|
|
|
|
switch (tcu::getTextureChannelClass(m_info.getFormat().type))
|
|
{
|
|
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
|
|
{
|
|
const Vec4 color (values[(m_drawBufferNdx + 0) % 4],
|
|
values[(m_drawBufferNdx + 1) % 4],
|
|
values[(m_drawBufferNdx + 2) % 4],
|
|
values[(m_drawBufferNdx + 3) % 4]);
|
|
|
|
rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
|
|
break;
|
|
}
|
|
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
|
|
{
|
|
const UVec4 color ((deUint32)(values[(m_drawBufferNdx + 0) % 4]),
|
|
(deUint32)(values[(m_drawBufferNdx + 1) % 4]),
|
|
(deUint32)(values[(m_drawBufferNdx + 2) % 4]),
|
|
(deUint32)(values[(m_drawBufferNdx + 3) % 4]));
|
|
|
|
rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
|
|
break;
|
|
}
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
|
|
{
|
|
const IVec4 color ((deInt32)(values[(m_drawBufferNdx + 0) % 4]),
|
|
(deInt32)(values[(m_drawBufferNdx + 1) % 4]),
|
|
(deInt32)(values[(m_drawBufferNdx + 2) % 4]),
|
|
(deInt32)(values[(m_drawBufferNdx + 3) % 4]));
|
|
|
|
rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
rr::VertexAttrib createVertexAttrib (const float* coords)
|
|
{
|
|
rr::VertexAttrib attrib;
|
|
|
|
attrib.type = rr::VERTEXATTRIBTYPE_FLOAT;
|
|
attrib.size = 2;
|
|
attrib.pointer = coords;
|
|
|
|
return attrib;
|
|
}
|
|
|
|
void renderRefQuad (const BlendState& preCommonBlendState,
|
|
const BlendState& postCommonBlendState,
|
|
const vector<DrawBufferInfo>& drawBuffers,
|
|
const int subpixelBits,
|
|
vector<TextureLevel>& refRenderbuffers)
|
|
{
|
|
const rr::Renderer renderer;
|
|
const rr::PrimitiveList primitives (rr::PRIMITIVETYPE_TRIANGLES, 6, 0);
|
|
const rr::VertexAttrib vertexAttribs[] =
|
|
{
|
|
createVertexAttrib(s_quadCoords)
|
|
};
|
|
|
|
for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
|
|
{
|
|
if (drawBuffers[drawBufferNdx].getRender())
|
|
{
|
|
const rr::RenderState renderState (createRenderState(preCommonBlendState, postCommonBlendState, drawBuffers[drawBufferNdx], subpixelBits));
|
|
const rr::RenderTarget renderTarget (rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refRenderbuffers[drawBufferNdx].getAccess()));
|
|
const VertexShader vertexShader;
|
|
const FragmentShader fragmentShader (drawBufferNdx, drawBuffers[drawBufferNdx]);
|
|
const rr::Program program (&vertexShader, &fragmentShader);
|
|
const rr::DrawCommand command (renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), vertexAttribs, primitives);
|
|
|
|
renderer.draw(command);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool requiresAdvancedBlendEq (const BlendState& pre, const BlendState post, const vector<DrawBufferInfo>& drawBuffers)
|
|
{
|
|
bool requiresAdvancedBlendEq = false;
|
|
|
|
if (pre.blendEq && pre.blendEq->is<BlendEq>())
|
|
requiresAdvancedBlendEq |= isAdvancedBlendEq(pre.blendEq->get<BlendEq>());
|
|
|
|
if (post.blendEq && post.blendEq->is<BlendEq>())
|
|
requiresAdvancedBlendEq |= isAdvancedBlendEq(post.blendEq->get<BlendEq>());
|
|
|
|
for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
|
|
{
|
|
const BlendState& drawBufferBlendState = drawBuffers[drawBufferNdx].getBlendState();
|
|
|
|
if (drawBufferBlendState.blendEq && drawBufferBlendState.blendEq->is<BlendEq>())
|
|
requiresAdvancedBlendEq |= isAdvancedBlendEq(drawBufferBlendState.blendEq->get<BlendEq>());
|
|
}
|
|
|
|
return requiresAdvancedBlendEq;
|
|
}
|
|
|
|
glu::VertexSource genVertexSource (glu::RenderContext& renderContext)
|
|
{
|
|
const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
|
|
|
|
const char* const vertexSource =
|
|
"${GLSL_VERSION_DECL}\n"
|
|
"layout(location=0) in highp vec2 i_coord;\n"
|
|
"out highp vec2 v_color;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
"\tv_color = 0.5 * (vec2(1.0) + i_coord);\n"
|
|
"\tgl_Position = vec4(i_coord, 0.0, 1.0);\n"
|
|
"}";
|
|
|
|
map<string, string> args;
|
|
args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
|
|
|
|
return glu::VertexSource(tcu::StringTemplate(vertexSource).specialize(args));
|
|
}
|
|
|
|
glu::FragmentSource genFragmentSource (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext)
|
|
{
|
|
std::ostringstream stream;
|
|
const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
|
|
|
|
stream << "${GLSL_VERSION_DECL}\n";
|
|
|
|
if (requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers))
|
|
{
|
|
stream << "${GLSL_EXTENSION}"
|
|
<< "layout(blend_support_all_equations) out;\n";
|
|
}
|
|
|
|
stream << "in highp vec2 v_color;\n";
|
|
|
|
for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
|
|
{
|
|
const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
|
|
const TextureFormat& format = drawBuffer.getFormat();
|
|
|
|
stream << "layout(location=" << drawBufferNdx << ") out highp ";
|
|
|
|
switch (tcu::getTextureChannelClass(format.type))
|
|
{
|
|
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
|
|
stream << "vec4";
|
|
break;
|
|
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
|
|
stream << "uvec4";
|
|
break;
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
|
|
stream << "ivec4";
|
|
break;
|
|
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
};
|
|
|
|
stream << " o_drawBuffer" << drawBufferNdx << ";\n";
|
|
}
|
|
|
|
stream << "void main (void)\n"
|
|
<< "{\n";
|
|
|
|
for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
|
|
{
|
|
const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
|
|
const TextureFormat& format = drawBuffer.getFormat();
|
|
const char* const values[] =
|
|
{
|
|
"v_color.x",
|
|
"v_color.y",
|
|
"(1.0 - v_color.x)",
|
|
"(1.0 - v_color.y)"
|
|
};
|
|
|
|
stream << "\to_drawBuffer" << drawBufferNdx;
|
|
|
|
switch (tcu::getTextureChannelClass(format.type))
|
|
{
|
|
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
|
|
stream << " = vec4(" << values[(drawBufferNdx + 0) % 4]
|
|
<< ", " << values[(drawBufferNdx + 1) % 4]
|
|
<< ", " << values[(drawBufferNdx + 2) % 4]
|
|
<< ", " << values[(drawBufferNdx + 3) % 4] << ");\n";
|
|
break;
|
|
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
|
|
stream << " = uvec4(uint(" << values[(drawBufferNdx + 0) % 4]
|
|
<< "), uint(" << values[(drawBufferNdx + 1) % 4]
|
|
<< "), uint(" << values[(drawBufferNdx + 2) % 4]
|
|
<< "), uint(" << values[(drawBufferNdx + 3) % 4] << "));\n";
|
|
break;
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
|
|
stream << " = ivec4(int(" << values[(drawBufferNdx + 0) % 4]
|
|
<< "), int(" << values[(drawBufferNdx + 1) % 4]
|
|
<< "), int(" << values[(drawBufferNdx + 2) % 4]
|
|
<< "), int(" << values[(drawBufferNdx + 3) % 4] << "));\n";
|
|
break;
|
|
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
};
|
|
}
|
|
|
|
stream << "}";
|
|
|
|
map<string, string> args;
|
|
args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
|
|
args["GLSL_EXTENSION"] = supportsES32 ? "\n" : "#extension GL_KHR_blend_equation_advanced : require\n";
|
|
|
|
return glu::FragmentSource(tcu::StringTemplate(stream.str()).specialize(args));
|
|
}
|
|
|
|
glu::ProgramSources genShaderSources (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext)
|
|
{
|
|
return glu::ProgramSources() << genVertexSource(renderContext) << genFragmentSource(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext);
|
|
}
|
|
|
|
void renderGLQuad (glu::RenderContext& renderContext,
|
|
const glu::ShaderProgram& program)
|
|
{
|
|
const glu::VertexArrayBinding vertexArrays[] =
|
|
{
|
|
glu::VertexArrayBinding(glu::BindingPoint(0), glu::VertexArrayPointer(glu::VTX_COMP_FLOAT, glu::VTX_COMP_CONVERT_NONE, 2, 6, 0, s_quadCoords))
|
|
};
|
|
|
|
glu::draw(renderContext, program.getProgram(), 1, vertexArrays, glu::pr::Triangles(6));
|
|
}
|
|
|
|
void renderQuad (TestLog& log,
|
|
glu::RenderContext& renderContext,
|
|
const BlendState& preCommonBlendState,
|
|
const BlendState& postCommonBlendState,
|
|
const vector<DrawBufferInfo>& drawBuffers,
|
|
const glu::Framebuffer& framebuffer,
|
|
vector<TextureLevel>& refRenderbuffers)
|
|
{
|
|
const glw::Functions& gl = renderContext.getFunctions();
|
|
const glu::ShaderProgram program (gl, genShaderSources(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext));
|
|
const IVec2 size = drawBuffers[0].getSize();
|
|
const bool requiresBlendBarriers = requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers);
|
|
|
|
vector<deUint32> bufs;
|
|
|
|
bufs.resize(drawBuffers.size());
|
|
|
|
for (int bufNdx = 0; bufNdx < (int)bufs.size(); bufNdx++)
|
|
bufs[bufNdx] = (drawBuffers[bufNdx].getRender() ? GL_COLOR_ATTACHMENT0 + bufNdx : GL_NONE);
|
|
|
|
log << program;
|
|
|
|
gl.viewport(0, 0, size.x(), size.y());
|
|
gl.useProgram(program.getProgram());
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
|
|
|
|
setCommonBlendState(gl, preCommonBlendState);
|
|
|
|
for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
|
|
setIndexedBlendState(gl, drawBuffers[renderbufferNdx].getBlendState(), renderbufferNdx);
|
|
|
|
setCommonBlendState(gl, postCommonBlendState);
|
|
|
|
gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));
|
|
|
|
if (requiresBlendBarriers)
|
|
gl.blendBarrier();
|
|
|
|
renderGLQuad(renderContext, program);
|
|
|
|
if (requiresBlendBarriers)
|
|
gl.blendBarrier();
|
|
|
|
gl.drawBuffers(0, 0);
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
gl.useProgram(0);
|
|
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
|
|
|
|
int subpixelBits = 0;
|
|
gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
|
|
|
|
renderRefQuad(preCommonBlendState, postCommonBlendState, drawBuffers, subpixelBits, refRenderbuffers);
|
|
}
|
|
|
|
void logBlendState (TestLog& log,
|
|
const BlendState& blend)
|
|
{
|
|
if (blend.enableBlend)
|
|
{
|
|
if (*blend.enableBlend)
|
|
log << TestLog::Message << "Enable blending." << TestLog::EndMessage;
|
|
else
|
|
log << TestLog::Message << "Disable blending." << TestLog::EndMessage;
|
|
}
|
|
|
|
if (blend.colorMask)
|
|
{
|
|
const BVec4 mask = *blend.colorMask;
|
|
|
|
log << TestLog::Message << "Set color mask: " << mask << "." << TestLog::EndMessage;
|
|
}
|
|
|
|
if (blend.blendEq)
|
|
{
|
|
const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
|
|
|
|
if (blendEq.is<BlendEq>())
|
|
log << TestLog::Message << "Set blend equation: " << glu::getBlendEquationStr(blendEq.get<BlendEq>()) << "." << TestLog::EndMessage;
|
|
else if (blendEq.is<SeparateBlendEq>())
|
|
log << TestLog::Message << "Set blend equation rgb: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().rgb) << ", alpha: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().alpha) << "." << TestLog::EndMessage;
|
|
else
|
|
DE_ASSERT(false);
|
|
}
|
|
|
|
if (blend.blendFunc)
|
|
{
|
|
const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
|
|
|
|
if (blendFunc.is<BlendFunc>())
|
|
log << TestLog::Message << "Set blend function source: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().dst) << "." << TestLog::EndMessage;
|
|
else if (blendFunc.is<SeparateBlendFunc>())
|
|
{
|
|
log << TestLog::Message << "Set blend function rgb source: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().rgb.src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().rgb.dst) << "." << TestLog::EndMessage;
|
|
log << TestLog::Message << "Set blend function alpha source: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().alpha.src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().alpha.dst) << "." << TestLog::EndMessage;
|
|
}
|
|
else
|
|
DE_ASSERT(false);
|
|
}
|
|
}
|
|
|
|
void logTestCaseInfo (TestLog& log,
|
|
const BlendState& preCommonBlendState,
|
|
const BlendState& postCommonBlendState,
|
|
const vector<DrawBufferInfo>& drawBuffers)
|
|
{
|
|
{
|
|
tcu::ScopedLogSection drawBuffersSection(log, "DrawBuffers", "Draw buffers");
|
|
|
|
for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
|
|
{
|
|
const tcu::ScopedLogSection drawBufferSection (log, "DrawBuffer" + de::toString(drawBufferNdx), "Draw Buffer " + de::toString(drawBufferNdx));
|
|
const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx];
|
|
|
|
log << TestLog::Message << "Format: " << drawBuffer.getFormat() << TestLog::EndMessage;
|
|
log << TestLog::Message << "Size: " << drawBuffer.getSize() << TestLog::EndMessage;
|
|
log << TestLog::Message << "Render: " << (drawBuffer.getRender() ? "true" : "false") << TestLog::EndMessage;
|
|
}
|
|
}
|
|
|
|
if (!preCommonBlendState.isEmpty())
|
|
{
|
|
tcu::ScopedLogSection s(log, "PreCommonState", "First set common blend state");
|
|
logBlendState(log, preCommonBlendState);
|
|
}
|
|
|
|
for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
|
|
{
|
|
if (!drawBuffers[drawBufferNdx].getBlendState().isEmpty())
|
|
{
|
|
const tcu::ScopedLogSection s(log, "DrawBufferState" + de::toString(drawBufferNdx), "Set DrawBuffer " + de::toString(drawBufferNdx) + " state to");
|
|
|
|
logBlendState(log, drawBuffers[drawBufferNdx].getBlendState());
|
|
}
|
|
}
|
|
|
|
if (!postCommonBlendState.isEmpty())
|
|
{
|
|
tcu::ScopedLogSection s(log, "PostCommonState", "After set common blend state");
|
|
logBlendState(log, postCommonBlendState);
|
|
}
|
|
}
|
|
|
|
void runTest (TestLog& log,
|
|
tcu::ResultCollector& results,
|
|
glu::RenderContext& renderContext,
|
|
|
|
const BlendState& preCommonBlendState,
|
|
const BlendState& postCommonBlendState,
|
|
const vector<DrawBufferInfo>& drawBuffers)
|
|
{
|
|
const glw::Functions& gl = renderContext.getFunctions();
|
|
glu::RenderbufferVector renderbuffers (gl, drawBuffers.size());
|
|
glu::Framebuffer framebuffer (gl);
|
|
vector<TextureLevel> refRenderbuffers (drawBuffers.size());
|
|
|
|
logTestCaseInfo(log, preCommonBlendState, postCommonBlendState, drawBuffers);
|
|
|
|
genRenderbuffers(gl, drawBuffers, framebuffer, renderbuffers, refRenderbuffers);
|
|
|
|
renderQuad(log, renderContext, preCommonBlendState, postCommonBlendState, drawBuffers, framebuffer, refRenderbuffers);
|
|
|
|
verifyRenderbuffers(log, results, renderContext, renderbuffers, framebuffer, refRenderbuffers);
|
|
}
|
|
|
|
class DrawBuffersIndexedTest : public TestCase
|
|
{
|
|
public:
|
|
DrawBuffersIndexedTest (Context& context,
|
|
const BlendState& preCommonBlendState,
|
|
const BlendState& postCommonBlendState,
|
|
const vector<DrawBufferInfo>& drawBuffers,
|
|
const string& name,
|
|
const string& description);
|
|
|
|
void init (void);
|
|
IterateResult iterate (void);
|
|
|
|
private:
|
|
const BlendState m_preCommonBlendState;
|
|
const BlendState m_postCommonBlendState;
|
|
const vector<DrawBufferInfo> m_drawBuffers;
|
|
};
|
|
|
|
DrawBuffersIndexedTest::DrawBuffersIndexedTest (Context& context,
|
|
const BlendState& preCommonBlendState,
|
|
const BlendState& postCommonBlendState,
|
|
const vector<DrawBufferInfo>& drawBuffers,
|
|
const string& name,
|
|
const string& description)
|
|
: TestCase (context, name.c_str(), description.c_str())
|
|
, m_preCommonBlendState (preCommonBlendState)
|
|
, m_postCommonBlendState (postCommonBlendState)
|
|
, m_drawBuffers (drawBuffers)
|
|
{
|
|
}
|
|
|
|
void DrawBuffersIndexedTest::init (void)
|
|
{
|
|
const bool supportsES32orGL45 = checkES32orGL45Support(m_context);
|
|
|
|
if (!supportsES32orGL45)
|
|
{
|
|
if (requiresAdvancedBlendEq(m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers) && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"))
|
|
TCU_THROW(NotSupportedError, "Extension GL_KHR_blend_equation_advanced not supported");
|
|
|
|
if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
|
|
TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
|
|
}
|
|
}
|
|
|
|
TestCase::IterateResult DrawBuffersIndexedTest::iterate (void)
|
|
{
|
|
TestLog& log = m_testCtx.getLog();
|
|
tcu::ResultCollector results (log);
|
|
|
|
runTest(log, results, m_context.getRenderContext(), m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers);
|
|
|
|
results.setTestContextResult(m_testCtx);
|
|
|
|
return STOP;
|
|
}
|
|
|
|
BlendEq getRandomBlendEq (de::Random& rng)
|
|
{
|
|
const BlendEq eqs[] =
|
|
{
|
|
GL_FUNC_ADD,
|
|
GL_FUNC_SUBTRACT,
|
|
GL_FUNC_REVERSE_SUBTRACT,
|
|
GL_MIN,
|
|
GL_MAX
|
|
};
|
|
|
|
return de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(eqs)>(eqs, rng.getUint32() % DE_LENGTH_OF_ARRAY(eqs));
|
|
}
|
|
|
|
BlendFunc getRandomBlendFunc (de::Random& rng)
|
|
{
|
|
const deUint32 funcs[] =
|
|
{
|
|
GL_ZERO,
|
|
GL_ONE,
|
|
GL_SRC_COLOR,
|
|
GL_ONE_MINUS_SRC_COLOR,
|
|
GL_DST_COLOR,
|
|
GL_ONE_MINUS_DST_COLOR,
|
|
GL_SRC_ALPHA,
|
|
GL_ONE_MINUS_SRC_ALPHA,
|
|
GL_DST_ALPHA,
|
|
GL_ONE_MINUS_DST_ALPHA,
|
|
GL_CONSTANT_COLOR,
|
|
GL_ONE_MINUS_CONSTANT_COLOR,
|
|
GL_CONSTANT_ALPHA,
|
|
GL_ONE_MINUS_CONSTANT_ALPHA,
|
|
GL_SRC_ALPHA_SATURATE
|
|
};
|
|
|
|
const deUint32 src = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
|
|
const deUint32 dst = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
|
|
|
|
return BlendFunc(src, dst);
|
|
}
|
|
|
|
void genRandomBlendState (de::Random& rng, BlendState& blendState)
|
|
{
|
|
if (rng.getBool())
|
|
blendState.enableBlend = rng.getBool();
|
|
|
|
if (rng.getBool())
|
|
{
|
|
if (rng.getBool())
|
|
blendState.blendEq = getRandomBlendEq(rng);
|
|
else
|
|
{
|
|
const BlendEq rgb = getRandomBlendEq(rng);
|
|
const BlendEq alpha = getRandomBlendEq(rng);
|
|
|
|
blendState.blendEq = SeparateBlendEq(rgb, alpha);
|
|
}
|
|
}
|
|
|
|
if (rng.getBool())
|
|
{
|
|
if (rng.getBool())
|
|
blendState.blendFunc = getRandomBlendFunc(rng);
|
|
else
|
|
{
|
|
const BlendFunc rgb = getRandomBlendFunc(rng);
|
|
const BlendFunc alpha = getRandomBlendFunc(rng);
|
|
|
|
blendState.blendFunc = SeparateBlendFunc(rgb, alpha);
|
|
}
|
|
}
|
|
|
|
if (rng.getBool())
|
|
{
|
|
const bool red = rng.getBool();
|
|
const bool green = rng.getBool();
|
|
const bool blue = rng.getBool();
|
|
const bool alpha = rng.getBool();
|
|
|
|
blendState.colorMask = BVec4(red, blue, green, alpha);
|
|
}
|
|
}
|
|
|
|
TextureFormat getRandomFormat (de::Random& rng, Context& context)
|
|
{
|
|
const bool supportsES32orGL45 = checkES32orGL45Support(context);
|
|
|
|
const deUint32 glFormats[] =
|
|
{
|
|
GL_R8,
|
|
GL_RG8,
|
|
GL_RGB8,
|
|
GL_RGB565,
|
|
GL_RGBA4,
|
|
GL_RGB5_A1,
|
|
GL_RGBA8,
|
|
GL_RGB10_A2,
|
|
GL_RGB10_A2UI,
|
|
GL_R8I,
|
|
GL_R8UI,
|
|
GL_R16I,
|
|
GL_R16UI,
|
|
GL_R32I,
|
|
GL_R32UI,
|
|
GL_RG8I,
|
|
GL_RG8UI,
|
|
GL_RG16I,
|
|
GL_RG16UI,
|
|
GL_RG32I,
|
|
GL_RG32UI,
|
|
GL_RGBA8I,
|
|
GL_RGBA8UI,
|
|
GL_RGBA16I,
|
|
GL_RGBA16UI,
|
|
GL_RGBA32I,
|
|
GL_RGBA32UI,
|
|
GL_RGBA16F,
|
|
GL_R32F,
|
|
GL_RG32F,
|
|
GL_RGBA32F,
|
|
GL_R11F_G11F_B10F
|
|
};
|
|
|
|
if (supportsES32orGL45)
|
|
return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % DE_LENGTH_OF_ARRAY(glFormats)));
|
|
else
|
|
{
|
|
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(glFormats) == 32);
|
|
return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % (DE_LENGTH_OF_ARRAY(glFormats) - 5)));
|
|
}
|
|
}
|
|
|
|
void genRandomTest (de::Random& rng, BlendState& preCommon, BlendState& postCommon, vector<DrawBufferInfo>& drawBuffers, int maxDrawBufferCount, Context& context)
|
|
{
|
|
genRandomBlendState(rng, preCommon);
|
|
genRandomBlendState(rng, postCommon);
|
|
|
|
for (int drawBufferNdx = 0; drawBufferNdx < maxDrawBufferCount; drawBufferNdx++)
|
|
{
|
|
const bool render = rng.getFloat() > 0.1f;
|
|
const IVec2 size (64, 64);
|
|
const TextureFormat format (getRandomFormat(rng, context));
|
|
BlendState blendState;
|
|
|
|
genRandomBlendState(rng, blendState);
|
|
|
|
// 32bit float formats don't support blending in GLES32
|
|
if (format.type == tcu::TextureFormat::FLOAT)
|
|
{
|
|
// If format is 32bit float post common can't enable blending
|
|
if (postCommon.enableBlend && *postCommon.enableBlend)
|
|
{
|
|
// Either don't set enable blend or disable blending
|
|
if (rng.getBool())
|
|
postCommon.enableBlend = tcu::nothing<bool>();
|
|
else
|
|
postCommon.enableBlend = tcu::just(false);
|
|
}
|
|
|
|
// If post common doesn't disable blending, per attachment state or
|
|
// pre common must.
|
|
if (!postCommon.enableBlend)
|
|
{
|
|
// If pre common enables blend per attachment must disable it
|
|
// If per attachment state changes blend state it must disable it
|
|
if ((preCommon.enableBlend && *preCommon.enableBlend)
|
|
|| blendState.enableBlend)
|
|
blendState.enableBlend = tcu::just(false);
|
|
}
|
|
}
|
|
|
|
drawBuffers.push_back(DrawBufferInfo(render, size, blendState, format));
|
|
}
|
|
}
|
|
|
|
class MaxDrawBuffersIndexedTest : public TestCase
|
|
{
|
|
public:
|
|
MaxDrawBuffersIndexedTest (Context& contet, int seed);
|
|
|
|
void init (void);
|
|
IterateResult iterate (void);
|
|
|
|
private:
|
|
const int m_seed;
|
|
};
|
|
|
|
MaxDrawBuffersIndexedTest::MaxDrawBuffersIndexedTest (Context& context, int seed)
|
|
: TestCase (context, de::toString(seed).c_str(), de::toString(seed).c_str())
|
|
, m_seed (deInt32Hash(seed) ^ 1558001307u)
|
|
{
|
|
}
|
|
|
|
void MaxDrawBuffersIndexedTest::init (void)
|
|
{
|
|
const bool supportsES32orGL45 = checkES32orGL45Support(m_context);
|
|
|
|
if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
|
|
TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
|
|
}
|
|
|
|
TestCase::IterateResult MaxDrawBuffersIndexedTest::iterate (void)
|
|
{
|
|
TestLog& log = m_testCtx.getLog();
|
|
tcu::ResultCollector results (log);
|
|
de::Random rng (m_seed);
|
|
BlendState preCommonBlendState;
|
|
BlendState postCommonBlendState;
|
|
vector<DrawBufferInfo> drawBuffers;
|
|
|
|
genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, 4, m_context);
|
|
|
|
runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
|
|
|
|
results.setTestContextResult(m_testCtx);
|
|
|
|
return STOP;
|
|
}
|
|
|
|
class ImplMaxDrawBuffersIndexedTest : public TestCase
|
|
{
|
|
public:
|
|
ImplMaxDrawBuffersIndexedTest (Context& contet, int seed);
|
|
|
|
void init (void);
|
|
IterateResult iterate (void);
|
|
|
|
private:
|
|
const int m_seed;
|
|
};
|
|
|
|
ImplMaxDrawBuffersIndexedTest::ImplMaxDrawBuffersIndexedTest (Context& context, int seed)
|
|
: TestCase (context, de::toString(seed).c_str(), de::toString(seed).c_str())
|
|
, m_seed (deInt32Hash(seed) ^ 2686315738u)
|
|
{
|
|
}
|
|
|
|
void ImplMaxDrawBuffersIndexedTest::init (void)
|
|
{
|
|
const bool supportsES32orGL45 = checkES32orGL45Support(m_context);
|
|
|
|
if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
|
|
TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
|
|
}
|
|
|
|
TestCase::IterateResult ImplMaxDrawBuffersIndexedTest::iterate (void)
|
|
{
|
|
TestLog& log = m_testCtx.getLog();
|
|
tcu::ResultCollector results (log);
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
de::Random rng (m_seed);
|
|
deInt32 maxDrawBuffers = 0;
|
|
BlendState preCommonBlendState;
|
|
BlendState postCommonBlendState;
|
|
vector<DrawBufferInfo> drawBuffers;
|
|
|
|
gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_DRAW_BUFFERS) failed");
|
|
|
|
TCU_CHECK(maxDrawBuffers > 0);
|
|
|
|
genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, maxDrawBuffers, m_context);
|
|
|
|
runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
|
|
|
|
results.setTestContextResult(m_testCtx);
|
|
|
|
return STOP;
|
|
}
|
|
|
|
enum PrePost
|
|
{
|
|
PRE,
|
|
POST
|
|
};
|
|
|
|
TestCase* createDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
|
|
{
|
|
const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());
|
|
|
|
if (prepost == PRE)
|
|
{
|
|
const BlendState preState = BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
|
|
commonState.blendEq,
|
|
(commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
|
|
tcu::nothing<BVec4>());
|
|
vector<DrawBufferInfo> drawBuffers;
|
|
|
|
drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
|
|
drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
|
|
|
|
return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
|
|
}
|
|
else if (prepost == POST)
|
|
{
|
|
const BlendState preState = BlendState(just(true),
|
|
tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
|
|
Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
|
|
tcu::nothing<BVec4>());
|
|
vector<DrawBufferInfo> drawBuffers;
|
|
|
|
drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
|
|
drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
|
|
|
|
return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
|
|
}
|
|
else
|
|
{
|
|
DE_ASSERT(false);
|
|
return DE_NULL;
|
|
}
|
|
}
|
|
|
|
TestCase* createAdvancedEqDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
|
|
{
|
|
const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());
|
|
|
|
if (prepost == PRE)
|
|
{
|
|
const BlendState preState = BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
|
|
commonState.blendEq,
|
|
(commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
|
|
tcu::nothing<BVec4>());
|
|
vector<DrawBufferInfo> drawBuffers;
|
|
|
|
drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
|
|
|
|
return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
|
|
}
|
|
else if (prepost == POST)
|
|
{
|
|
const BlendState preState = BlendState(just(true),
|
|
tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
|
|
Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
|
|
tcu::nothing<BVec4>());
|
|
vector<DrawBufferInfo> drawBuffers;
|
|
|
|
drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
|
|
|
|
return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
|
|
}
|
|
else
|
|
{
|
|
DE_ASSERT(false);
|
|
return DE_NULL;
|
|
}
|
|
}
|
|
|
|
void addDrawBufferCommonTests (TestCaseGroup* root, PrePost prepost)
|
|
{
|
|
const BlendState emptyState = BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
|
|
|
|
{
|
|
const BlendState disableState = BlendState(just(false), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
|
|
const BlendState enableState = BlendState(just(true), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
|
|
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_enable", enableState, enableState));
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_disable", disableState, disableState));
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_enable", disableState, enableState));
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_disable", enableState, disableState));
|
|
}
|
|
|
|
{
|
|
const BlendState eqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_ADD), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
|
|
const BlendState eqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_SUBTRACT), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
|
|
|
|
const BlendState separateEqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_ADD, GL_FUNC_SUBTRACT)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
|
|
const BlendState separateEqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_SUBTRACT, GL_FUNC_ADD)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
|
|
|
|
const BlendState advancedEqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_DIFFERENCE), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
|
|
const BlendState advancedEqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_SCREEN), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
|
|
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_blend_eq", eqStateA, eqStateB));
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_separate_blend_eq", eqStateA, separateEqStateB));
|
|
root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_advanced_blend_eq", eqStateA, advancedEqStateB));
|
|
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_blend_eq", separateEqStateA, eqStateB));
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_separate_blend_eq", separateEqStateA, separateEqStateB));
|
|
root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_advanced_blend_eq", separateEqStateA, advancedEqStateB));
|
|
|
|
root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_blend_eq", advancedEqStateA, eqStateB));
|
|
root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_separate_blend_eq", advancedEqStateA, separateEqStateB));
|
|
root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_advanced_blend_eq", advancedEqStateA, advancedEqStateB));
|
|
}
|
|
|
|
{
|
|
const BlendState funcStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA)), Maybe<BVec4>());
|
|
const BlendState funcStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA)), Maybe<BVec4>());
|
|
const BlendState separateFuncStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA), BlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA))), Maybe<BVec4>());
|
|
const BlendState separateFuncStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA), BlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA))), Maybe<BVec4>());
|
|
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_blend_func", funcStateA, funcStateB));
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_separate_blend_func", funcStateA, separateFuncStateB));
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_blend_func", separateFuncStateA, funcStateB));
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_separate_blend_func", separateFuncStateA, separateFuncStateB));
|
|
}
|
|
|
|
{
|
|
const BlendState commonColorMaskState = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(true, false, true, false)));
|
|
const BlendState bufferColorMaskState = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(false, true, false, true)));
|
|
|
|
root->addChild(createDiffTest(root->getContext(), prepost, "common_color_mask_buffer_color_mask", commonColorMaskState, bufferColorMaskState));
|
|
}
|
|
}
|
|
|
|
void addRandomMaxTest (TestCaseGroup* root)
|
|
{
|
|
for (int i = 0; i < 20; i++)
|
|
root->addChild(new MaxDrawBuffersIndexedTest(root->getContext(), i));
|
|
}
|
|
|
|
void addRandomImplMaxTest (TestCaseGroup* root)
|
|
{
|
|
for (int i = 0; i < 20; i++)
|
|
root->addChild(new ImplMaxDrawBuffersIndexedTest(root->getContext(), i));
|
|
}
|
|
|
|
} // anonymous
|
|
|
|
TestCaseGroup* createDrawBuffersIndexedTests (Context& context)
|
|
{
|
|
const BlendState emptyState = BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
|
|
TestCaseGroup* const group = new TestCaseGroup(context, "draw_buffers_indexed", "Test for indexed draw buffers. GL_EXT_draw_buffers_indexed.");
|
|
|
|
TestCaseGroup* const preGroup = new TestCaseGroup(context, "overwrite_common", "Set common state and overwrite it with draw buffer blend state.");
|
|
TestCaseGroup* const postGroup = new TestCaseGroup(context, "overwrite_indexed", "Set indexed blend state and overwrite it with common state.");
|
|
TestCaseGroup* const randomGroup = new TestCaseGroup(context, "random", "Random indexed blend state tests.");
|
|
TestCaseGroup* const maxGroup = new TestCaseGroup(context, "max_required_draw_buffers", "Random tests using minimum maximum number of draw buffers.");
|
|
TestCaseGroup* const maxImplGroup = new TestCaseGroup(context, "max_implementation_draw_buffers", "Random tests using maximum number of draw buffers reported by implementation.");
|
|
|
|
group->addChild(preGroup);
|
|
group->addChild(postGroup);
|
|
group->addChild(randomGroup);
|
|
|
|
randomGroup->addChild(maxGroup);
|
|
randomGroup->addChild(maxImplGroup);
|
|
|
|
addDrawBufferCommonTests(preGroup, PRE);
|
|
addDrawBufferCommonTests(postGroup, POST);
|
|
addRandomMaxTest(maxGroup);
|
|
addRandomImplMaxTest(maxImplGroup);
|
|
|
|
return group;
|
|
}
|
|
|
|
} // Functional
|
|
} // gles31
|
|
} // deqp
|