Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f57e7540 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala
Browse files

CpuConsumer: inherit from ConsumerBase

Change-Id: I55178b1d673ffa0fbc6e63ef47642c64d4d03228
parent 13233e06
Loading
Loading
Loading
Loading
+6 −47
Original line number Original line Diff line number Diff line
@@ -17,7 +17,7 @@
#ifndef ANDROID_GUI_CPUCONSUMER_H
#ifndef ANDROID_GUI_CPUCONSUMER_H
#define ANDROID_GUI_CPUCONSUMER_H
#define ANDROID_GUI_CPUCONSUMER_H


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


#include <ui/GraphicBuffer.h>
#include <ui/GraphicBuffer.h>


@@ -37,19 +37,10 @@ namespace android {
 * This queue is synchronous by default.
 * This queue is synchronous by default.
 */
 */


class CpuConsumer: public virtual RefBase,
class CpuConsumer: public ConsumerBase
                     protected BufferQueue::ConsumerListener
{
{
  public:
  public:
    struct FrameAvailableListener : public virtual RefBase {
    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
        // onFrameAvailable() is called each time an additional frame becomes
        // available for consumption. A new frame queued will always trigger the
        // callback, whether the queue is empty or not.
        //
        // This is called without any lock held and can be called concurrently
        // by multiple threads.
        virtual void onFrameAvailable() = 0;
    };


    struct LockedBuffer {
    struct LockedBuffer {
        uint8_t    *data;
        uint8_t    *data;
@@ -68,8 +59,6 @@ class CpuConsumer: public virtual RefBase,
    // how many buffers can be locked for user access at the same time.
    // how many buffers can be locked for user access at the same time.
    CpuConsumer(uint32_t maxLockedBuffers);
    CpuConsumer(uint32_t maxLockedBuffers);


    virtual ~CpuConsumer();

    // set the name of the CpuConsumer that will be used to identify it in
    // set the name of the CpuConsumer that will be used to identify it in
    // log messages.
    // log messages.
    void setName(const String8& name);
    void setName(const String8& name);
@@ -91,50 +80,20 @@ class CpuConsumer: public virtual RefBase,
    // lockNextBuffer.
    // lockNextBuffer.
    status_t unlockBuffer(const LockedBuffer &nativeBuffer);
    status_t unlockBuffer(const LockedBuffer &nativeBuffer);


    // setFrameAvailableListener sets the listener object that will be notified
    sp<ISurfaceTexture> getProducerInterface() const { return getBufferQueue(); }
    // when a new frame becomes available.
    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);

    sp<ISurfaceTexture> getProducerInterface() const { return mBufferQueue; }
  protected:

    // Implementation of the BufferQueue::ConsumerListener interface.  These
    // calls are used to notify the CpuConsumer of asynchronous events in the
    // BufferQueue.
    virtual void onFrameAvailable();
    virtual void onBuffersReleased();


  private:
  private:
    // Free local buffer state
    status_t freeBufferLocked(int buf);

    // Maximum number of buffers that can be locked at a time
    // Maximum number of buffers that can be locked at a time
    uint32_t mMaxLockedBuffers;
    uint32_t mMaxLockedBuffers;


    // mName is a string used to identify the SurfaceTexture in log messages.
    void freeBufferLocked(int slotIndex);
    // It can be set by the setName method.
    String8 mName;

    // mFrameAvailableListener is the listener object that will be called when a
    // new frame becomes available. If it is not NULL it will be called from
    // queueBuffer.
    sp<FrameAvailableListener> mFrameAvailableListener;

    // Underlying buffer queue
    sp<BufferQueue> mBufferQueue;


    // Array for caching buffers from the buffer queue
    sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS];
    // Array for tracking pointers passed to the consumer, matching the
    // Array for tracking pointers passed to the consumer, matching the
    // mBufferSlot indexing
    // mSlots indexing
    void *mBufferPointers[BufferQueue::NUM_BUFFER_SLOTS];
    void *mBufferPointers[BufferQueue::NUM_BUFFER_SLOTS];
    // Count of currently locked buffers
    // Count of currently locked buffers
    uint32_t mCurrentLockedBuffers;
    uint32_t mCurrentLockedBuffers;


    // mMutex is the mutex used to prevent concurrent access to the member
    // variables of CpuConsumer objects. It must be locked whenever the
    // member variables are accessed.
    mutable Mutex mMutex;
};
};


} // namespace android
} // namespace android
+26 −113
Original line number Original line Diff line number Diff line
@@ -29,49 +29,18 @@


namespace android {
namespace android {


// Get an ID that's unique within this process.
static int32_t createProcessUniqueId() {
    static volatile int32_t globalCounter = 0;
    return android_atomic_inc(&globalCounter);
}

CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) :
CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) :
    ConsumerBase(new BufferQueue(true, maxLockedBuffers) ),
    mMaxLockedBuffers(maxLockedBuffers),
    mMaxLockedBuffers(maxLockedBuffers),
    mCurrentLockedBuffers(0)
    mCurrentLockedBuffers(0)
{
{
    mName = String8::format("cc-unnamed-%d-%d", getpid(),
            createProcessUniqueId());


    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
        mBufferPointers[i] = NULL;
        mBufferPointers[i] = NULL;
    }
    }


    mBufferQueue = new BufferQueue(true);

    wp<BufferQueue::ConsumerListener> listener;
    sp<BufferQueue::ConsumerListener> proxy;
    listener = static_cast<BufferQueue::ConsumerListener*>(this);
    proxy = new BufferQueue::ProxyConsumerListener(listener);

    status_t err = mBufferQueue->consumerConnect(proxy);
    if (err != NO_ERROR) {
        ALOGE("CpuConsumer: error connecting to BufferQueue: %s (%d)",
                strerror(-err), err);
    } else {
    mBufferQueue->setSynchronousMode(true);
    mBufferQueue->setSynchronousMode(true);
    mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
    mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
        mBufferQueue->setConsumerName(mName);
    }
}

CpuConsumer::~CpuConsumer()
{
    Mutex::Autolock _l(mMutex);
    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
        freeBufferLocked(i);
    }
    mBufferQueue->consumerDisconnect();
    mBufferQueue.clear();
}
}


void CpuConsumer::setName(const String8& name) {
void CpuConsumer::setName(const String8& name) {
@@ -92,7 +61,7 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {


    Mutex::Autolock _l(mMutex);
    Mutex::Autolock _l(mMutex);


    err = mBufferQueue->acquireBuffer(&b);
    err = acquireBufferLocked(&b);
    if (err != OK) {
    if (err != OK) {
        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
            return BAD_VALUE;
            return BAD_VALUE;
@@ -104,16 +73,6 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {


    int buf = b.mBuf;
    int buf = b.mBuf;


    if (b.mGraphicBuffer != NULL) {
        if (mBufferPointers[buf] != NULL) {
            CC_LOGE("Reallocation of buffer %d while in consumer use!", buf);
            mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
                    Fence::NO_FENCE);
            return BAD_VALUE;
        }
        mBufferSlot[buf] = b.mGraphicBuffer;
    }

    if (b.mFence.get()) {
    if (b.mFence.get()) {
        err = b.mFence->wait(Fence::TIMEOUT_NEVER);
        err = b.mFence->wait(Fence::TIMEOUT_NEVER);
        if (err != OK) {
        if (err != OK) {
@@ -123,7 +82,7 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
        }
        }
    }
    }


    err = mBufferSlot[buf]->lock(
    err = mSlots[buf].mGraphicBuffer->lock(
        GraphicBuffer::USAGE_SW_READ_OFTEN,
        GraphicBuffer::USAGE_SW_READ_OFTEN,
        b.mCrop,
        b.mCrop,
        &mBufferPointers[buf]);
        &mBufferPointers[buf]);
@@ -135,10 +94,10 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
    }
    }


    nativeBuffer->data   = reinterpret_cast<uint8_t*>(mBufferPointers[buf]);
    nativeBuffer->data   = reinterpret_cast<uint8_t*>(mBufferPointers[buf]);
    nativeBuffer->width  = mBufferSlot[buf]->getWidth();
    nativeBuffer->width  = mSlots[buf].mGraphicBuffer->getWidth();
    nativeBuffer->height = mBufferSlot[buf]->getHeight();
    nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight();
    nativeBuffer->format = mBufferSlot[buf]->getPixelFormat();
    nativeBuffer->format = mSlots[buf].mGraphicBuffer->getPixelFormat();
    nativeBuffer->stride = mBufferSlot[buf]->getStride();
    nativeBuffer->stride = mSlots[buf].mGraphicBuffer->getStride();


    nativeBuffer->crop        = b.mCrop;
    nativeBuffer->crop        = b.mCrop;
    nativeBuffer->transform   = b.mTransform;
    nativeBuffer->transform   = b.mTransform;
@@ -153,90 +112,44 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {


status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
    Mutex::Autolock _l(mMutex);
    Mutex::Autolock _l(mMutex);
    int buf = 0;
    int slotIndex = 0;
    status_t err;
    status_t err;


    void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
    void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
    for (; buf < BufferQueue::NUM_BUFFER_SLOTS; buf++) {
    for (; slotIndex < BufferQueue::NUM_BUFFER_SLOTS; slotIndex++) {
        if (bufPtr == mBufferPointers[buf]) break;
        if (bufPtr == mBufferPointers[slotIndex]) break;
    }
    }
    if (buf == BufferQueue::NUM_BUFFER_SLOTS) {
    if (slotIndex == BufferQueue::NUM_BUFFER_SLOTS) {
        CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
        CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    mBufferPointers[buf] = NULL;
    mBufferPointers[slotIndex] = NULL;
    err = mBufferSlot[buf]->unlock();
    err = mSlots[slotIndex].mGraphicBuffer->unlock();
    if (err != OK) {
    if (err != OK) {
        CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf);
        CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex);
        return err;
    }
    err = mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
            Fence::NO_FENCE);
    if (err == BufferQueue::STALE_BUFFER_SLOT) {
        freeBufferLocked(buf);
    } else if (err != OK) {
        CC_LOGE("%s: Unable to release graphic buffer %d to queue", __FUNCTION__,
                buf);
        return err;
        return err;
    }
    }
    releaseBufferLocked(slotIndex, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);


    mCurrentLockedBuffers--;
    mCurrentLockedBuffers--;


    return OK;
    return OK;
}
}


void CpuConsumer::setFrameAvailableListener(
void CpuConsumer::freeBufferLocked(int slotIndex) {
        const sp<FrameAvailableListener>& listener) {
    if (mBufferPointers[slotIndex] != NULL) {
    CC_LOGV("setFrameAvailableListener");
        status_t err;
    Mutex::Autolock lock(mMutex);
        CC_LOGW("Buffer %d freed while locked by consumer", slotIndex);
    mFrameAvailableListener = listener;
        mBufferPointers[slotIndex] = NULL;
}
        err = mSlots[slotIndex].mGraphicBuffer->unlock();


void CpuConsumer::onFrameAvailable() {
    CC_LOGV("onFrameAvailable");
    sp<FrameAvailableListener> listener;
    { // scope for the lock
        Mutex::Autolock _l(mMutex);
        listener = mFrameAvailableListener;
    }

    if (listener != NULL) {
        CC_LOGV("actually calling onFrameAvailable");
        listener->onFrameAvailable();
    }
}

void CpuConsumer::onBuffersReleased() {
    CC_LOGV("onBuffersReleased");

    Mutex::Autolock lock(mMutex);

    uint32_t mask = 0;
    mBufferQueue->getReleasedBuffers(&mask);
    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
        if (mask & (1 << i)) {
            freeBufferLocked(i);
        }
    }

}

status_t CpuConsumer::freeBufferLocked(int buf) {
    status_t err = OK;

    if (mBufferPointers[buf] != NULL) {
        CC_LOGW("Buffer %d freed while locked by consumer", buf);
        mBufferPointers[buf] = NULL;
        err = mBufferSlot[buf]->unlock();
        if (err != OK) {
        if (err != OK) {
            CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf);
            CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
                    slotIndex);
        }
        }
        mCurrentLockedBuffers--;
        mCurrentLockedBuffers--;
    }
    }
    mBufferSlot[buf] = NULL;
    ConsumerBase::freeBufferLocked(slotIndex);
    return err;
}
}


} // namespace android
} // namespace android