Loading include/gui/IGraphicBufferProducer.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -385,6 +385,7 @@ public: uint32_t numPendingBuffers{0}; uint32_t numPendingBuffers{0}; uint64_t nextFrameNumber{0}; uint64_t nextFrameNumber{0}; FrameEventHistoryDelta frameTimestamps; FrameEventHistoryDelta frameTimestamps; bool bufferReplaced{false}; }; }; virtual status_t queueBuffer(int slot, const QueueBufferInput& input, virtual status_t queueBuffer(int slot, const QueueBufferInput& input, Loading libs/gui/BufferQueueProducer.cpp +3 −0 Original line number Original line Diff line number Diff line Loading @@ -879,6 +879,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCore->mSharedBufferCache.dataspace = dataSpace; mCore->mSharedBufferCache.dataspace = dataSpace; } } output->bufferReplaced = false; if (mCore->mQueue.empty()) { if (mCore->mQueue.empty()) { // When the queue is empty, we can ignore mDequeueBufferCannotBlock // When the queue is empty, we can ignore mDequeueBufferCannotBlock // and simply queue this buffer // and simply queue this buffer Loading @@ -905,6 +906,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, if (!mSlots[last.mSlot].mBufferState.isShared()) { if (!mSlots[last.mSlot].mBufferState.isShared()) { mCore->mActiveBuffers.erase(last.mSlot); mCore->mActiveBuffers.erase(last.mSlot); mCore->mFreeBuffers.push_back(last.mSlot); mCore->mFreeBuffers.push_back(last.mSlot); output->bufferReplaced = true; } } } } Loading Loading @@ -1158,6 +1160,7 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, output->numPendingBuffers = output->numPendingBuffers = static_cast<uint32_t>(mCore->mQueue.size()); static_cast<uint32_t>(mCore->mQueue.size()); output->nextFrameNumber = mCore->mFrameCounter + 1; output->nextFrameNumber = mCore->mFrameCounter + 1; output->bufferReplaced = false; if (listener != NULL) { if (listener != NULL) { // Set up a death notification so that we can disconnect // Set up a death notification so that we can disconnect Loading libs/gui/IGraphicBufferProducer.cpp +4 −1 Original line number Original line Diff line number Diff line Loading @@ -831,7 +831,8 @@ constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() { sizeof(height) + sizeof(height) + sizeof(transformHint) + sizeof(transformHint) + sizeof(numPendingBuffers) + sizeof(numPendingBuffers) + sizeof(nextFrameNumber); sizeof(nextFrameNumber) + sizeof(bufferReplaced); } } size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const { size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const { Loading @@ -854,6 +855,7 @@ status_t IGraphicBufferProducer::QueueBufferOutput::flatten( FlattenableUtils::write(buffer, size, transformHint); FlattenableUtils::write(buffer, size, transformHint); FlattenableUtils::write(buffer, size, numPendingBuffers); FlattenableUtils::write(buffer, size, numPendingBuffers); FlattenableUtils::write(buffer, size, nextFrameNumber); FlattenableUtils::write(buffer, size, nextFrameNumber); FlattenableUtils::write(buffer, size, bufferReplaced); return frameTimestamps.flatten(buffer, size, fds, count); return frameTimestamps.flatten(buffer, size, fds, count); } } Loading @@ -870,6 +872,7 @@ status_t IGraphicBufferProducer::QueueBufferOutput::unflatten( FlattenableUtils::read(buffer, size, transformHint); FlattenableUtils::read(buffer, size, transformHint); FlattenableUtils::read(buffer, size, numPendingBuffers); FlattenableUtils::read(buffer, size, numPendingBuffers); FlattenableUtils::read(buffer, size, nextFrameNumber); FlattenableUtils::read(buffer, size, nextFrameNumber); FlattenableUtils::read(buffer, size, bufferReplaced); return frameTimestamps.unflatten(buffer, size, fds, count); return frameTimestamps.unflatten(buffer, size, fds, count); } } Loading libs/gui/tests/BufferQueue_test.cpp +41 −0 Original line number Original line Diff line number Diff line Loading @@ -1076,4 +1076,45 @@ TEST_F(BufferQueueTest, TestDiscardFreeBuffers) { } } } } TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) { 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)); ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1)); int slot = BufferQueue::INVALID_BUFFER_SLOT; sp<Fence> fence = Fence::NO_FENCE; sp<GraphicBuffer> buffer = nullptr; IGraphicBufferProducer::QueueBufferInput input(0ull, true, HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); BufferItem item{}; // Preallocate, dequeue, request, and cancel 2 buffers so we don't get // BUFFER_NEEDS_REALLOCATION below int slots[2] = {}; ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2)); for (size_t i = 0; i < 2; ++i) { status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr); ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result); ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer)); } for (size_t i = 0; i < 2; ++i) { ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE)); } // Fill 2 buffers without consumer consuming them. Verify that all // queued buffer returns proper bufferReplaced flag ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr)); ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); ASSERT_EQ(false, output.bufferReplaced); ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr)); ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); ASSERT_EQ(true, output.bufferReplaced); } } // namespace android } // namespace android Loading
include/gui/IGraphicBufferProducer.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -385,6 +385,7 @@ public: uint32_t numPendingBuffers{0}; uint32_t numPendingBuffers{0}; uint64_t nextFrameNumber{0}; uint64_t nextFrameNumber{0}; FrameEventHistoryDelta frameTimestamps; FrameEventHistoryDelta frameTimestamps; bool bufferReplaced{false}; }; }; virtual status_t queueBuffer(int slot, const QueueBufferInput& input, virtual status_t queueBuffer(int slot, const QueueBufferInput& input, Loading
libs/gui/BufferQueueProducer.cpp +3 −0 Original line number Original line Diff line number Diff line Loading @@ -879,6 +879,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCore->mSharedBufferCache.dataspace = dataSpace; mCore->mSharedBufferCache.dataspace = dataSpace; } } output->bufferReplaced = false; if (mCore->mQueue.empty()) { if (mCore->mQueue.empty()) { // When the queue is empty, we can ignore mDequeueBufferCannotBlock // When the queue is empty, we can ignore mDequeueBufferCannotBlock // and simply queue this buffer // and simply queue this buffer Loading @@ -905,6 +906,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, if (!mSlots[last.mSlot].mBufferState.isShared()) { if (!mSlots[last.mSlot].mBufferState.isShared()) { mCore->mActiveBuffers.erase(last.mSlot); mCore->mActiveBuffers.erase(last.mSlot); mCore->mFreeBuffers.push_back(last.mSlot); mCore->mFreeBuffers.push_back(last.mSlot); output->bufferReplaced = true; } } } } Loading Loading @@ -1158,6 +1160,7 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, output->numPendingBuffers = output->numPendingBuffers = static_cast<uint32_t>(mCore->mQueue.size()); static_cast<uint32_t>(mCore->mQueue.size()); output->nextFrameNumber = mCore->mFrameCounter + 1; output->nextFrameNumber = mCore->mFrameCounter + 1; output->bufferReplaced = false; if (listener != NULL) { if (listener != NULL) { // Set up a death notification so that we can disconnect // Set up a death notification so that we can disconnect Loading
libs/gui/IGraphicBufferProducer.cpp +4 −1 Original line number Original line Diff line number Diff line Loading @@ -831,7 +831,8 @@ constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() { sizeof(height) + sizeof(height) + sizeof(transformHint) + sizeof(transformHint) + sizeof(numPendingBuffers) + sizeof(numPendingBuffers) + sizeof(nextFrameNumber); sizeof(nextFrameNumber) + sizeof(bufferReplaced); } } size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const { size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const { Loading @@ -854,6 +855,7 @@ status_t IGraphicBufferProducer::QueueBufferOutput::flatten( FlattenableUtils::write(buffer, size, transformHint); FlattenableUtils::write(buffer, size, transformHint); FlattenableUtils::write(buffer, size, numPendingBuffers); FlattenableUtils::write(buffer, size, numPendingBuffers); FlattenableUtils::write(buffer, size, nextFrameNumber); FlattenableUtils::write(buffer, size, nextFrameNumber); FlattenableUtils::write(buffer, size, bufferReplaced); return frameTimestamps.flatten(buffer, size, fds, count); return frameTimestamps.flatten(buffer, size, fds, count); } } Loading @@ -870,6 +872,7 @@ status_t IGraphicBufferProducer::QueueBufferOutput::unflatten( FlattenableUtils::read(buffer, size, transformHint); FlattenableUtils::read(buffer, size, transformHint); FlattenableUtils::read(buffer, size, numPendingBuffers); FlattenableUtils::read(buffer, size, numPendingBuffers); FlattenableUtils::read(buffer, size, nextFrameNumber); FlattenableUtils::read(buffer, size, nextFrameNumber); FlattenableUtils::read(buffer, size, bufferReplaced); return frameTimestamps.unflatten(buffer, size, fds, count); return frameTimestamps.unflatten(buffer, size, fds, count); } } Loading
libs/gui/tests/BufferQueue_test.cpp +41 −0 Original line number Original line Diff line number Diff line Loading @@ -1076,4 +1076,45 @@ TEST_F(BufferQueueTest, TestDiscardFreeBuffers) { } } } } TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) { 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)); ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1)); int slot = BufferQueue::INVALID_BUFFER_SLOT; sp<Fence> fence = Fence::NO_FENCE; sp<GraphicBuffer> buffer = nullptr; IGraphicBufferProducer::QueueBufferInput input(0ull, true, HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); BufferItem item{}; // Preallocate, dequeue, request, and cancel 2 buffers so we don't get // BUFFER_NEEDS_REALLOCATION below int slots[2] = {}; ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2)); for (size_t i = 0; i < 2; ++i) { status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr); ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result); ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer)); } for (size_t i = 0; i < 2; ++i) { ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE)); } // Fill 2 buffers without consumer consuming them. Verify that all // queued buffer returns proper bufferReplaced flag ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr)); ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); ASSERT_EQ(false, output.bufferReplaced); ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr)); ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); ASSERT_EQ(true, output.bufferReplaced); } } // namespace android } // namespace android