// Copyright 2017 The Dawn Authors
//
// 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 "tests/DawnTest.h"

#include "common/Assert.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/WGPUHelpers.h"

// Primitive topology tests work by drawing the following vertices with all the different primitive
// topology states:
// -------------------------------------
// |                                   |
// |        1        2        5        |
// |                                   |
// |                                   |
// |                                   |
// |                                   |
// |        0        3        4        |
// |                                   |
// -------------------------------------
//
// Points: This case looks exactly like above
//
// Lines
// -------------------------------------
// |                                   |
// |        1        2        5        |
// |        |        |        |        |
// |        |        |        |        |
// |        |        |        |        |
// |        |        |        |        |
// |        0        3        4        |
// |                                   |
// -------------------------------------
//
// Line Strip
// -------------------------------------
// |                                   |
// |        1--------2        5        |
// |        |        |        |        |
// |        |        |        |        |
// |        |        |        |        |
// |        |        |        |        |
// |        0        3--------4        |
// |                                   |
// -------------------------------------
//
// Triangle
// -------------------------------------
// |                                   |
// |        1--------2        5        |
// |        |xxxxxxx         x|        |
// |        |xxxxx         xxx|        |
// |        |xxx         xxxxx|        |
// |        |x         xxxxxxx|        |
// |        0        3--------4        |
// |                                   |
// -------------------------------------
//
// Triangle Strip
// -------------------------------------
// |                                   |
// |        1--------2        5        |
// |        |xxxxxxxxx       x|        |
// |        |xxxxxxxxxxx   xxx|        |
// |        |xxx   xxxxxxxxxxx|        |
// |        |x      xxxxxxxxxx|        |
// |        0        3--------4        |
// |                                   |
// -------------------------------------
//
// Each of these different states is a superset of some of the previous states,
// so for every state, we check any new added test locations that are not contained in previous
// states We also check that the test locations of subsequent states are untouched

constexpr static unsigned int kRTSize = 32;

struct TestLocation {
    unsigned int x, y;
};

constexpr TestLocation GetMidpoint(const TestLocation& a, const TestLocation& b) noexcept {
    return {(a.x + b.x) / 2, (a.y + b.y) / 2};
}

constexpr TestLocation GetCentroid(const TestLocation& a,
                                   const TestLocation& b,
                                   const TestLocation& c) noexcept {
    return {(a.x + b.x + c.x) / 3, (a.y + b.y + c.y) / 3};
}

// clang-format off
// Offset towards one corner to avoid x or y symmetry false positives
constexpr static unsigned int kOffset = kRTSize / 8;

constexpr static TestLocation kPointTestLocations[] = {
    { kRTSize * 1 / 4 + kOffset, kRTSize * 1 / 4 + kOffset },
    { kRTSize * 1 / 4 + kOffset, kRTSize * 3 / 4 + kOffset },
    { kRTSize * 2 / 4 + kOffset, kRTSize * 3 / 4 + kOffset },
    { kRTSize * 2 / 4 + kOffset, kRTSize * 1 / 4 + kOffset },
    { kRTSize * 3 / 4 + kOffset, kRTSize * 1 / 4 + kOffset },
    { kRTSize * 3 / 4 + kOffset, kRTSize * 3 / 4 + kOffset },
};

constexpr static TestLocation kLineTestLocations[] = {
    GetMidpoint(kPointTestLocations[0], kPointTestLocations[1]),
    GetMidpoint(kPointTestLocations[2], kPointTestLocations[3]),
    GetMidpoint(kPointTestLocations[4], kPointTestLocations[5]),
};

constexpr static TestLocation kLineStripTestLocations[] = {
    GetMidpoint(kPointTestLocations[1], kPointTestLocations[2]),
    GetMidpoint(kPointTestLocations[3], kPointTestLocations[4]),
};

constexpr static TestLocation kTriangleTestLocations[] = {
    GetCentroid(kPointTestLocations[0], kPointTestLocations[1], kPointTestLocations[2]),
    GetCentroid(kPointTestLocations[3], kPointTestLocations[4], kPointTestLocations[5]),
};

constexpr static TestLocation kTriangleStripTestLocations[] = {
    GetCentroid(kPointTestLocations[1], kPointTestLocations[2], kPointTestLocations[3]),
    GetCentroid(kPointTestLocations[2], kPointTestLocations[3], kPointTestLocations[4]),
};

constexpr static float kRTSizef = static_cast<float>(kRTSize);
constexpr static float kVertices[] = {
    2.f * (kPointTestLocations[0].x + 0.5f) / kRTSizef - 1.f, -2.f * (kPointTestLocations[0].y + 0.5f) / kRTSizef + 1.0f, 0.f, 1.f,
    2.f * (kPointTestLocations[1].x + 0.5f) / kRTSizef - 1.f, -2.f * (kPointTestLocations[1].y + 0.5f) / kRTSizef + 1.0f, 0.f, 1.f,
    2.f * (kPointTestLocations[2].x + 0.5f) / kRTSizef - 1.f, -2.f * (kPointTestLocations[2].y + 0.5f) / kRTSizef + 1.0f, 0.f, 1.f,
    2.f * (kPointTestLocations[3].x + 0.5f) / kRTSizef - 1.f, -2.f * (kPointTestLocations[3].y + 0.5f) / kRTSizef + 1.0f, 0.f, 1.f,
    2.f * (kPointTestLocations[4].x + 0.5f) / kRTSizef - 1.f, -2.f * (kPointTestLocations[4].y + 0.5f) / kRTSizef + 1.0f, 0.f, 1.f,
    2.f * (kPointTestLocations[5].x + 0.5f) / kRTSizef - 1.f, -2.f * (kPointTestLocations[5].y + 0.5f) / kRTSizef + 1.0f, 0.f, 1.f,
};
// clang-format on

class PrimitiveTopologyTest : public DawnTest {
  protected:
    void SetUp() override {
        DawnTest::SetUp();

        renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);

        vsModule = utils::CreateShaderModule(device, R"(
            [[stage(vertex)]]
            fn main([[location(0)]] pos : vec4<f32>) -> [[builtin(position)]] vec4<f32> {
                return pos;
            })");

        fsModule = utils::CreateShaderModule(device, R"(
            [[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
                return vec4<f32>(0.0, 1.0, 0.0, 1.0);
            })");

        vertexBuffer = utils::CreateBufferFromData(device, kVertices, sizeof(kVertices),
                                                   wgpu::BufferUsage::Vertex);
    }

    struct LocationSpec {
        const TestLocation* locations;
        size_t count;
        bool include;
    };

    template <std::size_t N>
    constexpr LocationSpec TestPoints(TestLocation const (&points)[N], bool include) noexcept {
        return {points, N, include};
    }

    // Draw the vertices with the given primitive topology and check the pixel values of the test
    // locations
    void DoTest(wgpu::PrimitiveTopology primitiveTopology,
                const std::vector<LocationSpec>& locationSpecs) {
        utils::ComboRenderPipelineDescriptor descriptor;
        descriptor.vertex.module = vsModule;
        descriptor.cFragment.module = fsModule;

        descriptor.primitive.topology = primitiveTopology;
        if (primitiveTopology == wgpu::PrimitiveTopology::TriangleStrip ||
            primitiveTopology == wgpu::PrimitiveTopology::LineStrip) {
            descriptor.primitive.stripIndexFormat = wgpu::IndexFormat::Uint32;
        }

        descriptor.vertex.bufferCount = 1;
        descriptor.cBuffers[0].arrayStride = 4 * sizeof(float);
        descriptor.cBuffers[0].attributeCount = 1;
        descriptor.cAttributes[0].format = wgpu::VertexFormat::Float32x4;
        descriptor.cTargets[0].format = renderPass.colorFormat;

        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        {
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
            pass.SetPipeline(pipeline);
            pass.SetVertexBuffer(0, vertexBuffer);
            pass.Draw(6);
            pass.EndPass();
        }

        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);

        for (auto& locationSpec : locationSpecs) {
            for (size_t i = 0; i < locationSpec.count; ++i) {
                // If this pixel is included, check that it is green. Otherwise, check that it is
                // black
                RGBA8 color = locationSpec.include ? RGBA8::kGreen : RGBA8::kZero;
                EXPECT_PIXEL_RGBA8_EQ(color, renderPass.color, locationSpec.locations[i].x,
                                      locationSpec.locations[i].y)
                    << "Expected (" << locationSpec.locations[i].x << ", "
                    << locationSpec.locations[i].y << ") to be " << color;
            }
        }
    }

    utils::BasicRenderPass renderPass;
    wgpu::ShaderModule vsModule;
    wgpu::ShaderModule fsModule;
    wgpu::Buffer vertexBuffer;
};

// Test Point primitive topology
TEST_P(PrimitiveTopologyTest, PointList) {
    DoTest(wgpu::PrimitiveTopology::PointList,
           {
               // Check that the points are drawn
               TestPoints(kPointTestLocations, true),

               // Check that line and triangle locations are untouched
               TestPoints(kLineTestLocations, false),
               TestPoints(kLineStripTestLocations, false),
               TestPoints(kTriangleTestLocations, false),
               TestPoints(kTriangleStripTestLocations, false),
           });
}

// Test Line primitive topology
TEST_P(PrimitiveTopologyTest, LineList) {
    DoTest(wgpu::PrimitiveTopology::LineList,
           {
               // Check that lines are drawn
               TestPoints(kLineTestLocations, true),

               // Check that line strip and triangle locations are untouched
               TestPoints(kLineStripTestLocations, false),
               TestPoints(kTriangleTestLocations, false),
               TestPoints(kTriangleStripTestLocations, false),
           });
}

// Test LineStrip primitive topology
TEST_P(PrimitiveTopologyTest, LineStrip) {
    DoTest(wgpu::PrimitiveTopology::LineStrip, {
                                                   // Check that lines are drawn
                                                   TestPoints(kLineTestLocations, true),
                                                   TestPoints(kLineStripTestLocations, true),

                                                   // Check that triangle locations are untouched
                                                   TestPoints(kTriangleTestLocations, false),
                                                   TestPoints(kTriangleStripTestLocations, false),
                                               });
}

// Test Triangle primitive topology
TEST_P(PrimitiveTopologyTest, TriangleList) {
    DoTest(wgpu::PrimitiveTopology::TriangleList,
           {
               // Check that triangles are drawn
               TestPoints(kTriangleTestLocations, true),

               // Check that triangle strip locations are untouched
               TestPoints(kTriangleStripTestLocations, false),
           });
}

// Test TriangleStrip primitive topology
TEST_P(PrimitiveTopologyTest, TriangleStrip) {
    DoTest(wgpu::PrimitiveTopology::TriangleStrip,
           {
               TestPoints(kTriangleTestLocations, true),
               TestPoints(kTriangleStripTestLocations, true),
           });
}

DAWN_INSTANTIATE_TEST(PrimitiveTopologyTest,
                      D3D12Backend(),
                      MetalBackend(),
                      OpenGLBackend(),
                      OpenGLESBackend(),
                      VulkanBackend());
