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

#include "src/gpu/ccpr/GrCCAtlas.h"

#include "include/private/SkTPin.h"
#include "src/core/SkIPoint16.h"
#include "src/gpu/GrOnFlushResourceProvider.h"
#include "src/gpu/ccpr/GrCCPathCache.h"

static SkISize choose_initial_atlas_size(const GrCCAtlas::Specs& specs) {
    // Begin with the first pow2 dimensions whose area is theoretically large enough to contain the
    // pending paths, favoring height over width if necessary.
    int log2area = SkNextLog2(std::max(specs.fApproxNumPixels, 1));
    int height = 1 << ((log2area + 1) / 2);
    int width = 1 << (log2area / 2);

    width = SkTPin(width, specs.fMinTextureSize, specs.fMaxPreferredTextureSize);
    height = SkTPin(height, specs.fMinTextureSize, specs.fMaxPreferredTextureSize);

    return SkISize::Make(width, height);
}

static int choose_max_atlas_size(const GrCCAtlas::Specs& specs, const GrCaps& caps) {
    return (std::max(specs.fMinHeight, specs.fMinWidth) <= specs.fMaxPreferredTextureSize) ?
            specs.fMaxPreferredTextureSize : caps.maxRenderTargetSize();
}

GrCCAtlas::GrCCAtlas(CoverageType coverageType, const Specs& specs, const GrCaps& caps)
        : GrDynamicAtlas(CoverageTypeToColorType(coverageType),
                         CoverageTypeHasInternalMultisample(coverageType),
                         choose_initial_atlas_size(specs), choose_max_atlas_size(specs, caps), caps)
        , fCoverageType(coverageType) {
    SkASSERT(specs.fMaxPreferredTextureSize > 0);
}

GrCCAtlas::~GrCCAtlas() {
}

void GrCCAtlas::setFillBatchID(int id) {
    // This can't be called anymore once makeRenderTargetContext() has been called.
    SkASSERT(!this->isInstantiated());
    fFillBatchID = id;
}

void GrCCAtlas::setStrokeBatchID(int id) {
    // This can't be called anymore once makeRenderTargetContext() has been called.
    SkASSERT(!this->isInstantiated());
    fStrokeBatchID = id;
}

void GrCCAtlas::setEndStencilResolveInstance(int idx) {
    // This can't be called anymore once makeRenderTargetContext() has been called.
    SkASSERT(!this->isInstantiated());
    fEndStencilResolveInstance = idx;
}

static uint32_t next_atlas_unique_id() {
    static std::atomic<uint32_t> nextID;
    return nextID++;
}

sk_sp<GrCCCachedAtlas> GrCCAtlas::refOrMakeCachedAtlas(GrOnFlushResourceProvider* onFlushRP) {
    if (!fCachedAtlas) {
        static const GrUniqueKey::Domain kAtlasDomain = GrUniqueKey::GenerateDomain();

        GrUniqueKey atlasUniqueKey;
        GrUniqueKey::Builder builder(&atlasUniqueKey, kAtlasDomain, 1, "CCPR Atlas");
        builder[0] = next_atlas_unique_id();
        builder.finish();

        onFlushRP->assignUniqueKeyToProxy(atlasUniqueKey, this->textureProxy());

        fCachedAtlas = sk_make_sp<GrCCCachedAtlas>(fCoverageType, atlasUniqueKey,
                                                   sk_ref_sp(this->textureProxy()));
    }

    SkASSERT(fCachedAtlas->coverageType() == fCoverageType);
    SkASSERT(fCachedAtlas->getOnFlushProxy() == this->textureProxy());
    return fCachedAtlas;
}

GrCCAtlas* GrCCAtlasStack::addRect(const SkIRect& devIBounds, SkIVector* devToAtlasOffset) {
    GrCCAtlas* retiredAtlas = nullptr;
    SkIPoint16 location;
    if (fAtlases.empty() ||
        !fAtlases.back().addRect(devIBounds.width(), devIBounds.height(), &location)) {
        // The retired atlas is out of room and can't grow any bigger.
        retiredAtlas = !fAtlases.empty() ? &fAtlases.back() : nullptr;
        fAtlases.emplace_back(fCoverageType, fSpecs, *fCaps);
        SkASSERT(devIBounds.width() <= fSpecs.fMinWidth);
        SkASSERT(devIBounds.height() <= fSpecs.fMinHeight);
        SkAssertResult(fAtlases.back().addRect(devIBounds.width(), devIBounds.height(), &location));
    }
    devToAtlasOffset->set(location.x() - devIBounds.left(), location.y() - devIBounds.top());
    return retiredAtlas;
}
