RingBufferConsumer.h revision bc1713d3b85d7ce656e032da6e4b6b342f14db03
140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin/*
240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * Copyright (C) 2013 The Android Open Source Project
340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * you may not use this file except in compliance with the License.
640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * You may obtain a copy of the License at
740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
1040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * Unless required by applicable law or agreed to in writing, software
1140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
1240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * See the License for the specific language governing permissions and
1440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * limitations under the License.
1540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin */
1640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
1740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#ifndef ANDROID_GUI_RINGBUFFERCONSUMER_H
1840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#define ANDROID_GUI_RINGBUFFERCONSUMER_H
1940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
20549e735c2ca22d16eea32fda418ba80da32a8558Dan Stoza#include <gui/BufferItem.h>
2140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#include <gui/ConsumerBase.h>
22bc1713d3b85d7ce656e032da6e4b6b342f14db03Mathias Agopian#include <gui/BufferQueue.h>
2340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
2440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#include <utils/List.h>
2540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
2640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#define ANDROID_GRAPHICS_RINGBUFFERCONSUMER_JNI_ID "mRingBufferConsumer"
2740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
2840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkinnamespace android {
2940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
30bc1713d3b85d7ce656e032da6e4b6b342f14db03Mathias Agopianclass String8;
31bc1713d3b85d7ce656e032da6e4b6b342f14db03Mathias Agopian
3240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin/**
3340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * The RingBufferConsumer maintains a ring buffer of BufferItem objects,
3440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * (which are 'acquired' as long as they are part of the ring buffer, and
3540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *  'released' when they leave the ring buffer).
3640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
3740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * When new buffers are produced, the oldest non-pinned buffer item is immediately
3840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * dropped from the ring buffer, and overridden with the newest buffer.
3940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
4040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * Users can only access a buffer item after pinning it (which also guarantees
4140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * that during its duration it will not be released back into the BufferQueue).
4240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
4340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * Note that the 'oldest' buffer is the one with the smallest timestamp.
4440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
4540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * Edge cases:
4640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *  - If ringbuffer is not full, no drops occur when a buffer is produced.
4740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *  - If all the buffers get filled or pinned then there will be no empty
4840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *    buffers left, so the producer will block on dequeue.
4940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin */
5040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkinclass RingBufferConsumer : public ConsumerBase,
5140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                           public ConsumerBase::FrameAvailableListener
5240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin{
5340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin  public:
5440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
5540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
5640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
5740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };
5840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
5940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Create a new ring buffer consumer. The consumerUsage parameter determines
6040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // the consumer usage flags passed to the graphics allocator. The
6140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // bufferCount parameter specifies how many buffers can be pinned for user
6240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // access at the same time.
63deeef54487a34034dc0cfaab20b20d557224c07cMathias Agopian    RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer, uint32_t consumerUsage,
64054aab3479a094b0a04d48db9cb8f325ea5be162Igor Murashkin            int bufferCount);
6540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
6640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    virtual ~RingBufferConsumer();
6740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
6840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // set the name of the RingBufferConsumer that will be used to identify it in
6940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // log messages.
7040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    void setName(const String8& name);
7140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
7240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // setDefaultBufferSize is used to set the size of buffers returned by
7340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // requestBuffers when a with and height of zero is requested.
7440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    status_t setDefaultBufferSize(uint32_t w, uint32_t h);
7540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
7640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // setDefaultBufferFormat allows the BufferQueue to create
7740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // GraphicBuffers of a defaultFormat if no format is specified
7840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // by the producer endpoint.
7940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    status_t setDefaultBufferFormat(uint32_t defaultFormat);
8040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
8140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // setConsumerUsage allows the BufferQueue consumer usage to be
8240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // set at a later time after construction.
8340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    status_t setConsumerUsage(uint32_t usage);
8440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
8540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Buffer info, minus the graphics buffer/slot itself.
8640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    struct BufferInfo {
8740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mCrop is the current crop rectangle for this buffer slot.
8840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        Rect mCrop;
8940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
9040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mTransform is the current transform flags for this buffer slot.
9140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        uint32_t mTransform;
9240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
9340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mScalingMode is the current scaling mode for this buffer slot.
9440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        uint32_t mScalingMode;
9540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
9640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mTimestamp is the current timestamp for this buffer slot. This gets
9740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // to set by queueBuffer each time this slot is queued.
9840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        int64_t mTimestamp;
9940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
10040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mFrameNumber is the number of the queued frame for this slot.
10140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        uint64_t mFrameNumber;
10240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
10340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mPinned is whether or not the buffer has been pinned already.
10440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        bool mPinned;
10540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    };
10640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
10740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    struct RingBufferComparator {
10840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // Return < 0 to select i1, > 0 to select i2, 0 for neither
10940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // i1 or i2 can be NULL.
11040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        //
11140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // The comparator has to implement a total ordering. Otherwise
11240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // a linear scan won't find the most preferred buffer.
11340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        virtual int compare(const BufferInfo* i1,
11440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                            const BufferInfo* i2) const = 0;
11540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
11640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        virtual ~RingBufferComparator() {}
11740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    };
11840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
11940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    struct PinnedBufferItem : public LightRefBase<PinnedBufferItem> {
12040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        PinnedBufferItem(wp<RingBufferConsumer> consumer,
12140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                         const BufferItem& item) :
12240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                mConsumer(consumer),
12340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                mBufferItem(item) {
12440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        }
12540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
12640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        ~PinnedBufferItem() {
12740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin            sp<RingBufferConsumer> consumer = mConsumer.promote();
12840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin            if (consumer != NULL) {
12940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                consumer->unpinBuffer(mBufferItem);
13040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin            }
13140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        }
13240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
13340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        bool isEmpty() {
134e361bc024ee7e34b7d53223aa2b209ef120ee78aPablo Ceballos            return mBufferItem.mSlot == BufferQueue::INVALID_BUFFER_SLOT;
13540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        }
13640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
13740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        BufferItem& getBufferItem() { return mBufferItem; }
13840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        const BufferItem& getBufferItem() const { return mBufferItem; }
13940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
14040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin      private:
14140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        wp<RingBufferConsumer> mConsumer;
14240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        BufferItem             mBufferItem;
14340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    };
14440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
14540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Find a buffer using the filter, then pin it before returning it.
14640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    //
14740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // The filter will be invoked on each buffer item in the ring buffer,
14840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // passing the item that was selected from each previous iteration,
14940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // as well as the current iteration's item.
15040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    //
15140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Pinning will ensure that the buffer will not be dropped when a new
15240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // frame is available.
15340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    sp<PinnedBufferItem> pinSelectedBuffer(const RingBufferComparator& filter,
15440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                                           bool waitForFence = true);
15540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
15640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Release all the non-pinned buffers in the ring buffer
15740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    status_t clear();
15840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
1596b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh    // Return 0 if RingBuffer is empty, otherwise return timestamp of latest buffer.
1606b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh    nsecs_t getLatestTimestamp();
1616b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh
16240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin  private:
16340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
16440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Override ConsumerBase::onFrameAvailable
165549e735c2ca22d16eea32fda418ba80da32a8558Dan Stoza    virtual void onFrameAvailable(const BufferItem& item);
16640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
16740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    void pinBufferLocked(const BufferItem& item);
16840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    void unpinBuffer(const BufferItem& item);
16940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
17040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Releases oldest buffer. Returns NO_BUFFER_AVAILABLE
17140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // if all the buffers were pinned.
17240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Returns NOT_ENOUGH_DATA if list was empty.
17340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    status_t releaseOldestBufferLocked(size_t* pinnedFrames);
17440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
17540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    struct RingBufferItem : public BufferItem {
17640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        RingBufferItem() : BufferItem(), mPinCount(0) {}
17740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        int mPinCount;
17840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    };
17940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
18040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // List of acquired buffers in our ring buffer
18140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    List<RingBufferItem>       mBufferItemList;
18240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    const int                  mBufferCount;
1836b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh
1846b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh    // Timestamp of latest buffer
1856b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh    nsecs_t mLatestTimestamp;
18640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin};
18740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
18840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin} // namespace android
18940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
190125684aba1a11b7adbf5f9d607ee2bcc9449081cZhijun He#endif // ANDROID_GUI_RINGBUFFERCONSUMER_H
191