// Copyright 2019 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.

// D3D12Backend.cpp: contains the definition of symbols exported by D3D12Backend.h so that they
// can be compiled twice: once export (shared library), once not exported (static library)

#include "dawn_native/D3D12Backend.h"

#include "common/Log.h"
#include "common/Math.h"
#include "common/SwapChainUtils.h"
#include "dawn_native/d3d12/D3D11on12Util.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/NativeSwapChainImplD3D12.h"
#include "dawn_native/d3d12/ResidencyManagerD3D12.h"
#include "dawn_native/d3d12/TextureD3D12.h"

namespace dawn_native::d3d12 {

    ComPtr<ID3D12Device> GetD3D12Device(WGPUDevice device) {
        return ToBackend(FromAPI(device))->GetD3D12Device();
    }

    DawnSwapChainImplementation CreateNativeSwapChainImpl(WGPUDevice device, HWND window) {
        Device* backendDevice = ToBackend(FromAPI(device));

        DawnSwapChainImplementation impl;
        impl = CreateSwapChainImplementation(new NativeSwapChainImpl(backendDevice, window));
        impl.textureUsage = WGPUTextureUsage_Present;

        return impl;
    }

    WGPUTextureFormat GetNativeSwapChainPreferredFormat(
        const DawnSwapChainImplementation* swapChain) {
        NativeSwapChainImpl* impl = reinterpret_cast<NativeSwapChainImpl*>(swapChain->userData);
        return static_cast<WGPUTextureFormat>(impl->GetPreferredFormat());
    }

    ExternalImageDescriptorDXGISharedHandle::ExternalImageDescriptorDXGISharedHandle()
        : ExternalImageDescriptor(ExternalImageType::DXGISharedHandle) {
    }

    ExternalImageDXGI::ExternalImageDXGI(ComPtr<ID3D12Resource> d3d12Resource,
                                         const WGPUTextureDescriptor* descriptor)
        : mD3D12Resource(std::move(d3d12Resource)),
          mUsage(descriptor->usage),
          mDimension(descriptor->dimension),
          mSize(descriptor->size),
          mFormat(descriptor->format),
          mMipLevelCount(descriptor->mipLevelCount),
          mSampleCount(descriptor->sampleCount) {
        ASSERT(!descriptor->nextInChain ||
               descriptor->nextInChain->sType == WGPUSType_DawnTextureInternalUsageDescriptor);
        if (descriptor->nextInChain) {
            mUsageInternal = reinterpret_cast<const WGPUDawnTextureInternalUsageDescriptor*>(
                                 descriptor->nextInChain)
                                 ->internalUsage;
        }
        mD3D11on12ResourceCache = std::make_unique<D3D11on12ResourceCache>();
    }

    ExternalImageDXGI::~ExternalImageDXGI() = default;

    WGPUTexture ExternalImageDXGI::ProduceTexture(
        WGPUDevice device,
        const ExternalImageAccessDescriptorDXGIKeyedMutex* descriptor) {
        Device* backendDevice = ToBackend(FromAPI(device));

        // Ensure the texture usage is allowed
        if (!IsSubset(descriptor->usage, mUsage)) {
            dawn::ErrorLog() << "Texture usage is not valid for external image";
            return nullptr;
        }

        TextureDescriptor textureDescriptor = {};
        textureDescriptor.usage = static_cast<wgpu::TextureUsage>(descriptor->usage);
        textureDescriptor.dimension = static_cast<wgpu::TextureDimension>(mDimension);
        textureDescriptor.size = {mSize.width, mSize.height, mSize.depthOrArrayLayers};
        textureDescriptor.format = static_cast<wgpu::TextureFormat>(mFormat);
        textureDescriptor.mipLevelCount = mMipLevelCount;
        textureDescriptor.sampleCount = mSampleCount;

        DawnTextureInternalUsageDescriptor internalDesc = {};
        if (mUsageInternal) {
            textureDescriptor.nextInChain = &internalDesc;
            internalDesc.internalUsage = static_cast<wgpu::TextureUsage>(mUsageInternal);
            internalDesc.sType = wgpu::SType::DawnTextureInternalUsageDescriptor;
        }

        Ref<D3D11on12ResourceCacheEntry> d3d11on12Resource =
            mD3D11on12ResourceCache->GetOrCreateD3D11on12Resource(device, mD3D12Resource.Get());
        if (d3d11on12Resource == nullptr) {
            dawn::ErrorLog() << "Unable to create 11on12 resource for external image";
            return nullptr;
        }

        Ref<TextureBase> texture = backendDevice->CreateExternalTexture(
            &textureDescriptor, mD3D12Resource, std::move(d3d11on12Resource),
            ExternalMutexSerial(descriptor->acquireMutexKey),
            ExternalMutexSerial(descriptor->releaseMutexKey), descriptor->isSwapChainTexture,
            descriptor->isInitialized);

        return ToAPI(texture.Detach());
    }

    // static
    std::unique_ptr<ExternalImageDXGI> ExternalImageDXGI::Create(
        WGPUDevice device,
        const ExternalImageDescriptorDXGISharedHandle* descriptor) {
        Device* backendDevice = ToBackend(FromAPI(device));

        Microsoft::WRL::ComPtr<ID3D12Resource> d3d12Resource;
        if (FAILED(backendDevice->GetD3D12Device()->OpenSharedHandle(
                descriptor->sharedHandle, IID_PPV_ARGS(&d3d12Resource)))) {
            return nullptr;
        }

        const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);

        if (backendDevice->ConsumedError(
                ValidateTextureDescriptor(backendDevice, textureDescriptor))) {
            return nullptr;
        }

        if (backendDevice->ConsumedError(
                ValidateTextureDescriptorCanBeWrapped(textureDescriptor),
                "validating that a D3D12 external image can be wrapped with %s",
                textureDescriptor)) {
            return nullptr;
        }

        if (backendDevice->ConsumedError(
                ValidateD3D12TextureCanBeWrapped(d3d12Resource.Get(), textureDescriptor))) {
            return nullptr;
        }

        // Shared handle is assumed to support resource sharing capability. The resource
        // shared capability tier must agree to share resources between D3D devices.
        const Format* format =
            backendDevice->GetInternalFormat(textureDescriptor->format).AcquireSuccess();
        if (format->IsMultiPlanar()) {
            if (backendDevice->ConsumedError(ValidateD3D12VideoTextureCanBeShared(
                    backendDevice, D3D12TextureFormat(textureDescriptor->format)))) {
                return nullptr;
            }
        }

        std::unique_ptr<ExternalImageDXGI> result(
            new ExternalImageDXGI(std::move(d3d12Resource), descriptor->cTextureDescriptor));
        return result;
    }

    uint64_t SetExternalMemoryReservation(WGPUDevice device,
                                          uint64_t requestedReservationSize,
                                          MemorySegment memorySegment) {
        Device* backendDevice = ToBackend(FromAPI(device));

        return backendDevice->GetResidencyManager()->SetExternalMemoryReservation(
            memorySegment, requestedReservationSize);
    }

    AdapterDiscoveryOptions::AdapterDiscoveryOptions()
        : AdapterDiscoveryOptionsBase(WGPUBackendType_D3D12), dxgiAdapter(nullptr) {
    }

    AdapterDiscoveryOptions::AdapterDiscoveryOptions(ComPtr<IDXGIAdapter> adapter)
        : AdapterDiscoveryOptionsBase(WGPUBackendType_D3D12), dxgiAdapter(std::move(adapter)) {
    }
}  // namespace dawn_native::d3d12
