// 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 "src/dawn/native/SwapChain.h"

#include <utility>
#include <vector>

#include "dawn/native/ObjectType_autogen.h"
#include "dawn/native/ValidationUtils_autogen.h"
#include "src/dawn/common/Constants.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/PhysicalDevice.h"
#include "src/dawn/native/Surface.h"
#include "src/dawn/native/Texture.h"
#include "src/utils/compiler.h"

namespace dawn::native {

TextureDescriptor GetSwapChainBaseTextureDescriptor(SwapChainBase* swapChain) {
    TextureDescriptor desc;
    desc.usage = swapChain->GetUsage();
    desc.dimension = wgpu::TextureDimension::e2D;
    desc.size = {swapChain->GetWidth(), swapChain->GetHeight(), 1};
    desc.format = swapChain->GetFormat();
    desc.viewFormats = swapChain->GetViewFormats();
    desc.mipLevelCount = 1;
    desc.sampleCount = 1;

    return desc;
}

SwapChainBase::SwapChainBase(DeviceBase* device,
                             Surface* surface,
                             const SurfaceConfiguration* config)
    : ApiObjectBase(device, kLabelNotImplemented),
      mWidth(config->width),
      mHeight(config->height),
      mFormat(config->format),
      mUsage(config->usage),
      mPresentMode(config->presentMode),
      mAlphaMode(config->alphaMode),
      mSurface(surface) {
    for (wgpu::TextureFormat viewFormat : config->viewFormats) {
        if (viewFormat == config->format) {
            // Skip our own format, like texture creations does.
            continue;
        }
        mViewFormats.push_back(viewFormat);
    }
    GetObjectTrackingList()->Track(this);
}

FormatSet SwapChainBase::ComputeViewFormatSet() const {
    FormatSet viewFormatSet;
    for (wgpu::TextureFormat format : mViewFormats) {
        viewFormatSet[GetDevice()->GetValidInternalFormat(format)] = true;
    }
    return viewFormatSet;
}

SwapChainBase::~SwapChainBase() {
    if (mCurrentTextureInfo.texture != nullptr) {
        DAWN_CHECK(mCurrentTextureInfo.texture->IsDestroyed());
    }

    DAWN_CHECK(!mAttached);
}

void SwapChainBase::DestroyImpl(DestroyReason reason) {
    // The surface has a Ref on the swapchains attached to it and detaches them before dropping
    // that Ref, so a swapchain that is being deleted is already detached. The swapchain can
    // still be attached when the device is destroyed though: detach it so that its backend
    // resources are released before the device's, and so that the surface stops using a
    // swapchain of a destroyed device.
    if (mAttached) {
        mSurface->DetachSwapChain(this);
    }
    DAWN_ASSERT(!mAttached);
}

void SwapChainBase::DetachFromSurface() {
    if (mAttached) {
        DetachFromSurfaceImpl();
        mSurface = nullptr;
        mAttached = false;
    }
}

void SwapChainBase::SetIsAttached() {
    DAWN_ASSERT(!mAttached);
    mAttached = true;
}

ResultOrError<SurfaceTexture> SwapChainBase::GetCurrentTexture() {
    if (mCurrentTextureInfo.texture == nullptr) {
        DAWN_TRY_ASSIGN(mCurrentTextureInfo, GetCurrentTextureImpl());
    }

    SurfaceTexture surfaceTexture;
    surfaceTexture.texture = nullptr;
    surfaceTexture.status = mCurrentTextureInfo.status;

    // Handle cases where the backend swapchain goes bad and can't return a texture.
    if (mCurrentTextureInfo.texture == nullptr) {
        return surfaceTexture;
    }

    SetChildLabel(mCurrentTextureInfo.texture.Get());

    // Check that the return texture matches exactly what was given for this descriptor.
    DAWN_CHECK(mCurrentTextureInfo.texture->GetFormat().format == mFormat);
    DAWN_CHECK(IsSubset(mUsage, mCurrentTextureInfo.texture->GetUsage()));
    DAWN_CHECK(mCurrentTextureInfo.texture->GetDimension() == wgpu::TextureDimension::e2D);
    DAWN_CHECK(mCurrentTextureInfo.texture->GetWidth(Aspect::Color) == mWidth);
    DAWN_CHECK(mCurrentTextureInfo.texture->GetHeight(Aspect::Color) == mHeight);
    DAWN_CHECK(mCurrentTextureInfo.texture->GetNumMipLevels() == 1);
    DAWN_CHECK(mCurrentTextureInfo.texture->GetArrayLayers() == 1);
    DAWN_CHECK(mCurrentTextureInfo.texture->GetViewFormats() == ComputeViewFormatSet());

    // Calling GetCurrentTexture always returns a new reference.
    auto texture = mCurrentTextureInfo.texture;
    surfaceTexture.texture = ReturnToAPI(std::move(texture));
    return surfaceTexture;
}

MaybeUnknownError SwapChainBase::Present() {
    DAWN_TRY(ValidatePresent());
    DAWN_TRY(PresentImpl());

    DAWN_CHECK(mCurrentTextureInfo.texture->IsDestroyed());
    mCurrentTextureInfo.texture = nullptr;
    return {};
}

ObjectType SwapChainBase::GetType() const {
    return ObjectType::SwapChain;
}

uint32_t SwapChainBase::GetWidth() const {
    return mWidth;
}

uint32_t SwapChainBase::GetHeight() const {
    return mHeight;
}

wgpu::TextureFormat SwapChainBase::GetFormat() const {
    return mFormat;
}

const std::vector<wgpu::TextureFormat>& SwapChainBase::GetViewFormats() const {
    return mViewFormats;
}

wgpu::TextureUsage SwapChainBase::GetUsage() const {
    return mUsage;
}

wgpu::PresentMode SwapChainBase::GetPresentMode() const {
    return mPresentMode;
}

wgpu::CompositeAlphaMode SwapChainBase::GetAlphaMode() const {
    return mAlphaMode;
}

Surface* SwapChainBase::GetSurface() const {
    return mSurface;
}

bool SwapChainBase::IsAttached() const {
    return mAttached;
}

wgpu::BackendType SwapChainBase::GetBackendType() const {
    return GetDevice()->GetPhysicalDevice()->GetBackendType();
}

MaybeValError SwapChainBase::ValidatePresent() const {
    DAWN_TRY(GetDevice()->ValidateIsAlive());
    DAWN_CHECK(mAttached);

    DAWN_INVALID_IF(mCurrentTextureInfo.texture == nullptr,
                    "GetCurrentTexture was not called on %s this frame prior to calling Present.",
                    this->GetSurface());

    return {};
}

MaybeValError SwapChainBase::ValidateGetCurrentTexture() const {
    DAWN_TRY(GetDevice()->ValidateIsAlive());
    DAWN_CHECK(mAttached);

    return {};
}

void SwapChainBase::SetChildLabel(ApiObjectBase* child) const {
    child->SetLabel(absl::StrFormat("of %s", this->GetSurface()));
}

}  // namespace dawn::native
