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

Commit 295a9fc8 authored by Pablo Ceballos's avatar Pablo Ceballos
Browse files

BQ: Allow shared buffer to be the first queued buffer

- When single-buffer mode is enabled the shared buffer will now be
  either the first buffer dequeued or the first buffer queued.
  Whichever comes first.

Bug 24940410

Change-Id: I9f7e2630640e37fe1fb967aed41a3025567247a8
parent ec3c05b2
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -292,9 +292,6 @@ private:
    bool mAsyncMode;

    // mSingleBufferMode indicates whether or not single buffer mode is enabled.
    // In single buffer mode, the last buffer that was dequeued is cached and
    // returned to all calls to dequeueBuffer and acquireBuffer. This allows the
    // consumer and producer to access the same buffer simultaneously.
    bool mSingleBufferMode;

    // When single buffer mode is enabled, this indicates whether the consumer
+4 −3
Original line number Diff line number Diff line
@@ -526,9 +526,10 @@ public:

    // Used to enable/disable single buffer mode.
    //
    // In single buffer mode the last buffer that was dequeued will be cached
    // and returned to all calls to dequeueBuffer and acquireBuffer. This allows
    // the producer and consumer to simultaneously access the same buffer.
    // When single buffer mode is enabled the first buffer that is queued or
    // dequeued will be cached and returned to all subsequent calls to
    // dequeueBuffer and acquireBuffer. This allows the producer and consumer to
    // simultaneously access the same buffer.
    virtual status_t setSingleBufferMode(bool singleBufferMode) = 0;

    // Used to enable/disable auto-refresh.
+8 −0
Original line number Diff line number Diff line
@@ -761,6 +761,14 @@ status_t BufferQueueProducer::queueBuffer(int slot,
            return BAD_VALUE;
        }

        // If single buffer mode has just been enabled, cache the slot of the
        // first buffer that is queued and mark it as the shared buffer.
        if (mCore->mSingleBufferMode && mCore->mSingleBufferSlot ==
                BufferQueueCore::INVALID_BUFFER_SLOT) {
            mCore->mSingleBufferSlot = slot;
            mSlots[slot].mBufferState.mShared = true;
        }

        BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
                " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
                slot, mCore->mFrameCounter + 1, timestamp, dataSpace,
+51 −0
Original line number Diff line number Diff line
@@ -661,6 +661,57 @@ TEST_F(BufferQueueTest, TestSingleBufferModeWithAutoRefresh) {
    }
}

TEST_F(BufferQueueTest, TestSingleBufferModeUsingAlreadyDequeuedBuffer) {
    createBufferQueue();
    sp<DummyConsumer> dc(new DummyConsumer);
    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
    IGraphicBufferProducer::QueueBufferOutput output;
    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
            NATIVE_WINDOW_API_CPU, true, &output));

    // Dequeue a buffer
    int singleSlot;
    sp<Fence> fence;
    sp<GraphicBuffer> buffer;
    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
            mProducer->dequeueBuffer(&singleSlot, &fence, 0, 0, 0, 0));
    ASSERT_EQ(OK, mProducer->requestBuffer(singleSlot, &buffer));

    // Enable single buffer mode
    ASSERT_EQ(OK, mProducer->setSingleBufferMode(true));

    // Queue the buffer
    IGraphicBufferProducer::QueueBufferInput input(0, false,
            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
    ASSERT_EQ(OK, mProducer->queueBuffer(singleSlot, input, &output));

    // Repeatedly queue and dequeue a buffer from the producer side, it should
    // always return the same one. And we won't run out of buffers because it's
    // always the same one and because async mode gets enabled.
    int slot;
    for (int i = 0; i < 5; i++) {
        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
        ASSERT_EQ(singleSlot, slot);
        ASSERT_EQ(OK, mProducer->queueBuffer(singleSlot, input, &output));
    }

    // acquire the buffer
    BufferItem item;
    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
    ASSERT_EQ(singleSlot, item.mSlot);
    testBufferItem(input, item);
    ASSERT_EQ(true, item.mQueuedBuffer);
    ASSERT_EQ(false, item.mAutoRefresh);

    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));

    // attempt to acquire a second time should return no buffer available
    ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
            mConsumer->acquireBuffer(&item, 0));
}

TEST_F(BufferQueueTest, TestTimeouts) {
    createBufferQueue();
    sp<DummyConsumer> dc(new DummyConsumer);