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

#include "tools/gpu/vk/VkTestContext.h"

#ifdef SK_VULKAN

#include "include/gpu/GrDirectContext.h"
#include "include/gpu/vk/VulkanExtensions.h"
#include "tools/gpu/vk/VkTestUtils.h"

namespace {

class VkTestContextImpl : public sk_gpu_test::VkTestContext {
public:
    static VkTestContext* Create(VkTestContext* sharedContext) {
        GrVkBackendContext backendContext;
        skgpu::VulkanExtensions* extensions;
        VkPhysicalDeviceFeatures2* features;
        bool ownsContext = true;
        VkDebugReportCallbackEXT debugCallback = VK_NULL_HANDLE;
        PFN_vkDestroyDebugReportCallbackEXT destroyCallback = nullptr;
        if (sharedContext) {
            backendContext = sharedContext->getVkBackendContext();
            extensions = const_cast<skgpu::VulkanExtensions*>(sharedContext->getVkExtensions());
            features = const_cast<VkPhysicalDeviceFeatures2*>(sharedContext->getVkFeatures());
            // We always delete the parent context last so make sure the child does not think they
            // own the vulkan context.
            ownsContext = false;
        } else {
            PFN_vkGetInstanceProcAddr instProc;
            if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
                return nullptr;
            }

            extensions = new skgpu::VulkanExtensions();
            features = new VkPhysicalDeviceFeatures2;
            memset(features, 0, sizeof(VkPhysicalDeviceFeatures2));
            if (!sk_gpu_test::CreateVkBackendContext(instProc, &backendContext, extensions,
                                                     features, &debugCallback)) {
                sk_gpu_test::FreeVulkanFeaturesStructs(features);
                delete features;
                delete extensions;
                return nullptr;
            }
            if (debugCallback != VK_NULL_HANDLE) {
                destroyCallback = (PFN_vkDestroyDebugReportCallbackEXT) instProc(
                        backendContext.fInstance, "vkDestroyDebugReportCallbackEXT");
            }
        }
        return new VkTestContextImpl(backendContext, extensions, features, ownsContext,
                                     debugCallback, destroyCallback);
    }

    ~VkTestContextImpl() override { this->teardown(); }

    void testAbandon() override {}

    void finish() override {}

    sk_sp<GrDirectContext> makeContext(const GrContextOptions& options) override {
        return GrDirectContext::MakeVulkan(fVk, options);
    }

protected:
#define ACQUIRE_VK_PROC_LOCAL(name, inst)                                            \
    PFN_vk##name grVk##name =                                                        \
            reinterpret_cast<PFN_vk##name>(fVk.fGetProc("vk" #name, inst, nullptr)); \
    do {                                                                             \
        if (grVk##name == nullptr) {                                                 \
            SkDebugf("Function ptr for vk%s could not be acquired\n", #name);        \
            return;                                                                  \
        }                                                                            \
    } while (0)

    void teardown() override {
        INHERITED::teardown();
        fVk.fMemoryAllocator.reset();
        if (fOwnsContext) {
            ACQUIRE_VK_PROC_LOCAL(DeviceWaitIdle, fVk.fInstance);
            ACQUIRE_VK_PROC_LOCAL(DestroyDevice, fVk.fInstance);
            ACQUIRE_VK_PROC_LOCAL(DestroyInstance, fVk.fInstance);
            grVkDeviceWaitIdle(fVk.fDevice);
            grVkDestroyDevice(fVk.fDevice, nullptr);
#ifdef SK_ENABLE_VK_LAYERS
            if (fDebugCallback != VK_NULL_HANDLE) {
                fDestroyDebugReportCallbackEXT(fVk.fInstance, fDebugCallback, nullptr);
            }
#endif
            grVkDestroyInstance(fVk.fInstance, nullptr);
            delete fExtensions;

            sk_gpu_test::FreeVulkanFeaturesStructs(fFeatures);
            delete fFeatures;
        }
    }

private:
    VkTestContextImpl(const GrVkBackendContext& backendContext,
                      const skgpu::VulkanExtensions* extensions,
                      VkPhysicalDeviceFeatures2* features,
                      bool ownsContext,
                      VkDebugReportCallbackEXT debugCallback,
                      PFN_vkDestroyDebugReportCallbackEXT destroyCallback)
            : VkTestContext(backendContext, extensions, features, ownsContext, debugCallback,
                            destroyCallback) {
        fFenceSupport = true;
    }

    void onPlatformMakeNotCurrent() const override {}
    void onPlatformMakeCurrent() const override {}
    std::function<void()> onPlatformGetAutoContextRestore() const override  { return nullptr; }

    using INHERITED = sk_gpu_test::VkTestContext;
};
}  // anonymous namespace

namespace sk_gpu_test {
VkTestContext* CreatePlatformVkTestContext(VkTestContext* sharedContext) {
    return VkTestContextImpl::Create(sharedContext);
}
}  // namespace sk_gpu_test

#endif
