| 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 | f377a76 | 2019-02-13 13:46:42 -0800 | [diff] [blame] | 18 |     mBufferState = new (&metadataHeader->bufferState) std::atomic<uint32_t>(0); | 
 | 19 |     mFenceState = new (&metadataHeader->fenceState) std::atomic<uint32_t>(0); | 
 | 20 |     mActiveClientsBitMask = new (&metadataHeader->activeClientsBitMask) 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 |