// Copyright 2017 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/d3d12/SwapChainD3D12.h"

#if defined(DAWN_USE_WINDOWS_UI)
#include <windows.ui.xaml.media.dxinterop.h>
#endif  // defined(DAWN_USE_WINDOWS_UI)

#include <utility>

#include "dawn/native/ChainUtils.h"
#include "dawn/native/Surface.h"
#include "dawn/native/d3d/D3DError.h"
#include "dawn/native/d3d/UtilsD3D.h"
#include "dawn/native/d3d12/DeviceD3D12.h"
#include "dawn/native/d3d12/QueueD3D12.h"
#include "dawn/native/d3d12/TextureD3D12.h"

namespace dawn::native::d3d12 {
// static
ResultOrError<Ref<SwapChain>> SwapChain::Create(Device* device,
                                                Surface* surface,
                                                SwapChainBase* previousSwapChain,
                                                const SurfaceConfiguration* config) {
    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, config));
    DAWN_TRY(swapchain->Initialize(previousSwapChain));
    return swapchain;
}

SwapChain::~SwapChain() = default;

IUnknown* SwapChain::GetD3DDeviceForCreatingSwapChain() {
    return ToBackend(GetDevice()->GetQueue())->GetCommandQueue();
}

void SwapChain::ReuseBuffers(SwapChainBase* previousSwapChain) {
    SwapChain* previousD3DSwapChain = ToBackend(previousSwapChain);
    mBuffers = std::move(previousD3DSwapChain->mBuffers);

    // Remember the current state of the ID3D12Resource for the current buffer if we didn't have
    // chance to present it yet.
    if (previousD3DSwapChain->mApiTexture != nullptr) {
        D3D12_RESOURCE_STATES state =
            previousD3DSwapChain->mApiTexture->GetCurrentStateForSwapChain();
        mBuffers[previousD3DSwapChain->mCurrentBuffer].acquireState = state;
    }
}

MaybeError SwapChain::CollectSwapChainBuffers() {
    DAWN_ASSERT(GetDXGISwapChain() != nullptr);
    DAWN_ASSERT(mBuffers.empty());

    IDXGISwapChain3* dxgiSwapChain = GetDXGISwapChain();
    const auto& config = GetConfig();

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

    return {};
}

MaybeError SwapChain::PresentImpl() {
    Queue* queue = ToBackend(GetDevice()->GetQueue());

    // Transition the texture to the present state as required by IDXGISwapChain1::Present()
    // TODO(crbug.com/dawn/269): Remove the need for this by eagerly transitioning the
    // presentable texture to present at the end of submits that use them.
    CommandRecordingContext* commandContext = queue->GetPendingCommandContext();
    mApiTexture->TrackUsageAndTransitionNow(commandContext, kPresentReleaseTextureUsage,
                                            mApiTexture->GetAllSubresources());
    DAWN_TRY(queue->SubmitPendingCommands());

    DAWN_TRY(PresentDXGISwapChain());

    // Record that "new" is the last time the buffer has been used.
    DAWN_TRY(queue->NextSerial());
    mBuffers[mCurrentBuffer].lastUsed = queue->GetLastSubmittedCommandSerial();
    mBuffers[mCurrentBuffer].acquireState = D3D12_RESOURCE_STATE_COMMON;

    mApiTexture->APIDestroy();
    mApiTexture = nullptr;

    return {};
}

ResultOrError<SwapChainTextureInfo> SwapChain::GetCurrentTextureImpl() {
    Queue* queue = ToBackend(GetDevice()->GetQueue());

    // Synchronously wait until previous operations on the next swapchain buffer are finished.
    // This is the logic that performs frame pacing.
    // TODO(crbug.com/dawn/269): Consider whether this should  be lifted for Mailbox so that
    // there is not frame pacing.
    mCurrentBuffer = GetDXGISwapChain()->GetCurrentBackBufferIndex();
    const Buffer& buffer = mBuffers[mCurrentBuffer];

    DAWN_TRY(queue->WaitForSerial(buffer.lastUsed));

    // Create the API side objects for this use of the swapchain's buffer.
    TextureDescriptor descriptor = GetSwapChainBaseTextureDescriptor(this);
    DAWN_TRY_ASSIGN(mApiTexture,
                    Texture::CreateForSwapChain(ToBackend(GetDevice()), Unpack(&descriptor),
                                                buffer.resource, buffer.acquireState));

    SwapChainTextureInfo info;
    info.texture = mApiTexture;
    // TODO(dawn:2320): Check for optimality
    info.status = wgpu::SurfaceGetCurrentTextureStatus::SuccessOptimal;
    return info;
}

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.
    Queue* queue = ToBackend(GetDevice()->GetQueue());
    DAWN_TRY(queue->EnsureCommandsFlushed(queue->GetPendingCommandSerial()));
    DAWN_TRY(queue->WaitForSerial(queue->GetLastSubmittedCommandSerial()));
    return ToBackend(GetDevice())->TickImpl();
}

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

    ReleaseDXGISwapChain();
}

}  // namespace dawn::native::d3d12
