// Copyright 2020 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/Subresource.h"

#include "common/Assert.h"
#include "dawn_native/Format.h"

namespace dawn::native {

    Aspect ConvertSingleAspect(const Format& format, wgpu::TextureAspect aspect) {
        Aspect aspectMask = ConvertAspect(format, aspect);
        ASSERT(HasOneBit(aspectMask));
        return aspectMask;
    }

    Aspect ConvertAspect(const Format& format, wgpu::TextureAspect aspect) {
        Aspect aspectMask = SelectFormatAspects(format, aspect);
        ASSERT(aspectMask != Aspect::None);
        return aspectMask;
    }

    Aspect ConvertViewAspect(const Format& format, wgpu::TextureAspect aspect) {
        // Color view |format| must be treated as the same plane |aspect|.
        if (format.aspects == Aspect::Color) {
            switch (aspect) {
                case wgpu::TextureAspect::Plane0Only:
                    return Aspect::Plane0;
                case wgpu::TextureAspect::Plane1Only:
                    return Aspect::Plane1;
                default:
                    break;
            }
        }
        return ConvertAspect(format, aspect);
    }

    Aspect SelectFormatAspects(const Format& format, wgpu::TextureAspect aspect) {
        switch (aspect) {
            case wgpu::TextureAspect::All:
                return format.aspects;
            case wgpu::TextureAspect::DepthOnly:
                return format.aspects & Aspect::Depth;
            case wgpu::TextureAspect::StencilOnly:
                return format.aspects & Aspect::Stencil;
            case wgpu::TextureAspect::Plane0Only:
                return format.aspects & Aspect::Plane0;
            case wgpu::TextureAspect::Plane1Only:
                return format.aspects & Aspect::Plane1;
        }
        UNREACHABLE();
    }

    uint8_t GetAspectIndex(Aspect aspect) {
        ASSERT(HasOneBit(aspect));
        switch (aspect) {
            case Aspect::Color:
            case Aspect::Depth:
            case Aspect::Plane0:
            case Aspect::CombinedDepthStencil:
                return 0;
            case Aspect::Plane1:
            case Aspect::Stencil:
                return 1;
            default:
                UNREACHABLE();
        }
    }

    uint8_t GetAspectCount(Aspect aspects) {
        // TODO(crbug.com/dawn/829): This should use popcount once Dawn has such a function.
        // Note that we can't do a switch because compilers complain that Depth | Stencil is not
        // a valid enum value.
        if (aspects == Aspect::Color || aspects == Aspect::Depth ||
            aspects == Aspect::CombinedDepthStencil) {
            return 1;
        } else if (aspects == (Aspect::Plane0 | Aspect::Plane1)) {
            return 2;
        } else {
            ASSERT(aspects == (Aspect::Depth | Aspect::Stencil));
            return 2;
        }
    }

    SubresourceRange::SubresourceRange(Aspect aspects,
                                       FirstAndCountRange<uint32_t> arrayLayerParam,
                                       FirstAndCountRange<uint32_t> mipLevelParams)
        : aspects(aspects),
          baseArrayLayer(arrayLayerParam.first),
          layerCount(arrayLayerParam.count),
          baseMipLevel(mipLevelParams.first),
          levelCount(mipLevelParams.count) {
    }

    SubresourceRange::SubresourceRange()
        : aspects(Aspect::None), baseArrayLayer(0), layerCount(0), baseMipLevel(0), levelCount(0) {
    }

    // static
    SubresourceRange SubresourceRange::SingleMipAndLayer(uint32_t baseMipLevel,
                                                         uint32_t baseArrayLayer,
                                                         Aspect aspects) {
        return {aspects, {baseArrayLayer, 1}, {baseMipLevel, 1}};
    }

    // static
    SubresourceRange SubresourceRange::MakeSingle(Aspect aspect,
                                                  uint32_t baseArrayLayer,
                                                  uint32_t baseMipLevel) {
        ASSERT(HasOneBit(aspect));
        return {aspect, {baseArrayLayer, 1}, {baseMipLevel, 1}};
    }

    // static
    SubresourceRange SubresourceRange::MakeFull(Aspect aspects,
                                                uint32_t layerCount,
                                                uint32_t levelCount) {
        return {aspects, {0, layerCount}, {0, levelCount}};
    }

}  // namespace dawn::native
