// Copyright 2017 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/d3d12/SwapChainD3D12.h"

#include "dawn_native/Surface.h"
#include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/TextureD3D12.h"

#include <dawn/dawn_wsi.h>

namespace dawn_native { namespace d3d12 {
    namespace {

        uint32_t PresentModeToBufferCount(wgpu::PresentMode mode) {
            switch (mode) {
                case wgpu::PresentMode::Immediate:
                case wgpu::PresentMode::Fifo:
                    return 2;
                case wgpu::PresentMode::Mailbox:
                    return 3;
            }
        }

        uint32_t PresentModeToSwapInterval(wgpu::PresentMode mode) {
            switch (mode) {
                case wgpu::PresentMode::Immediate:
                case wgpu::PresentMode::Mailbox:
                    return 0;
                case wgpu::PresentMode::Fifo:
                    return 1;
            }
        }

        UINT PresentModeToSwapChainFlags(wgpu::PresentMode mode) {
            UINT flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

            if (mode == wgpu::PresentMode::Immediate) {
                flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
            }

            return flags;
        }

        DXGI_USAGE ToDXGIUsage(wgpu::TextureUsage usage) {
            DXGI_USAGE dxgiUsage = DXGI_CPU_ACCESS_NONE;
            if (usage & wgpu::TextureUsage::Sampled) {
                dxgiUsage |= DXGI_USAGE_SHADER_INPUT;
            }
            if (usage & wgpu::TextureUsage::Storage) {
                dxgiUsage |= DXGI_USAGE_UNORDERED_ACCESS;
            }
            if (usage & wgpu::TextureUsage::RenderAttachment) {
                dxgiUsage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
            }
            return dxgiUsage;
        }

    }  // namespace

    // OldSwapChain

    // static
    Ref<OldSwapChain> OldSwapChain::Create(Device* device, const SwapChainDescriptor* descriptor) {
        return AcquireRef(new OldSwapChain(device, descriptor));
    }

    OldSwapChain::OldSwapChain(Device* device, const SwapChainDescriptor* descriptor)
        : OldSwapChainBase(device, descriptor) {
        const auto& im = GetImplementation();
        DawnWSIContextD3D12 wsiContext = {};
        wsiContext.device = reinterpret_cast<WGPUDevice>(GetDevice());
        im.Init(im.userData, &wsiContext);

        ASSERT(im.textureUsage != WGPUTextureUsage_None);
        mTextureUsage = static_cast<wgpu::TextureUsage>(im.textureUsage);
    }

    OldSwapChain::~OldSwapChain() = default;

    TextureBase* OldSwapChain::GetNextTextureImpl(const TextureDescriptor* descriptor) {
        DeviceBase* device = GetDevice();
        const auto& im = GetImplementation();
        DawnSwapChainNextTexture next = {};
        DawnSwapChainError error = im.GetNextTexture(im.userData, &next);
        if (error) {
            device->HandleError(InternalErrorType::Internal, error);
            return nullptr;
        }

        ComPtr<ID3D12Resource> d3d12Texture = static_cast<ID3D12Resource*>(next.texture.ptr);
        Ref<Texture> dawnTexture;
        if (device->ConsumedError(
                Texture::Create(ToBackend(GetDevice()), descriptor, std::move(d3d12Texture)),
                &dawnTexture)) {
            return nullptr;
        }

        return dawnTexture.Detach();
    }

    MaybeError OldSwapChain::OnBeforePresent(TextureViewBase* view) {
        Device* device = ToBackend(GetDevice());

        CommandRecordingContext* commandContext;
        DAWN_TRY_ASSIGN(commandContext, device->GetPendingCommandContext());

        // Perform the necessary transition for the texture to be presented.
        ToBackend(view->GetTexture())
            ->TrackUsageAndTransitionNow(commandContext, mTextureUsage,
                                         view->GetSubresourceRange());

        DAWN_TRY(device->ExecutePendingCommandContext());

        return {};
    }

    // SwapChain

    // static
    ResultOrError<Ref<SwapChain>> SwapChain::Create(Device* device,
                                                Surface* surface,
                                                NewSwapChainBase* previousSwapChain,
                                                const SwapChainDescriptor* descriptor) {
        Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, descriptor));
        DAWN_TRY(swapchain->Initialize(previousSwapChain));
        return swapchain;
    }

    SwapChain::~SwapChain() {
        DetachFromSurface();
    }

    // Initializes the swapchain on the surface. Note that `previousSwapChain` may or may not be
    // nullptr. If it is not nullptr it means that it is the swapchain previously in use on the
    // surface and that we have a chance to reuse it's underlying IDXGISwapChain and "buffers".
    MaybeError SwapChain::Initialize(NewSwapChainBase* previousSwapChain) {
        ASSERT(GetSurface()->GetType() == Surface::Type::WindowsHWND);

        // Precompute the configuration parameters we want for the DXGI swapchain.
        mConfig.bufferCount = PresentModeToBufferCount(GetPresentMode());
        mConfig.format = D3D12TextureFormat(GetFormat());
        mConfig.swapChainFlags = PresentModeToSwapChainFlags(GetPresentMode());
        mConfig.usage = ToDXGIUsage(GetUsage());

        // There is no previous swapchain so we can create one directly and don't have anything else
        // to do.
        if (previousSwapChain == nullptr) {
            return InitializeSwapChainFromScratch();
        }

        // TODO(crbug.com/dawn/269): figure out what should happen when surfaces are used by
        // multiple backends one after the other. It probably needs to block until the backend
        // and GPU are completely finished with the previous swapchain.
        if (previousSwapChain->GetBackendType() != wgpu::BackendType::D3D12) {
            return DAWN_VALIDATION_ERROR("d3d12::SwapChain cannot switch between APIs");
        }

        // TODO(crbug.com/dawn/269): use ToBackend once OldSwapChainBase is removed.
        SwapChain* previousD3D12SwapChain = static_cast<SwapChain*>(previousSwapChain);

        // TODO(crbug.com/dawn/269): Figure out switching an HWND between devices, it might
        // require just losing the reference to the swapchain, but might also need to wait for
        // all previous operations to complete.
        if (GetDevice() != previousSwapChain->GetDevice()) {
            return DAWN_VALIDATION_ERROR("d3d12::SwapChain cannot switch between devices");
        }

        // The previous swapchain is on the same device so we want to reuse it but it is still not
        // always possible. Because DXGI requires that a new swapchain be created if the
        // DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING flag is changed.
        bool canReuseSwapChain =
            ((mConfig.swapChainFlags ^ previousD3D12SwapChain->mConfig.swapChainFlags) &
             DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) == 0;

        // We can't reuse the previous swapchain, so we destroy it and wait for all of its reference
        // to be forgotten (otherwise DXGI complains that there are outstanding references).
        if (!canReuseSwapChain) {
            DAWN_TRY(previousD3D12SwapChain->DetachAndWaitForDeallocation());
            return InitializeSwapChainFromScratch();
        }

        // After all this we know we can reuse the swapchain, see if it is possible to also reuse
        // the buffers.
        mDXGISwapChain = std::move(previousD3D12SwapChain->mDXGISwapChain);

        bool canReuseBuffers = GetWidth() == previousSwapChain->GetWidth() &&
                               GetHeight() == previousSwapChain->GetHeight() &&
                               GetFormat() == previousSwapChain->GetFormat() &&
                               GetPresentMode() == previousSwapChain->GetPresentMode();
        if (canReuseBuffers) {
            mBuffers = std::move(previousD3D12SwapChain->mBuffers);
            mBufferLastUsedSerials = std::move(previousD3D12SwapChain->mBufferLastUsedSerials);
            mCurrentBuffer = previousD3D12SwapChain->mCurrentBuffer;
            return {};
        }

        // We can't reuse the buffers so we need to resize, IDXGSwapChain->ResizeBuffers requires
        // that all references to buffers are lost before it is called. Contrary to D3D11, the
        // application is responsible for keeping references to the buffers until the GPU is done
        // using them so we have no choice but to synchrounously wait for all operations to complete
        // on the previous swapchain and then lose references to its buffers.
        DAWN_TRY(previousD3D12SwapChain->DetachAndWaitForDeallocation());
        DAWN_TRY(
            CheckHRESULT(mDXGISwapChain->ResizeBuffers(mConfig.bufferCount, GetWidth(), GetHeight(),
                                                       mConfig.format, mConfig.swapChainFlags),
                         "IDXGISwapChain::ResizeBuffer"));
        return CollectSwapChainBuffers();
    }

    MaybeError SwapChain::InitializeSwapChainFromScratch() {
        ASSERT(mDXGISwapChain == nullptr);

        Device* device = ToBackend(GetDevice());

        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
        swapChainDesc.Width = GetWidth();
        swapChainDesc.Height = GetHeight();
        swapChainDesc.Format = mConfig.format;
        swapChainDesc.Stereo = false;
        swapChainDesc.SampleDesc.Count = 1;
        swapChainDesc.SampleDesc.Quality = 0;
        swapChainDesc.BufferUsage = mConfig.usage;
        swapChainDesc.BufferCount = mConfig.bufferCount;
        swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
        swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
        swapChainDesc.Flags = mConfig.swapChainFlags;

        ComPtr<IDXGIFactory2> factory2 = nullptr;
        DAWN_TRY(CheckHRESULT(device->GetFactory()->QueryInterface(IID_PPV_ARGS(&factory2)),
                              "Getting IDXGIFactory2"));

        ComPtr<IDXGISwapChain1> swapChain1;
        switch (GetSurface()->GetType()) {
            case Surface::Type::WindowsHWND: {
                DAWN_TRY(CheckHRESULT(
                    factory2->CreateSwapChainForHwnd(device->GetCommandQueue().Get(),
                                                     static_cast<HWND>(GetSurface()->GetHWND()),
                                                     &swapChainDesc, nullptr, nullptr, &swapChain1),
                    "Creating the IDXGISwapChain1"));
                break;
            }
            case Surface::Type::WindowsCoreWindow: {
                DAWN_TRY(CheckHRESULT(
                    factory2->CreateSwapChainForCoreWindow(device->GetCommandQueue().Get(),
                                                           GetSurface()->GetCoreWindow(),
                                                           &swapChainDesc, nullptr, &swapChain1),
                    "Creating the IDXGISwapChain1"));
                break;
            }
            default:
                UNREACHABLE();
        }

        DAWN_TRY(CheckHRESULT(swapChain1.As(&mDXGISwapChain), "Gettting IDXGISwapChain1"));

        return CollectSwapChainBuffers();
    }

    MaybeError SwapChain::CollectSwapChainBuffers() {
        ASSERT(mDXGISwapChain != nullptr);
        ASSERT(mBuffers.empty());

        mBuffers.resize(mConfig.bufferCount);
        for (uint32_t i = 0; i < mConfig.bufferCount; i++) {
            DAWN_TRY(CheckHRESULT(mDXGISwapChain->GetBuffer(i, IID_PPV_ARGS(&mBuffers[i])),
                                  "Getting IDXGISwapChain buffer"));
        }

        // Pretend all the buffers were last used at the beginning of time.
        mBufferLastUsedSerials.resize(mConfig.bufferCount, ExecutionSerial(0));
        return {};
    }

    MaybeError SwapChain::PresentImpl() {
        Device* device = ToBackend(GetDevice());

        // Transition the texture to the present state as required by IDXGISwapChain1::Present()
        // TODO(cwallez@chromium.org): Remove the need for this by eagerly transitioning the
        // presentable texture to present at the end of submits that use them.
        CommandRecordingContext* commandContext;
        DAWN_TRY_ASSIGN(commandContext, device->GetPendingCommandContext());
        mApiTexture->TrackUsageAndTransitionNow(commandContext, kPresentTextureUsage,
                                                mApiTexture->GetAllSubresources());
        DAWN_TRY(device->ExecutePendingCommandContext());

        // Do the actual present. DXGI_STATUS_OCCLUDED is a valid return value that's just a
        // message to the application that it could stop rendering.
        HRESULT presentResult =
            mDXGISwapChain->Present(PresentModeToSwapInterval(GetPresentMode()), 0);
        if (presentResult != DXGI_STATUS_OCCLUDED) {
            DAWN_TRY(CheckHRESULT(presentResult, "IDXGISwapChain::Present"));
        }

        // Record that "new" is the last time the buffer has been used.
        DAWN_TRY(device->NextSerial());
        mBufferLastUsedSerials[mCurrentBuffer] = device->GetPendingCommandSerial();

        mApiTexture->APIDestroy();
        mApiTexture = nullptr;

        return {};
    }

    ResultOrError<TextureViewBase*> SwapChain::GetCurrentTextureViewImpl() {
        Device* device = ToBackend(GetDevice());

        // Synchronously wait until previous operations on the next swapchain buffer are finished.
        // This is the logic that performs frame pacing.
        // TODO(cwallez@chromium.org): Consider whether this should  be lifted for Mailbox so that
        // there is not frame pacing.
        mCurrentBuffer = mDXGISwapChain->GetCurrentBackBufferIndex();
        DAWN_TRY(device->WaitForSerial(mBufferLastUsedSerials[mCurrentBuffer]));

        // Create the API side objects for this use of the swapchain's buffer.
        TextureDescriptor descriptor = GetSwapChainBaseTextureDescriptor(this);
        DAWN_TRY_ASSIGN(mApiTexture, Texture::Create(ToBackend(GetDevice()), &descriptor,
                                                     mBuffers[mCurrentBuffer]));

        // TODO(dawn:723): change to not use AcquireRef for reentrant object creation.
        return mApiTexture->APICreateView();
    }

    MaybeError SwapChain::DetachAndWaitForDeallocation() {
        DetachFromSurface();

        // DetachFromSurface calls Texture->Destroy that enqueues the D3D12 resource in a
        // SerialQueue with the current "pending serial" so that we don't destroy the texture
        // before it is finished being used. Flush the commands and wait for that serial to be
        // passed, then Tick the device to make sure the reference to the D3D12 texture is removed.
        Device* device = ToBackend(GetDevice());
        DAWN_TRY(device->NextSerial());
        DAWN_TRY(device->WaitForSerial(device->GetLastSubmittedCommandSerial()));
        return device->TickImpl();
    }

    void SwapChain::DetachFromSurfaceImpl() {
        if (mApiTexture != nullptr) {
            mApiTexture->APIDestroy();
            mApiTexture = nullptr;
        }

        mDXGISwapChain = nullptr;
        mBuffers.clear();
    }

}}  // namespace dawn_native::d3d12
