// Copyright 2018 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn/native/Instance.h"

#include <utility>

#include "dawn/common/Assert.h"
#include "dawn/common/GPUInfo.h"
#include "dawn/common/Log.h"
#include "dawn/common/SystemUtils.h"
#include "dawn/native/ChainUtils_autogen.h"
#include "dawn/native/ErrorData.h"
#include "dawn/native/Surface.h"
#include "dawn/native/ValidationUtils_autogen.h"
#include "dawn/platform/DawnPlatform.h"

// For SwiftShader fallback
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
#include "dawn/native/VulkanBackend.h"
#endif  // defined(DAWN_ENABLE_BACKEND_VULKAN)

#if defined(DAWN_USE_X11)
#include "dawn/native/XlibXcbFunctions.h"
#endif  // defined(DAWN_USE_X11)

#include <optional>

namespace dawn::native {

// Forward definitions of each backend's "Connect" function that creates new BackendConnection.
// Conditionally compiled declarations are used to avoid using static constructors instead.
#if defined(DAWN_ENABLE_BACKEND_D3D12)
namespace d3d12 {
BackendConnection* Connect(InstanceBase* instance);
}
#endif  // defined(DAWN_ENABLE_BACKEND_D3D12)
#if defined(DAWN_ENABLE_BACKEND_METAL)
namespace metal {
BackendConnection* Connect(InstanceBase* instance);
}
#endif  // defined(DAWN_ENABLE_BACKEND_METAL)
#if defined(DAWN_ENABLE_BACKEND_NULL)
namespace null {
BackendConnection* Connect(InstanceBase* instance);
}
#endif  // defined(DAWN_ENABLE_BACKEND_NULL)
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
namespace opengl {
BackendConnection* Connect(InstanceBase* instance, wgpu::BackendType backendType);
}
#endif  // defined(DAWN_ENABLE_BACKEND_OPENGL)
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
namespace vulkan {
BackendConnection* Connect(InstanceBase* instance);
}
#endif  // defined(DAWN_ENABLE_BACKEND_VULKAN)

namespace {

BackendsBitset GetEnabledBackends() {
    BackendsBitset enabledBackends;
#if defined(DAWN_ENABLE_BACKEND_NULL)
    enabledBackends.set(wgpu::BackendType::Null);
#endif  // defined(DAWN_ENABLE_BACKEND_NULL)
#if defined(DAWN_ENABLE_BACKEND_D3D12)
    enabledBackends.set(wgpu::BackendType::D3D12);
#endif  // defined(DAWN_ENABLE_BACKEND_D3D12)
#if defined(DAWN_ENABLE_BACKEND_METAL)
    enabledBackends.set(wgpu::BackendType::Metal);
#endif  // defined(DAWN_ENABLE_BACKEND_METAL)
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
    enabledBackends.set(wgpu::BackendType::Vulkan);
#endif  // defined(DAWN_ENABLE_BACKEND_VULKAN)
#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
    enabledBackends.set(wgpu::BackendType::OpenGL);
#endif  // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
#if defined(DAWN_ENABLE_BACKEND_OPENGLES)
    enabledBackends.set(wgpu::BackendType::OpenGLES);
#endif  // defined(DAWN_ENABLE_BACKEND_OPENGLES)

    return enabledBackends;
}

dawn::platform::CachingInterface* GetCachingInterface(dawn::platform::Platform* platform) {
    if (platform != nullptr) {
        return platform->GetCachingInterface(/*fingerprint*/ nullptr,
                                             /*fingerprintSize*/ 0);
    }
    return nullptr;
}

}  // anonymous namespace

InstanceBase* APICreateInstance(const InstanceDescriptor* descriptor) {
    return InstanceBase::Create().Detach();
}

// InstanceBase

// static
Ref<InstanceBase> InstanceBase::Create(const InstanceDescriptor* descriptor) {
    Ref<InstanceBase> instance = AcquireRef(new InstanceBase);
    static constexpr InstanceDescriptor kDefaultDesc = {};
    if (descriptor == nullptr) {
        descriptor = &kDefaultDesc;
    }
    if (instance->ConsumedError(instance->Initialize(descriptor))) {
        return nullptr;
    }
    return instance;
}

InstanceBase::InstanceBase() = default;

InstanceBase::~InstanceBase() = default;

// TODO(crbug.com/dawn/832): make the platform an initialization parameter of the instance.
MaybeError InstanceBase::Initialize(const InstanceDescriptor* descriptor) {
    DAWN_TRY(ValidateSingleSType(descriptor->nextInChain, wgpu::SType::DawnInstanceDescriptor));
    const DawnInstanceDescriptor* dawnDesc = nullptr;
    FindInChain(descriptor->nextInChain, &dawnDesc);
    if (dawnDesc != nullptr) {
        for (uint32_t i = 0; i < dawnDesc->additionalRuntimeSearchPathsCount; ++i) {
            mRuntimeSearchPaths.push_back(dawnDesc->additionalRuntimeSearchPaths[i]);
        }
    }
    // Default paths to search are next to the shared library, next to the executable, and
    // no path (just libvulkan.so).
    if (auto p = GetModuleDirectory()) {
        mRuntimeSearchPaths.push_back(std::move(*p));
    }
    if (auto p = GetExecutableDirectory()) {
        mRuntimeSearchPaths.push_back(std::move(*p));
    }
    mRuntimeSearchPaths.push_back("");

    // Initialize the platform to the default for now.
    mDefaultPlatform = std::make_unique<dawn::platform::Platform>();
    SetPlatform(mDefaultPlatform.get());

    return {};
}

void InstanceBase::APIRequestAdapter(const RequestAdapterOptions* options,
                                     WGPURequestAdapterCallback callback,
                                     void* userdata) {
    static constexpr RequestAdapterOptions kDefaultOptions = {};
    if (options == nullptr) {
        options = &kDefaultOptions;
    }
    auto result = RequestAdapterInternal(options);
    if (result.IsError()) {
        auto err = result.AcquireError();
        std::string msg = err->GetFormattedMessage();
        // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
        callback(WGPURequestAdapterStatus_Error, nullptr, msg.c_str(), userdata);
    } else {
        Ref<AdapterBase> adapter = result.AcquireSuccess();
        // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
        callback(WGPURequestAdapterStatus_Success, ToAPI(adapter.Detach()), nullptr, userdata);
    }
}

ResultOrError<Ref<AdapterBase>> InstanceBase::RequestAdapterInternal(
    const RequestAdapterOptions* options) {
    ASSERT(options != nullptr);
    if (options->forceFallbackAdapter) {
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
        if (GetEnabledBackends()[wgpu::BackendType::Vulkan]) {
            dawn_native::vulkan::AdapterDiscoveryOptions vulkanOptions;
            vulkanOptions.forceSwiftShader = true;
            DAWN_TRY(DiscoverAdaptersInternal(&vulkanOptions));
        }
#else
        return Ref<AdapterBase>(nullptr);
#endif  // defined(DAWN_ENABLE_BACKEND_VULKAN)
    } else {
        DiscoverDefaultAdapters();
    }

    wgpu::AdapterType preferredType;
    switch (options->powerPreference) {
        case wgpu::PowerPreference::LowPower:
            preferredType = wgpu::AdapterType::IntegratedGPU;
            break;
        case wgpu::PowerPreference::Undefined:
        case wgpu::PowerPreference::HighPerformance:
            preferredType = wgpu::AdapterType::DiscreteGPU;
            break;
    }

    std::optional<size_t> discreteGPUAdapterIndex;
    std::optional<size_t> integratedGPUAdapterIndex;
    std::optional<size_t> cpuAdapterIndex;
    std::optional<size_t> unknownAdapterIndex;

    for (size_t i = 0; i < mAdapters.size(); ++i) {
        AdapterProperties properties;
        mAdapters[i]->APIGetProperties(&properties);

        if (options->forceFallbackAdapter) {
            if (!gpu_info::IsSwiftshader(properties.vendorID, properties.deviceID)) {
                continue;
            }
            return mAdapters[i];
        }
        if (properties.adapterType == preferredType) {
            return mAdapters[i];
        }
        switch (properties.adapterType) {
            case wgpu::AdapterType::DiscreteGPU:
                discreteGPUAdapterIndex = i;
                break;
            case wgpu::AdapterType::IntegratedGPU:
                integratedGPUAdapterIndex = i;
                break;
            case wgpu::AdapterType::CPU:
                cpuAdapterIndex = i;
                break;
            case wgpu::AdapterType::Unknown:
                unknownAdapterIndex = i;
                break;
        }
    }

    // For now, we always prefer the discrete GPU
    if (discreteGPUAdapterIndex) {
        return mAdapters[*discreteGPUAdapterIndex];
    }
    if (integratedGPUAdapterIndex) {
        return mAdapters[*integratedGPUAdapterIndex];
    }
    if (cpuAdapterIndex) {
        return mAdapters[*cpuAdapterIndex];
    }
    if (unknownAdapterIndex) {
        return mAdapters[*unknownAdapterIndex];
    }

    return Ref<AdapterBase>(nullptr);
}

void InstanceBase::DiscoverDefaultAdapters() {
    for (wgpu::BackendType b : IterateBitSet(GetEnabledBackends())) {
        EnsureBackendConnection(b);
    }

    if (mDiscoveredDefaultAdapters) {
        return;
    }

    // Query and merge all default adapters for all backends
    for (std::unique_ptr<BackendConnection>& backend : mBackends) {
        std::vector<Ref<AdapterBase>> backendAdapters = backend->DiscoverDefaultAdapters();

        for (Ref<AdapterBase>& adapter : backendAdapters) {
            ASSERT(adapter->GetBackendType() == backend->GetType());
            ASSERT(adapter->GetInstance() == this);
            mAdapters.push_back(std::move(adapter));
        }
    }

    mDiscoveredDefaultAdapters = true;
}

// This is just a wrapper around the real logic that uses Error.h error handling.
bool InstanceBase::DiscoverAdapters(const AdapterDiscoveryOptionsBase* options) {
    return !ConsumedError(DiscoverAdaptersInternal(options));
}

const ToggleInfo* InstanceBase::GetToggleInfo(const char* toggleName) {
    return mTogglesInfo.GetToggleInfo(toggleName);
}

Toggle InstanceBase::ToggleNameToEnum(const char* toggleName) {
    return mTogglesInfo.ToggleNameToEnum(toggleName);
}

const FeatureInfo* InstanceBase::GetFeatureInfo(wgpu::FeatureName feature) {
    return mFeaturesInfo.GetFeatureInfo(feature);
}

const std::vector<Ref<AdapterBase>>& InstanceBase::GetAdapters() const {
    return mAdapters;
}

void InstanceBase::EnsureBackendConnection(wgpu::BackendType backendType) {
    if (mBackendsConnected[backendType]) {
        return;
    }

    auto Register = [this](BackendConnection* connection, wgpu::BackendType expectedType) {
        if (connection != nullptr) {
            ASSERT(connection->GetType() == expectedType);
            ASSERT(connection->GetInstance() == this);
            mBackends.push_back(std::unique_ptr<BackendConnection>(connection));
        }
    };

    switch (backendType) {
#if defined(DAWN_ENABLE_BACKEND_NULL)
        case wgpu::BackendType::Null:
            Register(null::Connect(this), wgpu::BackendType::Null);
            break;
#endif  // defined(DAWN_ENABLE_BACKEND_NULL)

#if defined(DAWN_ENABLE_BACKEND_D3D12)
        case wgpu::BackendType::D3D12:
            Register(d3d12::Connect(this), wgpu::BackendType::D3D12);
            break;
#endif  // defined(DAWN_ENABLE_BACKEND_D3D12)

#if defined(DAWN_ENABLE_BACKEND_METAL)
        case wgpu::BackendType::Metal:
            Register(metal::Connect(this), wgpu::BackendType::Metal);
            break;
#endif  // defined(DAWN_ENABLE_BACKEND_METAL)

#if defined(DAWN_ENABLE_BACKEND_VULKAN)
        case wgpu::BackendType::Vulkan:
            Register(vulkan::Connect(this), wgpu::BackendType::Vulkan);
            break;
#endif  // defined(DAWN_ENABLE_BACKEND_VULKAN)

#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
        case wgpu::BackendType::OpenGL:
            Register(opengl::Connect(this, wgpu::BackendType::OpenGL), wgpu::BackendType::OpenGL);
            break;
#endif  // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)

#if defined(DAWN_ENABLE_BACKEND_OPENGLES)
        case wgpu::BackendType::OpenGLES:
            Register(opengl::Connect(this, wgpu::BackendType::OpenGLES),
                     wgpu::BackendType::OpenGLES);
            break;
#endif  // defined(DAWN_ENABLE_BACKEND_OPENGLES)

        default:
            UNREACHABLE();
    }

    mBackendsConnected.set(backendType);
}

MaybeError InstanceBase::DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options) {
    wgpu::BackendType backendType = static_cast<wgpu::BackendType>(options->backendType);
    DAWN_TRY(ValidateBackendType(backendType));

    if (!GetEnabledBackends()[backendType]) {
        return DAWN_FORMAT_VALIDATION_ERROR("%s not supported.", backendType);
    }

    EnsureBackendConnection(backendType);

    bool foundBackend = false;
    for (std::unique_ptr<BackendConnection>& backend : mBackends) {
        if (backend->GetType() != backendType) {
            continue;
        }
        foundBackend = true;

        std::vector<Ref<AdapterBase>> newAdapters;
        DAWN_TRY_ASSIGN(newAdapters, backend->DiscoverAdapters(options));

        for (Ref<AdapterBase>& adapter : newAdapters) {
            ASSERT(adapter->GetBackendType() == backend->GetType());
            ASSERT(adapter->GetInstance() == this);
            mAdapters.push_back(std::move(adapter));
        }
    }

    DAWN_INVALID_IF(!foundBackend, "%s not available.", backendType);
    return {};
}

bool InstanceBase::ConsumedError(MaybeError maybeError) {
    if (maybeError.IsError()) {
        std::unique_ptr<ErrorData> error = maybeError.AcquireError();

        ASSERT(error != nullptr);
        dawn::ErrorLog() << error->GetFormattedMessage();
        return true;
    }
    return false;
}

bool InstanceBase::IsBackendValidationEnabled() const {
    return mBackendValidationLevel != BackendValidationLevel::Disabled;
}

void InstanceBase::SetBackendValidationLevel(BackendValidationLevel level) {
    mBackendValidationLevel = level;
}

BackendValidationLevel InstanceBase::GetBackendValidationLevel() const {
    return mBackendValidationLevel;
}

void InstanceBase::EnableBeginCaptureOnStartup(bool beginCaptureOnStartup) {
    mBeginCaptureOnStartup = beginCaptureOnStartup;
}

bool InstanceBase::IsBeginCaptureOnStartupEnabled() const {
    return mBeginCaptureOnStartup;
}

void InstanceBase::SetPlatform(dawn::platform::Platform* platform) {
    if (platform == nullptr) {
        mPlatform = mDefaultPlatform.get();
    } else {
        mPlatform = platform;
    }
    mBlobCache = std::make_unique<BlobCache>(GetCachingInterface(platform));
}

void InstanceBase::SetPlatformForTesting(dawn::platform::Platform* platform) {
    SetPlatform(platform);
}

dawn::platform::Platform* InstanceBase::GetPlatform() {
    return mPlatform;
}

BlobCache* InstanceBase::GetBlobCache() {
    return mBlobCache.get();
}

uint64_t InstanceBase::GetDeviceCountForTesting() const {
    return mDeviceCountForTesting.load();
}

void InstanceBase::IncrementDeviceCountForTesting() {
    mDeviceCountForTesting++;
}

void InstanceBase::DecrementDeviceCountForTesting() {
    mDeviceCountForTesting--;
}

const std::vector<std::string>& InstanceBase::GetRuntimeSearchPaths() const {
    return mRuntimeSearchPaths;
}

const XlibXcbFunctions* InstanceBase::GetOrCreateXlibXcbFunctions() {
#if defined(DAWN_USE_X11)
    if (mXlibXcbFunctions == nullptr) {
        mXlibXcbFunctions = std::make_unique<XlibXcbFunctions>();
    }
    return mXlibXcbFunctions.get();
#else
    UNREACHABLE();
#endif  // defined(DAWN_USE_X11)
}

Surface* InstanceBase::APICreateSurface(const SurfaceDescriptor* descriptor) {
    if (ConsumedError(ValidateSurfaceDescriptor(this, descriptor))) {
        return nullptr;
    }

    return new Surface(this, descriptor);
}

}  // namespace dawn::native
