//
// Copyright 2022 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// FragDepthTest:
//   Tests the correctness of gl_FragDepth usage.
//

#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"

using namespace angle;

class FragDepthTest : public ANGLETest
{
  protected:
    struct FragDepthTestResources
    {
        GLuint program;
        GLint depthLocation;
        GLTexture colorTexture;
        GLTexture depthTexture;
        GLFramebuffer framebuffer;
    };

    void setupResources(FragDepthTestResources &resources)
    {

        // Writes a fixed depth value and green.
        constexpr char kFS[] =
            R"(#version 300 es
            precision highp float;
            layout(location = 0) out vec4 fragColor;
            uniform float u_depth;
            void main(){
                gl_FragDepth = u_depth;
                fragColor = vec4(0.0, 1.0, 0.0, 1.0);
            })";

        resources.program       = CompileProgram(essl3_shaders::vs::Simple(), kFS);
        resources.depthLocation = glGetUniformLocation(resources.program, "u_depth");

        glBindTexture(GL_TEXTURE_2D, resources.colorTexture);
        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        glBindTexture(GL_TEXTURE_2D, resources.depthTexture);
        glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, 1, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

        glBindFramebuffer(GL_FRAMEBUFFER, resources.framebuffer);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                               resources.colorTexture, 0);
    }

    void cleanupResources(FragDepthTestResources &resources) { glDeleteProgram(resources.program); }

    void checkDepthWritten(float expectedDepth, float fsDepth, bool bindDepthBuffer)
    {
        FragDepthTestResources resources;
        setupResources(resources);
        ASSERT_NE(0u, resources.program);
        ASSERT_NE(-1, resources.depthLocation);
        ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
        ASSERT_GL_NO_ERROR();

        glBindFramebuffer(GL_FRAMEBUFFER, resources.framebuffer);
        if (bindDepthBuffer)
        {
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
                                   resources.depthTexture, 0);
            EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);

            // Clear to the expected depth so it will be compared to the FS depth with
            // DepthFunc(GL_EQUAL)
            glClearDepthf(expectedDepth);
            glDepthFunc(GL_EQUAL);
            glEnable(GL_DEPTH_TEST);
        }
        else
        {
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
            EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
            glDisable(GL_DEPTH_TEST);
        }
        glUseProgram(resources.program);

        // Clear to red, the FS will write green on success
        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
        // Clear to the expected depth so it will be compared to the FS depth with
        // DepthFunc(GL_EQUAL)

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glUniform1f(resources.depthLocation, fsDepth);

        drawQuad(resources.program, "a_position", 0.0f);
        EXPECT_GL_NO_ERROR();

        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
        cleanupResources(resources);
    }
};

// Test that writing to gl_FragDepth works
TEST_P(FragDepthTest, DepthBufferBound)
{
    checkDepthWritten(0.5f, 0.5f, true);
}

// Test that writing to gl_FragDepth with no depth buffer works.
TEST_P(FragDepthTest, DepthBufferUnbound)
{
    // Depth test is disabled, so the expected depth should not matter.
    checkDepthWritten(0.f, 0.5f, false);
}

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FragDepthTest);
ANGLE_INSTANTIATE_TEST_ES3(FragDepthTest);
