blob: c7ce3dd9ae4c09b25e0a8402a58f54d54984aa81 [file] [log] [blame]
/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 3.1 Module
* -------------------------------------------------
*
* Copyright 2016 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 Negative Advanced Blend Equation Tests
*//*--------------------------------------------------------------------*/
#include "es31fNegativeAdvancedBlendEquationTests.hpp"
#include "gluShaderProgram.hpp"
#include "glwEnums.hpp"
namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace NegativeTestShared
{
namespace
{
enum BlendEquation
{
BLEND_EQUATION_MULTIPLY = 0,
BLEND_EQUATION_SCREEN,
BLEND_EQUATION_OVERLAY,
BLEND_EQUATION_DARKEN,
BLEND_EQUATION_LIGHTEN,
BLEND_EQUATION_COLORDODGE,
BLEND_EQUATION_COLORBURN,
BLEND_EQUATION_HARDLIGHT,
BLEND_EQUATION_SOFTLIGHT,
BLEND_EQUATION_DIFFERENCE,
BLEND_EQUATION_EXCLUSION,
BLEND_EQUATION_HSL_HUE,
BLEND_EQUATION_HSL_SATURATION,
BLEND_EQUATION_HSL_COLOR,
BLEND_EQUATION_HSL_LUMINOSITY,
BLEND_EQUATION_ALL_EQUATIONS,
BLEND_EQUATION_LAST
};
static const BlendEquation s_equations[] = {
BLEND_EQUATION_MULTIPLY, BLEND_EQUATION_SCREEN, BLEND_EQUATION_OVERLAY, BLEND_EQUATION_DARKEN,
BLEND_EQUATION_LIGHTEN, BLEND_EQUATION_COLORDODGE, BLEND_EQUATION_COLORBURN, BLEND_EQUATION_HARDLIGHT,
BLEND_EQUATION_SOFTLIGHT, BLEND_EQUATION_DIFFERENCE, BLEND_EQUATION_EXCLUSION, BLEND_EQUATION_HSL_HUE,
BLEND_EQUATION_HSL_SATURATION, BLEND_EQUATION_HSL_COLOR, BLEND_EQUATION_HSL_LUMINOSITY};
std::string getShaderLayoutEquation(BlendEquation equation)
{
switch (equation)
{
case BLEND_EQUATION_MULTIPLY:
return "blend_support_multiply";
case BLEND_EQUATION_SCREEN:
return "blend_support_screen";
case BLEND_EQUATION_OVERLAY:
return "blend_support_overlay";
case BLEND_EQUATION_DARKEN:
return "blend_support_darken";
case BLEND_EQUATION_LIGHTEN:
return "blend_support_lighten";
case BLEND_EQUATION_COLORDODGE:
return "blend_support_colordodge";
case BLEND_EQUATION_COLORBURN:
return "blend_support_colorburn";
case BLEND_EQUATION_HARDLIGHT:
return "blend_support_hardlight";
case BLEND_EQUATION_SOFTLIGHT:
return "blend_support_softlight";
case BLEND_EQUATION_DIFFERENCE:
return "blend_support_difference";
case BLEND_EQUATION_EXCLUSION:
return "blend_support_exclusion";
case BLEND_EQUATION_HSL_HUE:
return "blend_support_hsl_hue";
case BLEND_EQUATION_HSL_SATURATION:
return "blend_support_hsl_saturation";
case BLEND_EQUATION_HSL_COLOR:
return "blend_support_hsl_color";
case BLEND_EQUATION_HSL_LUMINOSITY:
return "blend_support_hsl_luminosity";
case BLEND_EQUATION_ALL_EQUATIONS:
return "blend_support_all_equations";
default:
DE_FATAL("Equation not supported.");
}
return DE_NULL;
}
glw::GLenum getEquation(BlendEquation equation)
{
switch (equation)
{
case BLEND_EQUATION_MULTIPLY:
return GL_MULTIPLY;
case BLEND_EQUATION_SCREEN:
return GL_SCREEN;
case BLEND_EQUATION_OVERLAY:
return GL_OVERLAY;
case BLEND_EQUATION_DARKEN:
return GL_DARKEN;
case BLEND_EQUATION_LIGHTEN:
return GL_LIGHTEN;
case BLEND_EQUATION_COLORDODGE:
return GL_COLORDODGE;
case BLEND_EQUATION_COLORBURN:
return GL_COLORBURN;
case BLEND_EQUATION_HARDLIGHT:
return GL_HARDLIGHT;
case BLEND_EQUATION_SOFTLIGHT:
return GL_SOFTLIGHT;
case BLEND_EQUATION_DIFFERENCE:
return GL_DIFFERENCE;
case BLEND_EQUATION_EXCLUSION:
return GL_EXCLUSION;
case BLEND_EQUATION_HSL_HUE:
return GL_HSL_HUE;
case BLEND_EQUATION_HSL_SATURATION:
return GL_HSL_SATURATION;
case BLEND_EQUATION_HSL_COLOR:
return GL_HSL_COLOR;
case BLEND_EQUATION_HSL_LUMINOSITY:
return GL_HSL_LUMINOSITY;
default:
DE_FATAL("Equation not supported.");
}
return DE_NULL;
}
std::string generateVertexShaderSource(NegativeTestContext &ctx)
{
const bool supportsES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
const glu::GLSLVersion version = supportsES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
std::ostringstream source;
source << glu::getGLSLVersionDeclaration(version) << "\n"
<< "void main ()\n"
<< "{\n"
<< " gl_Position = vec4(0.0);\n"
<< "}\n";
return source.str();
}
std::string generateFragmentShaderSource(NegativeTestContext &ctx, BlendEquation equation)
{
const bool supportsES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
const glu::GLSLVersion version = supportsES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
std::ostringstream source;
source << glu::getGLSLVersionDeclaration(version) << "\n"
<< (supportsES32 ? "" : "#extension GL_KHR_blend_equation_advanced : enable\n") << "layout("
<< getShaderLayoutEquation(equation) << ") out;\n"
<< "layout(location=0) out mediump vec4 o_color;\n"
<< "void main ()\n"
<< "{\n"
<< " o_color = vec4(0);\n"
<< "}\n";
return source.str();
}
glu::ProgramSources generateProgramSources(NegativeTestContext &ctx, BlendEquation equation)
{
return glu::ProgramSources() << glu::VertexSource(generateVertexShaderSource(ctx))
<< glu::FragmentSource(generateFragmentShaderSource(ctx, equation));
}
void blend_qualifier_mismatch(NegativeTestContext &ctx)
{
TCU_CHECK_AND_THROW(NotSupportedError,
ctx.isExtensionSupported("GL_KHR_blend_equation_advanced") ||
contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)),
"This test requires support for the extension GL_KHR_blend_equation_advanced or context "
"version 3.2 or higher.");
glw::GLuint vao = 0;
bool isES = glu::isContextTypeES(ctx.getRenderContext().getType());
if (!isES)
{
ctx.glGenVertexArrays(1, &vao);
ctx.glBindVertexArray(vao);
}
ctx.beginSection("GL_INVALID_OPERATION is generated if blending is enabled, and the blend qualifier is different "
"from blend_support_all_equations and does not match the blend equation.");
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_equations); ++ndx)
{
glu::ShaderProgram program(ctx.getRenderContext(), generateProgramSources(ctx, s_equations[ndx]));
ctx.getLog() << program;
TCU_CHECK(program.isOk());
ctx.glUseProgram(program.getProgram());
ctx.expectError(GL_NO_ERROR);
for (int ndx2 = 0; ndx2 < DE_LENGTH_OF_ARRAY(s_equations); ++ndx2)
{
if (s_equations[ndx] == s_equations[ndx2])
continue;
ctx.glEnable(GL_BLEND);
ctx.glBlendEquation(getEquation(s_equations[ndx2]));
ctx.expectError(GL_NO_ERROR);
ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
ctx.expectError(GL_INVALID_OPERATION);
ctx.glDisable(GL_BLEND);
ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
ctx.expectError(GL_NO_ERROR);
}
}
ctx.endSection();
if (!isES)
ctx.glDeleteVertexArrays(1, &vao);
}
void attachment_advanced_equation(NegativeTestContext &ctx)
{
TCU_CHECK_AND_THROW(NotSupportedError,
ctx.isExtensionSupported("GL_KHR_blend_equation_advanced") ||
contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)),
"This test requires support for the extension GL_KHR_blend_equation_advanced or context "
"version 3.2 or higher.");
glw::GLuint vao = 0;
glw::GLuint fbo = 0x1234;
glw::GLuint texture = 0x1234;
const glw::GLenum attachments[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
const bool isES = glu::isContextTypeES(ctx.getRenderContext().getType());
if (!isES)
{
ctx.glGenVertexArrays(1, &vao);
ctx.glBindVertexArray(vao);
}
ctx.glGenTextures(1, &texture);
ctx.glBindTexture(GL_TEXTURE_2D, texture);
ctx.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
ctx.glGenFramebuffers(1, &fbo);
ctx.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
ctx.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
ctx.expectError(GL_NO_ERROR);
ctx.glCheckFramebufferStatus(GL_FRAMEBUFFER);
ctx.beginSection(
"GL_INVALID_OPERATION is generated if blending is enabled, advanced equations are used, and the draw buffer "
"for other color outputs is not NONE unless NVX_blend_equation_advanced_multi_draw_buffers is supported.");
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_equations); ++ndx)
{
glu::ShaderProgram program(ctx.getRenderContext(), generateProgramSources(ctx, s_equations[ndx]));
ctx.getLog() << program;
TCU_CHECK(program.isOk());
ctx.glUseProgram(program.getProgram());
ctx.glEnable(GL_BLEND);
ctx.glDrawBuffers(2, attachments);
ctx.expectError(GL_NO_ERROR);
ctx.glBlendEquation(getEquation(s_equations[ndx]));
ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
if (ctx.isExtensionSupported("GL_NVX_blend_equation_advanced_multi_draw_buffers"))
ctx.expectError(GL_NO_ERROR);
else
ctx.expectError(GL_INVALID_OPERATION);
}
ctx.endSection();
ctx.beginSection("GL_NO_ERROR is generated if no advanced blend equations are used.");
ctx.glBlendEquation(GL_FUNC_ADD);
ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
ctx.expectError(GL_NO_ERROR);
ctx.endSection();
ctx.beginSection("GL_NO_ERROR is generated if blending is disabled.");
ctx.glDisable(GL_BLEND);
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_equations); ++ndx)
{
ctx.glBlendEquation(getEquation(s_equations[ndx]));
ctx.glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, 0);
ctx.expectError(GL_NO_ERROR);
}
ctx.endSection();
if (!isES)
ctx.glDeleteVertexArrays(1, &vao);
ctx.glDeleteFramebuffers(1, &fbo);
ctx.glDeleteTextures(1, &texture);
}
} // namespace
std::vector<FunctionContainer> getNegativeAdvancedBlendEquationTestFunctions(void)
{
const FunctionContainer funcs[] = {
{blend_qualifier_mismatch, "blend_qualifier_mismatch", "Test blend qualifier mismatch."},
{attachment_advanced_equation, "attachment_advanced_equation", "Test draw buffer for other color outputs."},
};
return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
}
} // namespace NegativeTestShared
} // namespace Functional
} // namespace gles31
} // namespace deqp