Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 1 | #include <errno.h> |
| 2 | |
Fan Xu | ffde786 | 2018-11-08 16:29:13 -0800 | [diff] [blame] | 3 | #include <bufferhub/BufferHubService.h> |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 4 | #include <bufferhub/BufferNode.h> |
Tianyu Jiang | 2ceb320 | 2018-12-17 12:58:34 -0800 | [diff] [blame] | 5 | #include <log/log.h> |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 6 | #include <ui/GraphicBufferAllocator.h> |
| 7 | |
| 8 | namespace android { |
| 9 | namespace frameworks { |
| 10 | namespace bufferhub { |
| 11 | namespace V1_0 { |
| 12 | namespace implementation { |
| 13 | |
Tianyu Jiang | 727ede4 | 2019-02-01 11:44:51 -0800 | [diff] [blame] | 14 | void BufferNode::initializeMetadata() { |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 15 | // Using placement new here to reuse shared memory instead of new allocation |
| 16 | // Initialize the atomic variables to zero. |
Tianyu Jiang | 727ede4 | 2019-02-01 11:44:51 -0800 | [diff] [blame] | 17 | BufferHubDefs::MetadataHeader* metadataHeader = mMetadata.metadataHeader(); |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 18 | mBufferState = new (&metadataHeader->buffer_state) std::atomic<uint32_t>(0); |
| 19 | mFenceState = new (&metadataHeader->fence_state) std::atomic<uint32_t>(0); |
| 20 | mActiveClientsBitMask = new (&metadataHeader->active_clients_bit_mask) std::atomic<uint32_t>(0); |
Tianyu Jiang | 2ceb320 | 2018-12-17 12:58:34 -0800 | [diff] [blame] | 21 | // The C++ standard recommends (but does not require) that lock-free atomic operations are |
| 22 | // also address-free, that is, suitable for communication between processes using shared |
| 23 | // memory. |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 24 | LOG_ALWAYS_FATAL_IF(!std::atomic_is_lock_free(mBufferState) || |
| 25 | !std::atomic_is_lock_free(mFenceState) || |
| 26 | !std::atomic_is_lock_free(mActiveClientsBitMask), |
Tianyu Jiang | 2ceb320 | 2018-12-17 12:58:34 -0800 | [diff] [blame] | 27 | "Atomic variables in ashmen are not lock free."); |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 28 | } |
| 29 | |
| 30 | // Allocates a new BufferNode. |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 31 | BufferNode::BufferNode(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format, |
| 32 | uint64_t usage, size_t userMetadataSize, int id) |
Fan Xu | ffde786 | 2018-11-08 16:29:13 -0800 | [diff] [blame] | 33 | : mId(id) { |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 34 | uint32_t outStride = 0; |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 35 | // graphicBufferId is not used in GraphicBufferAllocator::allocate |
| 36 | // TODO(b/112338294) After move to the service folder, stop using the |
| 37 | // hardcoded service name "bufferhub". |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 38 | int ret = GraphicBufferAllocator::get().allocate(width, height, format, layerCount, usage, |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 39 | const_cast<const native_handle_t**>( |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 40 | &mBufferHandle), |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 41 | &outStride, |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 42 | /*graphicBufferId=*/0, |
| 43 | /*requestor=*/"bufferhub"); |
| 44 | |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 45 | if (ret != OK || mBufferHandle == nullptr) { |
Fan Xu | 19a3e2b | 2018-11-12 13:45:33 -0800 | [diff] [blame] | 46 | ALOGE("%s: Failed to allocate buffer: %s", __FUNCTION__, strerror(-ret)); |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 47 | return; |
| 48 | } |
| 49 | |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 50 | mBufferDesc.width = width; |
| 51 | mBufferDesc.height = height; |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 52 | mBufferDesc.layers = layerCount; |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 53 | mBufferDesc.format = format; |
| 54 | mBufferDesc.usage = usage; |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 55 | mBufferDesc.stride = outStride; |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 56 | |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 57 | mMetadata = BufferHubMetadata::create(userMetadataSize); |
Tianyu Jiang | 727ede4 | 2019-02-01 11:44:51 -0800 | [diff] [blame] | 58 | if (!mMetadata.isValid()) { |
Fan Xu | 19a3e2b | 2018-11-12 13:45:33 -0800 | [diff] [blame] | 59 | ALOGE("%s: Failed to allocate metadata.", __FUNCTION__); |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 60 | return; |
| 61 | } |
Tianyu Jiang | 727ede4 | 2019-02-01 11:44:51 -0800 | [diff] [blame] | 62 | initializeMetadata(); |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 63 | } |
| 64 | |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 65 | BufferNode::~BufferNode() { |
Fan Xu | ffde786 | 2018-11-08 16:29:13 -0800 | [diff] [blame] | 66 | // Free the handle |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 67 | if (mBufferHandle != nullptr) { |
| 68 | status_t ret = GraphicBufferAllocator::get().free(mBufferHandle); |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 69 | if (ret != OK) { |
Fan Xu | 19a3e2b | 2018-11-12 13:45:33 -0800 | [diff] [blame] | 70 | ALOGE("%s: Failed to free handle; Got error: %d", __FUNCTION__, ret); |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 71 | } |
| 72 | } |
Fan Xu | ffde786 | 2018-11-08 16:29:13 -0800 | [diff] [blame] | 73 | |
| 74 | // Free the id, if valid |
Fan Xu | 6b4b1e5 | 2018-12-18 14:03:44 -0800 | [diff] [blame] | 75 | if (mId >= 0) { |
| 76 | BufferHubIdGenerator::getInstance().freeId(mId); |
Fan Xu | ffde786 | 2018-11-08 16:29:13 -0800 | [diff] [blame] | 77 | } |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 78 | } |
| 79 | |
Tianyu Jiang | 727ede4 | 2019-02-01 11:44:51 -0800 | [diff] [blame] | 80 | uint32_t BufferNode::getActiveClientsBitMask() const { |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 81 | return mActiveClientsBitMask->load(std::memory_order_acquire); |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 82 | } |
| 83 | |
Tianyu Jiang | 727ede4 | 2019-02-01 11:44:51 -0800 | [diff] [blame] | 84 | uint32_t BufferNode::addNewActiveClientsBitToMask() { |
| 85 | uint32_t currentActiveClientsBitMask = getActiveClientsBitMask(); |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 86 | uint32_t clientStateMask = 0U; |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 87 | uint32_t updatedActiveClientsBitMask = 0U; |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 88 | do { |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 89 | clientStateMask = |
Tianyu Jiang | 727ede4 | 2019-02-01 11:44:51 -0800 | [diff] [blame] | 90 | BufferHubDefs::findNextAvailableClientStateMask(currentActiveClientsBitMask); |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 91 | if (clientStateMask == 0U) { |
Fan Xu | d34a80a | 2018-12-04 11:32:39 -0800 | [diff] [blame] | 92 | ALOGE("%s: reached the maximum number of channels per buffer node: %d.", __FUNCTION__, |
| 93 | BufferHubDefs::kMaxNumberOfClients); |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 94 | errno = E2BIG; |
Tianyu Jiang | a99f911 | 2018-12-13 18:23:07 -0800 | [diff] [blame] | 95 | return 0U; |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 96 | } |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 97 | updatedActiveClientsBitMask = currentActiveClientsBitMask | clientStateMask; |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 98 | } while (!(mActiveClientsBitMask->compare_exchange_weak(currentActiveClientsBitMask, |
| 99 | updatedActiveClientsBitMask, |
| 100 | std::memory_order_acq_rel, |
| 101 | std::memory_order_acquire))); |
Tianyu Jiang | c9d8d58 | 2019-02-10 22:05:34 -0800 | [diff] [blame] | 102 | return clientStateMask; |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 103 | } |
| 104 | |
Tianyu Jiang | 727ede4 | 2019-02-01 11:44:51 -0800 | [diff] [blame] | 105 | void BufferNode::removeClientsBitFromMask(const uint32_t& value) { |
Tianyu Jiang | 1543d88 | 2019-02-04 10:53:53 -0800 | [diff] [blame] | 106 | mActiveClientsBitMask->fetch_and(~value); |
Fan Xu | 574a685 | 2018-11-02 13:22:42 -0700 | [diff] [blame] | 107 | } |
| 108 | |
| 109 | } // namespace implementation |
| 110 | } // namespace V1_0 |
| 111 | } // namespace bufferhub |
| 112 | } // namespace frameworks |
| 113 | } // namespace android |