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