Loading libs/gui/Surface.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ #include <gui/Surface.h> #include <condition_variable> #include <cstddef> #include <cstdint> #include <deque> #include <mutex> #include <thread> Loading Loading @@ -161,6 +163,12 @@ void Surface::allocateBuffers() { mReqFormat, mReqUsage); } #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) status_t Surface::allowAllocation(bool allowAllocation) { return mGraphicBufferProducer->allowAllocation(allowAllocation); } #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) status_t Surface::setGenerationNumber(uint32_t generation) { status_t result = mGraphicBufferProducer->setGenerationNumber(generation); if (result == NO_ERROR) { Loading Loading @@ -693,6 +701,50 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { return OK; } #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer, sp<Fence>* outFence) { if (buffer == nullptr || outFence == nullptr) { return BAD_VALUE; } android_native_buffer_t* anb; int fd = -1; status_t res = dequeueBuffer(&anb, &fd); *buffer = GraphicBuffer::from(anb); *outFence = sp<Fence>::make(fd); return res; } status_t Surface::queueBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& fd) { if (buffer == nullptr) { return BAD_VALUE; } return queueBuffer(buffer.get(), fd ? fd->get() : -1); } status_t Surface::detachBuffer(const sp<GraphicBuffer>& buffer) { if (nullptr == buffer) { return BAD_VALUE; } Mutex::Autolock lock(mMutex); uint64_t bufferId = buffer->getId(); for (int slot = 0; slot < Surface::NUM_BUFFER_SLOTS; ++slot) { auto& bufferSlot = mSlots[slot]; if (bufferSlot.buffer != nullptr && bufferSlot.buffer->getId() == bufferId) { bufferSlot.buffer = nullptr; bufferSlot.dirtyRegion = Region::INVALID_REGION; return mGraphicBufferProducer->detachBuffer(slot); } } return BAD_VALUE; } #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) int Surface::dequeueBuffers(std::vector<BatchBuffer>* buffers) { using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput; using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput; Loading libs/gui/include/gui/Surface.h +22 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define ANDROID_GUI_SURFACE_H #include <android/gui/FrameTimelineInfo.h> #include <com_android_graphics_libgui_flags.h> #include <gui/BufferQueueDefs.h> #include <gui/HdrMetadata.h> #include <gui/IGraphicBufferProducer.h> Loading @@ -35,6 +36,8 @@ namespace android { class GraphicBuffer; namespace gui { class ISurfaceComposer; } // namespace gui Loading Loading @@ -164,6 +167,11 @@ public: */ virtual void allocateBuffers(); #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) // See IGraphicBufferProducer::allowAllocation status_t allowAllocation(bool allowAllocation); #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) /* Sets the generation number on the IGraphicBufferProducer and updates the * generation number on any buffers attached to the Surface after this call. * See IGBP::setGenerationNumber for more information. */ Loading Loading @@ -395,6 +403,20 @@ public: static status_t attachAndQueueBufferWithDataspace(Surface* surface, sp<GraphicBuffer> buffer, ui::Dataspace dataspace); #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) // Dequeues a buffer and its outFence, which must be signalled before the buffer can be used. status_t dequeueBuffer(sp<GraphicBuffer>* buffer, sp<Fence>* outFence); // Queues a buffer, with an optional fd fence that captures pending work on the buffer. This // buffer must have been returned by dequeueBuffer or associated with this Surface via an // attachBuffer operation. status_t queueBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& fd = Fence::NO_FENCE); // Detaches this buffer, dissociating it from this Surface. This buffer must have been returned // by queueBuffer or associated with this Surface via an attachBuffer operation. status_t detachBuffer(const sp<GraphicBuffer>& buffer); #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) // Batch version of dequeueBuffer, cancelBuffer and queueBuffer // Note that these batched operations are not supported when shared buffer mode is being used. struct BatchBuffer { Loading libs/gui/tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ cc_test { "-Wthread-safety", "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_SETFRAMERATE=true", "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_EXTENDEDALLOCATE=true", "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_WB_PLATFORM_API_IMPROVEMENTS=true", ], srcs: [ Loading libs/gui/tests/Surface_test.cpp +90 −1 Original line number Diff line number Diff line Loading @@ -24,23 +24,26 @@ #include <android/gui/ISurfaceComposer.h> #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> #include <binder/ProcessState.h> #include <com_android_graphics_libgui_flags.h> #include <configstore/Utils.h> #include <gui/AidlStatusUtil.h> #include <gui/BufferItemConsumer.h> #include <gui/CpuConsumer.h> #include <gui/ISurfaceComposer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <gui/SyncScreenCaptureListener.h> #include <inttypes.h> #include <private/gui/ComposerService.h> #include <private/gui/ComposerServiceAIDL.h> #include <sys/types.h> #include <ui/BufferQueueDefs.h> #include <ui/DisplayMode.h> #include <ui/GraphicBuffer.h> #include <ui/Rect.h> #include <utils/Errors.h> #include <utils/String8.h> #include <cstddef> #include <limits> #include <thread> Loading Loading @@ -2225,4 +2228,90 @@ TEST_F(SurfaceTest, BatchIllegalOperations) { ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU)); } #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) TEST_F(SurfaceTest, PlatformBufferMethods) { sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer); sp<CpuConsumer> cpuConsumer = sp<CpuConsumer>::make(consumer, 1); sp<Surface> surface = sp<Surface>::make(producer); sp<StubSurfaceListener> listener = sp<StubSurfaceListener>::make(); sp<GraphicBuffer> buffer; sp<Fence> fence; EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, listener, /* reportBufferRemoval */ false)); // // Verify nullptrs are handled safely: // EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer((sp<GraphicBuffer>*)nullptr, nullptr)); EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer((sp<GraphicBuffer>*)nullptr, &fence)); EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer(&buffer, nullptr)); EXPECT_EQ(BAD_VALUE, surface->queueBuffer(nullptr, nullptr)); EXPECT_EQ(BAD_VALUE, surface->detachBuffer(nullptr)); // // Verify dequeue/queue: // EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)); EXPECT_NE(nullptr, buffer); EXPECT_EQ(OK, surface->queueBuffer(buffer, fence)); // // Verify dequeue/detach: // wp<GraphicBuffer> weakBuffer; { EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)); EXPECT_EQ(OK, surface->detachBuffer(buffer)); weakBuffer = buffer; buffer = nullptr; } EXPECT_EQ(nullptr, weakBuffer.promote()) << "Weak buffer still held by Surface."; // // Verify detach without borrowing the buffer does not work: // sp<GraphicBuffer> heldTooLongBuffer; EXPECT_EQ(OK, surface->dequeueBuffer(&heldTooLongBuffer, &fence)); EXPECT_EQ(OK, surface->queueBuffer(heldTooLongBuffer)); EXPECT_EQ(BAD_VALUE, surface->detachBuffer(heldTooLongBuffer)); } TEST_F(SurfaceTest, AllowAllocation) { sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer); // controlledByApp must be true to disable blocking sp<CpuConsumer> cpuConsumer = sp<CpuConsumer>::make(consumer, 1, /*controlledByApp*/ true); sp<Surface> surface = sp<Surface>::make(producer, /*controlledByApp*/ true); sp<StubSurfaceListener> listener = sp<StubSurfaceListener>::make(); sp<GraphicBuffer> buffer; sp<Fence> fence; EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, listener, /* reportBufferRemoval */ false)); EXPECT_EQ(OK, surface->allowAllocation(false)); EXPECT_EQ(OK, surface->setDequeueTimeout(-1)); EXPECT_EQ(WOULD_BLOCK, surface->dequeueBuffer(&buffer, &fence)); EXPECT_EQ(OK, surface->setDequeueTimeout(10)); EXPECT_EQ(TIMED_OUT, surface->dequeueBuffer(&buffer, &fence)); EXPECT_EQ(OK, surface->allowAllocation(true)); EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)); } #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) } // namespace android Loading
libs/gui/Surface.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ #include <gui/Surface.h> #include <condition_variable> #include <cstddef> #include <cstdint> #include <deque> #include <mutex> #include <thread> Loading Loading @@ -161,6 +163,12 @@ void Surface::allocateBuffers() { mReqFormat, mReqUsage); } #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) status_t Surface::allowAllocation(bool allowAllocation) { return mGraphicBufferProducer->allowAllocation(allowAllocation); } #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) status_t Surface::setGenerationNumber(uint32_t generation) { status_t result = mGraphicBufferProducer->setGenerationNumber(generation); if (result == NO_ERROR) { Loading Loading @@ -693,6 +701,50 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { return OK; } #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer, sp<Fence>* outFence) { if (buffer == nullptr || outFence == nullptr) { return BAD_VALUE; } android_native_buffer_t* anb; int fd = -1; status_t res = dequeueBuffer(&anb, &fd); *buffer = GraphicBuffer::from(anb); *outFence = sp<Fence>::make(fd); return res; } status_t Surface::queueBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& fd) { if (buffer == nullptr) { return BAD_VALUE; } return queueBuffer(buffer.get(), fd ? fd->get() : -1); } status_t Surface::detachBuffer(const sp<GraphicBuffer>& buffer) { if (nullptr == buffer) { return BAD_VALUE; } Mutex::Autolock lock(mMutex); uint64_t bufferId = buffer->getId(); for (int slot = 0; slot < Surface::NUM_BUFFER_SLOTS; ++slot) { auto& bufferSlot = mSlots[slot]; if (bufferSlot.buffer != nullptr && bufferSlot.buffer->getId() == bufferId) { bufferSlot.buffer = nullptr; bufferSlot.dirtyRegion = Region::INVALID_REGION; return mGraphicBufferProducer->detachBuffer(slot); } } return BAD_VALUE; } #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) int Surface::dequeueBuffers(std::vector<BatchBuffer>* buffers) { using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput; using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput; Loading
libs/gui/include/gui/Surface.h +22 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define ANDROID_GUI_SURFACE_H #include <android/gui/FrameTimelineInfo.h> #include <com_android_graphics_libgui_flags.h> #include <gui/BufferQueueDefs.h> #include <gui/HdrMetadata.h> #include <gui/IGraphicBufferProducer.h> Loading @@ -35,6 +36,8 @@ namespace android { class GraphicBuffer; namespace gui { class ISurfaceComposer; } // namespace gui Loading Loading @@ -164,6 +167,11 @@ public: */ virtual void allocateBuffers(); #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) // See IGraphicBufferProducer::allowAllocation status_t allowAllocation(bool allowAllocation); #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) /* Sets the generation number on the IGraphicBufferProducer and updates the * generation number on any buffers attached to the Surface after this call. * See IGBP::setGenerationNumber for more information. */ Loading Loading @@ -395,6 +403,20 @@ public: static status_t attachAndQueueBufferWithDataspace(Surface* surface, sp<GraphicBuffer> buffer, ui::Dataspace dataspace); #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) // Dequeues a buffer and its outFence, which must be signalled before the buffer can be used. status_t dequeueBuffer(sp<GraphicBuffer>* buffer, sp<Fence>* outFence); // Queues a buffer, with an optional fd fence that captures pending work on the buffer. This // buffer must have been returned by dequeueBuffer or associated with this Surface via an // attachBuffer operation. status_t queueBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& fd = Fence::NO_FENCE); // Detaches this buffer, dissociating it from this Surface. This buffer must have been returned // by queueBuffer or associated with this Surface via an attachBuffer operation. status_t detachBuffer(const sp<GraphicBuffer>& buffer); #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) // Batch version of dequeueBuffer, cancelBuffer and queueBuffer // Note that these batched operations are not supported when shared buffer mode is being used. struct BatchBuffer { Loading
libs/gui/tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ cc_test { "-Wthread-safety", "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_SETFRAMERATE=true", "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_EXTENDEDALLOCATE=true", "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_WB_PLATFORM_API_IMPROVEMENTS=true", ], srcs: [ Loading
libs/gui/tests/Surface_test.cpp +90 −1 Original line number Diff line number Diff line Loading @@ -24,23 +24,26 @@ #include <android/gui/ISurfaceComposer.h> #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> #include <binder/ProcessState.h> #include <com_android_graphics_libgui_flags.h> #include <configstore/Utils.h> #include <gui/AidlStatusUtil.h> #include <gui/BufferItemConsumer.h> #include <gui/CpuConsumer.h> #include <gui/ISurfaceComposer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <gui/SyncScreenCaptureListener.h> #include <inttypes.h> #include <private/gui/ComposerService.h> #include <private/gui/ComposerServiceAIDL.h> #include <sys/types.h> #include <ui/BufferQueueDefs.h> #include <ui/DisplayMode.h> #include <ui/GraphicBuffer.h> #include <ui/Rect.h> #include <utils/Errors.h> #include <utils/String8.h> #include <cstddef> #include <limits> #include <thread> Loading Loading @@ -2225,4 +2228,90 @@ TEST_F(SurfaceTest, BatchIllegalOperations) { ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU)); } #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) TEST_F(SurfaceTest, PlatformBufferMethods) { sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer); sp<CpuConsumer> cpuConsumer = sp<CpuConsumer>::make(consumer, 1); sp<Surface> surface = sp<Surface>::make(producer); sp<StubSurfaceListener> listener = sp<StubSurfaceListener>::make(); sp<GraphicBuffer> buffer; sp<Fence> fence; EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, listener, /* reportBufferRemoval */ false)); // // Verify nullptrs are handled safely: // EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer((sp<GraphicBuffer>*)nullptr, nullptr)); EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer((sp<GraphicBuffer>*)nullptr, &fence)); EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer(&buffer, nullptr)); EXPECT_EQ(BAD_VALUE, surface->queueBuffer(nullptr, nullptr)); EXPECT_EQ(BAD_VALUE, surface->detachBuffer(nullptr)); // // Verify dequeue/queue: // EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)); EXPECT_NE(nullptr, buffer); EXPECT_EQ(OK, surface->queueBuffer(buffer, fence)); // // Verify dequeue/detach: // wp<GraphicBuffer> weakBuffer; { EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)); EXPECT_EQ(OK, surface->detachBuffer(buffer)); weakBuffer = buffer; buffer = nullptr; } EXPECT_EQ(nullptr, weakBuffer.promote()) << "Weak buffer still held by Surface."; // // Verify detach without borrowing the buffer does not work: // sp<GraphicBuffer> heldTooLongBuffer; EXPECT_EQ(OK, surface->dequeueBuffer(&heldTooLongBuffer, &fence)); EXPECT_EQ(OK, surface->queueBuffer(heldTooLongBuffer)); EXPECT_EQ(BAD_VALUE, surface->detachBuffer(heldTooLongBuffer)); } TEST_F(SurfaceTest, AllowAllocation) { sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer); // controlledByApp must be true to disable blocking sp<CpuConsumer> cpuConsumer = sp<CpuConsumer>::make(consumer, 1, /*controlledByApp*/ true); sp<Surface> surface = sp<Surface>::make(producer, /*controlledByApp*/ true); sp<StubSurfaceListener> listener = sp<StubSurfaceListener>::make(); sp<GraphicBuffer> buffer; sp<Fence> fence; EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, listener, /* reportBufferRemoval */ false)); EXPECT_EQ(OK, surface->allowAllocation(false)); EXPECT_EQ(OK, surface->setDequeueTimeout(-1)); EXPECT_EQ(WOULD_BLOCK, surface->dequeueBuffer(&buffer, &fence)); EXPECT_EQ(OK, surface->setDequeueTimeout(10)); EXPECT_EQ(TIMED_OUT, surface->dequeueBuffer(&buffer, &fence)); EXPECT_EQ(OK, surface->allowAllocation(true)); EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)); } #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) } // namespace android