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