/*
 * 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.mBuf == 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_CPUCONSUMER_H
