// 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/ObjectType_autogen.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_FORMAT_VALIDATION_ERROR("%s is an error swapchain.", this));
            }

            TextureViewBase* APIGetCurrentTextureView() override {
                GetDevice()->ConsumedError(
                    DAWN_FORMAT_VALIDATION_ERROR("%s is an error swapchain.", this));
                return TextureViewBase::MakeError(GetDevice());
            }

            void APIPresent() override {
                GetDevice()->ConsumedError(
                    DAWN_FORMAT_VALIDATION_ERROR("%s is an error swapchain.", this));
            }
        };

    }  // anonymous namespace

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

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

            DAWN_INVALID_IF(!impl->Init || !impl->Destroy || !impl->Configure ||
                                !impl->GetNextTexture || !impl->Present,
                            "Implementation is incomplete");

        } else {
            DAWN_INVALID_IF(surface == nullptr,
                            "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.
            DAWN_INVALID_IF(descriptor->format != wgpu::TextureFormat::BGRA8Unorm,
                            "Format (%s) is not %s, which is (currently) the only accepted format.",
                            descriptor->format, wgpu::TextureFormat::BGRA8Unorm);

            DAWN_INVALID_IF(descriptor->usage != wgpu::TextureUsage::RenderAttachment,
                            "Usage (%s) is not %s, which is (currently) the only accepted usage.",
                            descriptor->usage, wgpu::TextureUsage::RenderAttachment);

            DAWN_INVALID_IF(descriptor->width == 0 || descriptor->height == 0,
                            "Swap Chain size (width: %u, height: %u) is empty.", descriptor->width,
                            descriptor->height);

            DAWN_INVALID_IF(
                descriptor->width > device->GetLimits().v1.maxTextureDimension2D ||
                    descriptor->height > device->GetLimits().v1.maxTextureDimension2D,
                "Swap Chain size (width: %u, height: %u) is greater than the maximum 2D texture "
                "size (width: %u, height: %u).",
                descriptor->width, descriptor->height, device->GetLimits().v1.maxTextureDimension2D,
                device->GetLimits().v1.maxTextureDimension2D);
        }

        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) : ApiObjectBase(device, kLabelNotImplemented) {
        TrackInDevice();
    }

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

    SwapChainBase::~SwapChainBase() {
    }

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

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

    // 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));

        DAWN_INVALID_IF(width == 0 || height == 0,
                        "Configuration size (width: %u, height: %u) for %s is empty.", width,
                        height, this);

        return {};
    }

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

        // If width is 0, it implies swap chain has never been configured
        DAWN_INVALID_IF(mWidth == 0, "%s was not configured prior to calling GetNextTexture.",
                        this);

        return {};
    }

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

        DAWN_INVALID_IF(
            mCurrentTextureView == nullptr,
            "GetCurrentTextureView was not called on %s this frame prior to calling Present.",
            this);

        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_FORMAT_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));

        DAWN_INVALID_IF(!mAttached, "Cannot call Present called on detached %s.", this);

        DAWN_INVALID_IF(
            mCurrentTextureView == nullptr,
            "GetCurrentTextureView was not called on %s this frame prior to calling Present.",
            this);

        return {};
    }

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

        DAWN_INVALID_IF(!mAttached, "Cannot call GetCurrentTextureView on detached %s.", this);

        return {};
    }

}  // namespace dawn_native
