/*
 * 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 "GrContextFactory.h"
#include "GrContextPriv.h"
#include "GrTest.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
