/*
 * Copyright 2023 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/gpu/graphite/YUVABackendTextures.h"

#include "include/gpu/graphite/Recorder.h"
#include "include/private/SkAttributes.h"
#include "src/core/SkYUVAInfoLocation.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/TextureInfoPriv.h"

namespace skgpu::graphite {

namespace {
int num_channels(uint32_t ChannelMasks) {
    switch (ChannelMasks) {
        case kRed_SkColorChannelFlag        : return 1;
        case kAlpha_SkColorChannelFlag      : return 1;
        case kGray_SkColorChannelFlag       : return 1;
        case kGrayAlpha_SkColorChannelFlags : return 2;
        case kRG_SkColorChannelFlags        : return 2;
        case kRGB_SkColorChannelFlags       : return 3;
        case kRGBA_SkColorChannelFlags      : return 4;
        default                             : return 0;
    }
    SkUNREACHABLE;
}
}

YUVABackendTextureInfo::YUVABackendTextureInfo(const SkYUVAInfo& yuvaInfo,
                                               SkSpan<const TextureInfo> textureInfo,
                                               Mipmapped mipmapped)
        : fYUVAInfo(yuvaInfo)
        , fMipmapped(mipmapped) {
    int numPlanes = yuvaInfo.numPlanes();
    if (!yuvaInfo.isValid() ||
        numPlanes == 0 ||
        (size_t)numPlanes > textureInfo.size()) {
        *this = {};
        SkASSERT(!this->isValid());
        return;
    }
    for (int i = 0; i < numPlanes; ++i) {
        int numRequiredChannels = yuvaInfo.numChannelsInPlane(i);
        SkASSERT(numRequiredChannels > 0);
        fPlaneChannelMasks[i] = TextureInfoPriv::ChannelMask(textureInfo[i]);
        if (!textureInfo[i].isValid() ||
            textureInfo[i].backend() != textureInfo[0].backend() ||
            num_channels(fPlaneChannelMasks[i]) < numRequiredChannels) {
            *this = {};
            SkASSERT(!this->isValid());
            return;
        }
        fPlaneTextureInfos[i] = textureInfo[i];
    }
    SkASSERT(this->isValid());
}

bool YUVABackendTextureInfo::operator==(const YUVABackendTextureInfo& that) const {
    if (fYUVAInfo != that.fYUVAInfo || fMipmapped != that.fMipmapped) {
        return false;
    }
    return fPlaneTextureInfos == that.fPlaneTextureInfos;
}

SkYUVAInfo::YUVALocations YUVABackendTextureInfo::toYUVALocations() const {
    auto result = fYUVAInfo.toYUVALocations(fPlaneChannelMasks.data());
    SkDEBUGCODE(int numPlanes;)
    SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes));
    SkASSERT(numPlanes == this->numPlanes());
    return result;
}

//////////////////////////////////////////////////////////////////////////////

YUVABackendTextures::YUVABackendTextures(const SkYUVAInfo& yuvaInfo,
                                         SkSpan<const BackendTexture> textures)
        : fYUVAInfo(yuvaInfo) {
    if (!yuvaInfo.isValid()) {
        SkASSERT(!this->isValid());
        return;
    }
    SkISize planeDimensions[kMaxPlanes];
    int numPlanes = yuvaInfo.planeDimensions(planeDimensions);
    if (numPlanes == 0 || (size_t)numPlanes > textures.size()) {
        fYUVAInfo = {};
        SkASSERT(!this->isValid());
        return;
    }
    for (int i = 0; i < numPlanes; ++i) {
        int numRequiredChannels = yuvaInfo.numChannelsInPlane(i);
        SkASSERT(numRequiredChannels > 0);
        fPlaneChannelMasks[i] = TextureInfoPriv::ChannelMask(textures[i].info());
        if (!textures[i].isValid() ||
            textures[i].dimensions() != SK_UNSAFE_TODO(planeDimensions[i]) ||
            textures[i].backend() != textures[0].backend() ||
            num_channels(fPlaneChannelMasks[i]) < numRequiredChannels) {
            SkASSERT(!this->isValid());
            return;
        }
        fPlaneTextures[i] = textures[i];
    }
    SkASSERT(this->isValid());
}

SkYUVAInfo::YUVALocations YUVABackendTextures::toYUVALocations() const {
    auto result = fYUVAInfo.toYUVALocations(fPlaneChannelMasks.data());
    SkDEBUGCODE(int numPlanes;)
    SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes));
    SkASSERT(numPlanes == this->numPlanes());
    return result;
}

}  // End of namespace skgpu::graphite
