/*
 * 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_GUI_RINGBUFFERCONSUMER_H
#define ANDROID_GUI_RINGBUFFERCONSUMER_H

#include <gui/BufferItem.h>
#include <gui/ConsumerBase.h>

#include <ui/GraphicBuffer.h>

#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/threads.h>
#include <utils/List.h>

#define ANDROID_GRAPHICS_RINGBUFFERCONSUMER_JNI_ID "mRingBufferConsumer"

namespace android {

/**
 * The RingBufferConsumer maintains a ring buffer of BufferItem objects,
 * (which are 'acquired' as long as they are part of the ring buffer, and
 *  'released' when they leave the ring buffer).
 *
 * When new buffers are produced, the oldest non-pinned buffer item is immediately
 * dropped from the ring buffer, and overridden with the newest buffer.
 *
 * Users can only access a buffer item after pinning it (which also guarantees
 * that during its duration it will not be released back into the BufferQueue).
 *
 * Note that the 'oldest' buffer is the one with the smallest timestamp.
 *
 * Edge cases:
 *  - If ringbuffer is not full, no drops occur when a buffer is produced.
 *  - If all the buffers get filled or pinned then there will be no empty
 *    buffers left, so the producer will block on dequeue.
 */
class RingBufferConsumer : public ConsumerBase,
                           public ConsumerBase::FrameAvailableListener
{
  public:
    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;

    enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
    enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };

    // Create a new ring buffer consumer. The consumerUsage parameter determines
    // the consumer usage flags passed to the graphics allocator. The
    // bufferCount parameter specifies how many buffers can be pinned for user
    // access at the same time.
    RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer, uint32_t consumerUsage,
            int bufferCount);

    virtual ~RingBufferConsumer();

    // set the name of the RingBufferConsumer that will be used to identify it in
    // log messages.
    void setName(const String8& name);

    // setDefaultBufferSize is used to set the size of buffers returned by
    // requestBuffers when a with and height of zero is requested.
    status_t setDefaultBufferSize(uint32_t w, uint32_t h);

    // setDefaultBufferFormat allows the BufferQueue to create
    // GraphicBuffers of a defaultFormat if no format is specified
    // by the producer endpoint.
    status_t setDefaultBufferFormat(uint32_t defaultFormat);

    // setConsumerUsage allows the BufferQueue consumer usage to be
    // set at a later time after construction.
    status_t setConsumerUsage(uint32_t usage);

    // Buffer info, minus the graphics buffer/slot itself.
    struct BufferInfo {
        // mCrop is the current crop rectangle for this buffer slot.
        Rect mCrop;

        // mTransform is the current transform flags for this buffer slot.
        uint32_t mTransform;

        // mScalingMode is the current scaling mode for this buffer slot.
        uint32_t mScalingMode;

        // mTimestamp is the current timestamp for this buffer slot. This gets
        // to set by queueBuffer each time this slot is queued.
        int64_t mTimestamp;

        // mFrameNumber is the number of the queued frame for this slot.
        uint64_t mFrameNumber;

        // mPinned is whether or not the buffer has been pinned already.
        bool mPinned;
    };

    struct RingBufferComparator {
        // Return < 0 to select i1, > 0 to select i2, 0 for neither
        // i1 or i2 can be NULL.
        //
        // The comparator has to implement a total ordering. Otherwise
        // a linear scan won't find the most preferred buffer.
        virtual int compare(const BufferInfo* i1,
                            const BufferInfo* i2) const = 0;

        virtual ~RingBufferComparator() {}
    };

    struct PinnedBufferItem : public LightRefBase<PinnedBufferItem> {
        PinnedBufferItem(wp<RingBufferConsumer> consumer,
                         const BufferItem& item) :
                mConsumer(consumer),
                mBufferItem(item) {
        }

        ~PinnedBufferItem() {
            sp<RingBufferConsumer> consumer = mConsumer.promote();
            if (consumer != NULL) {
                consumer->unpinBuffer(mBufferItem);
            }
        }

        bool isEmpty() {
            return mBufferItem.mSlot == BufferQueue::INVALID_BUFFER_SLOT;
        }

        BufferItem& getBufferItem() { return mBufferItem; }
        const BufferItem& getBufferItem() const { return mBufferItem; }

      private:
        wp<RingBufferConsumer> mConsumer;
        BufferItem             mBufferItem;
    };

    // Find a buffer using the filter, then pin it before returning it.
    //
    // The filter will be invoked on each buffer item in the ring buffer,
    // passing the item that was selected from each previous iteration,
    // as well as the current iteration's item.
    //
    // Pinning will ensure that the buffer will not be dropped when a new
    // frame is available.
    sp<PinnedBufferItem> pinSelectedBuffer(const RingBufferComparator& filter,
                                           bool waitForFence = true);

    // Release all the non-pinned buffers in the ring buffer
    status_t clear();

    // Return 0 if RingBuffer is empty, otherwise return timestamp of latest buffer.
    nsecs_t getLatestTimestamp();

  private:

    // Override ConsumerBase::onFrameAvailable
    virtual void onFrameAvailable(const BufferItem& item);

    void pinBufferLocked(const BufferItem& item);
    void unpinBuffer(const BufferItem& item);

    // Releases oldest buffer. Returns NO_BUFFER_AVAILABLE
    // if all the buffers were pinned.
    // Returns NOT_ENOUGH_DATA if list was empty.
    status_t releaseOldestBufferLocked(size_t* pinnedFrames);

    struct RingBufferItem : public BufferItem {
        RingBufferItem() : BufferItem(), mPinCount(0) {}
        int mPinCount;
    };

    // List of acquired buffers in our ring buffer
    List<RingBufferItem>       mBufferItemList;
    const int                  mBufferCount;

    // Timestamp of latest buffer
    nsecs_t mLatestTimestamp;
};

} // namespace android

#endif // ANDROID_GUI_RINGBUFFERCONSUMER_H
