// Copyright 2021 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/ExternalTexture.h"

#include "dawn_native/Device.h"
#include "dawn_native/ObjectType_autogen.h"
#include "dawn_native/Texture.h"

#include "dawn_native/dawn_platform.h"

namespace dawn_native {

    MaybeError ValidateExternalTexturePlane(const TextureViewBase* textureView,
                                            wgpu::TextureFormat format) {
        if (textureView->GetFormat().format != format) {
            return DAWN_VALIDATION_ERROR(
                "The external texture descriptor specifies a texture format that is different from "
                "at least one of the passed texture views.");
        }

        if ((textureView->GetTexture()->GetUsage() & wgpu::TextureUsage::TextureBinding) !=
            wgpu::TextureUsage::TextureBinding) {
            return DAWN_VALIDATION_ERROR(
                "The external texture descriptor specifies a texture that was not created with "
                "TextureUsage::TextureBinding.");
        }

        if (textureView->GetDimension() != wgpu::TextureViewDimension::e2D) {
            return DAWN_VALIDATION_ERROR(
                "The external texture descriptor contains a texture view with a non-2D dimension.");
        }

        if (textureView->GetLevelCount() > 1) {
            return DAWN_VALIDATION_ERROR(
                "The external texture descriptor contains a texture view with a level count "
                "greater than 1.");
        }

        return {};
    }

    MaybeError ValidateExternalTextureDescriptor(const DeviceBase* device,
                                                 const ExternalTextureDescriptor* descriptor) {
        ASSERT(descriptor);
        ASSERT(descriptor->plane0);

        DAWN_TRY(device->ValidateObject(descriptor->plane0));

        const Format* format;
        DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
        DAWN_UNUSED(format);

        switch (descriptor->format) {
            case wgpu::TextureFormat::RGBA8Unorm:
            case wgpu::TextureFormat::BGRA8Unorm:
            case wgpu::TextureFormat::RGBA16Float:
                DAWN_TRY(ValidateExternalTexturePlane(descriptor->plane0, descriptor->format));
                break;
            default:
                return DAWN_VALIDATION_ERROR(
                    "The external texture descriptor specifies an unsupported format.");
        }

        return {};
    }

    // static
    ResultOrError<Ref<ExternalTextureBase>> ExternalTextureBase::Create(
        DeviceBase* device,
        const ExternalTextureDescriptor* descriptor) {
        Ref<ExternalTextureBase> externalTexture =
            AcquireRef(new ExternalTextureBase(device, descriptor));
        return std::move(externalTexture);
    }

    ExternalTextureBase::ExternalTextureBase(DeviceBase* device,
                                             const ExternalTextureDescriptor* descriptor)
        : ApiObjectBase(device, kLabelNotImplemented), mState(ExternalTextureState::Alive) {
        textureViews[0] = descriptor->plane0;
    }

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

    const std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat>&
    ExternalTextureBase::GetTextureViews() const {
        return textureViews;
    }

    MaybeError ExternalTextureBase::ValidateCanUseInSubmitNow() const {
        ASSERT(!IsError());
        if (mState == ExternalTextureState::Destroyed) {
            return DAWN_VALIDATION_ERROR("Destroyed external texture used in a submit");
        }
        return {};
    }

    void ExternalTextureBase::APIDestroy() {
        if (GetDevice()->ConsumedError(GetDevice()->ValidateObject(this))) {
            return;
        }
        mState = ExternalTextureState::Destroyed;
        ASSERT(!IsError());
    }

    // static
    ExternalTextureBase* ExternalTextureBase::MakeError(DeviceBase* device) {
        return new ExternalTextureBase(device, ObjectBase::kError);
    }

    ObjectType ExternalTextureBase::GetType() const {
        return ObjectType::ExternalTexture;
    }

}  // namespace dawn_native
