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

Commit 7cdd786f authored by Mathias Agopian's avatar Mathias Agopian
Browse files

Make ANW.setSwapInterval(0) work again

we can now queue/dequeue a buffer in asynchrnous mode by using the
async parameter to these calls. async mode is only specified
with those calls (it is not modal anymore).

as a consequence it can only be specified when the buffer count
is not overidden, as error is returned otherwise.

Change-Id: Ic63f4f96f671cb9d65c4cecbcc192615e09a8b6b
parent a3fbda3c
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ public:
    //
    // In both cases, the producer will need to call requestBuffer to get a
    // GraphicBuffer handle for the returned slot.
    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
            uint32_t width, uint32_t height, uint32_t format, uint32_t usage);

    // queueBuffer returns a filled buffer to the BufferQueue.
@@ -229,7 +229,7 @@ public:
           mTimestamp(0),
           mFrameNumber(0),
           mBuf(INVALID_BUFFER_SLOT),
           mDequeueBufferCannotBlock(false),
           mIsDroppable(false),
           mAcquireCalled(false) {
             mCrop.makeInvalid();
        }
@@ -260,12 +260,12 @@ public:
        // mFence is a fence that will signal when the buffer is idle.
        sp<Fence> mFence;

        // mDequeueBufferCannotBlock whether this buffer was queued with the
        // mIsDroppable whether this buffer was queued with the
        // property that it can be replaced by a new buffer for the purpose of
        // making sure dequeueBuffer() won't block.
        // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer
        // was queued.
        bool mDequeueBufferCannotBlock;
        bool mIsDroppable;

        // Indicates whether this buffer has been seen by a consumer yet
        bool mAcquireCalled;
@@ -379,9 +379,15 @@ private:
    // The initial default is 2.
    status_t setDefaultMaxBufferCountLocked(int count);

    // getMinUndequeuedBufferCount returns the minimum number of buffers
    // that must remain in a state other than DEQUEUED.
    // The async parameter tells whether we're in asynchronous mode.
    int getMinUndequeuedBufferCount(bool async) const;

    // getMinBufferCountLocked returns the minimum number of buffers allowed
    // given the current BufferQueue state.
    int getMinMaxBufferCountLocked() const;
    // The async parameter tells whether we're in asynchronous mode.
    int getMinMaxBufferCountLocked(bool async) const;

    // getMaxBufferCountLocked returns the maximum number of buffers that can
    // be allocated at once.  This value depends upon the following member
@@ -391,10 +397,11 @@ private:
    //      mMaxAcquiredBufferCount
    //      mDefaultMaxBufferCount
    //      mOverrideMaxBufferCount
    //      async parameter
    //
    // Any time one of these member variables is changed while a producer is
    // connected, mDequeueCondition must be broadcast.
    int getMaxBufferCountLocked() const;
    int getMaxBufferCountLocked(bool async) const;

    // stillTracking returns true iff the buffer item is still being tracked
    // in one of the slots.
@@ -516,11 +523,6 @@ private:
    // in dequeueBuffer() if a width and height of zero is specified.
    uint32_t mDefaultHeight;

    // mMinUndequeuedBufferCount holds the minimum number of buffers
    // that must remain in a state other than DEQUEUED.
    // This value cannot change while connected.
    int mMinUndequeuedBufferCount;

    // mMaxAcquiredBufferCount is the number of buffers that the consumer may
    // acquire at one time.  It defaults to 1 and can be changed by the
    // consumer via the setMaxAcquiredBufferCount method, but this may only be
+12 −5
Original line number Diff line number Diff line
@@ -84,7 +84,10 @@ public:
    // the buffer. The contents of the buffer must not be overwritten until the
    // fence signals. If the fence is NULL, the buffer may be written
    // immediately.
    virtual status_t dequeueBuffer(int *slot, sp<Fence>* fence,
    //
    // The async parameter sets whether we're in asynchrnous mode for this
    // deququeBuffer() call.
    virtual status_t dequeueBuffer(int *slot, sp<Fence>* fence, bool async,
            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;

    // queueBuffer indicates that the client has finished filling in the
@@ -96,6 +99,8 @@ public:
    // must be monotonically increasing. Its other properties (zero point, etc)
    // are client-dependent, and should be documented by the client.
    //
    // The async parameter sets whether we're queuing a buffer in asynchronous mode.
    //
    // outWidth, outHeight and outTransform are filled with the default width
    // and height of the window and current transform applied to buffers,
    // respectively.
@@ -103,17 +108,18 @@ public:
    struct QueueBufferInput : public Flattenable {
        inline QueueBufferInput(const Parcel& parcel);
        inline QueueBufferInput(int64_t timestamp,
                const Rect& crop, int scalingMode, uint32_t transform,
                sp<Fence> fence)
                const Rect& crop, int scalingMode, uint32_t transform, bool async,
                const sp<Fence>& fence)
        : timestamp(timestamp), crop(crop), scalingMode(scalingMode),
          transform(transform), fence(fence) { }
          transform(transform), async(async), fence(fence) { }
        inline void deflate(int64_t* outTimestamp, Rect* outCrop,
                int* outScalingMode, uint32_t* outTransform,
                int* outScalingMode, uint32_t* outTransform, bool* outAsync,
                sp<Fence>* outFence) const {
            *outTimestamp = timestamp;
            *outCrop = crop;
            *outScalingMode = scalingMode;
            *outTransform = transform;
            *outAsync = bool(async);
            *outFence = fence;
        }

@@ -130,6 +136,7 @@ public:
        Rect crop;
        int scalingMode;
        uint32_t transform;
        int async;
        sp<Fence> fence;
    };

+4 −0
Original line number Diff line number Diff line
@@ -235,6 +235,10 @@ private:
    // by the application
    bool mProducerControlledByApp;

    // mSwapIntervalZero set if we should drop buffers at queue() time to
    // achieve an asynchronous swap interval
    bool mSwapIntervalZero;

    // mConsumerRunningBehind whether the consumer is running more than
    // one buffer behind the producer.
    mutable bool mConsumerRunningBehind;
+59 −32
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@

#include <utils/Log.h>
#include <utils/Trace.h>
#include <utils/CallStack.h>

// Macros for including the BufferQueue name in log messages
#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
@@ -150,21 +151,21 @@ status_t BufferQueue::setBufferCount(int bufferCount) {
        }

        // Error out if the user has dequeued buffers
        int maxBufferCount = getMaxBufferCountLocked();
        for (int i=0 ; i<maxBufferCount; i++) {
        for (int i=0 ; i<NUM_BUFFER_SLOTS; i++) {
            if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
                ST_LOGE("setBufferCount: client owns some buffers");
                return -EINVAL;
            }
        }

        const int minBufferSlots = getMinMaxBufferCountLocked();
        if (bufferCount == 0) {
            mOverrideMaxBufferCount = 0;
            mDequeueCondition.broadcast();
            return NO_ERROR;
        }

        // fine to assume async to false before we're setting the buffer count
        const int minBufferSlots = getMinMaxBufferCountLocked(false);
        if (bufferCount < minBufferSlots) {
            ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
                    "minimum (%d)", bufferCount, minBufferSlots);
@@ -209,7 +210,7 @@ int BufferQueue::query(int what, int* outValue)
        value = mDefaultBufferFormat;
        break;
    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
        value = mMinUndequeuedBufferCount;
        value = getMinUndequeuedBufferCount(false);
        break;
    case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
        value = (mQueue.size() >= 2);
@@ -229,15 +230,11 @@ status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
        ST_LOGE("requestBuffer: BufferQueue has been abandoned!");
        return NO_INIT;
    }
    int maxBufferCount = getMaxBufferCountLocked();
    if (slot < 0 || maxBufferCount <= slot) {
    if (slot < 0 || slot >= NUM_BUFFER_SLOTS) {
        ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
                maxBufferCount, slot);
                NUM_BUFFER_SLOTS, slot);
        return BAD_VALUE;
    } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
        // XXX: I vaguely recall there was some reason this can be valid, but
        // for the life of me I can't recall under what circumstances that's
        // the case.
        ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
                slot, mSlots[slot].mBufferState);
        return BAD_VALUE;
@@ -247,7 +244,7 @@ status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
    return NO_ERROR;
}

status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async,
        uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
    ATRACE_CALL();
    ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
@@ -279,7 +276,16 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
                return NO_INIT;
            }

            const int maxBufferCount = getMaxBufferCountLocked();
            const int maxBufferCount = getMaxBufferCountLocked(async);
            if (async && mOverrideMaxBufferCount) {
                // FIXME: some drivers are manually setting the buffer-count (which they
                // shouldn't), so we do this extra test here to handle that case.
                // This is TEMPORARY, until we get this fixed.
                if (mOverrideMaxBufferCount < maxBufferCount) {
                    ST_LOGE("dequeueBuffer: async mode is invalid with buffercount override");
                    return BAD_VALUE;
                }
            }

            // Free up any buffers that are in slots beyond the max buffer
            // count.
@@ -328,7 +334,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
                // make sure the client is not trying to dequeue more buffers
                // than allowed.
                const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
                const int minUndequeuedCount = mMinUndequeuedBufferCount;
                const int minUndequeuedCount = getMinUndequeuedBufferCount(async);
                if (newUndequeuedCount < minUndequeuedCount) {
                    ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
                            "exceeded (dequeued=%d undequeudCount=%d)",
@@ -448,9 +454,10 @@ status_t BufferQueue::queueBuffer(int buf,
    uint32_t transform;
    int scalingMode;
    int64_t timestamp;
    bool async;
    sp<Fence> fence;

    input.deflate(&timestamp, &crop, &scalingMode, &transform, &fence);
    input.deflate(&timestamp, &crop, &scalingMode, &transform, &async, &fence);

    if (fence == NULL) {
        ST_LOGE("queueBuffer: fence is NULL");
@@ -477,7 +484,17 @@ status_t BufferQueue::queueBuffer(int buf,
            ST_LOGE("queueBuffer: BufferQueue has been abandoned!");
            return NO_INIT;
        }
        int maxBufferCount = getMaxBufferCountLocked();

        const int maxBufferCount = getMaxBufferCountLocked(async);
        if (async && mOverrideMaxBufferCount) {
            // FIXME: some drivers are manually setting the buffer-count (which they
            // shouldn't), so we do this extra test here to handle that case.
            // This is TEMPORARY, until we get this fixed.
            if (mOverrideMaxBufferCount < maxBufferCount) {
                ST_LOGE("queueBuffer: async mode is invalid with buffercount override");
                return BAD_VALUE;
            }
        }
        if (buf < 0 || buf >= maxBufferCount) {
            ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
                    maxBufferCount, buf);
@@ -523,7 +540,7 @@ status_t BufferQueue::queueBuffer(int buf,
        item.mFrameNumber = mFrameCounter;
        item.mBuf = buf;
        item.mFence = fence;
        item.mDequeueBufferCannotBlock = mDequeueBufferCannotBlock;
        item.mIsDroppable = mDequeueBufferCannotBlock || async;

        if (mQueue.empty()) {
            // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and
@@ -534,7 +551,7 @@ status_t BufferQueue::queueBuffer(int buf,
            // when the queue is not empty, we need to look at the front buffer
            // state and see if we need to replace it.
            Fifo::iterator front(mQueue.begin());
            if (front->mDequeueBufferCannotBlock) {
            if (front->mIsDroppable) {
                // buffer slot currently queued is marked free if still tracked
                if (stillTracking(front)) {
                    mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
@@ -573,10 +590,9 @@ void BufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
        return;
    }

    int maxBufferCount = getMaxBufferCountLocked();
    if (buf < 0 || buf >= maxBufferCount) {
    if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
        ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
                maxBufferCount, buf);
                NUM_BUFFER_SLOTS, buf);
        return;
    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
        ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
@@ -630,8 +646,6 @@ status_t BufferQueue::connect(int api, bool producerControlledByApp, QueueBuffer

    mBufferHasBeenQueued = false;
    mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp;
    mMinUndequeuedBufferCount = mDequeueBufferCannotBlock ?
            mMaxAcquiredBufferCount+1 : mMaxAcquiredBufferCount;

    return err;
}
@@ -704,12 +718,11 @@ void BufferQueue::dump(String8& result, const char* prefix) const {
        fifoSize++;
    }

    int maxBufferCount = getMaxBufferCountLocked();

    result.appendFormat(
            "%s-BufferQueue maxBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
            "%s-BufferQueue mMaxAcquiredBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
            "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
            prefix, maxBufferCount, mDequeueBufferCannotBlock, mDefaultWidth,
            prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, mDefaultWidth,
            mDefaultHeight, mDefaultBufferFormat, mTransformHint,
            fifoSize, fifo.string());

@@ -725,16 +738,25 @@ void BufferQueue::dump(String8& result, const char* prefix) const {
        }
    } stateName;

    // just trim the free buffers to not spam the dump
    int maxBufferCount = 0;
    for (int i=NUM_BUFFER_SLOTS-1 ; i>=0 ; i--) {
        const BufferSlot& slot(mSlots[i]);
        if ((slot.mBufferState != BufferSlot::FREE) || (slot.mGraphicBuffer != NULL)) {
            maxBufferCount = i+1;
            break;
        }
    }

    for (int i=0 ; i<maxBufferCount ; i++) {
        const BufferSlot& slot(mSlots[i]);
        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
        result.appendFormat(
            "%s%s[%02d:%p] state=%-8s",
                prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
                slot.mGraphicBuffer.get(),
                prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, buf.get(),
                stateName(slot.mBufferState)
        );

        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
        if (buf != NULL) {
            result.appendFormat(
                    ", %p [%4ux%4u:%4u,%3X]",
@@ -1018,12 +1040,17 @@ status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
    return NO_ERROR;
}

int BufferQueue::getMinMaxBufferCountLocked() const {
    return mMinUndequeuedBufferCount + 1;
int BufferQueue::getMinUndequeuedBufferCount(bool async) const {
    return (mDequeueBufferCannotBlock || async) ?
                mMaxAcquiredBufferCount+1 : mMaxAcquiredBufferCount;
}

int BufferQueue::getMinMaxBufferCountLocked(bool async) const {
    return getMinUndequeuedBufferCount(async) + 1;
}

int BufferQueue::getMaxBufferCountLocked() const {
    int minMaxBufferCount = getMinMaxBufferCountLocked();
int BufferQueue::getMaxBufferCountLocked(bool async) const {
    int minMaxBufferCount = getMinMaxBufferCountLocked(async);

    int maxBufferCount = mDefaultMaxBufferCount;
    if (maxBufferCount < minMaxBufferCount) {
+7 −2
Original line number Diff line number Diff line
@@ -80,10 +80,11 @@ public:
        return result;
    }

    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
        Parcel data, reply;
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
        data.writeInt32(async);
        data.writeInt32(w);
        data.writeInt32(h);
        data.writeInt32(format);
@@ -197,13 +198,14 @@ status_t BnGraphicBufferProducer::onTransact(
        } break;
        case DEQUEUE_BUFFER: {
            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
            bool async      = data.readInt32();
            uint32_t w      = data.readInt32();
            uint32_t h      = data.readInt32();
            uint32_t format = data.readInt32();
            uint32_t usage  = data.readInt32();
            int buf;
            sp<Fence> fence;
            int result = dequeueBuffer(&buf, &fence, w, h, format, usage);
            int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage);
            reply->writeInt32(buf);
            reply->writeInt32(fence != NULL);
            if (fence != NULL) {
@@ -274,6 +276,7 @@ size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const
         + sizeof(crop)
         + sizeof(scalingMode)
         + sizeof(transform)
         + sizeof(async)
         + fence->getFlattenedSize();
}

@@ -291,6 +294,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten(void* buffer, size_t
    memcpy(p, &crop,        sizeof(crop));        p += sizeof(crop);
    memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode);
    memcpy(p, &transform,   sizeof(transform));   p += sizeof(transform);
    memcpy(p, &async,       sizeof(async));       p += sizeof(async);
    err = fence->flatten(p, size - (p - (char*)buffer), fds, count);
    return err;
}
@@ -304,6 +308,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten(void const* buffer,
    memcpy(&crop,        p, sizeof(crop));        p += sizeof(crop);
    memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode);
    memcpy(&transform,   p, sizeof(transform));   p += sizeof(transform);
    memcpy(&async,       p, sizeof(async));       p += sizeof(async);
    fence = new Fence();
    err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count);
    return err;
Loading