/*
 * 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 "src/gpu/graphite/AtlasProvider.h"

#include "include/core/SkSize.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "include/private/SkLog.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ClipAtlasManager.h"
#include "src/gpu/graphite/ComputePathAtlas.h"
#include "src/gpu/graphite/RasterPathAtlas.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/RendererProvider.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/text/TextAtlasManager.h"

#include <utility>

namespace skgpu::graphite {

static bool use_clip_atlas(const Recorder* recorder) {
    // Currently only the raster atlas strategy utilizes the clip atlas.
    return recorder->priv().rendererProvider()->pathRendererStrategy() ==
            PathRendererStrategy::kRasterAtlas;
}

AtlasProvider::AtlasProvider(Recorder* recorder)
        : fTextAtlasManager(std::make_unique<TextAtlasManager>(recorder))
        , fRasterPathAtlas(std::make_unique<RasterPathAtlas>(recorder))
        , fClipAtlasManager(use_clip_atlas(recorder) ? std::make_unique<ClipAtlasManager>(recorder)
                                                     : nullptr) {}

AtlasProvider::~AtlasProvider() = default;

std::unique_ptr<ComputePathAtlas> AtlasProvider::createComputePathAtlas(Recorder* recorder) const {
    if (recorder->priv().caps()->computeSupport()) {
        return ComputePathAtlas::CreateDefault(recorder);
    }
    return nullptr;
}

RasterPathAtlas* AtlasProvider::getRasterPathAtlas() const {
    return fRasterPathAtlas.get();
}

ClipAtlasManager* AtlasProvider::getClipAtlasManager() const {
    return fClipAtlasManager.get();
}

sk_sp<TextureProxy> AtlasProvider::getAtlasTexture(Recorder* recorder,
                                                   uint16_t width,
                                                   uint16_t height,
                                                   SkColorType colorType,
                                                   uint16_t identifier,
                                                   bool requireStorageUsage) {
    uint64_t key = static_cast<uint64_t>(width)  << 48 |
                   static_cast<uint64_t>(height) << 32 |
                   static_cast<uint64_t>(colorType) << 16 |
                   static_cast<uint64_t>(identifier);
    auto iter = fTexturePool.find(key);
    if (iter != fTexturePool.end()) {
        return iter->second;
    }

    // We currently only make the distinction between a storage texture (written by a
    // compute pass) and a plain sampleable texture (written via upload) that won't be
    // used as a render attachment.
    const Caps* caps = recorder->priv().caps();
    auto textureInfo = requireStorageUsage
            ? caps->getDefaultStorageTextureInfo(colorType)
            : caps->getDefaultSampledTextureInfo(colorType,
                                                 Mipmapped::kNo,
                                                 recorder->priv().isProtected(),
                                                 Renderable::kNo);
    sk_sp<TextureProxy> proxy = TextureProxy::Make(caps,
                                                   recorder->priv().resourceProvider(),
                                                   SkISize::Make((int32_t) width, (int32_t) height),
                                                   textureInfo,
                                                   "AtlasProviderTexture",
                                                   Budgeted::kYes);
    if (!proxy) {
        return nullptr;
    }

    fTexturePool[key] = proxy;
    return proxy;
}

void AtlasProvider::freeGpuResources() {
    // Clear out any pages not in use or needed for any pending work on the Recorder.
    // In the event this is called right after a snap(), all pages would be eligible
    // for cleanup anyways.
    fTextAtlasManager->freeGpuResources();
    if (fRasterPathAtlas) {
        fRasterPathAtlas->freeGpuResources();
    }
    if (fClipAtlasManager) {
        fClipAtlasManager->freeGpuResources();
    }
    // Release any textures held directly by the provider. These textures are used by transient
    // ComputePathAtlases that are reset every time a DrawContext snaps a DrawTask so there is no
    // need to reset those atlases explicitly here. Since the AtlasProvider gives out refs to the
    // TextureProxies in the pool, it should be safe to clear the pool in the middle of Recording.
    // Draws that use the previous TextureProxies will have refs on them.
    fTexturePool.clear();
}

void AtlasProvider::recordUploads(DrawContext* dc) {
    if (!fTextAtlasManager->recordUploads(dc)) {
        SKIA_LOG_E("TextAtlasManager uploads have failed -- may see invalid results.");
    }

    if (fRasterPathAtlas) {
        fRasterPathAtlas->recordUploads(dc);
    }
    if (fClipAtlasManager) {
        fClipAtlasManager->recordUploads(dc);
    }
}

void AtlasProvider::compact() {
    fTextAtlasManager->compact();
    if (fRasterPathAtlas) {
        fRasterPathAtlas->compact();
    }
    if (fClipAtlasManager) {
        fClipAtlasManager->compact();
    }
}

void AtlasProvider::invalidateAtlases() {
    // We must also evict atlases on a failure. The failed tasks can include uploads that the
    // atlas was depending on for its caches. Failing to prepare means they will never run so
    // future "successful" Recorder snaps would otherwise reference atlas pages that had stale
    // contents.
    fTextAtlasManager->evictAtlases();
    if (fRasterPathAtlas) {
        fRasterPathAtlas->evictAtlases();
    }
    if (fClipAtlasManager) {
        fClipAtlasManager->evictAtlases();
    }
}

}  // namespace skgpu::graphite
