// 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 "common/Assert.h"
#include "common/GPUInfo.h"
#include "common/Log.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;
        }

    }  // anonymous namespace

    // InstanceBase

    // static
    InstanceBase* InstanceBase::Create(const InstanceDescriptor* descriptor) {
        Ref<InstanceBase> instance = AcquireRef(new InstanceBase);
        if (!instance->Initialize(descriptor)) {
            return nullptr;
        }
        return instance.Detach();
    }

    // TODO(crbug.com/dawn/832): make the platform an initialization parameter of the instance.
    bool InstanceBase::Initialize(const InstanceDescriptor*) {
        return true;
    }

    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::InfoLog() << 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) {
        mPlatform = platform;
    }

    dawn::platform::Platform* InstanceBase::GetPlatform() {
        if (mPlatform != nullptr) {
            return mPlatform;
        }

        if (mDefaultPlatform == nullptr) {
            mDefaultPlatform = std::make_unique<dawn::platform::Platform>();
        }
        return mDefaultPlatform.get();
    }

    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
