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

#include "dawn/dawncpp.h"
#include "dawn_native/DawnNative.h"
#include "tools/gpu/dawn/DawnTestContext.h"

#ifdef SK_BUILD_FOR_UNIX
#include "GL/glx.h"
#endif

#ifdef SK_BUILD_FOR_WIN
#include <windows.h>
#endif

#define USE_OPENGL_BACKEND 0

#ifdef SK_DAWN
#include "dawn/dawn.h"
#include "dawn/dawn_proc.h"
#include "include/gpu/GrContext.h"
#include "tools/AutoreleasePool.h"
#if USE_OPENGL_BACKEND
#include "dawn_native/OpenGLBackend.h"
#endif

#if defined(SK_BUILD_FOR_MAC) && USE_OPENGL_BACKEND
#include <dlfcn.h>
static void* getProcAddressMacOS(const char* procName) {
    return dlsym(RTLD_DEFAULT, procName);
}
#endif

namespace {

#ifdef SK_BUILD_FOR_WIN
class ProcGetter {
public:
    typedef void(*Proc)();

    ProcGetter()
      : fModule(LoadLibraryA("opengl32.dll")) {
        SkASSERT(!fInstance);
        fInstance = this;
    }

    ~ProcGetter() {
        if (fModule) {
            FreeLibrary(fModule);
        }
        fInstance = nullptr;
    }

    static void* getProcAddress(const char* name) {
        return fInstance->getProc(name);
    }

private:
    Proc getProc(const char* name) {
        PROC proc;
        if (proc = GetProcAddress(fModule, name)) {
            return (Proc) proc;
        }
        if (proc = wglGetProcAddress(name)) {
            return (Proc) proc;
        }
        return nullptr;
    }

    HMODULE fModule;
    static ProcGetter* fInstance;
};

ProcGetter* ProcGetter::fInstance;
#endif

class DawnFence {
public:
    DawnFence(const dawn::Device& device, const dawn::Buffer& buffer)
      : fDevice(device), fBuffer(buffer), fCalled(false) {
        fBuffer.MapReadAsync(callback, this);
    }

    bool wait() {
        while (!fCalled) {
            fDevice.Tick();
        }
        return true;
    }

    ~DawnFence() {
    }

    static void callback(DawnBufferMapAsyncStatus status, const void* data, uint64_t dataLength,
                         void* userData) {
        DawnFence* fence = static_cast<DawnFence*>(userData);
        fence->fCalled = true;
    }
    dawn::Buffer buffer() { return fBuffer; }

private:
    dawn::Device                   fDevice;
    dawn::Buffer                   fBuffer;
    bool                           fCalled;
};

/**
 * Implements sk_gpu_test::FenceSync for Dawn.
 */
class DawnFenceSync : public sk_gpu_test::FenceSync {
public:
    DawnFenceSync(dawn::Device device) : fDevice(device) {
    }

    ~DawnFenceSync() override {
    }

    sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override {
        dawn::Buffer buffer;
        if (fBuffers.empty()) {
            dawn::BufferDescriptor desc;
            desc.usage = dawn::BufferUsage::MapRead | dawn::BufferUsage::CopyDst;
            desc.size = 1;
            buffer = fDevice.CreateBuffer(&desc);
        } else {
            buffer = fBuffers.back();
            fBuffers.pop_back();
        }
        DawnFence* fence = new DawnFence(fDevice, buffer);
        return reinterpret_cast<sk_gpu_test::PlatformFence>(fence);
    }

    bool waitFence(sk_gpu_test::PlatformFence opaqueFence) const override {
        fAutoreleasePool.drain();
        DawnFence* fence = reinterpret_cast<DawnFence*>(opaqueFence);
        return fence->wait();
    }

    void deleteFence(sk_gpu_test::PlatformFence opaqueFence) const override {
        DawnFence* fence = reinterpret_cast<DawnFence*>(opaqueFence);
        fBuffers.push_back(fence->buffer());
        delete fence;
    }

private:
    dawn::Device                      fDevice;
    mutable std::vector<dawn::Buffer> fBuffers;
    mutable AutoreleasePool           fAutoreleasePool;
    typedef sk_gpu_test::FenceSync INHERITED;
};

class DawnTestContextImpl : public sk_gpu_test::DawnTestContext {
public:
    static dawn::Device createDevice(const dawn_native::Instance& instance,
                                     dawn_native::BackendType type) {
        DawnProcTable backendProcs = dawn_native::GetProcs();
        dawnProcSetProcs(&backendProcs);

        std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
        for (dawn_native::Adapter adapter : adapters) {
            if (adapter.GetBackendType() == type) {
                return adapter.CreateDevice();
            }
        }
        return nullptr;
    }

    static DawnTestContext* Create(DawnTestContext* sharedContext) {
        std::unique_ptr<dawn_native::Instance> instance = std::make_unique<dawn_native::Instance>();
        dawn::Device device;
        if (sharedContext) {
            device = sharedContext->getDevice();
        } else {
            dawn_native::BackendType type;
#if USE_OPENGL_BACKEND
            dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
            adapterOptions.getProc = reinterpret_cast<void*(*)(const char*)>(
#if defined(SK_BUILD_FOR_UNIX)
                glXGetProcAddress
#elif defined(SK_BUILD_FOR_MAC)
                getProcAddressMacOS
#elif defined(SK_BUILD_FOR_WIN)
                ProcGetter::getProcAddress
#endif
            );
            instance->DiscoverAdapters(&adapterOptions);
            type = dawn_native::BackendType::OpenGL;
#else
            instance->DiscoverDefaultAdapters();
#if defined(SK_BUILD_FOR_MAC)
            type = dawn_native::BackendType::Metal;
#elif defined(SK_BUILD_FOR_WIN)
            type = dawn_native::BackendType::D3D12;
#elif defined(SK_BUILD_FOR_UNIX)
            type = dawn_native::BackendType::Vulkan;
#endif
#endif
            device = createDevice(*instance, type);
        }
        if (!device) {
            return nullptr;
        }
        return new DawnTestContextImpl(std::move(instance), device);
    }

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

    void testAbandon() override {}

    // There is really nothing to here since we don't own any unqueued command buffers here.
    void submit() override {}

    void finish() override {}

    sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override {
        return GrContext::MakeDawn(fDevice, options);
    }

protected:
    void teardown() override {
        INHERITED::teardown();
    }

private:
    DawnTestContextImpl(std::unique_ptr<dawn_native::Instance> instance,
                        const dawn::Device& device)
            : DawnTestContext(device)
            , fInstance(std::move(instance)) {
        fFenceSync.reset(new DawnFenceSync(fDevice));
    }

    void onPlatformMakeCurrent() const override {}
    std::function<void()> onPlatformGetAutoContextRestore() const override  { return nullptr; }
    void onPlatformSwapBuffers() const override {}
    std::unique_ptr<dawn_native::Instance> fInstance;

    typedef sk_gpu_test::DawnTestContext INHERITED;
};
}  // anonymous namespace

namespace sk_gpu_test {
DawnTestContext* CreatePlatformDawnTestContext(DawnTestContext* sharedContext) {
    return DawnTestContextImpl::Create(sharedContext);
}
}  // namespace sk_gpu_test

#endif
