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

#include "common/Constants.h"
#include "dawn_native/Adapter.h"
#include "dawn_native/Device.h"
#include "dawn_native/Surface.h"
#include "dawn_native/Texture.h"
#include "dawn_native/ValidationUtils_autogen.h"

namespace dawn_native {

    namespace {

        class ErrorSwapChain final : public SwapChainBase {
          public:
            ErrorSwapChain(DeviceBase* device) : SwapChainBase(device, ObjectBase::kError) {
            }

          private:
            void APIConfigure(wgpu::TextureFormat format,
                              wgpu::TextureUsage allowedUsage,
                              uint32_t width,
                              uint32_t height) override {
                GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("error swapchain"));
            }

            TextureViewBase* APIGetCurrentTextureView() override {
                GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("error swapchain"));
                return TextureViewBase::MakeError(GetDevice());
            }

            void APIPresent() override {
                GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("error swapchain"));
            }
        };

    }  // anonymous namespace

    MaybeError ValidateSwapChainDescriptor(const DeviceBase* device,
                                           const Surface* surface,
                                           const SwapChainDescriptor* descriptor) {
        if (descriptor->implementation != 0) {
            if (surface != nullptr) {
                return DAWN_VALIDATION_ERROR(
                    "Exactly one of surface or implementation must be set");
            }

            DawnSwapChainImplementation* impl =
                reinterpret_cast<DawnSwapChainImplementation*>(descriptor->implementation);

            if (!impl->Init || !impl->Destroy || !impl->Configure || !impl->GetNextTexture ||
                !impl->Present) {
                return DAWN_VALIDATION_ERROR("Implementation is incomplete");
            }

        } else {
            if (surface == nullptr) {
                return DAWN_VALIDATION_ERROR(
                    "At least one of surface or implementation must be set");
            }

            DAWN_TRY(ValidatePresentMode(descriptor->presentMode));

            // TODO(crbug.com/dawn/160): Lift this restriction once
            // wgpu::Instance::GetPreferredSurfaceFormat is implemented.
            if (descriptor->format != wgpu::TextureFormat::BGRA8Unorm) {
                return DAWN_VALIDATION_ERROR("Format must (currently) be BGRA8Unorm");
            }

            if (descriptor->usage != wgpu::TextureUsage::RenderAttachment) {
                return DAWN_VALIDATION_ERROR("Usage must (currently) be RenderAttachment");
            }

            if (descriptor->width == 0 || descriptor->height == 0) {
                return DAWN_VALIDATION_ERROR("Swapchain size can't be empty");
            }

            if (descriptor->width > kMaxTextureDimension2D ||
                descriptor->height > kMaxTextureDimension2D) {
                return DAWN_VALIDATION_ERROR("Swapchain size too big");
            }
        }

        return {};
    }

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

        return desc;
    }

    // SwapChainBase

    SwapChainBase::SwapChainBase(DeviceBase* device) : ObjectBase(device) {
    }

    SwapChainBase::SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag)
        : ObjectBase(device, tag) {
    }

    SwapChainBase::~SwapChainBase() {
    }

    // static
    SwapChainBase* SwapChainBase::MakeError(DeviceBase* device) {
        return new ErrorSwapChain(device);
    }

    // OldSwapChainBase

    OldSwapChainBase::OldSwapChainBase(DeviceBase* device, const SwapChainDescriptor* descriptor)
        : SwapChainBase(device),
          mImplementation(
              *reinterpret_cast<DawnSwapChainImplementation*>(descriptor->implementation)) {
    }

    OldSwapChainBase::~OldSwapChainBase() {
        if (!IsError()) {
            const auto& im = GetImplementation();
            im.Destroy(im.userData);
        }
    }

    void OldSwapChainBase::APIConfigure(wgpu::TextureFormat format,
                                        wgpu::TextureUsage allowedUsage,
                                        uint32_t width,
                                        uint32_t height) {
        if (GetDevice()->ConsumedError(ValidateConfigure(format, allowedUsage, width, height))) {
            return;
        }
        ASSERT(!IsError());

        allowedUsage |= wgpu::TextureUsage::Present;

        mFormat = format;
        mAllowedUsage = allowedUsage;
        mWidth = width;
        mHeight = height;
        mImplementation.Configure(mImplementation.userData, static_cast<WGPUTextureFormat>(format),
                                  static_cast<WGPUTextureUsage>(allowedUsage), width, height);
    }

    TextureViewBase* OldSwapChainBase::APIGetCurrentTextureView() {
        if (GetDevice()->ConsumedError(ValidateGetCurrentTextureView())) {
            return TextureViewBase::MakeError(GetDevice());
        }
        ASSERT(!IsError());

        // Return the same current texture view until Present is called.
        if (mCurrentTextureView != nullptr) {
            // Calling GetCurrentTextureView always returns a new reference so add it even when
            // reuse the existing texture view.
            mCurrentTextureView->Reference();
            return mCurrentTextureView.Get();
        }

        // Create the backing texture and the view.
        TextureDescriptor descriptor;
        descriptor.dimension = wgpu::TextureDimension::e2D;
        descriptor.size.width = mWidth;
        descriptor.size.height = mHeight;
        descriptor.size.depthOrArrayLayers = 1;
        descriptor.sampleCount = 1;
        descriptor.format = mFormat;
        descriptor.mipLevelCount = 1;
        descriptor.usage = mAllowedUsage;

        // Get the texture but remove the external refcount because it is never passed outside
        // of dawn_native
        mCurrentTexture = AcquireRef(GetNextTextureImpl(&descriptor));

        mCurrentTextureView = mCurrentTexture->APICreateView();
        return mCurrentTextureView.Get();
    }

    void OldSwapChainBase::APIPresent() {
        if (GetDevice()->ConsumedError(ValidatePresent())) {
            return;
        }
        ASSERT(!IsError());

        if (GetDevice()->ConsumedError(OnBeforePresent(mCurrentTextureView.Get()))) {
            return;
        }

        mImplementation.Present(mImplementation.userData);

        mCurrentTexture = nullptr;
        mCurrentTextureView = nullptr;
    }

    const DawnSwapChainImplementation& OldSwapChainBase::GetImplementation() {
        ASSERT(!IsError());
        return mImplementation;
    }

    MaybeError OldSwapChainBase::ValidateConfigure(wgpu::TextureFormat format,
                                                   wgpu::TextureUsage allowedUsage,
                                                   uint32_t width,
                                                   uint32_t height) const {
        DAWN_TRY(GetDevice()->ValidateIsAlive());
        DAWN_TRY(GetDevice()->ValidateObject(this));

        DAWN_TRY(ValidateTextureUsage(allowedUsage));
        DAWN_TRY(ValidateTextureFormat(format));

        if (width == 0 || height == 0) {
            return DAWN_VALIDATION_ERROR("Swap chain cannot be configured to zero size");
        }

        return {};
    }

    MaybeError OldSwapChainBase::ValidateGetCurrentTextureView() const {
        DAWN_TRY(GetDevice()->ValidateIsAlive());
        DAWN_TRY(GetDevice()->ValidateObject(this));

        if (mWidth == 0) {
            // If width is 0, it implies swap chain has never been configured
            return DAWN_VALIDATION_ERROR("Swap chain needs to be configured before GetNextTexture");
        }

        return {};
    }

    MaybeError OldSwapChainBase::ValidatePresent() const {
        DAWN_TRY(GetDevice()->ValidateIsAlive());
        DAWN_TRY(GetDevice()->ValidateObject(this));

        if (mCurrentTextureView == nullptr) {
            return DAWN_VALIDATION_ERROR(
                "Cannot call present without a GetCurrentTextureView call for this frame");
        }

        return {};
    }

    // Implementation of NewSwapChainBase

    NewSwapChainBase::NewSwapChainBase(DeviceBase* device,
                                       Surface* surface,
                                       const SwapChainDescriptor* descriptor)
        : SwapChainBase(device),
          mAttached(false),
          mWidth(descriptor->width),
          mHeight(descriptor->height),
          mFormat(descriptor->format),
          mUsage(descriptor->usage),
          mPresentMode(descriptor->presentMode),
          mSurface(surface) {
    }

    NewSwapChainBase::~NewSwapChainBase() {
        if (mCurrentTextureView != nullptr) {
            ASSERT(mCurrentTextureView->GetTexture()->GetTextureState() ==
                   TextureBase::TextureState::Destroyed);
        }

        ASSERT(!mAttached);
    }

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

    void NewSwapChainBase::SetIsAttached() {
        mAttached = true;
    }

    void NewSwapChainBase::APIConfigure(wgpu::TextureFormat format,
                                        wgpu::TextureUsage allowedUsage,
                                        uint32_t width,
                                        uint32_t height) {
        GetDevice()->ConsumedError(
            DAWN_VALIDATION_ERROR("Configure is invalid for surface-based swapchains"));
    }

    TextureViewBase* NewSwapChainBase::APIGetCurrentTextureView() {
        if (GetDevice()->ConsumedError(ValidateGetCurrentTextureView())) {
            return TextureViewBase::MakeError(GetDevice());
        }

        if (mCurrentTextureView != nullptr) {
            // Calling GetCurrentTextureView always returns a new reference so add it even when
            // reusing the existing texture view.
            mCurrentTextureView->Reference();
            return mCurrentTextureView.Get();
        }

        TextureViewBase* view = nullptr;
        if (GetDevice()->ConsumedError(GetCurrentTextureViewImpl(), &view)) {
            return TextureViewBase::MakeError(GetDevice());
        }

        // Check that the return texture view matches exactly what was given for this descriptor.
        ASSERT(view->GetTexture()->GetFormat().format == mFormat);
        ASSERT(IsSubset(mUsage, view->GetTexture()->GetUsage()));
        ASSERT(view->GetLevelCount() == 1);
        ASSERT(view->GetLayerCount() == 1);
        ASSERT(view->GetDimension() == wgpu::TextureViewDimension::e2D);
        ASSERT(view->GetTexture()->GetMipLevelVirtualSize(view->GetBaseMipLevel()).width == mWidth);
        ASSERT(view->GetTexture()->GetMipLevelVirtualSize(view->GetBaseMipLevel()).height ==
               mHeight);

        mCurrentTextureView = view;
        return view;
    }

    void NewSwapChainBase::APIPresent() {
        if (GetDevice()->ConsumedError(ValidatePresent())) {
            return;
        }

        if (GetDevice()->ConsumedError(PresentImpl())) {
            return;
        }

        ASSERT(mCurrentTextureView->GetTexture()->GetTextureState() ==
               TextureBase::TextureState::Destroyed);
        mCurrentTextureView = nullptr;
    }

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

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

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

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

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

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

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

    wgpu::BackendType NewSwapChainBase::GetBackendType() const {
        return GetDevice()->GetAdapter()->GetBackendType();
    }

    MaybeError NewSwapChainBase::ValidatePresent() const {
        DAWN_TRY(GetDevice()->ValidateIsAlive());
        DAWN_TRY(GetDevice()->ValidateObject(this));

        if (!mAttached) {
            return DAWN_VALIDATION_ERROR("Presenting on detached swapchain");
        }

        if (mCurrentTextureView == nullptr) {
            return DAWN_VALIDATION_ERROR("Presenting without prior GetCurrentTextureView");
        }

        return {};
    }

    MaybeError NewSwapChainBase::ValidateGetCurrentTextureView() const {
        DAWN_TRY(GetDevice()->ValidateIsAlive());
        DAWN_TRY(GetDevice()->ValidateObject(this));

        if (!mAttached) {
            return DAWN_VALIDATION_ERROR("Getting view on detached swapchain");
        }

        return {};
    }

}  // namespace dawn_native
