// Copyright (C) 2018 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.

#include "GLSnapshotTesting.h"
#include "OpenGLTestContext.h"

#include <gtest/gtest.h>

namespace emugl {

struct GlStencilFunc {
    GLenum func;
    GLint ref;
    GLuint mask;
};

struct GlStencilOp {
    GLenum sfail;
    GLenum dpfail;
    GLenum dppass;
};

struct GlBlendFunc {
    GLenum srcRGB;
    GLenum dstRGB;
    GLenum srcAlpha;
    GLenum dstAlpha;
};

// Scissor box settings to attempt
static const std::vector<GLint> kGLES2TestScissorBox = {2, 3, 10, 20};

// Default stencil operation modes
static const GlStencilOp kGLES2DefaultStencilOp = {GL_KEEP, GL_KEEP, GL_KEEP};

// Stencil reference value to attempt
static const GLint kGLES2TestStencilRef = 1;

// Stencil mask values to attempt
static const GLuint kGLES2TestStencilMasks[] = {0, 1, 0x1000000, 0x7FFFFFFF};

// Blend function settings to attempt
static const GlBlendFunc kGLES2TestBlendFuncs[] = {
        {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, GL_ONE, GL_SRC_ALPHA_SATURATE, GL_ONE}};

class SnapshotGlScissorBoxTest
    : public SnapshotSetValueTest<std::vector<GLint>>,
      public ::testing::WithParamInterface<std::vector<GLint>> {
    void stateCheck(std::vector<GLint> expected) override {
        EXPECT_TRUE(compareGlobalGlIntv(gl, GL_SCISSOR_BOX, expected));
    }
    void stateChange() override {
        gl->glScissor(GetParam()[0], GetParam()[1], GetParam()[2],
                      GetParam()[3]);
    }
};

TEST_P(SnapshotGlScissorBoxTest, SetScissorBox) {
    // different drivers act differently; get the default scissorbox
    std::vector<GLint> defaultBox;
    defaultBox.resize(4);
    gl->glGetIntegerv(GL_SCISSOR_BOX, &defaultBox[0]);
    EXPECT_EQ(GL_NO_ERROR, gl->glGetError());

    setExpectedValues(defaultBox, GetParam());
    doCheckedSnapshot();
}

INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
                         SnapshotGlScissorBoxTest,
                         ::testing::Values(kGLES2TestScissorBox));

// Tests preservation of stencil test conditional state, set by glStencilFunc.
class SnapshotGlStencilConditionsTest
    : public SnapshotSetValueTest<GlStencilFunc> {
    void stateCheck(GlStencilFunc expected) override {
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_FUNC, expected.func));
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_REF, expected.ref));
        EXPECT_TRUE(
                compareGlobalGlInt(gl, GL_STENCIL_VALUE_MASK, expected.mask));
        EXPECT_TRUE(
                compareGlobalGlInt(gl, GL_STENCIL_BACK_FUNC, expected.func));
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_BACK_REF, expected.ref));
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_BACK_VALUE_MASK,
                                       expected.mask));
    }
    void stateChange() override {
        GlStencilFunc sFunc = *m_changed_value;
        gl->glStencilFunc(sFunc.func, sFunc.ref, sFunc.mask);
    }
};

class SnapshotGlStencilFuncTest : public SnapshotGlStencilConditionsTest,
                                  public ::testing::WithParamInterface<GLenum> {
};

class SnapshotGlStencilMaskTest : public SnapshotGlStencilConditionsTest,
                                  public ::testing::WithParamInterface<GLuint> {
};

TEST_P(SnapshotGlStencilFuncTest, SetStencilFunc) {
    // different drivers act differently; get the default mask
    GLint defaultStencilMask;
    gl->glGetIntegerv(GL_STENCIL_VALUE_MASK, &defaultStencilMask);
    EXPECT_EQ(GL_NO_ERROR, gl->glGetError());

    GlStencilFunc defaultStencilFunc = {GL_ALWAYS, 0,
                                        (GLuint)defaultStencilMask};
    GlStencilFunc testStencilFunc = {GetParam(), kGLES2TestStencilRef, 0};
    setExpectedValues(defaultStencilFunc, testStencilFunc);
    doCheckedSnapshot();
}

TEST_P(SnapshotGlStencilMaskTest, SetStencilMask) {
    // different drivers act differently; get the default mask
    GLint defaultStencilMask;
    gl->glGetIntegerv(GL_STENCIL_VALUE_MASK, &defaultStencilMask);
    EXPECT_EQ(GL_NO_ERROR, gl->glGetError());

    GlStencilFunc defaultStencilFunc = {GL_ALWAYS, 0,
                                        (GLuint)defaultStencilMask};
    GlStencilFunc testStencilFunc = {GL_ALWAYS, kGLES2TestStencilRef,
                                     GetParam()};
    setExpectedValues(defaultStencilFunc, testStencilFunc);
    doCheckedSnapshot();
}

INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
                         SnapshotGlStencilFuncTest,
                         ::testing::ValuesIn(kGLES2StencilFuncs));

INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
                         SnapshotGlStencilMaskTest,
                         ::testing::ValuesIn(kGLES2TestStencilMasks));

class SnapshotGlStencilConsequenceTest
    : public SnapshotSetValueTest<GlStencilOp> {
    void stateCheck(GlStencilOp expected) override {
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_FAIL, expected.sfail));
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_PASS_DEPTH_FAIL,
                                       expected.dpfail));
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_PASS_DEPTH_PASS,
                                       expected.dppass));
        EXPECT_TRUE(
                compareGlobalGlInt(gl, GL_STENCIL_BACK_FAIL, expected.sfail));
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_BACK_PASS_DEPTH_FAIL,
                                       expected.dpfail));
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_BACK_PASS_DEPTH_PASS,
                                       expected.dppass));
    }
    void stateChange() override {
        GlStencilOp sOp = *m_changed_value;
        gl->glStencilOp(sOp.sfail, sOp.dpfail, sOp.dppass);
    }
};

class SnapshotGlStencilFailTest : public SnapshotGlStencilConsequenceTest,
                                  public ::testing::WithParamInterface<GLenum> {
};

class SnapshotGlStencilDepthFailTest
    : public SnapshotGlStencilConsequenceTest,
      public ::testing::WithParamInterface<GLenum> {};

class SnapshotGlStencilDepthPassTest
    : public SnapshotGlStencilConsequenceTest,
      public ::testing::WithParamInterface<GLenum> {};

TEST_P(SnapshotGlStencilFailTest, SetStencilOps) {
    GlStencilOp testStencilOp = {GetParam(), GL_KEEP, GL_KEEP};
    setExpectedValues(kGLES2DefaultStencilOp, testStencilOp);
    doCheckedSnapshot();
}

TEST_P(SnapshotGlStencilDepthFailTest, SetStencilOps) {
    GlStencilOp testStencilOp = {GL_KEEP, GetParam(), GL_KEEP};
    setExpectedValues(kGLES2DefaultStencilOp, testStencilOp);
    doCheckedSnapshot();
}

TEST_P(SnapshotGlStencilDepthPassTest, SetStencilOps) {
    GlStencilOp testStencilOp = {GL_KEEP, GL_KEEP, GetParam()};
    setExpectedValues(kGLES2DefaultStencilOp, testStencilOp);
    doCheckedSnapshot();
}

INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
                         SnapshotGlStencilFailTest,
                         ::testing::ValuesIn(kGLES2StencilOps));

INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
                         SnapshotGlStencilDepthFailTest,
                         ::testing::ValuesIn(kGLES2StencilOps));

INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
                         SnapshotGlStencilDepthPassTest,
                         ::testing::ValuesIn(kGLES2StencilOps));

class SnapshotGlDepthFuncTest : public SnapshotSetValueTest<GLenum>,
                                public ::testing::WithParamInterface<GLenum> {
    void stateCheck(GLenum expected) override {
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_DEPTH_FUNC, expected));
    }
    void stateChange() override { gl->glDepthFunc(*m_changed_value); }
};

TEST_P(SnapshotGlDepthFuncTest, SetDepthFunc) {
    setExpectedValues(GL_LESS, GetParam());
    doCheckedSnapshot();
}

INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
                         SnapshotGlDepthFuncTest,
                         ::testing::ValuesIn(kGLES2StencilFuncs));

class SnapshotGlBlendEquationTest
    : public SnapshotSetValueTest<GLenum>,
      public ::testing::WithParamInterface<GLenum> {
    void stateCheck(GLenum expected) override {
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_BLEND_EQUATION_RGB, expected));
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_BLEND_EQUATION_ALPHA, expected));
    }
    void stateChange() override { gl->glBlendEquation(*m_changed_value); }
};

TEST_P(SnapshotGlBlendEquationTest, SetBlendEquation) {
    setExpectedValues(GL_FUNC_ADD, GetParam());
    doCheckedSnapshot();
}

INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
                         SnapshotGlBlendEquationTest,
                         ::testing::ValuesIn(kGLES2BlendEquations));

class SnapshotGlBlendFuncTest
    : public SnapshotSetValueTest<GlBlendFunc>,
      public ::testing::WithParamInterface<GlBlendFunc> {
    void stateCheck(GlBlendFunc expected) {
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_BLEND_SRC_RGB, expected.srcRGB));
        EXPECT_TRUE(compareGlobalGlInt(gl, GL_BLEND_DST_RGB, expected.dstRGB));
        EXPECT_TRUE(
                compareGlobalGlInt(gl, GL_BLEND_SRC_ALPHA, expected.srcAlpha));
        EXPECT_TRUE(
                compareGlobalGlInt(gl, GL_BLEND_DST_ALPHA, expected.dstAlpha));
    }
    void stateChange() {
        GlBlendFunc target = *m_changed_value;
        gl->glBlendFuncSeparate(target.srcRGB, target.dstRGB, target.srcAlpha,
                                target.dstAlpha);
    }
};

TEST_P(SnapshotGlBlendFuncTest, SetBlendFunc) {
    GlBlendFunc defaultBlendFunc = {.srcRGB = GL_ONE,
                                    .dstRGB = GL_ZERO,
                                    .srcAlpha = GL_ONE,
                                    .dstAlpha = GL_ZERO};
    setExpectedValues(defaultBlendFunc, GetParam());
    doCheckedSnapshot();
}

INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
                         SnapshotGlBlendFuncTest,
                         ::testing::ValuesIn(kGLES2TestBlendFuncs));

}  // namespace emugl
