/*
 * Copyright 2022 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/graphite/text/TextAtlasManager.h"

#include "include/core/SkColorType.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkSpan.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "include/private/SkDebug.h"
#include "include/private/SkMalloc.h"
#include "include/private/SkTLogic.h"
#include "src/core/SkAutoMalloc.h"
#include "src/core/SkDistanceFieldGen.h"
#include "src/core/SkGlyph.h"
#include "src/core/SkMask.h"
#include "src/core/SkMasks.h"
#include "src/core/SkStrikeSpec.h"
#include "src/gpu/graphite/AtlasProvider.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/DrawAtlas.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/TextureProxy.h"  // IWYU pragma: keep
#include "src/gpu/graphite/text/GlyphData.h"
#include "src/sksl/SkSLUtil.h"
#include "src/text/gpu/GlyphUtils.h"
#include "src/text/gpu/StrikeCache.h"

#include <cstring>
#include <new>
#include <tuple>

using Glyph = skgpu::graphite::Glyph;

namespace skgpu::graphite {

using AtlasConfig = TextAtlasManager::AtlasConfig;

AtlasConfig::AtlasConfig(int maxTextureSize, size_t maxBytes) {
    static const SkISize kARGBDimensions[] = {
            {256, 256},    // maxBytes < 2^19
            {512, 256},    // 2^19 <= maxBytes < 2^20
            {512, 512},    // 2^20 <= maxBytes < 2^21
            {1024, 512},   // 2^21 <= maxBytes < 2^22
            {1024, 1024},  // 2^22 <= maxBytes < 2^23
            {2048, 1024},  // 2^23 <= maxBytes
    };

    // Index 0 corresponds to maxBytes of 2^18, so start by dividing it by that
    maxBytes >>= 18;
    // Take the floor of the log to get the index
    int index = maxBytes > 0
        ? SkTPin<int>(SkPrevLog2(maxBytes), 0, std::size(kARGBDimensions) - 1)
        : 0;

    SkASSERT(kARGBDimensions[index].width() <= kMaxAtlasDim);
    SkASSERT(kARGBDimensions[index].height() <= kMaxAtlasDim);
    fARGBDimensions.set(std::min<int>(kARGBDimensions[index].width(), maxTextureSize),
                        std::min<int>(kARGBDimensions[index].height(), maxTextureSize));
    fMaxTextureSize = std::min<int>(maxTextureSize, kMaxAtlasDim);
}

SkISize AtlasConfig::atlasDimensions(MaskFormat type) const {
    if (MaskFormat::kA8 == type) {
        // A8 is always 2x the ARGB dimensions, clamped to the max allowed texture size
        return {std::min<int>(2 * fARGBDimensions.width(), fMaxTextureSize),
                std::min<int>(2 * fARGBDimensions.height(), fMaxTextureSize)};
    } else {
        return fARGBDimensions;
    }
}

SkISize AtlasConfig::plotDimensions(MaskFormat type) const {
    if (MaskFormat::kA8 == type) {
        SkISize atlasDimensions = this->atlasDimensions(type);
        // For A8 we want to grow the plots at larger texture sizes to accept more of the
        // larger SDF glyphs. Since the largest SDF glyph can be 170x170 with padding, this
        // allows us to pack 3 in a 512x256 plot, or 9 in a 512x512 plot.

        // This will give us 512x256 plots for 2048x1024, 512x512 plots for 2048x2048,
        // and 256x256 plots otherwise.
        int plotWidth = atlasDimensions.width() >= 2048 ? 512 : 256;
        int plotHeight = atlasDimensions.height() >= 2048 ? 512 : 256;

        return {plotWidth, plotHeight};
    } else {
        // ARGB and LCD always use 256x256 plots -- this has been shown to be faster
        return {256, 256};
    }
}

TextAtlasManager::TextAtlasManager(Recorder* recorder)
        : fRecorder(recorder)
        , fSupportBilerpAtlas{recorder->priv().caps()->supportBilerpFromGlyphAtlas()}
        , fAtlasConfig{recorder->priv().caps()->maxTextureSize(),
                       recorder->priv().caps()->glyphCacheTextureMaximumBytes()} {
    if (!recorder->priv().caps()->allowMultipleAtlasTextures() ||
        // multitexturing supported only if range can represent the index + texcoords fully
        !(recorder->priv().caps()->shaderCaps()->fFloatIs32Bits ||
          recorder->priv().caps()->shaderCaps()->fIntegerSupport)) {
        fAllowMultitexturing = DrawAtlas::AllowMultitexturing::kNo;
    } else {
        fAllowMultitexturing = DrawAtlas::AllowMultitexturing::kYes;
    }
}

TextAtlasManager::~TextAtlasManager() = default;

void TextAtlasManager::freeGpuResources() {
    auto tokenTracker = fRecorder->priv().tokenTracker();
    for (int i = 0; i < kMaskFormatCount; ++i) {
        if (fAtlases[i]) {
            fAtlases[i]->freeGpuResources(tokenTracker->nextFlushToken());
        }
    }
}

bool TextAtlasManager::hasGlyph(const GlyphEntry& glyph) {
    return this->getAtlas(glyph.fKey.maskFormat())->hasID(glyph.fAtlasLocator.plotLocator());
}

template <typename INT_TYPE>
static void expand_bits(INT_TYPE* dst,
                        const uint8_t* src,
                        int width,
                        int height,
                        int dstRowBytes,
                        int srcRowBytes) {
    for (int y = 0; y < height; ++y) {
        int rowWritesLeft = width;
        const uint8_t* s = src;
        INT_TYPE* d = dst;
        while (rowWritesLeft > 0) {
            unsigned mask = *s++;
            for (int x = 7; x >= 0 && rowWritesLeft; --x, --rowWritesLeft) {
                *d++ = (mask & (1 << x)) ? (INT_TYPE)(~0UL) : 0;
            }
        }
        dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
        src += srcRowBytes;
    }
}

static void get_packed_glyph_image(
        const SkGlyph& glyph, int dstRB, MaskFormat expectedMaskFormat, void* dst) {
    const int width = glyph.width();
    const int height = glyph.height();
    const void* src = glyph.image();
    SkASSERT(src != nullptr);

    MaskFormat maskFormat = sktext::gpu::FormatFromSkGlyph(glyph.maskFormat());
    if (maskFormat == expectedMaskFormat) {
        int srcRB = glyph.rowBytes();
        // Notice this comparison is with the glyphs raw mask format, and not its MaskFormat.
        if (glyph.maskFormat() != SkMask::kBW_Format) {
            if (srcRB != dstRB) {
                const int bbp = MaskFormatBytesPerPixel(expectedMaskFormat);
                for (int y = 0; y < height; y++) {
                    memcpy(dst, src, width * bbp);
                    src = (const char*) src + srcRB;
                    dst = (char*) dst + dstRB;
                }
            } else {
                memcpy(dst, src, dstRB * height);
            }
        } else {
            // Handle 8-bit format by expanding the mask to the expected format.
            const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
            switch (expectedMaskFormat) {
                case MaskFormat::kA8: {
                    uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
                    expand_bits(bytes, bits, width, height, dstRB, srcRB);
                    break;
                }
                case MaskFormat::kA565: {
                    uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
                    expand_bits(rgb565, bits, width, height, dstRB, srcRB);
                    break;
                }
                default:
                    SK_ABORT("Invalid MaskFormat");
            }
        }
    } else if (maskFormat == MaskFormat::kA565 &&
               expectedMaskFormat == MaskFormat::kARGB) {
        // Convert if the glyph uses a 565 mask format since it is using LCD text rendering
        // but the expected format is 8888 (will happen on Intel MacOS with Metal since that
        // combination does not support 565).
        static constexpr SkMasks masks{
                {0b1111'1000'0000'0000, 11, 5},  // Red
                {0b0000'0111'1110'0000,  5, 6},  // Green
                {0b0000'0000'0001'1111,  0, 5},  // Blue
                {0, 0, 0}                        // Alpha
        };
        constexpr int a565Bpp = MaskFormatBytesPerPixel(MaskFormat::kA565);
        constexpr int argbBpp = MaskFormatBytesPerPixel(MaskFormat::kARGB);
        constexpr bool kBGRAIsNative = kN32_SkColorType == kBGRA_8888_SkColorType;
        char* dstRow = (char*)dst;
        for (int y = 0; y < height; y++) {
            dst = dstRow;
            for (int x = 0; x < width; x++) {
                uint16_t color565 = 0;
                memcpy(&color565, src, a565Bpp);
                uint32_t color8888;
                // On Windows (and possibly others), font data is stored as BGR.
                // So we need to swizzle the data to reflect that.
                if (kBGRAIsNative) {
                    color8888 = masks.getBlue(color565) |
                                (masks.getGreen(color565) << 8) |
                                (masks.getRed(color565) << 16) |
                                (0xFF << 24);
                } else {
                    color8888 = masks.getRed(color565) |
                                (masks.getGreen(color565) << 8) |
                                (masks.getBlue(color565) << 16) |
                                (0xFF << 24);
                }
                memcpy(dst, &color8888, argbBpp);
                src = (const char*)src + a565Bpp;
                dst = (      char*)dst + argbBpp;
            }
            dstRow += dstRB;
        }
    } else {
        SkUNREACHABLE;
    }
}

MaskFormat TextAtlasManager::resolveMaskFormat(MaskFormat format) const {
    if (MaskFormat::kA565 == format &&
        !fRecorder->priv().caps()->getDefaultSampledTextureInfo(kRGB_565_SkColorType,
                                                                /*mipmapped=*/Mipmapped::kNo,
                                                                Protected::kNo,
                                                                Renderable::kNo).isValid()) {
        format = MaskFormat::kARGB;
    }
    return format;
}

// Returns kSucceeded if glyph successfully added to texture atlas, kTryAgain if a RenderPassTask
// needs to be snapped before adding the glyph, and kError if it can't be added at all.
DrawAtlas::ErrorCode TextAtlasManager::addGlyphToAtlas(const SkGlyph& skGlyph, GlyphEntry* glyph) {
    if (skGlyph.image() == nullptr) {
        return DrawAtlas::ErrorCode::kError;
    }
    SkASSERT(glyph != nullptr);

    const int srcPadding = glyph->fKey.padding();

#if !defined(SK_DISABLE_SDF_TEXT)
    SkDEBUGCODE(const bool skGlyphIsSDF = skGlyph.maskFormat() == SkMask::Format::kSDF_Format;)
    SkASSERT(0 <= srcPadding && srcPadding <= SK_DistanceFieldInset);
    SkASSERT(skGlyphIsSDF == glyph->fKey.isSDF());
#else
    SkASSERT(0 <= srcPadding);
    SkASSERT(!glyph->fKey.isSDF());
#endif

    const MaskFormat expectedMaskFormat = glyph->fKey.maskFormat();
    SkASSERT(expectedMaskFormat == this->resolveMaskFormat(glyph->fKey.maskFormat()));

    int bytesPerPixel = MaskFormatBytesPerPixel(expectedMaskFormat);

    int padding;
    switch (srcPadding) {
        case 0:
            // The direct mask/image case; lifting to 1px padding should have happened earlier when
            // the glyph key was created.
            SkASSERT(!fSupportBilerpAtlas);
            padding = 0;
            break;
        case 1:
            // The transformed mask/image case.
            padding = 1;
            break;
#if !defined(SK_DISABLE_SDF_TEXT)
        case SK_DistanceFieldInset:
            // The SDFT case.
            SkASSERT(glyph->fKey.isSDF());
            // If the srcPadding == SK_DistanceFieldInset (SDFT case) then the padding is built
            // into the image on the glyph; no extra padding needed.
            // TODO: can the SDFT glyph image in the cache be reduced by the padding?
            padding = 0;
            break;
#endif
        default:
            // The padding is not one of the know forms.
            return DrawAtlas::ErrorCode::kError;
    }

    const int width = skGlyph.width() + 2*padding;
    const int height = skGlyph.height() + 2*padding;

    // Verify that the glyph data (received from potentially untrusted source) actually has room
    // for the padding. Under normal flow, this should always be the case, but if a glyph was
    // corrupted or manipulated it has no bearing on the code that *should* have produced the glyph.
    // It's strict comparison since equality would imply the original glyph was empty, which should
    // have been dropped.
    SkASSERT_RELEASE(width > 2*srcPadding && height > 2*srcPadding);

    int rowBytes = width * bytesPerPixel;
    size_t size = height * rowBytes;

    // Temporary storage for normalizing glyph image.
    SkAutoSMalloc<1024> storage(size);
    void* dataPtr = storage.get();
    if (padding > 0) {
        sk_bzero(dataPtr, size);
        // Advance in one row and one column.
        dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel;
    }

    get_packed_glyph_image(skGlyph, rowBytes, expectedMaskFormat, dataPtr);

    DrawAtlas* atlas = this->getAtlas(expectedMaskFormat);
    auto errorCode = atlas->addToAtlas(fRecorder,
                                       width,
                                       height,
                                       storage.get(),
                                       &glyph->fAtlasLocator);

    if (errorCode == DrawAtlas::ErrorCode::kSucceeded) {
        glyph->fAtlasLocator.insetSrc(srcPadding);
    }

    return errorCode;
}

bool TextAtlasManager::recordUploads(DrawContext* dc) {
    for (int i = 0; i < skgpu::kMaskFormatCount; i++) {
        if (fAtlases[i] && !fAtlases[i]->recordUploads(dc, fRecorder)) {
            return false;
        }
    }

    return true;
}

void TextAtlasManager::addGlyphToBulkAndSetUseToken(DrawAtlas::BulkUsePlotUpdater* updater,
                                                    const GlyphEntry& glyph,
                                                    Token token) {
    if (updater->add(glyph.fAtlasLocator)) {
        this->getAtlas(glyph.fKey.maskFormat())->setLastUseToken(glyph.fAtlasLocator, token);
    }
}

void TextAtlasManager::setAtlasDimensionsToMinimum_ForTesting() {
    // Delete any old atlases.
    // This should be safe to do as long as we are not in the middle of a flush.
    for (int i = 0; i < skgpu::kMaskFormatCount; i++) {
        fAtlases[i] = nullptr;
    }

    // Set all the atlas sizes to 1x1 plot each.
    new (&fAtlasConfig) AtlasConfig{2048, 0};
}

bool TextAtlasManager::initAtlas(MaskFormat resolvedMaskFormat) {
    SkASSERT(resolvedMaskFormat == this->resolveMaskFormat(resolvedMaskFormat));

    int index = MaskFormatToAtlasIndex(resolvedMaskFormat);
    if (fAtlases[index] == nullptr) {
        SkISize atlasDimensions = fAtlasConfig.atlasDimensions(resolvedMaskFormat);
        SkISize plotDimensions = fAtlasConfig.plotDimensions(resolvedMaskFormat);
        fAtlases[index] = DrawAtlas::Make(resolvedMaskFormat,
                                          atlasDimensions.width(), atlasDimensions.height(),
                                          plotDimensions.width(), plotDimensions.height(),
                                          /*generationCounter=*/this,
                                          fAllowMultitexturing,
                                          DrawAtlas::UseStorageTextures::kNo,
                                          /*evictor=*/nullptr,
                                          /*label=*/"TextAtlas");
        if (!fAtlases[index]) {
            return false;
        }
    }
    return true;
}

void TextAtlasManager::compact() {
    auto tokenTracker = fRecorder->priv().tokenTracker();
    for (int i = 0; i < kMaskFormatCount; ++i) {
        if (fAtlases[i]) {
            fAtlases[i]->compact(tokenTracker->nextFlushToken());
        }
    }
}

}  // namespace skgpu::graphite
