/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
#define ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H

#include <utils/Errors.h>
#include <utils/LinearAllocator.h>
#include <utils/Vector.h>
#include <utils/TinyHashMap.h>

#include "Matrix.h"
#include "OpenGLRenderer.h"
#include "Rect.h"

class SkBitmap;

namespace android {
namespace uirenderer {

class ClipOp;
class DrawOp;
class SaveOp;
class SaveLayerOp;
class StateOp;

class DeferredDisplayState;

class Batch;
class DrawBatch;
class MergingDrawBatch;

typedef const void* mergeid_t;

class DeferredDisplayState {
public:
    /** static void* operator new(size_t size); PURPOSELY OMITTED **/
    static void* operator new(size_t size, LinearAllocator& allocator) {
        return allocator.alloc(size);
    }

    // global op bounds, mapped by mMatrix to be in screen space coordinates, clipped
    Rect mBounds;

    // the below are set and used by the OpenGLRenderer at record and deferred playback
    bool mClipValid;
    Rect mClip;
    int mClipSideFlags; // specifies which sides of the bounds are clipped, unclipped if cleared
    bool mClipped;
    mat4 mMatrix;
    DrawModifiers mDrawModifiers;
    float mAlpha;
    const RoundRectClipState* mRoundRectClipState;
};

class OpStatePair {
public:
    OpStatePair()
            : op(NULL), state(NULL) {}
    OpStatePair(DrawOp* newOp, const DeferredDisplayState* newState)
            : op(newOp), state(newState) {}
    OpStatePair(const OpStatePair& other)
            : op(other.op), state(other.state) {}
    DrawOp* op;
    const DeferredDisplayState* state;
};

class DeferredDisplayList {
    friend class DeferStateStruct; // used to give access to allocator
public:
    DeferredDisplayList(const Rect& bounds, bool avoidOverdraw = true) :
            mBounds(bounds), mAvoidOverdraw(avoidOverdraw) {
        clear();
    }
    ~DeferredDisplayList() { clear(); }

    enum OpBatchId {
        kOpBatch_None = 0, // Don't batch
        kOpBatch_Bitmap,
        kOpBatch_Patch,
        kOpBatch_AlphaVertices,
        kOpBatch_Vertices,
        kOpBatch_AlphaMaskTexture,
        kOpBatch_Text,
        kOpBatch_ColorText,

        kOpBatch_Count, // Add other batch ids before this
    };

    bool isEmpty() { return mBatches.isEmpty(); }

    /**
     * Plays back all of the draw ops recorded into batches to the renderer.
     * Adjusts the state of the renderer as necessary, and restores it when complete
     */
    status_t flush(OpenGLRenderer& renderer, Rect& dirty);

    void addClip(OpenGLRenderer& renderer, ClipOp* op);
    void addSaveLayer(OpenGLRenderer& renderer, SaveLayerOp* op, int newSaveCount);
    void addSave(OpenGLRenderer& renderer, SaveOp* op, int newSaveCount);
    void addRestoreToCount(OpenGLRenderer& renderer, StateOp* op, int newSaveCount);

    /**
     * Add a draw op into the DeferredDisplayList, reordering as needed (for performance) if
     * disallowReorder is false, respecting draw order when overlaps occur.
     */
    void addDrawOp(OpenGLRenderer& renderer, DrawOp* op);

private:
    DeferredDisplayList(const DeferredDisplayList& other); // disallow copy

    DeferredDisplayState* createState() {
        return new (mAllocator) DeferredDisplayState();
    }

    void tryRecycleState(DeferredDisplayState* state) {
        mAllocator.rewindIfLastAlloc(state, sizeof(DeferredDisplayState));
    }

    /**
     * Resets the batching back-pointers, creating a barrier in the operation stream so that no ops
     * added in the future will be inserted into a batch that already exist.
     */
    void resetBatchingState();

    void clear();

    void storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op);
    void storeRestoreToCountBarrier(OpenGLRenderer& renderer, StateOp* op, int newSaveCount);

    bool recordingComplexClip() const { return mComplexClipStackStart >= 0; }

    int getStateOpDeferFlags() const;
    int getDrawOpDeferFlags() const;

    void discardDrawingBatches(const unsigned int maxIndex);

    // layer space bounds of rendering
    Rect mBounds;
    const bool mAvoidOverdraw;

    /**
     * At defer time, stores the *defer time* savecount of save/saveLayer ops that were deferred, so
     * that when an associated restoreToCount is deferred, it can be recorded as a
     * RestoreToCountBatch
     */
    Vector<int> mSaveStack;
    int mComplexClipStackStart;

    Vector<Batch*> mBatches;

    // Maps batch ids to the most recent *non-merging* batch of that id
    Batch* mBatchLookup[kOpBatch_Count];

    // Points to the index after the most recent barrier
    int mEarliestBatchIndex;

    // Points to the first index that may contain a pure drawing batch
    int mEarliestUnclearedIndex;

    /**
     * Maps the mergeid_t returned by an op's getMergeId() to the most recently seen
     * MergingDrawBatch of that id. These ids are unique per draw type and guaranteed to not
     * collide, which avoids the need to resolve mergeid collisions.
     */
    TinyHashMap<mergeid_t, DrawBatch*> mMergingBatches[kOpBatch_Count];

    LinearAllocator mAllocator;
};

/**
 * Struct containing information that instructs the defer
 */
struct DeferInfo {
public:
    DeferInfo() :
            batchId(DeferredDisplayList::kOpBatch_None),
            mergeId((mergeid_t) -1),
            mergeable(false),
            opaqueOverBounds(false) {
    };

    int batchId;
    mergeid_t mergeId;
    bool mergeable;
    bool opaqueOverBounds; // opaque over bounds in DeferredDisplayState - can skip ops below
};

}; // namespace uirenderer
}; // namespace android

#endif // ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
