/*
 * 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"

#ifdef SKQP_BUILD_HARDWAREBUFFER_TEST
#if SK_SUPPORT_GPU && defined(SK_VULKAN)

#include "GrBackendSemaphore.h"
#include "GrContext.h"
#include "GrContextFactory.h"
#include "GrContextPriv.h"
#include "GrGpu.h"
#include "GrProxyProvider.h"
#include "GrTest.h"
#include "SkAutoMalloc.h"
#include "SkCanvas.h"
#include "SkGr.h"
#include "SkImage.h"
#include "SkSurface.h"
#include "Test.h"
#include "../tools/gpu/vk/VkTestUtils.h"
#include "gl/GrGLDefines.h"
#include "gl/GrGLUtil.h"
#include "vk/GrVkBackendContext.h"
#include "vk/GrVkExtensions.h"

#include <android/hardware_buffer.h>
#include <cinttypes>

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES/gl.h>
#include <GLES/glext.h>

static const int DEV_W = 16, DEV_H = 16;

class BaseTestHelper {
public:
    virtual ~BaseTestHelper() {}

    virtual bool init(skiatest::Reporter* reporter) = 0;

    virtual void cleanup() = 0;
    virtual void releaseImage() = 0;

    virtual sk_sp<SkImage> importHardwareBufferForRead(skiatest::Reporter* reporter,
                                                       AHardwareBuffer* buffer) = 0;
    virtual sk_sp<SkSurface> importHardwareBufferForWrite(skiatest::Reporter* reporter,
                                                          AHardwareBuffer* buffer) = 0;

    virtual void doClientSync() = 0;
    virtual bool flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter, sk_sp<SkSurface>) = 0;
    virtual bool importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
                                          sk_sp<SkSurface>) = 0;

    virtual void makeCurrent() = 0;

    virtual GrContext* grContext() = 0;

    int getFdHandle() { return fFdHandle; }

protected:
    BaseTestHelper() {}

    int fFdHandle = 0;
};

class EGLTestHelper : public BaseTestHelper {
public:
    EGLTestHelper(const GrContextOptions& options) : fFactory(options) {}

    ~EGLTestHelper() override {}

    void releaseImage() override {
        this->makeCurrent();
        if (!fGLCtx) {
            return;
        }
        if (EGL_NO_IMAGE_KHR != fImage) {
            fGLCtx->destroyEGLImage(fImage);
            fImage = EGL_NO_IMAGE_KHR;
        }
        if (fTexID) {
            GR_GL_CALL(fGLCtx->gl(), DeleteTextures(1, &fTexID));
            fTexID = 0;
        }
    }

    void cleanup() override {
        this->releaseImage();
    }

    bool init(skiatest::Reporter* reporter) override;

    sk_sp<SkImage> importHardwareBufferForRead(skiatest::Reporter* reporter,
                                               AHardwareBuffer* buffer) override;
    sk_sp<SkSurface> importHardwareBufferForWrite(skiatest::Reporter* reporter,
                                                  AHardwareBuffer* buffer) override;

    void doClientSync() override;
    bool flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter, sk_sp<SkSurface>) override;
    bool importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
                                  sk_sp<SkSurface>) override;

    void makeCurrent() override { fGLCtx->makeCurrent(); }

    GrContext* grContext() override { return fGrContext; }

private:
    bool importHardwareBuffer(skiatest::Reporter* reporter, AHardwareBuffer* buffer);

    typedef EGLClientBuffer (*EGLGetNativeClientBufferANDROIDProc)(const struct AHardwareBuffer*);
    typedef EGLImageKHR (*EGLCreateImageKHRProc)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer,
                                                 const EGLint*);
    typedef void (*EGLImageTargetTexture2DOESProc)(EGLenum, void*);
    EGLGetNativeClientBufferANDROIDProc fEGLGetNativeClientBufferANDROID;
    EGLCreateImageKHRProc fEGLCreateImageKHR;
    EGLImageTargetTexture2DOESProc fEGLImageTargetTexture2DOES;

    PFNEGLCREATESYNCKHRPROC              fEGLCreateSyncKHR;
    PFNEGLWAITSYNCKHRPROC                fEGLWaitSyncKHR;
    PFNEGLGETSYNCATTRIBKHRPROC           fEGLGetSyncAttribKHR;
    PFNEGLDUPNATIVEFENCEFDANDROIDPROC    fEGLDupNativeFenceFDANDROID;
    PFNEGLDESTROYSYNCKHRPROC             fEGLDestroySyncKHR;

    EGLImageKHR fImage = EGL_NO_IMAGE_KHR;
    GrGLuint fTexID = 0;

    sk_gpu_test::GrContextFactory fFactory;
    sk_gpu_test::ContextInfo fGLESContextInfo;

    sk_gpu_test::GLTestContext* fGLCtx = nullptr;
    GrContext* fGrContext = nullptr;
};

bool EGLTestHelper::init(skiatest::Reporter* reporter) {
    fGLESContextInfo = fFactory.getContextInfo(sk_gpu_test::GrContextFactory::kGLES_ContextType);
    fGrContext = fGLESContextInfo.grContext();
    fGLCtx = fGLESContextInfo.glContext();
    if (!fGrContext || !fGLCtx) {
        return false;
    }

    if (kGLES_GrGLStandard != fGLCtx->gl()->fStandard) {
        return false;
    }

    // Confirm we have egl and the needed extensions
    if (!fGLCtx->gl()->hasExtension("EGL_KHR_image") ||
        !fGLCtx->gl()->hasExtension("EGL_ANDROID_get_native_client_buffer") ||
        !fGLCtx->gl()->hasExtension("GL_OES_EGL_image_external") ||
        !fGLCtx->gl()->hasExtension("GL_OES_EGL_image") ||
        !fGLCtx->gl()->hasExtension("EGL_KHR_fence_sync")) {
        return false;
    }

    fEGLGetNativeClientBufferANDROID =
        (EGLGetNativeClientBufferANDROIDProc) eglGetProcAddress("eglGetNativeClientBufferANDROID");
    if (!fEGLGetNativeClientBufferANDROID) {
        ERRORF(reporter, "Failed to get the eglGetNativeClientBufferAndroid proc");
        return false;
    }

    fEGLCreateImageKHR = (EGLCreateImageKHRProc) eglGetProcAddress("eglCreateImageKHR");
    if (!fEGLCreateImageKHR) {
        ERRORF(reporter, "Failed to get the proc eglCreateImageKHR");
        return false;
    }

    fEGLImageTargetTexture2DOES =
            (EGLImageTargetTexture2DOESProc) eglGetProcAddress("glEGLImageTargetTexture2DOES");
    if (!fEGLImageTargetTexture2DOES) {
        ERRORF(reporter, "Failed to get the proc EGLImageTargetTexture2DOES");
        return false;
    }

    fEGLCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC) eglGetProcAddress("eglCreateSyncKHR");
    if (!fEGLCreateSyncKHR) {
        ERRORF(reporter, "Failed to get the proc eglCreateSyncKHR");
        return false;

    }
    fEGLWaitSyncKHR = (PFNEGLWAITSYNCKHRPROC) eglGetProcAddress("eglWaitSyncKHR");
    if (!fEGLWaitSyncKHR) {
        ERRORF(reporter, "Failed to get the proc eglWaitSyncKHR");
        return false;

    }
    fEGLGetSyncAttribKHR = (PFNEGLGETSYNCATTRIBKHRPROC) eglGetProcAddress("eglGetSyncAttribKHR");
    if (!fEGLGetSyncAttribKHR) {
        ERRORF(reporter, "Failed to get the proc eglGetSyncAttribKHR");
        return false;

    }
    fEGLDupNativeFenceFDANDROID =
        (PFNEGLDUPNATIVEFENCEFDANDROIDPROC) eglGetProcAddress("eglDupNativeFenceFDANDROID");
    if (!fEGLDupNativeFenceFDANDROID) {
        ERRORF(reporter, "Failed to get the proc eglDupNativeFenceFDANDROID");
        return false;

    }
    fEGLDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC) eglGetProcAddress("eglDestroySyncKHR");
    if (!fEGLDestroySyncKHR) {
        ERRORF(reporter, "Failed to get the proc eglDestroySyncKHR");
        return false;

    }

    return true;
}

bool EGLTestHelper::importHardwareBuffer(skiatest::Reporter* reporter, AHardwareBuffer* buffer) {
    GrGLClearErr(fGLCtx->gl());

    EGLClientBuffer eglClientBuffer = fEGLGetNativeClientBufferANDROID(buffer);
    EGLint eglAttribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
                            EGL_NONE };
    EGLDisplay eglDisplay = eglGetCurrentDisplay();
    fImage = fEGLCreateImageKHR(eglDisplay, EGL_NO_CONTEXT,
                                EGL_NATIVE_BUFFER_ANDROID,
                                eglClientBuffer, eglAttribs);
    if (EGL_NO_IMAGE_KHR == fImage) {
        SkDebugf("Could not create EGL image, err = (%#x)\n", (int) eglGetError() );
        return false;
    }

    GR_GL_CALL(fGLCtx->gl(), GenTextures(1, &fTexID));
    if (!fTexID) {
        ERRORF(reporter, "Failed to create GL Texture");
        return false;
    }
    GR_GL_CALL_NOERRCHECK(fGLCtx->gl(), BindTexture(GR_GL_TEXTURE_2D, fTexID));
    if (GR_GL_GET_ERROR(fGLCtx->gl()) != GR_GL_NO_ERROR) {
        ERRORF(reporter, "Failed to bind GL Texture");
        return false;
    }

    fEGLImageTargetTexture2DOES(GL_TEXTURE_2D, fImage);
    GLenum status = GL_NO_ERROR;
    if ((status = glGetError()) != GL_NO_ERROR) {
        ERRORF(reporter, "EGLImageTargetTexture2DOES failed (%#x)", (int) status);
        return false;
    }

    fGrContext->resetContext(kTextureBinding_GrGLBackendState);
    return true;
}

sk_sp<SkImage> EGLTestHelper::importHardwareBufferForRead(skiatest::Reporter* reporter,
                                                          AHardwareBuffer* buffer) {
    if (!this->importHardwareBuffer(reporter, buffer)) {
        return nullptr;
    }
    GrGLTextureInfo textureInfo;
    textureInfo.fTarget = GR_GL_TEXTURE_2D;
    textureInfo.fID = fTexID;
    textureInfo.fFormat = GR_GL_RGBA8;

    GrBackendTexture backendTex(DEV_W, DEV_H, GrMipMapped::kNo, textureInfo);
    REPORTER_ASSERT(reporter, backendTex.isValid());

    sk_sp<SkImage> image = SkImage::MakeFromTexture(fGrContext,
                                                               backendTex,
                                                               kTopLeft_GrSurfaceOrigin,
                                                               kRGBA_8888_SkColorType,
                                                               kPremul_SkAlphaType,
                                                               nullptr);

    if (!image) {
        ERRORF(reporter, "Failed to make wrapped GL SkImage");
        return nullptr;
    }

    return image;
}

sk_sp<SkSurface> EGLTestHelper::importHardwareBufferForWrite(skiatest::Reporter* reporter,
                                                             AHardwareBuffer* buffer) {
    if (!this->importHardwareBuffer(reporter, buffer)) {
        return nullptr;
    }
    GrGLTextureInfo textureInfo;
    textureInfo.fTarget = GR_GL_TEXTURE_2D;
    textureInfo.fID = fTexID;
    textureInfo.fFormat = GR_GL_RGBA8;

    GrBackendTexture backendTex(DEV_W, DEV_H, GrMipMapped::kNo, textureInfo);
    REPORTER_ASSERT(reporter, backendTex.isValid());

    sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(fGrContext,
                                                                 backendTex,
                                                                 kTopLeft_GrSurfaceOrigin,
                                                                 0,
                                                                 kRGBA_8888_SkColorType,
                                                                 nullptr, nullptr);

    if (!surface) {
        ERRORF(reporter, "Failed to make wrapped GL SkSurface");
        return nullptr;
    }

    return surface;
}

bool EGLTestHelper::flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter,
                                                      sk_sp<SkSurface> surface) {
    EGLDisplay eglDisplay = eglGetCurrentDisplay();
    EGLSyncKHR eglsync = fEGLCreateSyncKHR(eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
    if (EGL_NO_SYNC_KHR == eglsync) {
        ERRORF(reporter, "Failed to create EGLSync for EGL_SYNC_NATIVE_FENCE_ANDROID\n");
        return false;
    }

    surface->flush();
    GR_GL_CALL(fGLCtx->gl(), Flush());
    fFdHandle = fEGLDupNativeFenceFDANDROID(eglDisplay, eglsync);

    EGLint result = fEGLDestroySyncKHR(eglDisplay, eglsync);
    if (EGL_TRUE != result) {
        ERRORF(reporter, "Failed to delete EGLSync, error: %d\n", result);
        return false;
    }

    return true;
}

bool EGLTestHelper::importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
                                             sk_sp<SkSurface> surface) {
    EGLDisplay eglDisplay = eglGetCurrentDisplay();
    EGLint attr[] = {
        EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fdHandle,
        EGL_NONE
    };
    EGLSyncKHR eglsync = fEGLCreateSyncKHR(eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attr);
    if (EGL_NO_SYNC_KHR == eglsync) {
        ERRORF(reporter,
               "Failed to create EGLSync when importing EGL_SYNC_NATIVE_FENCE_FD_ANDROID\n");
        return false;
    }
    EGLint result = fEGLWaitSyncKHR(eglDisplay, eglsync, 0);
    if (EGL_TRUE != result) {
        ERRORF(reporter, "Failed called to eglWaitSyncKHR, error: %d\n", result);
        // Don't return false yet, try to delete the sync first
    }
    result = fEGLDestroySyncKHR(eglDisplay, eglsync);
    if (EGL_TRUE != result) {
        ERRORF(reporter, "Failed to delete EGLSync, error: %d\n", result);
        return false;
    }
    return true;
}

void EGLTestHelper::doClientSync() {
    sk_gpu_test::FenceSync* fenceSync = fGLCtx->fenceSync();
    sk_gpu_test::PlatformFence fence = fenceSync->insertFence();
    fenceSync->waitFence(fence);
    fenceSync->deleteFence(fence);
}

#define DECLARE_VK_PROC(name) PFN_vk##name fVk##name

#define ACQUIRE_VK_PROC(name, instance, device)                                        \
    fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
    if (fVk##name == nullptr) {                                                        \
        ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name);      \
        return false;                                                                  \
    }

#define ACQUIRE_INST_VK_PROC(name)                                                          \
    fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, fInst, VK_NULL_HANDLE)); \
    if (fVk##name == nullptr) {                                                             \
        ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name);           \
        fVkDestroyInstance(fInst, nullptr);                                                 \
        return false;                                                                       \
    }

#define ACQUIRE_DEVICE_VK_PROC(name)                                                          \
    fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, VK_NULL_HANDLE, fDevice)); \
    if (fVk##name == nullptr) {                                                               \
        ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name);             \
        fVkDestroyDevice(fDevice, nullptr);                                                   \
        fVkDestroyInstance(fInst, nullptr);                                                   \
        return false;                                                                         \
    }

#ifdef SK_ENABLE_VK_LAYERS
const char* kMyDebugLayerNames[] = {
    // elements of VK_LAYER_LUNARG_standard_validation
    "VK_LAYER_GOOGLE_threading",
    "VK_LAYER_LUNARG_parameter_validation",
    "VK_LAYER_LUNARG_object_tracker",
    "VK_LAYER_LUNARG_image",
    "VK_LAYER_LUNARG_core_validation",
    "VK_LAYER_LUNARG_swapchain",
    "VK_LAYER_GOOGLE_unique_objects",
    // not included in standard_validation
    //"VK_LAYER_LUNARG_api_dump",
    //"VK_LAYER_LUNARG_vktrace",
    //"VK_LAYER_LUNARG_screenshot",
};
#endif

class VulkanTestHelper : public BaseTestHelper {
public:
    VulkanTestHelper() {}

    ~VulkanTestHelper() override {}

    void releaseImage() override {
        if (VK_NULL_HANDLE == fDevice) {
            return;
        }
        if (fImage != VK_NULL_HANDLE) {
            SkASSERT(fVkDestroyImage);
            fVkDestroyImage(fDevice, fImage, nullptr);
            fImage = VK_NULL_HANDLE;
        }

        if (fMemory != VK_NULL_HANDLE) {
            SkASSERT(fVkFreeMemory);
            fVkFreeMemory(fDevice, fMemory, nullptr);
            fMemory = VK_NULL_HANDLE;
        }
    }
    void cleanup() override {
        this->releaseImage();

        fGrContext.reset();
        fBackendContext.reset();

        fInst = VK_NULL_HANDLE;
        fPhysDev = VK_NULL_HANDLE;
        fDevice = VK_NULL_HANDLE;
    }

    bool init(skiatest::Reporter* reporter) override;

    void doClientSync() override {
        if (!fGrContext) {
            return;
        }

        fGrContext->contextPriv().getGpu()->testingOnly_flushGpuAndSync();
    }

    bool flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter, sk_sp<SkSurface>) override;
    bool importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
                                  sk_sp<SkSurface>) override;

    sk_sp<SkImage> importHardwareBufferForRead(skiatest::Reporter* reporter,
                                               AHardwareBuffer* buffer) override;

    sk_sp<SkSurface> importHardwareBufferForWrite(skiatest::Reporter* reporter,
                                                  AHardwareBuffer* buffer) override;

    void makeCurrent() override {}

    GrContext* grContext() override { return fGrContext.get(); }

private:
    bool checkOptimalHardwareBuffer(skiatest::Reporter* reporter);

    bool importHardwareBuffer(skiatest::Reporter* reporter, AHardwareBuffer* buffer, bool forWrite,
                              GrVkImageInfo* outImageInfo);

    bool setupSemaphoreForSignaling(skiatest::Reporter* reporter, GrBackendSemaphore*);
    bool exportSemaphore(skiatest::Reporter* reporter, const GrBackendSemaphore&);

    DECLARE_VK_PROC(EnumerateInstanceVersion);
    DECLARE_VK_PROC(CreateInstance);
    DECLARE_VK_PROC(DestroyInstance);
    DECLARE_VK_PROC(EnumeratePhysicalDevices);
    DECLARE_VK_PROC(GetPhysicalDeviceProperties);
    DECLARE_VK_PROC(GetPhysicalDeviceMemoryProperties2);
    DECLARE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties);
    DECLARE_VK_PROC(GetPhysicalDeviceFeatures);
    DECLARE_VK_PROC(GetPhysicalDeviceExternalSemaphoreProperties);
    DECLARE_VK_PROC(CreateDevice);
    DECLARE_VK_PROC(GetDeviceQueue);
    DECLARE_VK_PROC(DeviceWaitIdle);
    DECLARE_VK_PROC(DestroyDevice);
    DECLARE_VK_PROC(GetPhysicalDeviceImageFormatProperties2);
    DECLARE_VK_PROC(CreateImage);
    DECLARE_VK_PROC(GetImageMemoryRequirements2);
    DECLARE_VK_PROC(GetAndroidHardwareBufferPropertiesANDROID);
    DECLARE_VK_PROC(AllocateMemory);
    DECLARE_VK_PROC(BindImageMemory2);
    DECLARE_VK_PROC(DestroyImage);
    DECLARE_VK_PROC(FreeMemory);
    DECLARE_VK_PROC(CreateSemaphore);
    DECLARE_VK_PROC(GetSemaphoreFdKHR);
    DECLARE_VK_PROC(ImportSemaphoreFdKHR);
    DECLARE_VK_PROC(DestroySemaphore);

    VkInstance fInst = VK_NULL_HANDLE;
    VkPhysicalDevice fPhysDev = VK_NULL_HANDLE;
    VkDevice fDevice = VK_NULL_HANDLE;

    VkImage fImage = VK_NULL_HANDLE;
    VkDeviceMemory fMemory = VK_NULL_HANDLE;

    sk_sp<GrVkBackendContext> fBackendContext;
    sk_sp<GrContext> fGrContext;
};

bool VulkanTestHelper::init(skiatest::Reporter* reporter) {
    PFN_vkGetInstanceProcAddr instProc;
    PFN_vkGetDeviceProcAddr devProc;
    if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
        return false;
    }

    auto getProc = [&instProc, &devProc](const char* proc_name,
                                         VkInstance instance, VkDevice device) {
        if (device != VK_NULL_HANDLE) {
            return devProc(device, proc_name);
        }
        return instProc(instance, proc_name);
    };

    VkResult err;

    ACQUIRE_VK_PROC(EnumerateInstanceVersion, VK_NULL_HANDLE, VK_NULL_HANDLE);
    uint32_t instanceVersion = 0;
    if (fVkEnumerateInstanceVersion) {
        err = fVkEnumerateInstanceVersion(&instanceVersion);
        if (err) {
            ERRORF(reporter, "failed to enumerate instance version. Err: %d\n", err);
            return false;
        }
    }
    if (instanceVersion < VK_MAKE_VERSION(1, 1, 0)) {
        return false;
    }

    const VkApplicationInfo app_info = {
        VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
        nullptr,                            // pNext
        "vkHWBTest",                        // pApplicationName
        0,                                  // applicationVersion
        "vkHWBTest",                        // pEngineName
        0,                                  // engineVerison
        instanceVersion,                    // apiVersion
    };

    GrVkExtensions extensions(getProc);
    extensions.initInstance(instanceVersion);

    SkTArray<const char*> instanceLayerNames;
    SkTArray<const char*> instanceExtensionNames;
    uint32_t extensionFlags = 0;
#ifdef SK_ENABLE_VK_LAYERS
    for (size_t i = 0; i < SK_ARRAY_COUNT(kMyDebugLayerNames); ++i) {
        if (extensions.hasInstanceLayer(kMyDebugLayerNames[i])) {
            instanceLayerNames.push_back(kMyDebugLayerNames[i]);
        }
    }
    if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
        extensionFlags |= kEXT_debug_report_GrVkExtensionFlag;
    }
#endif

    const VkInstanceCreateInfo instance_create = {
        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,    // sType
        nullptr,                                   // pNext
        0,                                         // flags
        &app_info,                                 // pApplicationInfo
        (uint32_t) instanceLayerNames.count(),     // enabledLayerNameCount
        instanceLayerNames.begin(),                // ppEnabledLayerNames
        (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
        instanceExtensionNames.begin(),            // ppEnabledExtensionNames
    };

    ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE);
    err = fVkCreateInstance(&instance_create, nullptr, &fInst);
    if (err < 0) {
        ERRORF(reporter, "vkCreateInstance failed: %d\n", err);
        return false;
    }

    ACQUIRE_VK_PROC(DestroyInstance, fInst, VK_NULL_HANDLE);
    ACQUIRE_INST_VK_PROC(EnumeratePhysicalDevices);
    ACQUIRE_INST_VK_PROC(GetPhysicalDeviceProperties);
    ACQUIRE_INST_VK_PROC(GetPhysicalDeviceQueueFamilyProperties);
    ACQUIRE_INST_VK_PROC(GetPhysicalDeviceFeatures);
    ACQUIRE_INST_VK_PROC(CreateDevice);
    ACQUIRE_INST_VK_PROC(GetDeviceQueue);
    ACQUIRE_INST_VK_PROC(DeviceWaitIdle);
    ACQUIRE_INST_VK_PROC(DestroyDevice);

    uint32_t gpuCount;
    err = fVkEnumeratePhysicalDevices(fInst, &gpuCount, nullptr);
    if (err) {
        ERRORF(reporter, "vkEnumeratePhysicalDevices failed: %d\n", err);
        fVkDestroyInstance(fInst, nullptr);
        return false;
    }
    if (!gpuCount) {
        // We can no physical devices so this isn't an error and failure in the test.
        fVkDestroyInstance(fInst, nullptr);
        return false;
    }
    // Just returning the first physical device instead of getting the whole array.
    // TODO: find best match for our needs
    gpuCount = 1;
    err = fVkEnumeratePhysicalDevices(fInst, &gpuCount, &fPhysDev);
    if (err) {
        ERRORF(reporter, "vkEnumeratePhysicalDevices failed: %d\n", err);
        fVkDestroyInstance(fInst, nullptr);
        return false;
    }

    // query to get the initial queue props size
    uint32_t queueCount;
    fVkGetPhysicalDeviceQueueFamilyProperties(fPhysDev, &queueCount, nullptr);
    if (!queueCount) {
        ERRORF(reporter, "vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
        fVkDestroyInstance(fInst, nullptr);
        return false;
    }

    SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
    // now get the actual queue props
    VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();

    fVkGetPhysicalDeviceQueueFamilyProperties(fPhysDev, &queueCount, queueProps);

    // iterate to find the graphics queue
    uint32_t graphicsQueueIndex = queueCount;
    for (uint32_t i = 0; i < queueCount; i++) {
        if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
            graphicsQueueIndex = i;
            break;
        }
    }
    if (graphicsQueueIndex == queueCount) {
        ERRORF(reporter, "Could not find any supported graphics queues.\n");
        fVkDestroyInstance(fInst, nullptr);
        return false;
    }

    VkPhysicalDeviceProperties physDevProperties;
    fVkGetPhysicalDeviceProperties(fPhysDev, &physDevProperties);
    int physDevVersion = physDevProperties.apiVersion;

    if (physDevVersion < VK_MAKE_VERSION(1, 1, 0)) {
        return false;
    }

    // Physical-Device-level functions added in 1.1
    ACQUIRE_INST_VK_PROC(GetPhysicalDeviceMemoryProperties2);
    ACQUIRE_INST_VK_PROC(GetPhysicalDeviceImageFormatProperties2);
    ACQUIRE_INST_VK_PROC(GetPhysicalDeviceExternalSemaphoreProperties);

    extensions.initDevice(physDevVersion, fInst, fPhysDev);

    SkTArray<const char*> deviceLayerNames;
    SkTArray<const char*> deviceExtensionNames;
#ifdef SK_ENABLE_VK_LAYERS
    for (size_t i = 0; i < SK_ARRAY_COUNT(kMyDebugLayerNames); ++i) {
        if (extensions.hasDeviceLayer(kMyDebugLayerNames[i])) {
            deviceLayerNames.push_back(kMyDebugLayerNames[i]);
        }
    }
#endif

    if (extensions.hasDeviceExtension(
            VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME)) {
        deviceExtensionNames.push_back(
                VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME);
    } else {
        fVkDestroyInstance(fInst, nullptr);
        return false;
    }

    if (extensions.hasDeviceExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME)) {
        deviceExtensionNames.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
    } else {
        ERRORF(reporter, "Has HWB extension, but doesn't not have YCBCR coversion extension");
        fVkDestroyInstance(fInst, nullptr);
        return false;
    }

    if (extensions.hasDeviceExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME)) {
        deviceExtensionNames.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
    } else {
        fVkDestroyInstance(fInst, nullptr);
        return false;
    }

    if (extensions.hasDeviceExtension(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME)) {
        deviceExtensionNames.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME);
    } else {
        SkDebugf("We don't have the extension for VK_EXT_QUEUE_FAMILY_FOREIGN\n");
        //fVkDestroyInstance(fInst, nullptr);
        //return false;
    }

    // query to get the physical device properties
    VkPhysicalDeviceFeatures deviceFeatures;
    fVkGetPhysicalDeviceFeatures(fPhysDev, &deviceFeatures);
    // this looks like it would slow things down,
    // and we can't depend on it on all platforms
    deviceFeatures.robustBufferAccess = VK_FALSE;

    uint32_t featureFlags = 0;
    if (deviceFeatures.geometryShader) {
        featureFlags |= kGeometryShader_GrVkFeatureFlag;
    }
    if (deviceFeatures.dualSrcBlend) {
        featureFlags |= kDualSrcBlend_GrVkFeatureFlag;
    }
    if (deviceFeatures.sampleRateShading) {
        featureFlags |= kSampleRateShading_GrVkFeatureFlag;
    }

    float queuePriorities[1] = { 0.0 };
    // Here we assume no need for swapchain queue
    // If one is needed, the client will need its own setup code
    const VkDeviceQueueCreateInfo queueInfo[1] = {
        {
            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
            nullptr,                                    // pNext
            0,                                          // VkDeviceQueueCreateFlags
            graphicsQueueIndex,                         // queueFamilyIndex
            1,                                          // queueCount
            queuePriorities,                            // pQueuePriorities
        }
    };
    uint32_t queueInfoCount = 1;

    const VkDeviceCreateInfo deviceInfo = {
        VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,    // sType
        nullptr,                                 // pNext
        0,                                       // VkDeviceCreateFlags
        queueInfoCount,                          // queueCreateInfoCount
        queueInfo,                               // pQueueCreateInfos
        (uint32_t) deviceLayerNames.count(),     // layerCount
        deviceLayerNames.begin(),                // ppEnabledLayerNames
        (uint32_t) deviceExtensionNames.count(), // extensionCount
        deviceExtensionNames.begin(),            // ppEnabledExtensionNames
        &deviceFeatures                          // ppEnabledFeatures
    };

    err = fVkCreateDevice(fPhysDev, &deviceInfo, nullptr, &fDevice);
    if (err) {
        ERRORF(reporter, "CreateDevice failed: %d\n", err);
        fVkDestroyInstance(fInst, nullptr);
        return false;
    }

    ACQUIRE_DEVICE_VK_PROC(CreateImage);
    ACQUIRE_DEVICE_VK_PROC(GetImageMemoryRequirements2);
    ACQUIRE_DEVICE_VK_PROC(GetAndroidHardwareBufferPropertiesANDROID);
    ACQUIRE_DEVICE_VK_PROC(AllocateMemory);
    ACQUIRE_DEVICE_VK_PROC(BindImageMemory2);
    ACQUIRE_DEVICE_VK_PROC(DestroyImage);
    ACQUIRE_DEVICE_VK_PROC(FreeMemory);
    ACQUIRE_DEVICE_VK_PROC(CreateSemaphore);
    ACQUIRE_DEVICE_VK_PROC(GetSemaphoreFdKHR);
    ACQUIRE_DEVICE_VK_PROC(ImportSemaphoreFdKHR);
    ACQUIRE_DEVICE_VK_PROC(DestroySemaphore);

    VkQueue queue;
    fVkGetDeviceQueue(fDevice, graphicsQueueIndex, 0, &queue);

    // Setting up actual skia things now
    auto interface =
            sk_make_sp<GrVkInterface>(getProc, fInst, fDevice, extensionFlags);
    if (!interface->validate(extensionFlags)) {
        ERRORF(reporter, "Vulkan interface validation failed\n");
        fVkDeviceWaitIdle(fDevice);
        fVkDestroyDevice(fDevice, nullptr);
        fVkDestroyInstance(fInst, nullptr);
        return false;
    }

    fBackendContext.reset(new GrVkBackendContext());
    fBackendContext->fInstance = fInst;
    fBackendContext->fPhysicalDevice = fPhysDev;
    fBackendContext->fDevice = fDevice;
    fBackendContext->fQueue = queue;
    fBackendContext->fGraphicsQueueIndex = graphicsQueueIndex;
    fBackendContext->fMinAPIVersion = instanceVersion;
    fBackendContext->fExtensions = extensionFlags;
    fBackendContext->fFeatures = featureFlags;
    fBackendContext->fInterface.reset(interface.release());
    fBackendContext->fOwnsInstanceAndDevice = true;

    fGrContext = GrContext::MakeVulkan(fBackendContext);
    REPORTER_ASSERT(reporter, fGrContext.get());

    return this->checkOptimalHardwareBuffer(reporter);
}

bool VulkanTestHelper::checkOptimalHardwareBuffer(skiatest::Reporter* reporter) {
    VkResult err;

    VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo;
    externalImageFormatInfo.sType =
            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO;
    externalImageFormatInfo.pNext = nullptr;
    externalImageFormatInfo.handleType =
            VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
    //externalImageFormatInfo.handType = 0x80;

    // We will create the hardware buffer with gpu sampled so these usages should all be valid
    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
                                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
                                   VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    VkPhysicalDeviceImageFormatInfo2 imageFormatInfo;
    imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
    imageFormatInfo.pNext = &externalImageFormatInfo;
    imageFormatInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
    imageFormatInfo.type = VK_IMAGE_TYPE_2D;
    imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
    imageFormatInfo.usage = usageFlags;
    imageFormatInfo.flags = 0;

    VkAndroidHardwareBufferUsageANDROID hwbUsage;
    hwbUsage.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID;
    hwbUsage.pNext = nullptr;

    VkExternalImageFormatProperties externalImgFormatProps;
    externalImgFormatProps.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES;
    externalImgFormatProps.pNext = &hwbUsage;

    VkImageFormatProperties2 imgFormProps;
    imgFormProps.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
    imgFormProps.pNext = &externalImgFormatProps;

    err = fVkGetPhysicalDeviceImageFormatProperties2(fPhysDev, &imageFormatInfo,
                                                        &imgFormProps);
    if (VK_SUCCESS != err) {
        ERRORF(reporter, "vkGetPhysicalDeviceImageFormatProperites failed, err: %d", err);
        return false;
    }

    const VkImageFormatProperties& imageFormatProperties = imgFormProps.imageFormatProperties;
    REPORTER_ASSERT(reporter, DEV_W <= imageFormatProperties.maxExtent.width);
    REPORTER_ASSERT(reporter, DEV_H <= imageFormatProperties.maxExtent.height);

    const VkExternalMemoryProperties& externalImageFormatProps =
            externalImgFormatProps.externalMemoryProperties;
    REPORTER_ASSERT(reporter, SkToBool(VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT &
                                       externalImageFormatProps.externalMemoryFeatures));
    REPORTER_ASSERT(reporter, SkToBool(VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT &
                                       externalImageFormatProps.externalMemoryFeatures));

    REPORTER_ASSERT(reporter, SkToBool(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE &
                                       hwbUsage.androidHardwareBufferUsage));

    return true;
}

bool VulkanTestHelper::importHardwareBuffer(skiatest::Reporter* reporter,
                                            AHardwareBuffer* buffer,
                                            bool forWrite,
                                            GrVkImageInfo* outImageInfo) {
    VkResult err;

    VkAndroidHardwareBufferFormatPropertiesANDROID hwbFormatProps;
    hwbFormatProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
    hwbFormatProps.pNext = nullptr;

    VkAndroidHardwareBufferPropertiesANDROID hwbProps;
    hwbProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
    hwbProps.pNext = &hwbFormatProps;

    err = fVkGetAndroidHardwareBufferPropertiesANDROID(fDevice, buffer, &hwbProps);
    if (VK_SUCCESS != err) {
        ERRORF(reporter, "GetAndroidHardwareBufferPropertiesAndoird failed, err: %d", err);
        return false;
    }

    REPORTER_ASSERT(reporter, VK_FORMAT_R8G8B8A8_UNORM == hwbFormatProps.format);
    REPORTER_ASSERT(reporter,
                    SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & hwbFormatProps.formatFeatures) &&
                    SkToBool(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT & hwbFormatProps.formatFeatures) &&
                    SkToBool(VK_FORMAT_FEATURE_TRANSFER_DST_BIT & hwbFormatProps.formatFeatures));
    if (forWrite) {
        REPORTER_ASSERT(reporter,
                SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT & hwbFormatProps.formatFeatures));

    }

    bool useExternalFormat = VK_FORMAT_UNDEFINED == hwbFormatProps.format;
    const VkExternalFormatANDROID externalFormatInfo {
        VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,             // sType
        nullptr,                                               // pNext
        useExternalFormat ? hwbFormatProps.externalFormat : 0, // externalFormat
    };

    const VkExternalMemoryImageCreateInfo externalMemoryImageInfo {
        VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // sType
        &externalFormatInfo, // pNext
        //nullptr, // pNext
        VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, // handleTypes
        //0x80, // handleTypes
    };

    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
                                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
                                   VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    if (forWrite) {
        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    }

    const VkImageCreateInfo imageCreateInfo = {
        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
        &externalMemoryImageInfo,                    // pNext
        0,                                           // VkImageCreateFlags
        VK_IMAGE_TYPE_2D,                            // VkImageType
        hwbFormatProps.format,                       // VkFormat
        { DEV_W, DEV_H, 1 },                         // VkExtent3D
        1,                                           // mipLevels
        1,                                           // arrayLayers
        VK_SAMPLE_COUNT_1_BIT,                       // samples
        VK_IMAGE_TILING_OPTIMAL,                     // VkImageTiling
        usageFlags,                                  // VkImageUsageFlags
        VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
        0,                                           // queueFamilyCount
        0,                                           // pQueueFamilyIndices
        VK_IMAGE_LAYOUT_UNDEFINED,                   // initialLayout
    };

    err = fVkCreateImage(fDevice, &imageCreateInfo, nullptr, &fImage);
    if (VK_SUCCESS != err) {
        ERRORF(reporter, "Create Image failed, err: %d", err);
        return false;
    }

    VkImageMemoryRequirementsInfo2 memReqsInfo;
    memReqsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
    memReqsInfo.pNext = nullptr;
    memReqsInfo.image = fImage;

    VkMemoryDedicatedRequirements dedicatedMemReqs;
    dedicatedMemReqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
    dedicatedMemReqs.pNext = nullptr;

    VkMemoryRequirements2 memReqs;
    memReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
    memReqs.pNext = &dedicatedMemReqs;

    fVkGetImageMemoryRequirements2(fDevice, &memReqsInfo, &memReqs);
    REPORTER_ASSERT(reporter, VK_TRUE == dedicatedMemReqs.requiresDedicatedAllocation);

    VkPhysicalDeviceMemoryProperties2 phyDevMemProps;
    phyDevMemProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
    phyDevMemProps.pNext = nullptr;

    uint32_t typeIndex = 0;
    uint32_t heapIndex = 0;
    bool foundHeap = false;
    fVkGetPhysicalDeviceMemoryProperties2(fPhysDev, &phyDevMemProps);
    uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
    for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) {
        if (hwbProps.memoryTypeBits & (1 << i)) {
            const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties;
            uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
                    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
            if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
                typeIndex = i;
                heapIndex = pdmp.memoryTypes[i].heapIndex;
                foundHeap = true;
            }
        }
    }
    if (!foundHeap) {
        ERRORF(reporter, "Failed to find valid heap for imported memory");
        return false;
    }

    VkImportAndroidHardwareBufferInfoANDROID hwbImportInfo;
    hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
    hwbImportInfo.pNext = nullptr;
    hwbImportInfo.buffer = buffer;

    VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
    dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
    dedicatedAllocInfo.pNext = &hwbImportInfo;
    dedicatedAllocInfo.image = fImage;
    dedicatedAllocInfo.buffer = VK_NULL_HANDLE;

    VkMemoryAllocateInfo allocInfo = {
        VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,      // sType
        &dedicatedAllocInfo,                         // pNext
        hwbProps.allocationSize,                     // allocationSize
        typeIndex,                                   // memoryTypeIndex
    };

    err = fVkAllocateMemory(fDevice, &allocInfo, nullptr, &fMemory);
    if (VK_SUCCESS != err) {
        ERRORF(reporter, "AllocateMemory failed for imported buffer, err: %d", err);
        return false;
    }

    VkBindImageMemoryInfo bindImageInfo;
    bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
    bindImageInfo.pNext = nullptr;
    bindImageInfo.image = fImage;
    bindImageInfo.memory = fMemory;
    bindImageInfo.memoryOffset = 0;

    err = fVkBindImageMemory2(fDevice, 1, &bindImageInfo);
    if (VK_SUCCESS != err) {
        ERRORF(reporter, "BindImageMemory failed for imported buffer, err: %d", err);
        return false;
    }

    outImageInfo->fImage = fImage;
    outImageInfo->fAlloc = GrVkAlloc(fMemory, 0, hwbProps.allocationSize, 0);
    outImageInfo->fImageTiling = VK_IMAGE_TILING_OPTIMAL;
    outImageInfo->fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    outImageInfo->fFormat = VK_FORMAT_R8G8B8A8_UNORM;
    outImageInfo->fLevelCount = 1;
    outImageInfo->fInitialQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
    outImageInfo->fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
    return true;
}

sk_sp<SkImage> VulkanTestHelper::importHardwareBufferForRead(skiatest::Reporter* reporter,
                                                             AHardwareBuffer* buffer) {
    GrVkImageInfo imageInfo;
    if (!this->importHardwareBuffer(reporter, buffer, false, &imageInfo)) {
        return nullptr;
    }

    GrBackendTexture backendTex(DEV_W, DEV_H, imageInfo);

    sk_sp<SkImage> wrappedImage = SkImage::MakeFromTexture(fGrContext.get(),
                                                           backendTex,
                                                           kTopLeft_GrSurfaceOrigin,
                                                           kRGBA_8888_SkColorType,
                                                           kPremul_SkAlphaType,
                                                           nullptr);

    if (!wrappedImage.get()) {
        ERRORF(reporter, "Failed to create wrapped Vulkan SkImage");
        return nullptr;
    }

    return wrappedImage;
}

bool VulkanTestHelper::flushSurfaceAndSignalSemaphore(skiatest::Reporter* reporter,
                                                      sk_sp<SkSurface> surface) {
    surface->flush();
    surface.reset();
    GrBackendSemaphore semaphore;
    if (!this->setupSemaphoreForSignaling(reporter, &semaphore)) {
        return false;
    }
    GrSemaphoresSubmitted submitted = fGrContext->flushAndSignalSemaphores(1, &semaphore);
    if (GrSemaphoresSubmitted::kNo == submitted) {
        ERRORF(reporter, "Failing call to flushAndSignalSemaphores on SkSurface");
        return false;
    }
    SkASSERT(semaphore.isInitialized());
    if (!this->exportSemaphore(reporter, semaphore)) {
        return false;
    }
    return true;
}

bool VulkanTestHelper::setupSemaphoreForSignaling(skiatest::Reporter* reporter,
                                                  GrBackendSemaphore* beSemaphore) {
    // Query supported info
    VkPhysicalDeviceExternalSemaphoreInfo exSemInfo;
    exSemInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO;
    exSemInfo.pNext = nullptr;
    exSemInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;

    VkExternalSemaphoreProperties exSemProps;
    exSemProps.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
    exSemProps.pNext = nullptr;

    fVkGetPhysicalDeviceExternalSemaphoreProperties(fPhysDev, &exSemInfo, &exSemProps);

    if (!SkToBool(exSemProps.exportFromImportedHandleTypes &
                 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) {
        ERRORF(reporter, "HANDLE_TYPE_SYNC_FD not listed as exportFromImportedHandleTypes");
        return false;
    }
    if (!SkToBool(exSemProps.compatibleHandleTypes &
                  VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) {
        ERRORF(reporter, "HANDLE_TYPE_SYNC_FD not listed as compatibleHandleTypes");
        return false;
    }
    if (!SkToBool(exSemProps.externalSemaphoreFeatures &
                  VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) ||
        !SkToBool(exSemProps.externalSemaphoreFeatures &
                  VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) {
        ERRORF(reporter, "HANDLE_TYPE_SYNC_FD doesn't support export and import feature");
        return false;
    }

    VkExportSemaphoreCreateInfo exportInfo;
    exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
    exportInfo.pNext = nullptr;
    exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;

    VkSemaphoreCreateInfo semaphoreInfo;
    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    semaphoreInfo.pNext = &exportInfo;
    semaphoreInfo.flags = 0;

    VkSemaphore semaphore;
    VkResult err = fVkCreateSemaphore(fDevice, &semaphoreInfo, nullptr, &semaphore);
    if (VK_SUCCESS != err) {
        ERRORF(reporter, "Failed to create signal semaphore, err: %d", err);
        return false;
    }
    beSemaphore->initVulkan(semaphore);
    return true;
}

bool VulkanTestHelper::exportSemaphore(skiatest::Reporter* reporter,
                                       const GrBackendSemaphore& beSemaphore) {
    VkSemaphore semaphore = beSemaphore.vkSemaphore();
    if (VK_NULL_HANDLE == semaphore) {
        ERRORF(reporter, "Invalid vulkan handle in export call");
        return false;
    }

    VkSemaphoreGetFdInfoKHR getFdInfo;
    getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
    getFdInfo.pNext = nullptr;
    getFdInfo.semaphore = semaphore;
    getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;

    VkResult err = fVkGetSemaphoreFdKHR(fDevice, &getFdInfo, &fFdHandle);
    if (VK_SUCCESS != err) {
        ERRORF(reporter, "Failed to export signal semaphore, err: %d", err);
        return false;
    }
    fVkDestroySemaphore(fDevice, semaphore, nullptr);
    return true;
}

bool VulkanTestHelper::importAndWaitOnSemaphore(skiatest::Reporter* reporter, int fdHandle,
                                                sk_sp<SkSurface> surface) {
    VkSemaphoreCreateInfo semaphoreInfo;
    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    semaphoreInfo.pNext = nullptr;
    semaphoreInfo.flags = 0;

    VkSemaphore semaphore;
    VkResult err = fVkCreateSemaphore(fDevice, &semaphoreInfo, nullptr, &semaphore);
    if (VK_SUCCESS != err) {
        ERRORF(reporter, "Failed to create import semaphore, err: %d", err);
        return false;
    }

    VkImportSemaphoreFdInfoKHR importInfo;
    importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
    importInfo.pNext = nullptr;
    importInfo.semaphore = semaphore;
    importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
    importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
    importInfo.fd = fdHandle;

    err = fVkImportSemaphoreFdKHR(fDevice, &importInfo);
    if (VK_SUCCESS != err) {
        ERRORF(reporter, "Failed to import semaphore, err: %d", err);
        return false;
    }

    GrBackendSemaphore beSemaphore;
    beSemaphore.initVulkan(semaphore);
    if (!surface->wait(1, &beSemaphore)) {
        ERRORF(reporter, "Failed to add wait semaphore to surface");
        fVkDestroySemaphore(fDevice, semaphore, nullptr);
        return false;
    }
    return true;
}

sk_sp<SkSurface> VulkanTestHelper::importHardwareBufferForWrite(skiatest::Reporter* reporter,
                                                                AHardwareBuffer* buffer) {
    GrVkImageInfo imageInfo;
    if (!this->importHardwareBuffer(reporter, buffer, true, &imageInfo)) {
        return nullptr;
    }

    GrBackendTexture backendTex(DEV_W, DEV_H, imageInfo);

    sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(fGrContext.get(),
                                                                 backendTex,
                                                                 kTopLeft_GrSurfaceOrigin,
                                                                 0,
                                                                 kRGBA_8888_SkColorType,
                                                                 nullptr, nullptr);

    if (!surface.get()) {
        ERRORF(reporter, "Failed to create wrapped Vulkan SkSurface");
        return nullptr;
    }

    return surface;
}

static SkPMColor get_src_color(int x, int y) {
    SkASSERT(x >= 0 && x < DEV_W);
    SkASSERT(y >= 0 && y < DEV_H);

    U8CPU r = x;
    U8CPU g = y;
    U8CPU b = 0xc;

    U8CPU a = 0xff;
    switch ((x+y) % 5) {
        case 0:
            a = 0xff;
            break;
        case 1:
            a = 0x80;
            break;
        case 2:
            a = 0xCC;
            break;
        case 4:
            a = 0x01;
            break;
        case 3:
            a = 0x00;
            break;
    }
    a = 0xff;
    return SkPremultiplyARGBInline(a, r, g, b);
}

static SkBitmap make_src_bitmap() {
    static SkBitmap bmp;
    if (bmp.isNull()) {
        bmp.allocN32Pixels(DEV_W, DEV_H);
        intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels());
        for (int y = 0; y < DEV_H; ++y) {
            for (int x = 0; x < DEV_W; ++x) {
                SkPMColor* pixel = reinterpret_cast<SkPMColor*>(
                        pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel());
                *pixel = get_src_color(x, y);
            }
        }
    }
    return bmp;
}

static bool check_read(skiatest::Reporter* reporter, const SkBitmap& srcBitmap,
                       const SkBitmap& dstBitmap) {
    bool result = true;
    for (int y = 0; y < DEV_H && result; ++y) {
        for (int x = 0; x < DEV_W && result; ++x) {
            const uint32_t srcPixel = *srcBitmap.getAddr32(x, y);
            const uint32_t dstPixel = *dstBitmap.getAddr32(x, y);
            if (srcPixel != dstPixel) {
                ERRORF(reporter, "Expected readback pixel (%d, %d) value 0x%08x, got 0x%08x.",
                       x, y,  srcPixel, dstPixel);
                result = false;
            } /*else {
                ERRORF(reporter, "Got good readback pixel (%d, %d) value 0x%08x, got 0x%08x.",
                       x, y,  srcPixel, dstPixel);

            }*/
        }
    }
    return result;
}

static void cleanup_resources(BaseTestHelper* srcHelper, BaseTestHelper* dstHelper,
                              AHardwareBuffer* buffer) {
    if (srcHelper) {
        srcHelper->cleanup();
    }
    if (dstHelper) {
        dstHelper->cleanup();
    }
    if (buffer) {
        AHardwareBuffer_release(buffer);
    }
}

enum class SrcType {
    kCPU,
    kEGL,
    kVulkan,
};

enum class DstType {
    kEGL,
    kVulkan,
};

void run_test(skiatest::Reporter* reporter, const GrContextOptions& options,
              SrcType srcType, DstType dstType, bool shareSyncs) {
    if (SrcType::kCPU == srcType && shareSyncs) {
        // We don't currently test this since we don't do any syncs in this case.
        return;
    }
    std::unique_ptr<BaseTestHelper> srcHelper;
    std::unique_ptr<BaseTestHelper> dstHelper;
    AHardwareBuffer* buffer = nullptr;
    if (SrcType::kVulkan == srcType) {
        srcHelper.reset(new VulkanTestHelper());
    } else if (SrcType::kEGL == srcType) {
        srcHelper.reset(new EGLTestHelper(options));
    }
    if (srcHelper) {
        if (!srcHelper->init(reporter)) {
            cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
            return;
        }
    }

    if (DstType::kVulkan == dstType) {
        dstHelper.reset(new VulkanTestHelper());
    } else {
        SkASSERT(DstType::kEGL == dstType);
        dstHelper.reset(new EGLTestHelper(options));
    }
    if (dstHelper) {
        if (!dstHelper->init(reporter)) {
            cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
            return;
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Setup SkBitmaps
    ///////////////////////////////////////////////////////////////////////////

    SkBitmap srcBitmap = make_src_bitmap();
    SkBitmap dstBitmapSurface;
    dstBitmapSurface.allocN32Pixels(DEV_W, DEV_H);
    SkBitmap dstBitmapFinal;
    dstBitmapFinal.allocN32Pixels(DEV_W, DEV_H);

    ///////////////////////////////////////////////////////////////////////////
    // Setup AHardwareBuffer
    ///////////////////////////////////////////////////////////////////////////

    AHardwareBuffer_Desc hwbDesc;
    hwbDesc.width = DEV_W;
    hwbDesc.height = DEV_H;
    hwbDesc.layers = 1;
    if (SrcType::kCPU == srcType) {
        hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
                        AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
                        AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
    } else {
        hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
                        AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
                        AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
                        AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
    }
    hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
    // The following three are not used in the allocate
    hwbDesc.stride = 0;
    hwbDesc.rfu0= 0;
    hwbDesc.rfu1= 0;

    if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
        ERRORF(reporter, "Failed to allocated hardware buffer, error: %d", error);
        cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
        return;
    }

    if (SrcType::kCPU == srcType) {
        // Get actual desc for allocated buffer so we know the stride for uploading cpu data.
        AHardwareBuffer_describe(buffer, &hwbDesc);

        uint32_t* bufferAddr;
        if (AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, nullptr,
                                 reinterpret_cast<void**>(&bufferAddr))) {
            ERRORF(reporter, "Failed to lock hardware buffer");
            cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
            return;
        }

        int bbp = srcBitmap.bytesPerPixel();
        uint32_t* src = (uint32_t*)srcBitmap.getPixels();
        uint32_t* dst = bufferAddr;
        for (int y = 0; y < DEV_H; ++y) {
            memcpy(dst, src, DEV_W * bbp);
            src += DEV_W;
            dst += hwbDesc.stride;
        }

        for (int y = 0; y < DEV_H; ++y) {
            for (int x = 0; x < DEV_W; ++x) {
                const uint32_t srcPixel = *srcBitmap.getAddr32(x, y);
                uint32_t dstPixel = bufferAddr[y * hwbDesc.stride + x];
                if (srcPixel != dstPixel) {
                    ERRORF(reporter, "CPU HWB Expected readpix (%d, %d) value 0x%08x, got 0x%08x.",
                           x, y, srcPixel, dstPixel);
                }
            }
        }

        AHardwareBuffer_unlock(buffer, nullptr);

    } else {
        srcHelper->makeCurrent();
        sk_sp<SkSurface> surface = srcHelper->importHardwareBufferForWrite(reporter, buffer);

        if (!surface) {
            cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
            return;
        }

        sk_sp<SkImage> srcBmpImage = SkImage::MakeFromBitmap(srcBitmap);
        surface->getCanvas()->drawImage(srcBmpImage, 0, 0);

        // If we are testing sharing of syncs, don't do a read here since it forces sychronization
        // to occur.
        if (!shareSyncs) {
            bool readResult = surface->readPixels(dstBitmapSurface, 0, 0);
            if (!readResult) {
                ERRORF(reporter, "Read Pixels on surface failed");
                surface.reset();
                cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
                return;
            }
            REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, dstBitmapSurface));
        }

        ///////////////////////////////////////////////////////////////////////////
        // Cleanup GL/EGL and add syncs
        ///////////////////////////////////////////////////////////////////////////

        if (shareSyncs) {
            if (!srcHelper->flushSurfaceAndSignalSemaphore(reporter, std::move(surface))) {
                cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
                return;
            }
        } else {
            surface.reset();
            srcHelper->doClientSync();
            srcHelper->releaseImage();
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Import the HWB into backend and draw it to a surface
    ///////////////////////////////////////////////////////////////////////////

    dstHelper->makeCurrent();
    sk_sp<SkImage> wrappedImage = dstHelper->importHardwareBufferForRead(reporter, buffer);
    if (!wrappedImage) {
        cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
        return;
    }

    GrContext* grContext = dstHelper->grContext();

    // Make SkSurface to render wrapped HWB into.
    SkImageInfo imageInfo = SkImageInfo::Make(DEV_W, DEV_H, kRGBA_8888_SkColorType,
                                              kPremul_SkAlphaType, nullptr);

    sk_sp<SkSurface> dstSurf = SkSurface::MakeRenderTarget(grContext,
                                                           SkBudgeted::kNo, imageInfo, 0,
                                                           kTopLeft_GrSurfaceOrigin,
                                                           nullptr, false);
    if (!dstSurf.get()) {
        ERRORF(reporter, "Failed to create destination SkSurface");
        wrappedImage.reset();
        cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
        return;
    }

    if (shareSyncs) {
        if (!dstHelper->importAndWaitOnSemaphore(reporter, srcHelper->getFdHandle(), dstSurf)) {
            wrappedImage.reset();
            cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
            return;
        }
    }
    dstSurf->getCanvas()->drawImage(wrappedImage, 0, 0);

    bool readResult = dstSurf->readPixels(dstBitmapFinal, 0, 0);
    if (!readResult) {
        ERRORF(reporter, "Read Pixels failed");
        wrappedImage.reset();
        dstHelper->doClientSync();
        cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
        return;
    }

    REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, dstBitmapFinal));

    wrappedImage.reset();
    dstHelper->doClientSync();
    cleanup_resources(srcHelper.get(), dstHelper.get(), buffer);
}

DEF_GPUTEST(VulkanHardwareBuffer_CPU_Vulkan, reporter, options) {
    run_test(reporter, options, SrcType::kCPU, DstType::kVulkan, false);
}

DEF_GPUTEST(VulkanHardwareBuffer_EGL_Vulkan, reporter, options) {
    run_test(reporter, options, SrcType::kEGL, DstType::kVulkan, false);
}

DEF_GPUTEST(VulkanHardwareBuffer_Vulkan_Vulkan, reporter, options) {
    run_test(reporter, options, SrcType::kVulkan, DstType::kVulkan, false);
}

DEF_GPUTEST(VulkanHardwareBuffer_CPU_EGL, reporter, options) {
    run_test(reporter, options, SrcType::kCPU, DstType::kEGL, false);
}

DEF_GPUTEST(VulkanHardwareBuffer_EGL_EGL, reporter, options) {
    run_test(reporter, options, SrcType::kEGL, DstType::kEGL, false);
}

DEF_GPUTEST(VulkanHardwareBuffer_Vulkan_EGL, reporter, options) {
    run_test(reporter, options, SrcType::kVulkan, DstType::kEGL, false);
}

DEF_GPUTEST(VulkanHardwareBuffer_EGL_EGL_Syncs, reporter, options) {
    run_test(reporter, options, SrcType::kEGL, DstType::kEGL, true);
}

DEF_GPUTEST(VulkanHardwareBuffer_Vulkan_EGL_Syncs, reporter, options) {
    run_test(reporter, options, SrcType::kVulkan, DstType::kEGL, true);
}

DEF_GPUTEST(VulkanHardwareBuffer_EGL_Vulkan_Syncs, reporter, options) {
    run_test(reporter, options, SrcType::kEGL, DstType::kVulkan, true);
}

DEF_GPUTEST(VulkanHardwareBuffer_Vulkan_Vulkan_Syncs, reporter, options) {
    run_test(reporter, options, SrcType::kVulkan, DstType::kVulkan, true);
}

#endif
#endif

