/*
 * Copyright 2020 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/ops/SmallPathAtlasMgr.h"

#include "include/core/SkSize.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/private/SkIDChangeListener.h"
#include "include/private/SkTo.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/gpu/MaskFormat.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/geometry/GrStyledShape.h"
#include "src/gpu/ganesh/ops/SmallPathShapeData.h"

#include <cstddef>

#if !defined(SK_ENABLE_OPTIMIZE_SIZE)

#ifdef DF_PATH_TRACKING
static int g_NumCachedShapes = 0;
static int g_NumFreedShapes = 0;
#endif

namespace skgpu::ganesh {

SmallPathAtlasMgr::SmallPathAtlasMgr() {}

SmallPathAtlasMgr::~SmallPathAtlasMgr() {
    this->reset();
}

void SmallPathAtlasMgr::reset() {
    ShapeDataList::Iter iter;
    iter.init(fShapeList, ShapeDataList::Iter::kHead_IterStart);
    SmallPathShapeData* shapeData;
    while ((shapeData = iter.get())) {
        iter.next();
        delete shapeData;
    }

    fShapeList.reset();
    fShapeCache.reset();

#ifdef DF_PATH_TRACKING
    SkDebugf("Cached shapes: %d, freed shapes: %d\n", g_NumCachedShapes, g_NumFreedShapes);
#endif

    fAtlas = nullptr;
}

bool SmallPathAtlasMgr::initAtlas(GrProxyProvider* proxyProvider, const GrCaps* caps) {
    if (fAtlas) {
        return true;
    }

    static constexpr size_t kMaxAtlasTextureBytes = 2048 * 2048;
    static constexpr size_t kPlotWidth = 512;
    static constexpr size_t kPlotHeight = 256;

    GrColorType atlasColorType = GrColorType::kAlpha_8;
    const GrBackendFormat format = caps->getDefaultBackendFormat(atlasColorType,
                                                                 GrRenderable::kNo);

    GrDrawOpAtlasConfig atlasConfig(caps->maxTextureSize(), kMaxAtlasTextureBytes);
    SkISize size = atlasConfig.atlasDimensions(MaskFormat::kA8);
    fAtlas = GrDrawOpAtlas::Make(proxyProvider, format,
                                 GrColorTypeToSkColorType(atlasColorType),
                                 GrColorTypeBytesPerPixel(atlasColorType),
                                 size.width(), size.height(),
                                 kPlotWidth, kPlotHeight, this,
                                 GrDrawOpAtlas::AllowMultitexturing::kYes,
                                 this,
                                 /*label=*/"SmallPathAtlas");

    return SkToBool(fAtlas);
}

void SmallPathAtlasMgr::deleteCacheEntry(SmallPathShapeData* shapeData) {
    fShapeCache.remove(shapeData->fKey);
    fShapeList.remove(shapeData);
    delete shapeData;
}

SmallPathShapeData* SmallPathAtlasMgr::findOrCreate(const SmallPathShapeDataKey& key,
                                                    const GrStyledShape& shape) {
    auto shapeData = fShapeCache.find(key);

    if (shapeData && shapeData->fIDChangeListener->hasChanged()) {
        this->deleteCacheEntry(shapeData);
        shapeData = nullptr;
    }

    if (!shapeData) {
        // TODO: move the key into the ctor
        shapeData = new SmallPathShapeData(key);
        shape.addGenIDChangeListener(shapeData->fIDChangeListener);
        fShapeCache.add(shapeData);
        fShapeList.addToTail(shapeData);
#ifdef DF_PATH_TRACKING
        ++g_NumCachedShapes;
#endif
    } else if (!fAtlas->hasID(shapeData->fAtlasLocator.plotLocator())) {
        shapeData->fAtlasLocator.invalidatePlotLocator();
    }

    return shapeData;
}

SmallPathShapeData* SmallPathAtlasMgr::findOrCreate(const GrStyledShape& shape,
                                                    int desiredDimension) {
    SmallPathShapeDataKey key(shape, desiredDimension);

    // TODO: move the key into 'findOrCreate'
    return this->findOrCreate(key, shape);
}

SmallPathShapeData* SmallPathAtlasMgr::findOrCreate(const GrStyledShape& shape,
                                                    const SkMatrix& ctm) {
    SmallPathShapeDataKey key(shape, ctm);

    // TODO: move the key into 'findOrCreate'
    return this->findOrCreate(key, shape);
}

GrDrawOpAtlas::ErrorCode SmallPathAtlasMgr::addToAtlas(GrResourceProvider* resourceProvider,
                                                       GrDeferredUploadTarget* target,
                                                       int width, int height,
                                                       const void* image,
                                                       GrAtlasLocator* locator) {
    return fAtlas->addToAtlas(resourceProvider, target, width, height, image, locator);
}

void SmallPathAtlasMgr::setUseToken(SmallPathShapeData* shapeData,
                                    skgpu::Token token) {
    fAtlas->setLastUseToken(shapeData->fAtlasLocator, token);
}

// Callback to clear out internal path cache when eviction occurs
void SmallPathAtlasMgr::evict(GrPlotLocator plotLocator) {
    // remove any paths that use this plot
    ShapeDataList::Iter iter;
    iter.init(fShapeList, ShapeDataList::Iter::kHead_IterStart);
    SmallPathShapeData* shapeData;
    while ((shapeData = iter.get())) {
        iter.next();
        if (plotLocator == shapeData->fAtlasLocator.plotLocator()) {
            fShapeCache.remove(shapeData->fKey);
            fShapeList.remove(shapeData);
            delete shapeData;
#ifdef DF_PATH_TRACKING
            ++g_NumFreedShapes;
#endif
        }
    }
}

}  // namespace skgpu::ganesh

#endif // SK_ENABLE_OPTIMIZE_SIZE
