/*
 * 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_TESSELLATION_CACHE_H
#define ANDROID_HWUI_TESSELLATION_CACHE_H

#include <utils/LruCache.h>
#include <utils/Mutex.h>

#include "Debug.h"
#include "utils/Macros.h"
#include "utils/Pair.h"

class SkBitmap;
class SkCanvas;
class SkPaint;
class SkPath;
struct SkRect;

namespace android {
namespace uirenderer {

class Caches;
class VertexBuffer;

///////////////////////////////////////////////////////////////////////////////
// Classes
///////////////////////////////////////////////////////////////////////////////

class TessellationCache {
public:
    typedef Pair<VertexBuffer*, VertexBuffer*> vertexBuffer_pair_t;

    struct Description {
        DESCRIPTION_TYPE(Description);
        enum Type {
            kNone,
            kRoundRect,
        };

        Type type;
        float scaleX;
        float scaleY;
        bool aa;
        SkPaint::Cap cap;
        SkPaint::Style style;
        float strokeWidth;
        union Shape {
            struct RoundRect {
                float width;
                float height;
                float rx;
                float ry;
            } roundRect;
        } shape;

        Description();
        Description(Type type, const Matrix4& transform, const SkPaint& paint);
        hash_t hash() const;
        void setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const;
    };

    struct ShadowDescription {
        DESCRIPTION_TYPE(ShadowDescription);
        const void* nodeKey;
        float matrixData[16];

        ShadowDescription();
        ShadowDescription(const void* nodeKey, const Matrix4* drawTransform);
        hash_t hash() const;
    };

    TessellationCache();
    ~TessellationCache();

    /**
     * Clears the cache. This causes all TessellationBuffers to be deleted.
     */
    void clear();

    /**
     * Sets the maximum size of the cache in bytes.
     */
    void setMaxSize(uint32_t maxSize);
    /**
     * Returns the maximum size of the cache in bytes.
     */
    uint32_t getMaxSize();
    /**
     * Returns the current size of the cache in bytes.
     */
    uint32_t getSize();

    /**
     * Trims the contents of the cache, removing items until it's under its
     * specified limit.
     *
     * Trimming is used for caches that support pre-caching from a worker
     * thread. During pre-caching the maximum limit of the cache can be
     * exceeded for the duration of the frame. It is therefore required to
     * trim the cache at the end of the frame to keep the total amount of
     * memory used under control.
     *
     * Also removes transient Shadow VertexBuffers, which aren't cached between frames.
     */
    void trim();

    // TODO: precache/get for Oval, Lines, Points, etc.

    void precacheRoundRect(const Matrix4& transform, const SkPaint& paint,
            float width, float height, float rx, float ry) {
        getRoundRectBuffer(transform, paint, width, height, rx, ry);
    }
    const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint,
            float width, float height, float rx, float ry);

    void precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
            bool opaque, const SkPath* casterPerimeter,
            const Matrix4* transformXY, const Matrix4* transformZ,
            const Vector3& lightCenter, float lightRadius);

    void getShadowBuffers(const Matrix4* drawTransform, const Rect& localClip,
            bool opaque, const SkPath* casterPerimeter,
            const Matrix4* transformXY, const Matrix4* transformZ,
            const Vector3& lightCenter, float lightRadius,
            vertexBuffer_pair_t& outBuffers);

private:
    class Buffer;
    class TessellationTask;
    class TessellationProcessor;

    typedef VertexBuffer* (*Tessellator)(const Description&);

    Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint,
            float width, float height);
    Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint,
            float width, float height, float rx, float ry);

    Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator);

    uint32_t mSize;
    uint32_t mMaxSize;

    bool mDebugEnabled;

    mutable Mutex mLock;

    ///////////////////////////////////////////////////////////////////////////////
    // General tessellation caching
    ///////////////////////////////////////////////////////////////////////////////
    sp<TaskProcessor<VertexBuffer*> > mProcessor;
    LruCache<Description, Buffer*> mCache;
    class BufferRemovedListener : public OnEntryRemoved<Description, Buffer*> {
        void operator()(Description& description, Buffer*& buffer) override;
    };
    BufferRemovedListener mBufferRemovedListener;

    ///////////////////////////////////////////////////////////////////////////////
    // Shadow tessellation caching
    ///////////////////////////////////////////////////////////////////////////////
    sp<TaskProcessor<vertexBuffer_pair_t*> > mShadowProcessor;

    // holds a pointer, and implicit strong ref to each shadow task of the frame
    LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*> mShadowCache;
    class BufferPairRemovedListener : public OnEntryRemoved<ShadowDescription, Task<vertexBuffer_pair_t*>*> {
        void operator()(ShadowDescription& description, Task<vertexBuffer_pair_t*>*& bufferPairTask) override {
            bufferPairTask->decStrong(nullptr);
        }
    };
    BufferPairRemovedListener mBufferPairRemovedListener;

}; // class TessellationCache

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

#endif // ANDROID_HWUI_PATH_CACHE_H
