// Copyright (C) 2020 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 <gtest/gtest.h>

#include <vector>

#include "OSWindow.h"
#include "aemu/base/system/System.h"
#include "host-common/testing/MockGraphicsAgentFactory.h"
#include "virgl_hw.h"
#include "virtio-gpu-gfxstream-renderer-unstable.h"
#include "virtio-gpu-gfxstream-renderer.h"

using android::base::sleepMs;

class GfxStreamBackendTest : public ::testing::Test {
private:
 static void sWriteFence(void* cookie, struct stream_renderer_fence* fence) {
     uint32_t current = *(uint32_t*)cookie;
     if (current < fence->fence_id) *(uint64_t*)(cookie) = fence->fence_id;
 }

protected:
    uint32_t cookie;
    static const bool useWindow;
    std::vector<stream_renderer_param> streamRendererParams;
    std::vector<stream_renderer_param> minimumRequiredParams;
    static constexpr uint32_t width = 256;
    static constexpr uint32_t height = 256;
    static std::unique_ptr<OSWindow> window;
    static constexpr int rendererFlags = STREAM_RENDERER_FLAGS_USE_GLES_BIT;
    static constexpr int surfacelessFlags = STREAM_RENDERER_FLAGS_USE_SURFACELESS_BIT;

    GfxStreamBackendTest()
        : cookie(0),
          streamRendererParams{{STREAM_RENDERER_PARAM_USER_DATA,
                                static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&cookie))},
                               {STREAM_RENDERER_PARAM_FENCE_CALLBACK,
                                static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&sWriteFence))},
                               {STREAM_RENDERER_PARAM_RENDERER_FLAGS, surfacelessFlags},
                               {STREAM_RENDERER_PARAM_WIN0_WIDTH, width},
                               {STREAM_RENDERER_PARAM_WIN0_HEIGHT, height}},
          minimumRequiredParams{{STREAM_RENDERER_PARAM_USER_DATA,
                                 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&cookie))},
                                {STREAM_RENDERER_PARAM_FENCE_CALLBACK,
                                 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&sWriteFence))},
                                {STREAM_RENDERER_PARAM_RENDERER_FLAGS, surfacelessFlags}} {}

    static void SetUpTestSuite() {
        android::emulation::injectGraphicsAgents(android::emulation::MockGraphicsAgentFactory());
        if (useWindow) {
            window.reset(CreateOSWindow());
        }
    }

    static void TearDownTestSuite() { window.reset(nullptr); }

    void SetUp() override {
        android::base::setEnvironmentVariable("ANDROID_GFXSTREAM_EGL", "1");
        if (useWindow) {
            window->initialize("GfxStreamBackendTestWindow", width, height);
            window->setVisible(true);
            window->messageLoop();
        }
    }

    void TearDown() override {
        // Ensure background threads aren't mid-initialization.
        sleepMs(100);
        if (useWindow) {
            window->destroy();
        }
        stream_renderer_teardown();
    }
};

std::unique_ptr<OSWindow> GfxStreamBackendTest::window = nullptr;

const bool GfxStreamBackendTest::useWindow =
        android::base::getEnvironmentVariable("ANDROID_EMU_TEST_WITH_WINDOW") == "1";

TEST_F(GfxStreamBackendTest, Init) {
    stream_renderer_init(streamRendererParams.data(), streamRendererParams.size());
}

TEST_F(GfxStreamBackendTest, InitOpenGLWindow) {
    if (!useWindow) {
        return;
    }

    std::vector<stream_renderer_param> glParams = streamRendererParams;
    for (auto& param: glParams) {
        if (param.key == STREAM_RENDERER_PARAM_RENDERER_FLAGS) {
            param.value = rendererFlags;
        }
    }
    stream_renderer_init(glParams.data(), glParams.size());
    gfxstream_backend_setup_window(window->getFramebufferNativeWindow(), 0, 0,
                                       width, height, width, height);
}

TEST_F(GfxStreamBackendTest, SimpleFlush) {
    stream_renderer_init(streamRendererParams.data(), streamRendererParams.size());

    const uint32_t res_id = 8;
    struct stream_renderer_resource_create_args create_resource_args = {
        .handle = res_id,
        .target = 2,  // PIPE_TEXTURE_2D
        .format = VIRGL_FORMAT_R8G8B8A8_UNORM,
        .bind = VIRGL_BIND_SAMPLER_VIEW | VIRGL_BIND_SCANOUT | VIRGL_BIND_SHARED,
        .width = width,
        .height = height,
        .depth = 1,
        .array_size = 1,
        .last_level = 0,
        .nr_samples = 0,
        .flags = 0,
    };
    EXPECT_EQ(stream_renderer_resource_create(&create_resource_args, NULL, 0), 0);
    // R8G8B8A8 is used, so 4 bytes per pixel
    auto fb = std::make_unique<uint32_t[]>(width * height);
    EXPECT_NE(fb, nullptr);
    stream_renderer_flush(res_id);
}

// Tests compile and link only.
TEST_F(GfxStreamBackendTest, DISABLED_ApiCallLinkTest) {
    stream_renderer_init(streamRendererParams.data(), streamRendererParams.size());

    const uint32_t res_id = 8;
    struct stream_renderer_resource_create_args create_resource_args = {
        .handle = res_id,
        .target = 2,  // PIPE_TEXTURE_2D
        .format = VIRGL_FORMAT_R8G8B8A8_UNORM,
        .bind = VIRGL_BIND_SAMPLER_VIEW | VIRGL_BIND_SCANOUT | VIRGL_BIND_SHARED,
        .width = width,
        .height = height,
        .depth = 1,
        .array_size = 1,
        .last_level = 0,
        .nr_samples = 0,
        .flags = 0,
    };
    EXPECT_EQ(stream_renderer_resource_create(&create_resource_args, NULL, 0), 0);
    // R8G8B8A8 is used, so 4 bytes per pixel
    auto fb = std::make_unique<uint32_t[]>(width * height);
    EXPECT_NE(fb, nullptr);
    stream_renderer_flush(res_id);
    stream_renderer_resource_unref(0);
    stream_renderer_context_create(0, 0, NULL, 0);
    stream_renderer_context_destroy(0);
    stream_renderer_submit_cmd(0, 0, 0);
    stream_renderer_transfer_read_iov(0, 0, 0, 0, 0, 0, 0, 0, 0);
    stream_renderer_transfer_write_iov(0, 0, 0, 0, 0, 0, 0, 0, 0);

    stream_renderer_get_cap_set(0, 0, 0);
    stream_renderer_fill_caps(0, 0, 0);

    stream_renderer_resource_attach_iov(0, 0, 0);
    stream_renderer_resource_detach_iov(0, 0, 0);
    stream_renderer_create_fence(NULL);
    stream_renderer_ctx_attach_resource(0, 0);
    stream_renderer_ctx_detach_resource(0, 0);
    stream_renderer_resource_get_info(0, 0);
}

TEST_F(GfxStreamBackendTest, MinimumRequiredParameters) {
    // Only the minimum required parameters.
    int initResult =
        stream_renderer_init(minimumRequiredParams.data(), minimumRequiredParams.size());
    EXPECT_EQ(initResult, 0);
}

TEST_F(GfxStreamBackendTest, MissingRequiredParameter) {
    for (size_t i = 0; i < minimumRequiredParams.size(); ++i) {
        // For each parameter, remove it and try to init, expecting failure.
        std::vector<stream_renderer_param> insufficientParams = minimumRequiredParams;
        insufficientParams.erase(insufficientParams.begin() + i);
        int initResult = stream_renderer_init(insufficientParams.data(), insufficientParams.size());
        EXPECT_EQ(initResult, -1);

        // Ensure background threads aren't mid-initialization.
        sleepMs(100);
        stream_renderer_teardown();
    }

    // Initialize once more for the teardown function.
    int initResult = stream_renderer_init(streamRendererParams.data(), streamRendererParams.size());
    EXPECT_EQ(initResult, 0);
}
