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

#include "src/gpu/ganesh/GrYUVATextureProxies.h"

#ifdef SK_DEBUG
static int num_channels(uint32_t channelFlags) {
    switch (channelFlags) {
        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:
            SkDEBUGFAILF("Unexpected channel combination 0x%08x", channelFlags);
            return 0;
    }
}
#endif

GrYUVATextureProxies::GrYUVATextureProxies(const SkYUVAInfo& yuvaInfo,
                                           sk_sp<GrSurfaceProxy> proxies[SkYUVAInfo::kMaxPlanes],
                                           GrSurfaceOrigin textureOrigin)
        : fYUVAInfo(yuvaInfo), fTextureOrigin(textureOrigin) {
    int n = yuvaInfo.numPlanes();
    if (n == 0) {
        *this = {};
        SkASSERT(!this->isValid());
        return;
    }
    uint32_t textureChannelMasks[SkYUVAInfo::kMaxPlanes];
    for (int i = 0; i < n; ++i) {
        if (!proxies[i]) {
            *this = {};
            SkASSERT(!this->isValid());
            return;
        }
        textureChannelMasks[i] = proxies[i]->backendFormat().channelMask();
    }
    fYUVALocations = yuvaInfo.toYUVALocations(textureChannelMasks);
    if (fYUVALocations[0].fPlane < 0) {
        *this = {};
        SkASSERT(!this->isValid());
        return;
    }
    fMipmapped = GrMipmapped::kYes;
    for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
        if (!proxies[i]) {
            *this = {};
            SkASSERT(!this->isValid());
            return;
        }
        SkASSERT(proxies[i]->asTextureProxy());
        if (proxies[i]->asTextureProxy()->mipmapped() == GrMipmapped::kNo) {
            fMipmapped = GrMipmapped::kNo;
        }
        fProxies[i] = std::move(proxies[i]);
    }
    SkASSERT(this->isValid());
}

GrYUVATextureProxies::GrYUVATextureProxies(const SkYUVAInfo& yuvaInfo,
                                           GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes],
                                           GrColorType colorTypes[SkYUVAInfo::kMaxPlanes])
        : fYUVAInfo(yuvaInfo) {
    uint32_t pixmapChannelMasks[SkYUVAInfo::kMaxPlanes];
    int n = yuvaInfo.numPlanes();
    if (n == 0) {
        *this = {};
        SkASSERT(!this->isValid());
        return;
    }
    fMipmapped = GrMipmapped::kYes;
    for (int i = 0; i < n; ++i) {
        pixmapChannelMasks[i] = GrColorTypeChannelFlags(colorTypes[i]);
        SkASSERT(num_channels(pixmapChannelMasks[i]) <=
                 num_channels(views[i].proxy()->backendFormat().channelMask()));
        if (!views[i] || views[i].origin() != views[0].origin()) {
            *this = {};
            SkASSERT(!this->isValid());
            return;
        }
        if (views[i].proxy()->asTextureProxy()->mipmapped() == GrMipmapped::kNo) {
            fMipmapped = GrMipmapped::kNo;
        }
    }
    // Initial locations refer to the CPU pixmap channels.
    fYUVALocations = yuvaInfo.toYUVALocations(pixmapChannelMasks);
    if (fYUVALocations[0].fPlane < 0) {
        *this = {};
        SkASSERT(!this->isValid());
        return;
    }

    // Run each location through the proxy view's swizzle to get the actual texture format channel.
    for (int i = 0; i < SkYUVAInfo::kYUVAChannelCount; ++i) {
        int plane = fYUVALocations[i].fPlane;
        if (plane >= 0) {
            int chanAsIdx = static_cast<int>(fYUVALocations[i].fChannel);
            switch (views[plane].swizzle()[chanAsIdx]) {
                case 'r': fYUVALocations[i].fChannel = SkColorChannel::kR; break;
                case 'g': fYUVALocations[i].fChannel = SkColorChannel::kG; break;
                case 'b': fYUVALocations[i].fChannel = SkColorChannel::kB; break;
                case 'a': fYUVALocations[i].fChannel = SkColorChannel::kA; break;

                default:
                    SkDEBUGFAILF("Unexpected swizzle value: %c", views[i].swizzle()[chanAsIdx]);
                    *this = {};
                    SkASSERT(!this->isValid());
                    return;
            }
        }
    }
    for (int i = 0; i < n; ++i) {
        fProxies[i] = views[i].detachProxy();
    }
    fTextureOrigin = views[0].origin();
    SkASSERT(this->isValid());
}
