/*
 * Copyright 2016 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 SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_VULKAN)

#include "GrContextFactory.h"
#include "GrTest.h"
#include "Test.h"
#include "vk/GrVkCaps.h"
#include "vk/GrVkGpu.h"
#include "vk/GrVkMemory.h"
#include "vk/GrVkTypes.h"

using sk_gpu_test::GrContextFactory;

const int kW = 1024;
const int kH = 1024;
const GrPixelConfig kPixelConfig = kRGBA_8888_GrPixelConfig;

void wrap_tex_test(skiatest::Reporter* reporter, GrContext* context) {

    GrVkGpu* gpu = static_cast<GrVkGpu*>(context->getGpu());

    GrBackendObject backendObj = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH, kPixelConfig,
                                                                      false);
    const GrVkImageInfo* backendTex = reinterpret_cast<const GrVkImageInfo*>(backendObj);

    // check basic borrowed creation
    GrBackendTextureDesc desc;
    desc.fConfig = kPixelConfig;
    desc.fWidth = kW;
    desc.fHeight = kH;
    desc.fTextureHandle = backendObj;
    sk_sp<GrTexture> tex = gpu->wrapBackendTexture(desc, kBorrow_GrWrapOwnership);
    REPORTER_ASSERT(reporter, tex);

    // image is null
    GrVkImageInfo backendCopy = *backendTex;
    backendCopy.fImage = VK_NULL_HANDLE;
    desc.fTextureHandle = (GrBackendObject) &backendCopy;
    tex = gpu->wrapBackendTexture(desc, kBorrow_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !tex);
    tex = gpu->wrapBackendTexture(desc, kAdopt_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !tex);

    // alloc is null
    backendCopy.fImage = backendTex->fImage;
    backendCopy.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
    tex = gpu->wrapBackendTexture(desc, kBorrow_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !tex);
    tex = gpu->wrapBackendTexture(desc, kAdopt_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !tex);

    // check adopt creation
    backendCopy.fAlloc = backendTex->fAlloc;
    tex = gpu->wrapBackendTexture(desc, kAdopt_GrWrapOwnership);
    REPORTER_ASSERT(reporter, tex);

    gpu->deleteTestingOnlyBackendTexture(backendObj, true);
}

void wrap_rt_test(skiatest::Reporter* reporter, GrContext* context) {
    GrVkGpu* gpu = static_cast<GrVkGpu*>(context->getGpu());

    GrBackendObject backendObj = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH, kPixelConfig,
                                                                      true);
    const GrVkImageInfo* backendTex = reinterpret_cast<const GrVkImageInfo*>(backendObj);

    // check basic borrowed creation
    GrBackendRenderTargetDesc desc;
    desc.fWidth = kW;
    desc.fHeight = kH;
    desc.fConfig = kPixelConfig;
    desc.fOrigin = kTopLeft_GrSurfaceOrigin;
    desc.fSampleCnt = 0;
    desc.fStencilBits = 0;
    desc.fRenderTargetHandle = backendObj;
    sk_sp<GrRenderTarget> rt = gpu->wrapBackendRenderTarget(desc, kBorrow_GrWrapOwnership);
    REPORTER_ASSERT(reporter, rt);

    // image is null
    GrVkImageInfo backendCopy = *backendTex;
    backendCopy.fImage = VK_NULL_HANDLE;
    desc.fRenderTargetHandle = (GrBackendObject)&backendCopy;
    rt = gpu->wrapBackendRenderTarget(desc, kBorrow_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !rt);
    rt = gpu->wrapBackendRenderTarget(desc, kAdopt_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !rt);

    // alloc is null
    backendCopy.fImage = backendTex->fImage;
    backendCopy.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
    // can wrap null alloc if borrowing
    rt = gpu->wrapBackendRenderTarget(desc, kBorrow_GrWrapOwnership);
    REPORTER_ASSERT(reporter, rt);
    // but not if adopting
    rt = gpu->wrapBackendRenderTarget(desc, kAdopt_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !rt);

    // check adopt creation
    backendCopy.fAlloc = backendTex->fAlloc;
    rt = gpu->wrapBackendRenderTarget(desc, kAdopt_GrWrapOwnership);
    REPORTER_ASSERT(reporter, rt);

    gpu->deleteTestingOnlyBackendTexture(backendObj, true);
}

void wrap_trt_test(skiatest::Reporter* reporter, GrContext* context) {
    GrVkGpu* gpu = static_cast<GrVkGpu*>(context->getGpu());

    GrBackendObject backendObj = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH, kPixelConfig,
                                                                      true);
    const GrVkImageInfo* backendTex = reinterpret_cast<const GrVkImageInfo*>(backendObj);

    // check basic borrowed creation
    GrBackendTextureDesc desc;
    desc.fFlags = kRenderTarget_GrBackendTextureFlag;
    desc.fConfig = kPixelConfig;
    desc.fWidth = kW;
    desc.fHeight = kH;
    desc.fTextureHandle = backendObj;
    sk_sp<GrTexture> tex = gpu->wrapBackendTexture(desc, kBorrow_GrWrapOwnership);
    REPORTER_ASSERT(reporter, tex);

    // image is null
    GrVkImageInfo backendCopy = *backendTex;
    backendCopy.fImage = VK_NULL_HANDLE;
    desc.fTextureHandle = (GrBackendObject)&backendCopy;
    tex = gpu->wrapBackendTexture(desc, kBorrow_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !tex);
    tex = gpu->wrapBackendTexture(desc, kAdopt_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !tex);

    // alloc is null
    backendCopy.fImage = backendTex->fImage;
    backendCopy.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
    tex = gpu->wrapBackendTexture(desc, kBorrow_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !tex);
    tex = gpu->wrapBackendTexture(desc, kAdopt_GrWrapOwnership);
    REPORTER_ASSERT(reporter, !tex);

    // check adopt creation
    backendCopy.fAlloc = backendTex->fAlloc;
    tex = gpu->wrapBackendTexture(desc, kAdopt_GrWrapOwnership);
    REPORTER_ASSERT(reporter, tex);

    gpu->deleteTestingOnlyBackendTexture(backendObj, true);
}

DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkWrapTests, reporter, ctxInfo) {
    wrap_tex_test(reporter, ctxInfo.grContext());
    wrap_rt_test(reporter, ctxInfo.grContext());
    wrap_trt_test(reporter, ctxInfo.grContext());
}

#endif
