/*-------------------------------------------------------------------------
 * OpenGL Conformance Test Suite
 * -----------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 *
 * 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
 */ /*-------------------------------------------------------------------*/

/**
 */ /*!
 * \file  gl4cTextureFilterMinmaxTests.cpp
 * \brief Conformance tests for the ARB_texture_filter_minmax functionality.
 */ /*-------------------------------------------------------------------*/

#include "gl4cTextureFilterMinmaxTests.hpp"
#include "gluContextInfo.hpp"
#include "gluDefs.hpp"
#include "gluDrawUtil.hpp"
#include "gluObjectWrapper.hpp"
#include "gluShaderProgram.hpp"
#include "gluTexture.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuImageIO.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuTestLog.hpp"
#include "tcuTextureUtil.hpp"

#include "deUniquePtr.hpp"

#include <map>
#include <vector>

namespace gl4cts
{

static const int TEXTURE_FILTER_MINMAX_SIZE               = 32;
static const float TEXTURE_FILTER_MINMAX_DOWNSCALE_FACTOR = 0.57f;
static const float TEXTURE_FILTER_MINMAX_UPSCALE_FACTOR   = 1.63f;

TextureFilterMinmaxUtils::TextureFilterMinmaxUtils()
{
    m_reductionModeParams.push_back(ReductionModeParam(GL_MIN, false));
    m_reductionModeParams.push_back(ReductionModeParam(GL_WEIGHTED_AVERAGE_ARB, false));
    m_reductionModeParams.push_back(ReductionModeParam(GL_MAX, false));

    m_supportedTextureTypes.push_back(new Texture1D());
    m_supportedTextureTypes.push_back(new Texture1DArray());
    m_supportedTextureTypes.push_back(new Texture2D());
    m_supportedTextureTypes.push_back(new Texture2DArray());
    m_supportedTextureTypes.push_back(new Texture3D());
    m_supportedTextureTypes.push_back(new TextureCube());

    m_supportedTextureDataTypes.push_back(SupportedTextureDataType(GL_RED, GL_FLOAT, MINMAX));
    m_supportedTextureDataTypes.push_back(SupportedTextureDataType(GL_RED, GL_UNSIGNED_BYTE, MINMAX));
    m_supportedTextureDataTypes.push_back(
        SupportedTextureDataType(GL_DEPTH_COMPONENT, GL_FLOAT, MINMAX | EXCLUDE_3D | EXCLUDE_CUBE));
    m_supportedTextureDataTypes.push_back(
        SupportedTextureDataType(GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, MINMAX | EXCLUDE_3D | EXCLUDE_CUBE));
}

TextureFilterMinmaxUtils::~TextureFilterMinmaxUtils()
{
    for (SupportedTextureTypeIter iter = m_supportedTextureTypes.begin(); iter != m_supportedTextureTypes.end(); ++iter)
    {
        SupportedTextureType *textureType = *iter;
        delete textureType;
    }
}

// SupportedTextureType

void TextureFilterMinmaxUtils::SupportedTextureType::replaceAll(std::string &str, const std::string &from,
                                                                const std::string &to)
{
    size_t start = 0;
    while ((start = str.find(from, start)) != std::string::npos)
    {
        str.replace(start, from.length(), to);
        start += to.length();
    }
}

TextureFilterMinmaxUtils::SupportedTextureType::SupportedTextureType(glw::GLenum type,
                                                                     const std::string &shaderTexcoordType,
                                                                     const std::string &shaderSamplerType)
    : m_type(type)
{
    m_vertexShader = "#version 450 core\n"
                     "in highp vec2 position;\n"
                     "in <texcoord_type> inTexcoord;\n"
                     "out <texcoord_type> texcoord;\n"
                     "void main()\n"
                     "{\n"
                     "    texcoord = inTexcoord;\n"
                     "    gl_Position = vec4(position, 0.0, 1.0);\n"
                     "}\n";

    m_fragmentShader = "#version 450 core\n"
                       "uniform <sampler_type> sampler;\n"
                       "in <texcoord_type> texcoord;\n"
                       "out vec4 color;\n"
                       "void main()\n"
                       "{\n"
                       "    color = texture(sampler, texcoord);\n"
                       "}\n";

    replaceAll(m_vertexShader, "<texcoord_type>", shaderTexcoordType);
    replaceAll(m_fragmentShader, "<texcoord_type>", shaderTexcoordType);
    replaceAll(m_fragmentShader, "<sampler_type>", shaderSamplerType);
}

void TextureFilterMinmaxUtils::SupportedTextureType::renderToFBO(const glu::RenderContext &context,
                                                                 glw::GLuint resultTextureId, tcu::IVec2 size,
                                                                 glw::GLint reductionMode)
{
    const glw::Functions &gl = context.getFunctions();

    gl.bindTexture(GL_TEXTURE_2D, resultTextureId);
    GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");

    gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, size.x(), size.y());
    GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");

    glw::GLuint fbo = 0;
    gl.genFramebuffers(1, &fbo);
    GLU_EXPECT_NO_ERROR(gl.getError(), "genFramebuffers error occurred");

    gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
    GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer error occurred");

    gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resultTextureId, 0);
    GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D error occurred");

    if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    {
        throw 0;
    }

    gl.viewport(0, 0, size.x(), size.y());
    renderQuad(context, reductionMode);

    gl.deleteFramebuffers(1, &fbo);
}

void TextureFilterMinmaxUtils::SupportedTextureType::renderQuad(const glu::RenderContext &context,
                                                                glw::GLint reductionMode)
{
    const glw::Functions &gl = context.getFunctions();

    uint16_t const quadIndices[] = {0, 1, 2, 2, 1, 3};

    float const position[] = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f};

    std::vector<float> texCoords = getTexCoords();

    glu::VertexArrayBinding vertexArrays[] = {glu::va::Float("position", 2, 4, 0, position),
                                              glu::va::Float("inTexcoord", 1, 4, 0, texCoords.data())};

    gl.bindTexture(m_type, this->getTextureGL());
    GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");

    gl.texParameteri(m_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    gl.texParameteri(m_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    gl.texParameteri(m_type, GL_TEXTURE_REDUCTION_MODE_ARB, reductionMode);

    glu::ShaderProgram program(context, glu::makeVtxFragSources(m_vertexShader, m_fragmentShader));
    if (!program.isOk())
    {
        TCU_FAIL("Shader compilation failed");
    }

    gl.useProgram(program.getProgram());
    GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram failed");

    gl.uniform1i(gl.getUniformLocation(program.getProgram(), "sampler"), 0);
    GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i failed");

    gl.clear(GL_COLOR_BUFFER_BIT);

    glu::draw(context, program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
              glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices));
}

// Texture1D

TextureFilterMinmaxUtils::Texture1D::Texture1D() : SupportedTextureType(GL_TEXTURE_1D, "float", "sampler1D")
{
}

glw::GLuint TextureFilterMinmaxUtils::Texture1D::getTextureGL()
{
    return m_texture->getGLTexture();
}

std::vector<float> TextureFilterMinmaxUtils::Texture1D::getTexCoords()
{
    float const texCoord[] = {0.0f, 0.0f, 1.0f, 1.0f};
    return std::vector<float>(texCoord, texCoord + sizeof(texCoord) / sizeof(float));
}

void TextureFilterMinmaxUtils::Texture1D::generate(const glu::RenderContext &context, tcu::IVec3 size,
                                                   glw::GLenum format, glw::GLenum type, bool generateMipmaps)
{
    const glw::Functions &gl = context.getFunctions();

    m_texture = de::MovePtr<glu::Texture1D>(new glu::Texture1D(context, format, type, size.x()));

    m_texture->getRefTexture().allocLevel(0);
    if (generateMipmaps)
    {
        m_texture->getRefTexture().allocLevel(1);
    }
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture1D error occurred");

    tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 4, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
                      tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture1D error occurred");

    m_texture->upload();
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture1D error occurred");

    if (generateMipmaps)
    {
        gl.generateTextureMipmap(m_texture->getGLTexture());
    }

    gl.activeTexture(GL_TEXTURE0);
}

// Texture1DArray

TextureFilterMinmaxUtils::Texture1DArray::Texture1DArray()
    : SupportedTextureType(GL_TEXTURE_1D_ARRAY, "vec2", "sampler1DArray")
{
}

glw::GLuint TextureFilterMinmaxUtils::Texture1DArray::getTextureGL()
{
    return m_texture->getGLTexture();
}

std::vector<float> TextureFilterMinmaxUtils::Texture1DArray::getTexCoords()
{
    float const texCoord[] = {0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 0.5f, 1.0f, 0.5f};
    return std::vector<float>(texCoord, texCoord + sizeof(texCoord) / sizeof(float));
}

void TextureFilterMinmaxUtils::Texture1DArray::generate(const glu::RenderContext &context, tcu::IVec3 size,
                                                        glw::GLenum format, glw::GLenum type, bool generateMipmaps)
{
    DE_UNREF(generateMipmaps);

    const glw::Functions &gl = context.getFunctions();

    m_texture = de::MovePtr<glu::Texture1DArray>(new glu::Texture1DArray(context, format, type, size.x(), 2));

    m_texture->getRefTexture().allocLevel(0);
    m_texture->getRefTexture().allocLevel(1);
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture1DArray error occurred");

    tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 4, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
                      tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture1DArray error occurred");

    tcu::fillWithGrid(m_texture->getRefTexture().getLevel(1), 4, tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f),
                      tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture1DArray error occurred");

    m_texture->upload();
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture1DArray error occurred");

    gl.activeTexture(GL_TEXTURE0);
}

// Texture2D

TextureFilterMinmaxUtils::Texture2D::Texture2D() : SupportedTextureType(GL_TEXTURE_2D, "vec2", "sampler2D")
{
}

glw::GLuint TextureFilterMinmaxUtils::Texture2D::getTextureGL()
{
    return m_texture->getGLTexture();
}

std::vector<float> TextureFilterMinmaxUtils::Texture2D::getTexCoords()
{
    float const texCoord[] = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f};
    return std::vector<float>(texCoord, texCoord + sizeof(texCoord) / sizeof(float));
}

void TextureFilterMinmaxUtils::Texture2D::generate(const glu::RenderContext &context, tcu::IVec3 size,
                                                   glw::GLenum format, glw::GLenum type, bool generateMipmaps)
{
    const glw::Functions &gl = context.getFunctions();

    m_texture = de::MovePtr<glu::Texture2D>(new glu::Texture2D(context, format, type, size.x(), size.y()));

    m_texture->getRefTexture().allocLevel(0);
    if (generateMipmaps)
    {
        m_texture->getRefTexture().allocLevel(1);
    }
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture2D error occurred");

    tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 4, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
                      tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture2D error occurred");

    m_texture->upload();
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture2D error occurred");

    if (generateMipmaps)
    {
        gl.generateTextureMipmap(m_texture->getGLTexture());
    }

    gl.activeTexture(GL_TEXTURE0);
}

// Texture2DArray

TextureFilterMinmaxUtils::Texture2DArray::Texture2DArray()
    : SupportedTextureType(GL_TEXTURE_2D_ARRAY, "vec3", "sampler2DArray")
{
}

glw::GLuint TextureFilterMinmaxUtils::Texture2DArray::getTextureGL()
{
    return m_texture->getGLTexture();
}

std::vector<float> TextureFilterMinmaxUtils::Texture2DArray::getTexCoords()
{
    float const texCoord[] = {0.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.5f, 1.0f, 1.0f, 0.5f};
    return std::vector<float>(texCoord, texCoord + sizeof(texCoord) / sizeof(float));
}

void TextureFilterMinmaxUtils::Texture2DArray::generate(const glu::RenderContext &context, tcu::IVec3 size,
                                                        glw::GLenum format, glw::GLenum type, bool generateMipmaps)
{
    DE_UNREF(generateMipmaps);

    const glw::Functions &gl = context.getFunctions();

    m_texture = de::MovePtr<glu::Texture2DArray>(new glu::Texture2DArray(context, format, type, size.x(), size.y(), 2));

    m_texture->getRefTexture().allocLevel(0);
    m_texture->getRefTexture().allocLevel(1);
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture2DArray error occurred");

    tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 4, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
                      tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture2DArray error occurred");

    tcu::fillWithGrid(m_texture->getRefTexture().getLevel(1), 4, tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f),
                      tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture2DArray error occurred");

    m_texture->upload();
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture2DArray error occurred");

    gl.activeTexture(GL_TEXTURE0);
}

// Texture3D

TextureFilterMinmaxUtils::Texture3D::Texture3D() : SupportedTextureType(GL_TEXTURE_3D, "vec3", "sampler3D")
{
}

glw::GLuint TextureFilterMinmaxUtils::Texture3D::getTextureGL()
{
    return m_texture->getGLTexture();
}

std::vector<float> TextureFilterMinmaxUtils::Texture3D::getTexCoords()
{
    float const texCoord[] = {0.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.5f, 1.0f, 1.0f, 0.5f};
    return std::vector<float>(texCoord, texCoord + sizeof(texCoord) / sizeof(float));
}

void TextureFilterMinmaxUtils::Texture3D::generate(const glu::RenderContext &context, tcu::IVec3 size,
                                                   glw::GLenum format, glw::GLenum type, bool generateMipmaps)
{
    DE_UNREF(generateMipmaps);

    const glw::Functions &gl = context.getFunctions();

    m_texture = de::MovePtr<glu::Texture3D>(new glu::Texture3D(context, format, type, size.x(), size.y(), size.z()));

    m_texture->getRefTexture().allocLevel(0);
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture3D error occurred");

    tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 4, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
                      tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture3D error occurred");

    m_texture->upload();
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture3D error occurred");

    gl.activeTexture(GL_TEXTURE0);
}

// TextureCube

TextureFilterMinmaxUtils::TextureCube::TextureCube() : SupportedTextureType(GL_TEXTURE_CUBE_MAP, "vec3", "samplerCube")
{
}

glw::GLuint TextureFilterMinmaxUtils::TextureCube::getTextureGL()
{
    return m_texture->getGLTexture();
}

std::vector<float> TextureFilterMinmaxUtils::TextureCube::getTexCoords()
{
    float const texCoord[] = {1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f};
    return std::vector<float>(texCoord, texCoord + sizeof(texCoord) / sizeof(float));
}

void TextureFilterMinmaxUtils::TextureCube::generate(const glu::RenderContext &context, tcu::IVec3 size,
                                                     glw::GLenum format, glw::GLenum type, bool generateMipmaps)
{
    DE_UNREF(generateMipmaps);

    const glw::Functions &gl = context.getFunctions();

    m_texture = de::MovePtr<glu::TextureCube>(new glu::TextureCube(context, format, type, size.x()));

    for (int faceIndex = 0; faceIndex < tcu::CUBEFACE_LAST; ++faceIndex)
    {
        m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceIndex, 0);
        GLU_EXPECT_NO_ERROR(gl.getError(), "glu::TextureCube error occurred");

        tcu::fillWithGrid(m_texture->getRefTexture().getLevelFace(0, (tcu::CubeFace)faceIndex), 4,
                          tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
        GLU_EXPECT_NO_ERROR(gl.getError(), "glu::TextureCube error occurred");
    }

    m_texture->upload();
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::TextureCube error occurred");

    gl.activeTexture(GL_TEXTURE0);
}

// TextureFilterMinmaxUtils methods

std::vector<glw::GLuint> TextureFilterMinmaxUtils::getDataFromTexture(const glu::RenderContext &context,
                                                                      glw::GLuint textureId, tcu::IVec2 textureSize,
                                                                      glw::GLenum format, glw::GLenum type)
{
    const glw::Functions &gl = context.getFunctions();

    glw::GLsizei imageLength = textureSize.x() * textureSize.y();

    std::vector<glw::GLuint> data;
    data.resize(imageLength);

    gl.bindTexture(GL_TEXTURE_2D, textureId);
    GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture error occurred");

    gl.getTexImage(GL_TEXTURE_2D, 0, format, type, &data[0]);
    GLU_EXPECT_NO_ERROR(gl.getError(), "getTexImage error occurred");

    return data;
}

glw::GLuint TextureFilterMinmaxUtils::calcPixelSumValue(const glu::RenderContext &context, glw::GLuint textureId,
                                                        tcu::IVec2 textureSize, glw::GLenum format, glw::GLenum type)
{
    std::vector<glw::GLuint> textureData = getDataFromTexture(context, textureId, textureSize, format, type);

    glw::GLuint sum = 0;

    for (size_t texel = 0; texel < textureData.size(); ++texel)
    {
        tcu::RGBA rgba(textureData[texel]);
        sum += rgba.getRed();
        sum += rgba.getGreen();
        sum += rgba.getBlue();
        sum += rgba.getAlpha();
    }

    return sum;
}

/** Constructor.
 *
 *  @param context Rendering context
 */
TextureFilterMinmaxParameterQueriesTestCase::TextureFilterMinmaxParameterQueriesTestCase(deqp::Context &context)
    : TestCase(context, "TextureFilterMinmaxParameterQueries",
               "Implements all parameter queries tests described in CTS_ARB_texture_filter_minmax")
{
    /* Left blank intentionally */
}

/** Executes test iteration.
 *
 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
 */
tcu::TestNode::IterateResult TextureFilterMinmaxParameterQueriesTestCase::iterate()
{
    if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_filter_minmax"))
    {
        m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
        return STOP;
    }

    const glw::Functions &gl = m_context.getRenderContext().getFunctions();

    testReductionModeQueriesDefaultValues(gl);

    for (TextureFilterMinmaxUtils::ReductionModeParamIter iter = m_utils.getReductionModeParams().begin();
         iter != m_utils.getReductionModeParams().end(); ++iter)
    {
        testReductionModeQueries(gl, iter->m_reductionMode);
    }

    m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");

    return STOP;
}

void TextureFilterMinmaxParameterQueriesTestCase::testReductionModeQueriesDefaultValues(const glw::Functions &gl)
{
    const glu::RenderContext &renderContext = m_context.getRenderContext();
    de::MovePtr<glu::Sampler> sampler       = de::MovePtr<glu::Sampler>(new glu::Sampler(renderContext));
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Sampler error occurred");

    glw::GLint params;

    gl.getSamplerParameteriv(**sampler, GL_TEXTURE_REDUCTION_MODE_ARB, &params);
    GLU_EXPECT_NO_ERROR(gl.getError(), "getSamplerParameteriv error occurred");
    TCU_CHECK_MSG(params == GL_WEIGHTED_AVERAGE_ARB, "getSamplerParameteriv value mismatch with expected default");

    for (TextureFilterMinmaxUtils::SupportedTextureTypeIter iter = m_utils.getSupportedTextureTypes().begin();
         iter != m_utils.getSupportedTextureTypes().end(); ++iter)
    {
        TextureFilterMinmaxUtils::SupportedTextureType *textureType = *iter;

        gl.getTexParameteriv(textureType->getType(), GL_TEXTURE_REDUCTION_MODE_ARB, &params);
        GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv error occurred");
        TCU_CHECK_MSG(params == GL_WEIGHTED_AVERAGE_ARB, "getTexParameteriv value mismatch with expected default");

        gl.getTexParameterIiv(textureType->getType(), GL_TEXTURE_REDUCTION_MODE_ARB, &params);
        GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterIiv error occurred");
        TCU_CHECK_MSG(params == GL_WEIGHTED_AVERAGE_ARB, "getTexParameterIiv value mismatch with expected default");
    }

    for (TextureFilterMinmaxUtils::SupportedTextureDataTypeIter iter = m_utils.getSupportedTextureDataTypes().begin();
         iter != m_utils.getSupportedTextureDataTypes().end(); ++iter)
    {
        de::MovePtr<glu::Texture2D> texture = de::MovePtr<glu::Texture2D>(new glu::Texture2D(
            renderContext, iter->m_format, iter->m_type, TEXTURE_FILTER_MINMAX_SIZE, TEXTURE_FILTER_MINMAX_SIZE));
        texture->upload();
        GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture2D error occurred");

        gl.getTextureParameteriv(texture->getGLTexture(), GL_TEXTURE_REDUCTION_MODE_ARB, &params);
        GLU_EXPECT_NO_ERROR(gl.getError(), "getTextureParameteriv error occurred");
        TCU_CHECK_MSG(params == GL_WEIGHTED_AVERAGE_ARB, "getTextureParameteriv value mismatch with expected default");

        gl.getTextureParameterIiv(texture->getGLTexture(), GL_TEXTURE_REDUCTION_MODE_ARB, &params);
        GLU_EXPECT_NO_ERROR(gl.getError(), "getTextureParameterIiv error occurred");
        TCU_CHECK_MSG(params == GL_WEIGHTED_AVERAGE_ARB, "getTextureParameterIiv value mismatch with expected default");
    }
}

void TextureFilterMinmaxParameterQueriesTestCase::testReductionModeQueries(const glw::Functions &gl, glw::GLint pname)
{
    const glu::RenderContext &renderContext = m_context.getRenderContext();
    de::MovePtr<glu::Sampler> sampler       = de::MovePtr<glu::Sampler>(new glu::Sampler(renderContext));
    GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Sampler error occurred");

    gl.samplerParameteri(**sampler, GL_TEXTURE_REDUCTION_MODE_ARB, pname);
    GLU_EXPECT_NO_ERROR(gl.getError(), "samplerParameteri error occurred");

    for (TextureFilterMinmaxUtils::SupportedTextureTypeIter iter = m_utils.getSupportedTextureTypes().begin();
         iter != m_utils.getSupportedTextureTypes().end(); ++iter)
    {
        TextureFilterMinmaxUtils::SupportedTextureType *textureType = *iter;

        gl.texParameteriv(textureType->getType(), GL_TEXTURE_REDUCTION_MODE_ARB, &pname);
        GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteriv error occurred");

        gl.texParameterIiv(textureType->getType(), GL_TEXTURE_REDUCTION_MODE_ARB, &pname);
        GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterIiv error occurred");
    }

    for (TextureFilterMinmaxUtils::SupportedTextureDataTypeIter iter = m_utils.getSupportedTextureDataTypes().begin();
         iter != m_utils.getSupportedTextureDataTypes().end(); ++iter)
    {
        de::MovePtr<glu::Texture2D> texture = de::MovePtr<glu::Texture2D>(new glu::Texture2D(
            renderContext, iter->m_format, iter->m_type, TEXTURE_FILTER_MINMAX_SIZE, TEXTURE_FILTER_MINMAX_SIZE));
        texture->upload();
        GLU_EXPECT_NO_ERROR(gl.getError(), "glu::Texture2D error occurred");

        gl.textureParameteriv(texture->getGLTexture(), GL_TEXTURE_REDUCTION_MODE_ARB, &pname);
        GLU_EXPECT_NO_ERROR(gl.getError(), "textureParameteriv error occurred");

        gl.textureParameterIiv(texture->getGLTexture(), GL_TEXTURE_REDUCTION_MODE_ARB, &pname);
        GLU_EXPECT_NO_ERROR(gl.getError(), "textureParameterIiv error occurred");
    }
}

/** Base class for minmax render tests. Constructor.
 *
 *  @param context Rendering context
 *  @param name TestCase name
 *  @param description TestCase description
 *  @param renderScale Scale of rendered texture
 *  @param mipmapping Is mipmapping enabled
 */
TextureFilterMinmaxFilteringTestCaseBase::TextureFilterMinmaxFilteringTestCaseBase(deqp::Context &context,
                                                                                   const char *name,
                                                                                   const char *description,
                                                                                   float renderScale, bool mipmapping)
    : deqp::TestCase(context, name, description)
    , m_renderScale(renderScale)
    , m_mipmapping(mipmapping)
{
}

/** Executes test iteration.
 *
 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
 */
tcu::TestNode::IterateResult TextureFilterMinmaxFilteringTestCaseBase::iterate()
{
    if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_filter_minmax"))
    {
        m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
        return STOP;
    }

    const glu::RenderContext &renderContext = m_context.getRenderContext();
    const glw::Functions &gl                = renderContext.getFunctions();

    for (TextureFilterMinmaxUtils::SupportedTextureTypeIter textureTypeIter =
             m_utils.getSupportedTextureTypes().begin();
         textureTypeIter != m_utils.getSupportedTextureTypes().end(); ++textureTypeIter)
    {
        TextureFilterMinmaxUtils::SupportedTextureType *textureType = *textureTypeIter;

        for (TextureFilterMinmaxUtils::SupportedTextureDataTypeIter dataTypeIter =
                 m_utils.getSupportedTextureDataTypes().begin();
             dataTypeIter != m_utils.getSupportedTextureDataTypes().end(); ++dataTypeIter)
        {
            if (!dataTypeIter->hasFlag(TextureFilterMinmaxUtils::MINMAX))
                continue;

            if (dataTypeIter->hasFlag(TextureFilterMinmaxUtils::EXCLUDE_3D) && textureType->getType() == GL_TEXTURE_3D)
                continue;

            if (dataTypeIter->hasFlag(TextureFilterMinmaxUtils::EXCLUDE_CUBE) &&
                textureType->getType() == GL_TEXTURE_CUBE_MAP)
                continue;

            std::map<glw::GLint, glw::GLuint> reductionModeTexelSumMap;

            for (TextureFilterMinmaxUtils::ReductionModeParamIter paramIter = m_utils.getReductionModeParams().begin();
                 paramIter != m_utils.getReductionModeParams().end(); ++paramIter)
            {
                if (paramIter->m_queryTestOnly)
                    continue;

                tcu::IVec2 scaledTextureSize(int(float(TEXTURE_FILTER_MINMAX_SIZE) * m_renderScale));

                textureType->generate(renderContext, tcu::IVec3(TEXTURE_FILTER_MINMAX_SIZE), dataTypeIter->m_format,
                                      dataTypeIter->m_type, m_mipmapping);

                glw::GLuint resultTextureId = 0;
                gl.genTextures(1, &resultTextureId);
                GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");

                textureType->renderToFBO(renderContext, resultTextureId, scaledTextureSize, paramIter->m_reductionMode);

                reductionModeTexelSumMap[paramIter->m_reductionMode] = m_utils.calcPixelSumValue(
                    renderContext, resultTextureId, scaledTextureSize, GL_RED, GL_UNSIGNED_BYTE);

                gl.deleteTextures(1, &resultTextureId);
            }

            TCU_CHECK_MSG(reductionModeTexelSumMap[GL_MIN] < reductionModeTexelSumMap[GL_WEIGHTED_AVERAGE_ARB],
                          "Sum of texels for GL_MIN should be smaller than for GL_WEIGHTED_AVERAGE_ARB");

            TCU_CHECK_MSG(reductionModeTexelSumMap[GL_MAX] > reductionModeTexelSumMap[GL_WEIGHTED_AVERAGE_ARB],
                          "Sum of texels for GL_MAX should be greater than for GL_WEIGHTED_AVERAGE_ARB");
        }
    }

    m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");

    return STOP;
}

/** Constructor.
 *
 *  @param context Rendering context
 */
TextureFilterMinmaxMinificationFilteringTestCase::TextureFilterMinmaxMinificationFilteringTestCase(
    deqp::Context &context)
    : TextureFilterMinmaxFilteringTestCaseBase(
          context, "TextureFilterMinmaxMinificationFiltering",
          "Implements minification filtering tests described in CTS_ARB_texture_filter_minmax",
          TEXTURE_FILTER_MINMAX_DOWNSCALE_FACTOR, false)
{
    /* Left blank intentionally */
}

/** Constructor.
 *
 *  @param context Rendering context
 */
TextureFilterMinmaxMagnificationFilteringTestCase::TextureFilterMinmaxMagnificationFilteringTestCase(
    deqp::Context &context)
    : TextureFilterMinmaxFilteringTestCaseBase(
          context, "TextureFilterMinmaxMagnificationFiltering",
          "Implements magnification filtering tests described in CTS_ARB_texture_filter_minmax",
          TEXTURE_FILTER_MINMAX_UPSCALE_FACTOR, false)
{
    /* Left blank intentionally */
}

/** Constructor.
 *
 *  @param context Rendering context
 */
TextureFilterMinmaxMipmapMinificationFilteringTestCase::TextureFilterMinmaxMipmapMinificationFilteringTestCase(
    deqp::Context &context)
    : TextureFilterMinmaxFilteringTestCaseBase(
          context, "TextureFilterMinmaxMipmapMinificationFiltering",
          "Implements mipmap minification filtering tests described in CTS_ARB_texture_filter_minmax",
          TEXTURE_FILTER_MINMAX_DOWNSCALE_FACTOR, true)
{
    /* Left blank intentionally */
}

/** Constructor.
 *
 *  @param context Rendering context
 */
TextureFilterMinmaxSupportTestCase::TextureFilterMinmaxSupportTestCase(deqp::Context &context)
    : TestCase(context, "TextureFilterMinmaxSupport",
               "Implements calling GetInternalFormat* and validates with "
               "expected result described in CTS_ARB_texture_filter_minmax")
{
}

/** Executes test iteration.
 *
 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
 */
tcu::TestNode::IterateResult TextureFilterMinmaxSupportTestCase::iterate()
{
    if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_filter_minmax"))
    {
        m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
        return STOP;
    }

    const glu::RenderContext &renderContext = m_context.getRenderContext();
    const glw::Functions &gl                = renderContext.getFunctions();

    for (TextureFilterMinmaxUtils::SupportedTextureTypeIter textureTypeIter =
             m_utils.getSupportedTextureTypes().begin();
         textureTypeIter != m_utils.getSupportedTextureTypes().end(); ++textureTypeIter)
    {
        TextureFilterMinmaxUtils::SupportedTextureType *textureType = *textureTypeIter;

        for (TextureFilterMinmaxUtils::SupportedTextureDataTypeIter dataTypeIter =
                 m_utils.getSupportedTextureDataTypes().begin();
             dataTypeIter != m_utils.getSupportedTextureDataTypes().end(); ++dataTypeIter)
        {
            if (!dataTypeIter->hasFlag(TextureFilterMinmaxUtils::MINMAX))
                continue;

            if (dataTypeIter->hasFlag(TextureFilterMinmaxUtils::EXCLUDE_3D) && textureType->getType() == GL_TEXTURE_3D)
                continue;

            if (dataTypeIter->hasFlag(TextureFilterMinmaxUtils::EXCLUDE_CUBE) &&
                textureType->getType() == GL_TEXTURE_CUBE_MAP)
                continue;

            glw::GLint params = 0;
            gl.getInternalformativ(textureType->getType(), dataTypeIter->m_format, GL_TEXTURE_REDUCTION_MODE_ARB,
                                   sizeof(glw::GLint), &params);
            GLU_EXPECT_NO_ERROR(gl.getError(), "getInternalformativ() call failed.");
            TCU_CHECK_MSG(params, "GetInternalformativ incorrect value");
        }
    }

    m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");

    return STOP;
}

/** Constructor.
 *
 *  @param context Rendering context.
 */
TextureFilterMinmax::TextureFilterMinmax(deqp::Context &context)
    : TestCaseGroup(context, "texture_filter_minmax_tests",
                    "Verify conformance of CTS_ARB_texture_filter_minmax implementation")
{
}

/** Initializes the test group contents. */
void TextureFilterMinmax::init()
{
    addChild(new TextureFilterMinmaxParameterQueriesTestCase(m_context));
    addChild(new TextureFilterMinmaxMinificationFilteringTestCase(m_context));
    addChild(new TextureFilterMinmaxMagnificationFilteringTestCase(m_context));
    addChild(new TextureFilterMinmaxMipmapMinificationFilteringTestCase(m_context));
    addChild(new TextureFilterMinmaxSupportTestCase(m_context));
}
} // namespace gl4cts
