// 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.viewFormatCount = swapChain->GetViewFormats().size();
    desc.viewFormats = swapChain->GetViewFormats().data();
    desc.mipLevelCount = 1;
    desc.sampleCount = 1;

    return desc;
}

SwapChainBase::SwapChainBase(DeviceBase* device,
                             Surface* surface,
                             const SurfaceConfiguration* config)
    : mDevice(device),
      mWidth(config->width),
      mHeight(config->height),
      mFormat(config->format),
      mUsage(config->usage),
      mPresentMode(config->presentMode),
      mAlphaMode(config->alphaMode),
      mSurface(surface) {
    for (uint32_t i = 0; i < config->viewFormatCount; ++i) {
        if (DAWN_UNSAFE_TODO(config->viewFormats[i]) == config->format) {
            // Skip our own format, like texture creations does.
            continue;
        }
        mViewFormats.push_back(DAWN_UNSAFE_TODO(config->viewFormats[i]));
    }
}

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::DetachFromSurface() {
    if (mAttached) {
        DetachFromSurfaceImpl();
        mSurface = nullptr;
        mAttached = false;
    }
}

void SwapChainBase::SetIsAttached() {
    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;
}

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

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

DeviceBase* SwapChainBase::GetDevice() const {
    return mDevice.Get();
}
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();
}

MaybeError 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 {};
}

MaybeError 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
