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

#include "GrGpuResourcePriv.h"
#include "GrLayerAtlas.h"
#include "GrRectanizer.h"
#include "GrTextureProvider.h"

///////////////////////////////////////////////////////////////////////////////
GrLayerAtlas::Plot::Plot() 
    : fID(-1)
    , fRects(nullptr) {
    fOffset.set(0, 0);
}

GrLayerAtlas::Plot::~Plot() {
    delete fRects;
}

void GrLayerAtlas::Plot::init(int id, int offX, int offY, int width, int height) {
    fID = id;
    fRects = GrRectanizer::Factory(width, height);
    fOffset.set(offX * width, offY * height);
}

bool GrLayerAtlas::Plot::allocateRect(int width, int height, SkIPoint16* loc) {
    if (!fRects->addRect(width, height, loc)) {
        return false;
    }

    loc->fX += fOffset.fX;
    loc->fY += fOffset.fY;
    return true;
}

void GrLayerAtlas::Plot::reset() {
    SkASSERT(fRects);
    fRects->reset();
}

///////////////////////////////////////////////////////////////////////////////
GR_DECLARE_STATIC_UNIQUE_KEY(gLayerAtlasKey);
static const GrUniqueKey& get_layer_atlas_key() {
    GR_DEFINE_STATIC_UNIQUE_KEY(gLayerAtlasKey);
    return gLayerAtlasKey;
}

bool GrLayerAtlas::reattachBackingTexture() {
    SkASSERT(!fTexture);

    fTexture.reset(fTexProvider->findAndRefTextureByUniqueKey(get_layer_atlas_key()));
    return SkToBool(fTexture);
}

void GrLayerAtlas::createBackingTexture() {
    SkASSERT(!fTexture);

    GrSurfaceDesc desc;
    desc.fFlags = fFlags;
    desc.fWidth = fBackingTextureSize.width();
    desc.fHeight = fBackingTextureSize.height();
    desc.fConfig = fPixelConfig;

    fTexture.reset(fTexProvider->createTexture(desc, SkBudgeted::kYes, nullptr, 0));

    fTexture->resourcePriv().setUniqueKey(get_layer_atlas_key());
}

GrLayerAtlas::GrLayerAtlas(GrTextureProvider* texProvider, GrPixelConfig config, 
                           GrSurfaceFlags flags,
                           const SkISize& backingTextureSize,
                           int numPlotsX, int numPlotsY) {
    fTexProvider = texProvider;
    fPixelConfig = config;
    fFlags = flags;
    fBackingTextureSize = backingTextureSize;

    int textureWidth = fBackingTextureSize.width();
    int textureHeight = fBackingTextureSize.height();

    int plotWidth = textureWidth / numPlotsX;
    int plotHeight = textureHeight / numPlotsY;

    SkASSERT(plotWidth * numPlotsX == textureWidth);
    SkASSERT(plotHeight * numPlotsY == textureHeight);

    // We currently do not support compressed atlases...
    SkASSERT(!GrPixelConfigIsCompressed(config));

    // set up allocated plots
    fPlotArray = new Plot[numPlotsX * numPlotsY];

    Plot* currPlot = fPlotArray;
    for (int y = numPlotsY-1; y >= 0; --y) {
        for (int x = numPlotsX-1; x >= 0; --x) {
            currPlot->init(y*numPlotsX+x, x, y, plotWidth, plotHeight);

            // build LRU list
            fPlotList.addToHead(currPlot);
            ++currPlot;
        }
    }
}

void GrLayerAtlas::resetPlots() {
    PlotIter iter;
    for (Plot* plot = iter.init(fPlotList, PlotIter::kHead_IterStart); plot; plot = iter.next()) {
        plot->reset();
    }
}

GrLayerAtlas::~GrLayerAtlas() {
    delete[] fPlotArray;
}

void GrLayerAtlas::makeMRU(Plot* plot) {
    if (fPlotList.head() == plot) {
        return;
    }

    fPlotList.remove(plot);
    fPlotList.addToHead(plot);
};

GrLayerAtlas::Plot* GrLayerAtlas::addToAtlas(ClientPlotUsage* usage,
                                             int width, int height, SkIPoint16* loc) {
    // Iterate through the plots currently being used by this client and see if we can find a hole.
    // The last one was most recently added and probably most empty.
    // We want to consolidate the uses from individual clients to the same plot(s) so that
    // when a specific client goes away they are more likely to completely empty a plot.
    for (int i = usage->numPlots()-1; i >= 0; --i) {
        Plot* plot = usage->plot(i);
        if (plot->allocateRect(width, height, loc)) {
            this->makeMRU(plot);
            return plot;
        }
    }

    // before we get a new plot, make sure we have a backing texture
    if (nullptr == fTexture) {
        this->createBackingTexture();
        if (nullptr == fTexture) {
            return nullptr;
        }
    }

    // Now look through all allocated plots for one we can share, in MRU order
    // TODO: its seems like traversing from emptiest to fullest would make more sense
    PlotList::Iter plotIter;
    plotIter.init(fPlotList, PlotList::Iter::kHead_IterStart);
    Plot* plot;
    while ((plot = plotIter.get())) {
        if (plot->allocateRect(width, height, loc)) {
            this->makeMRU(plot);
            // new plot for atlas, put at end of array
            usage->appendPlot(plot);
            return plot;
        }
        plotIter.next();
    }

    // If the above fails, then the current plot list has no room
    return nullptr;
}

