/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This is a GPU-backend specific test. It relies on static intializers to work

#include "SkTypes.h"

#if defined(SK_VULKAN)

#include "vk/GrVkVulkan.h"

#include "GrBackendSurface.h"
#include "GrContextFactory.h"
#include "GrContextPriv.h"
#include "GrTexture.h"
#include "Test.h"
#include "vk/GrVkCopyPipeline.h"
#include "vk/GrVkGpu.h"
#include "vk/GrVkRenderTarget.h"
#include "vk/GrVkUtil.h"

using sk_gpu_test::GrContextFactory;

class TestVkCopyProgram {
public:
    TestVkCopyProgram()
            : fVertShaderModule(VK_NULL_HANDLE)
            , fFragShaderModule(VK_NULL_HANDLE)
            , fPipelineLayout(VK_NULL_HANDLE) {}

    void test(GrVkGpu* gpu, skiatest::Reporter* reporter) {
        const char vertShaderText[] =
            "#extension GL_ARB_separate_shader_objects : enable\n"
            "#extension GL_ARB_shading_language_420pack : enable\n"

            "layout(set = 0, binding = 0) uniform vertexUniformBuffer {"
            "half4 uPosXform;"
            "half4 uTexCoordXform;"
            "};"
            "layout(location = 0) in float2 inPosition;"
            "layout(location = 1) out half2 vTexCoord;"

            "// Copy Program VS\n"
            "void main() {"
            "vTexCoord = inPosition * uTexCoordXform.xy + uTexCoordXform.zw;"
            "sk_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;"
            "sk_Position.zw = half2(0, 1);"
            "}";

        const char fragShaderText[] =
            "#extension GL_ARB_separate_shader_objects : enable\n"
            "#extension GL_ARB_shading_language_420pack : enable\n"

            "layout(set = 1, binding = 0) uniform sampler2D uTextureSampler;"
            "layout(location = 1) in half2 vTexCoord;"

            "// Copy Program FS\n"
            "void main() {"
            "sk_FragColor = texture(uTextureSampler, vTexCoord);"
            "}";

        SkSL::Program::Settings settings;
        SkSL::Program::Inputs inputs;
        if (!GrCompileVkShaderModule(gpu, vertShaderText, VK_SHADER_STAGE_VERTEX_BIT,
                                     &fVertShaderModule, &fShaderStageInfo[0], settings, &inputs)) {
            this->destroyResources(gpu);
            REPORTER_ASSERT(reporter, false);
            return;
        }
        SkASSERT(inputs.isEmpty());

        if (!GrCompileVkShaderModule(gpu, fragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT,
                                     &fFragShaderModule, &fShaderStageInfo[1], settings, &inputs)) {
            this->destroyResources(gpu);
            REPORTER_ASSERT(reporter, false);
            return;
        }

        VkDescriptorSetLayout dsLayout[2];

        GrVkResourceProvider& resourceProvider = gpu->resourceProvider();

        dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();

        uint32_t samplerVisibility = kFragment_GrShaderFlag;
        SkTArray<uint32_t> visibilityArray(&samplerVisibility, 1);

        resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                                                       visibilityArray, &fSamplerDSHandle);
        dsLayout[GrVkUniformHandler::kSamplerDescSet] =
                resourceProvider.getSamplerDSLayout(fSamplerDSHandle);

        // Create the VkPipelineLayout
        VkPipelineLayoutCreateInfo layoutCreateInfo;
        memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
        layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
        layoutCreateInfo.pNext = 0;
        layoutCreateInfo.flags = 0;
        layoutCreateInfo.setLayoutCount = 2;
        layoutCreateInfo.pSetLayouts = dsLayout;
        layoutCreateInfo.pushConstantRangeCount = 0;
        layoutCreateInfo.pPushConstantRanges = nullptr;

        VkResult err = GR_VK_CALL(gpu->vkInterface(), CreatePipelineLayout(gpu->device(),
                                                                           &layoutCreateInfo,
                                                                           nullptr,
                                                                           &fPipelineLayout));
        if (err) {
            this->destroyResources(gpu);
            REPORTER_ASSERT(reporter, false);
            return;
        }

        GrSurfaceDesc surfDesc;
        surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
        surfDesc.fWidth = 16;
        surfDesc.fHeight = 16;
        surfDesc.fConfig = kRGBA_8888_GrPixelConfig;
        surfDesc.fSampleCnt = 1;
        sk_sp<GrTexture> tex = gpu->createTexture(surfDesc, SkBudgeted::kNo);
        if (!tex) {
            this->destroyResources(gpu);
            REPORTER_ASSERT(reporter, tex.get());
            return;

        }
        GrRenderTarget* rt = tex->asRenderTarget();
        REPORTER_ASSERT(reporter, rt);
        GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);

        GrVkCopyPipeline* copyPipeline = GrVkCopyPipeline::Create(gpu,
                                                                  fShaderStageInfo,
                                                                  fPipelineLayout,
                                                                  1,
                                                                  *vkRT->simpleRenderPass(),
                                                                  VK_NULL_HANDLE);

        REPORTER_ASSERT(reporter, copyPipeline);
        if (copyPipeline) {
            copyPipeline->unref(gpu);
        }

        this->destroyResources(gpu);
    }

    void destroyResources(GrVkGpu* gpu) {
        if (VK_NULL_HANDLE != fVertShaderModule) {
            GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fVertShaderModule,
                                                               nullptr));
            fVertShaderModule = VK_NULL_HANDLE;
        }

        if (VK_NULL_HANDLE != fFragShaderModule) {
            GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fFragShaderModule,
                                                               nullptr));
            fFragShaderModule = VK_NULL_HANDLE;
        }

        if (VK_NULL_HANDLE != fPipelineLayout) {
            GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(), fPipelineLayout,
                                                                 nullptr));
            fPipelineLayout = VK_NULL_HANDLE;
        }
    }

    VkShaderModule fVertShaderModule;
    VkShaderModule fFragShaderModule;
    VkPipelineShaderStageCreateInfo fShaderStageInfo[2];

    GrVkDescriptorSetManager::Handle fSamplerDSHandle;
    VkPipelineLayout fPipelineLayout;

};

DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkMakeCopyPipelineTest, reporter, ctxInfo) {
    GrContext* context = ctxInfo.grContext();
    GrVkGpu* gpu = static_cast<GrVkGpu*>(context->contextPriv().getGpu());

    TestVkCopyProgram copyProgram;
    copyProgram.test(gpu, reporter);
}

#endif
