RingBufferConsumer.h revision 04f101c35eaa90b1f95939afac30674ec1611e6f
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
2040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#include <gui/ConsumerBase.h>
2140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
2240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#include <ui/GraphicBuffer.h>
2340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
2440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#include <utils/String8.h>
2540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#include <utils/Vector.h>
2640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#include <utils/threads.h>
2740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#include <utils/List.h>
2840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
2940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#define ANDROID_GRAPHICS_RINGBUFFERCONSUMER_JNI_ID "mRingBufferConsumer"
3040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
3140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkinnamespace android {
3240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
3340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin/**
3440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * The RingBufferConsumer maintains a ring buffer of BufferItem objects,
3540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * (which are 'acquired' as long as they are part of the ring buffer, and
3640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *  'released' when they leave the ring buffer).
3740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
3840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * When new buffers are produced, the oldest non-pinned buffer item is immediately
3940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * dropped from the ring buffer, and overridden with the newest buffer.
4040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
4140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * Users can only access a buffer item after pinning it (which also guarantees
4240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * that during its duration it will not be released back into the BufferQueue).
4340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
4440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * Note that the 'oldest' buffer is the one with the smallest timestamp.
4540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *
4640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin * Edge cases:
4740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *  - If ringbuffer is not full, no drops occur when a buffer is produced.
4840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *  - If all the buffers get filled or pinned then there will be no empty
4940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin *    buffers left, so the producer will block on dequeue.
5040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin */
5140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkinclass RingBufferConsumer : public ConsumerBase,
5240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                           public ConsumerBase::FrameAvailableListener
5340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin{
5440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin  public:
5540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
5640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
5740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    typedef BufferQueue::BufferItem BufferItem;
5840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
5940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
6040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };
6140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
6240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Create a new ring buffer consumer. The consumerUsage parameter determines
6340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // the consumer usage flags passed to the graphics allocator. The
6440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // bufferCount parameter specifies how many buffers can be pinned for user
6540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // access at the same time.
66deeef54487a34034dc0cfaab20b20d557224c07cMathias Agopian    RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer, uint32_t consumerUsage,
67054aab3479a094b0a04d48db9cb8f325ea5be162Igor Murashkin            int bufferCount);
6840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
6940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    virtual ~RingBufferConsumer();
7040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
7140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // set the name of the RingBufferConsumer that will be used to identify it in
7240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // log messages.
7340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    void setName(const String8& name);
7440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
7540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // setDefaultBufferSize is used to set the size of buffers returned by
7640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // requestBuffers when a with and height of zero is requested.
7740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    status_t setDefaultBufferSize(uint32_t w, uint32_t h);
7840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
7940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // setDefaultBufferFormat allows the BufferQueue to create
8040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // GraphicBuffers of a defaultFormat if no format is specified
8140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // by the producer endpoint.
8240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    status_t setDefaultBufferFormat(uint32_t defaultFormat);
8340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
8440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // setConsumerUsage allows the BufferQueue consumer usage to be
8540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // set at a later time after construction.
8640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    status_t setConsumerUsage(uint32_t usage);
8740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
8840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Buffer info, minus the graphics buffer/slot itself.
8940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    struct BufferInfo {
9040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mCrop is the current crop rectangle for this buffer slot.
9140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        Rect mCrop;
9240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
9340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mTransform is the current transform flags for this buffer slot.
9440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        uint32_t mTransform;
9540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
9640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mScalingMode is the current scaling mode for this buffer slot.
9740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        uint32_t mScalingMode;
9840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
9940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mTimestamp is the current timestamp for this buffer slot. This gets
10040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // to set by queueBuffer each time this slot is queued.
10140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        int64_t mTimestamp;
10240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
10340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mFrameNumber is the number of the queued frame for this slot.
10440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        uint64_t mFrameNumber;
10540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
10640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // mPinned is whether or not the buffer has been pinned already.
10740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        bool mPinned;
10840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    };
10940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
11040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    struct RingBufferComparator {
11140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // Return < 0 to select i1, > 0 to select i2, 0 for neither
11240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // i1 or i2 can be NULL.
11340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        //
11440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // The comparator has to implement a total ordering. Otherwise
11540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        // a linear scan won't find the most preferred buffer.
11640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        virtual int compare(const BufferInfo* i1,
11740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                            const BufferInfo* i2) const = 0;
11840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
11940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        virtual ~RingBufferComparator() {}
12040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    };
12140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
12240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    struct PinnedBufferItem : public LightRefBase<PinnedBufferItem> {
12340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        PinnedBufferItem(wp<RingBufferConsumer> consumer,
12440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                         const BufferItem& item) :
12540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                mConsumer(consumer),
12640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                mBufferItem(item) {
12740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        }
12840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
12940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        ~PinnedBufferItem() {
13040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin            sp<RingBufferConsumer> consumer = mConsumer.promote();
13140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin            if (consumer != NULL) {
13240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                consumer->unpinBuffer(mBufferItem);
13340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin            }
13440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        }
13540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
13640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        bool isEmpty() {
13740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin            return mBufferItem.mBuf == BufferQueue::INVALID_BUFFER_SLOT;
13840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        }
13940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
14040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        BufferItem& getBufferItem() { return mBufferItem; }
14140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        const BufferItem& getBufferItem() const { return mBufferItem; }
14240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
14340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin      private:
14440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        wp<RingBufferConsumer> mConsumer;
14540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        BufferItem             mBufferItem;
14640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    };
14740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
14840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Find a buffer using the filter, then pin it before returning it.
14940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    //
15040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // The filter will be invoked on each buffer item in the ring buffer,
15140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // passing the item that was selected from each previous iteration,
15240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // as well as the current iteration's item.
15340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    //
15440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Pinning will ensure that the buffer will not be dropped when a new
15540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // frame is available.
15640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    sp<PinnedBufferItem> pinSelectedBuffer(const RingBufferComparator& filter,
15740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin                                           bool waitForFence = true);
15840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
15940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Release all the non-pinned buffers in the ring buffer
16040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    status_t clear();
16140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
1626b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh    // Return 0 if RingBuffer is empty, otherwise return timestamp of latest buffer.
1636b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh    nsecs_t getLatestTimestamp();
1646b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh
16540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin  private:
16640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
16740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Override ConsumerBase::onFrameAvailable
16804f101c35eaa90b1f95939afac30674ec1611e6fDan Stoza    virtual void onFrameAvailable(const android::BufferItem& item);
16940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
17040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    void pinBufferLocked(const BufferItem& item);
17140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    void unpinBuffer(const BufferItem& item);
17240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
17340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Releases oldest buffer. Returns NO_BUFFER_AVAILABLE
17440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // if all the buffers were pinned.
17540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // Returns NOT_ENOUGH_DATA if list was empty.
17640602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    status_t releaseOldestBufferLocked(size_t* pinnedFrames);
17740602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
17840602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    struct RingBufferItem : public BufferItem {
17940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        RingBufferItem() : BufferItem(), mPinCount(0) {}
18040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin        int mPinCount;
18140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    };
18240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
18340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    // List of acquired buffers in our ring buffer
18440602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    List<RingBufferItem>       mBufferItemList;
18540602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin    const int                  mBufferCount;
1866b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh
1876b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh    // Timestamp of latest buffer
1886b7a2294b9e4da784cfe4b562ee1720ad606c852Yin-Chia Yeh    nsecs_t mLatestTimestamp;
18940602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin};
19040602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
19140602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin} // namespace android
19240602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin
19340602741ae87e6bf368c17dd28db4d2db344bdedIgor Murashkin#endif // ANDROID_GUI_CPUCONSUMER_H
194