Fix Surface slot caching
- Now that it's possible to resize a BufferQueue while buffers are
dequeued/acquired, it's no longer correct for Surface to clear its
cache when the BufferQueue is resized since it must keep at least
the currently dequeued buffers.
- Add an onSlotsFreed callback to IProducerListener so that producers
that wish to be notified about buffers being freed can do so. Note
that this isn't currently used in Surface.
- Review and fixup all the places where the producer/consumer
listeners for freed buffers should be called.
Change-Id: I4ab0c92bc69b75a3c072ddf5d74d78f941dba4c8
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 45b6463..fad0baa 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -727,4 +727,55 @@
ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
}
+struct TestListener : public BnProducerListener {
+ virtual void onBufferReleased() {}
+ virtual void onSlotFreed(int slot) {
+ ASSERT_EQ(1, slot);
+ }
+};
+
+TEST_F(IGraphicBufferProducerTest, SlotFreedListenerReturnsCorrectSlot) {
+ const ::testing::TestInfo* const testInfo =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
+ testInfo->name());
+
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+
+ sp<DummyConsumer> consumerListener = new DummyConsumer;
+ ASSERT_OK(mConsumer->consumerConnect(consumerListener, false));
+
+ sp<TestListener> producerListener = new TestListener;
+ IGraphicBufferProducer::QueueBufferOutput output;
+ ASSERT_OK(mProducer->connect(producerListener, TEST_API,
+ TEST_CONTROLLED_BY_APP, &output));
+
+ ASSERT_OK(mProducer->setMaxDequeuedBufferCount(2));
+
+ DequeueBufferResult buffer0;
+ sp<GraphicBuffer> buf;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+ TEST_PRODUCER_USAGE_BITS, &buffer0));
+ ASSERT_OK(mProducer->requestBuffer(buffer0.slot, &buf));
+
+ DequeueBufferResult buffer1;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+ TEST_PRODUCER_USAGE_BITS, &buffer1));
+
+ IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+ ASSERT_OK(mProducer->queueBuffer(buffer0.slot, input, &output));
+
+ DequeueBufferResult buffer2;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+ TEST_PRODUCER_USAGE_BITS, &buffer2));
+
+ ASSERT_OK(mProducer->cancelBuffer(buffer1.slot, Fence::NO_FENCE));
+
+ ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1));
+}
+
+
} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 6f0104a..0de60c9 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -232,4 +232,30 @@
EXPECT_STREQ("TestConsumer", surface->getConsumerName().string());
}
+TEST_F(SurfaceTest, DynamicSetBufferCount) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+ consumer->consumerConnect(dummyConsumer, false);
+ consumer->setConsumerName(String8("TestConsumer"));
+
+ sp<Surface> surface = new Surface(producer);
+ sp<ANativeWindow> window(surface);
+
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(window.get(),
+ NATIVE_WINDOW_API_CPU));
+ native_window_set_buffer_count(window.get(), 4);
+
+ int fence;
+ ANativeWindowBuffer* buffer;
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+ native_window_set_buffer_count(window.get(), 3);
+ ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
+ native_window_set_buffer_count(window.get(), 2);
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+ ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
+}
+
}