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

#ifndef GrClipMaskCache_DEFINED
#define GrClipMaskCache_DEFINED

#include "GrContext.h"
#include "SkClipStack.h"
#include "SkTypes.h"

class GrTexture;

/**
 * The stencil buffer stores the last clip path - providing a single entry
 * "cache". This class provides similar functionality for AA clip paths
 */
class GrClipMaskCache : SkNoncopyable {
public:
    GrClipMaskCache();

    ~GrClipMaskCache() {

        while (!fStack.empty()) {
            GrClipStackFrame* temp = (GrClipStackFrame*) fStack.back();
            temp->~GrClipStackFrame();
            fStack.pop_back();
        }
    }

    bool canReuse(int32_t clipGenID, const SkIRect& bounds) {

        SkASSERT(clipGenID != SkClipStack::kWideOpenGenID);
        SkASSERT(clipGenID != SkClipStack::kEmptyGenID);

        GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();

        // We could reuse the mask if bounds is a subset of last bounds. We'd have to communicate
        // an offset to the caller.
        if (back->fLastMask &&
            !back->fLastMask->wasDestroyed() &&
            back->fLastBound == bounds &&
            back->fLastClipGenID == clipGenID) {
            return true;
        }

        return false;
    }

    void reset() {
        if (fStack.empty()) {
//            SkASSERT(false);
            return;
        }

        GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();

        back->reset();
    }

    /**
     * After a "push" the clip state is entirely open. Currently, the
     * entire clip stack will be re-rendered into a new clip mask.
     * TODO: can we take advantage of the nested nature of the clips to
     * reduce the mask creation cost?
     */
    void push();

    void pop() {
        //SkASSERT(!fStack.empty());

        if (!fStack.empty()) {
            GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();

            back->~GrClipStackFrame();
            fStack.pop_back();
        }
    }

    int32_t getLastClipGenID() const {

        if (fStack.empty()) {
            return SkClipStack::kInvalidGenID;
        }

        return ((GrClipStackFrame*) fStack.back())->fLastClipGenID;
    }

    GrTexture* getLastMask() {

        if (fStack.empty()) {
            SkASSERT(false);
            return NULL;
        }

        GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();

        return back->fLastMask;
    }

    const GrTexture* getLastMask() const {

        if (fStack.empty()) {
            SkASSERT(false);
            return NULL;
        }

        GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();

        return back->fLastMask;
    }

    void acquireMask(int32_t clipGenID,
                     const GrSurfaceDesc& desc,
                     const SkIRect& bound) {

        if (fStack.empty()) {
            SkASSERT(false);
            return;
        }

        GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();

        back->acquireMask(fContext, clipGenID, desc, bound);
    }

    int getLastMaskWidth() const {

        if (fStack.empty()) {
            SkASSERT(false);
            return -1;
        }

        GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();

        if (NULL == back->fLastMask) {
            return -1;
        }

        return back->fLastMask->width();
    }

    int getLastMaskHeight() const {

        if (fStack.empty()) {
            SkASSERT(false);
            return -1;
        }

        GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();

        if (NULL == back->fLastMask) {
            return -1;
        }

        return back->fLastMask->height();
    }

    void getLastBound(SkIRect* bound) const {

        if (fStack.empty()) {
            SkASSERT(false);
            bound->setEmpty();
            return;
        }

        GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();

        *bound = back->fLastBound;
    }

    void setContext(GrContext* context) {
        fContext = context;
    }

    GrContext* getContext() {
        return fContext;
    }

    //  TODO: Remove this when we hold cache keys instead of refs to textures.
    void purgeResources() {
        SkDeque::F2BIter iter(fStack);
        for (GrClipStackFrame* frame = (GrClipStackFrame*) iter.next();
                frame != NULL;
                frame = (GrClipStackFrame*) iter.next()) {
            frame->reset();
        }
    }

private:
    struct GrClipStackFrame {

        GrClipStackFrame() {
            this->reset();
        }

        void acquireMask(GrContext* context,
                         int32_t clipGenID,
                         const GrSurfaceDesc& desc,
                         const SkIRect& bound) {

            fLastClipGenID = clipGenID;

            // HACK: set the last param to true to indicate that this request is at
            // flush time and therefore we require a scratch texture with no pending IO operations.
            fLastMask.reset(context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch,
                                                       /*flushing=*/true));

            fLastBound = bound;
        }

        void reset () {
            fLastClipGenID = SkClipStack::kInvalidGenID;

            GrSurfaceDesc desc;

            fLastMask.reset(NULL);
            fLastBound.setEmpty();
        }

        int32_t                 fLastClipGenID;
        // The mask's width & height values are used by GrClipMaskManager to correctly scale the
        // texture coords for the geometry drawn with this mask. TODO: This should be a cache key
        // and not a hard ref to a texture.
        SkAutoTUnref<GrTexture> fLastMask;
        // fLastBound stores the bounding box of the clip mask in clip-stack space. This rect is
        // used by GrClipMaskManager to position a rect and compute texture coords for the mask.
        SkIRect                 fLastBound;
    };

    GrContext*   fContext;
    SkDeque      fStack;

    typedef SkNoncopyable INHERITED;
};

#endif // GrClipMaskCache_DEFINED
