blob: 1efb27ee0a965c6f96de2f9b147ef9823d0f824b [file] [log] [blame]
Fan Xu574a6852018-11-02 13:22:42 -07001#include <errno.h>
2
Fan Xuffde7862018-11-08 16:29:13 -08003#include <bufferhub/BufferHubService.h>
Fan Xu574a6852018-11-02 13:22:42 -07004#include <bufferhub/BufferNode.h>
Tianyu Jiang2ceb3202018-12-17 12:58:34 -08005#include <log/log.h>
Fan Xu574a6852018-11-02 13:22:42 -07006#include <ui/GraphicBufferAllocator.h>
7
8namespace android {
9namespace frameworks {
10namespace bufferhub {
11namespace V1_0 {
12namespace implementation {
13
Tianyu Jiang727ede42019-02-01 11:44:51 -080014void BufferNode::initializeMetadata() {
Fan Xu574a6852018-11-02 13:22:42 -070015 // Using placement new here to reuse shared memory instead of new allocation
16 // Initialize the atomic variables to zero.
Tianyu Jiang727ede42019-02-01 11:44:51 -080017 BufferHubDefs::MetadataHeader* metadataHeader = mMetadata.metadataHeader();
Tianyu Jiang1543d882019-02-04 10:53:53 -080018 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 Jiang2ceb3202018-12-17 12:58:34 -080021 // 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 Jiang1543d882019-02-04 10:53:53 -080024 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 Jiang2ceb3202018-12-17 12:58:34 -080027 "Atomic variables in ashmen are not lock free.");
Fan Xu574a6852018-11-02 13:22:42 -070028}
29
30// Allocates a new BufferNode.
Tianyu Jiangc9d8d582019-02-10 22:05:34 -080031BufferNode::BufferNode(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
32 uint64_t usage, size_t userMetadataSize, int id)
Fan Xuffde7862018-11-08 16:29:13 -080033 : mId(id) {
Tianyu Jiangc9d8d582019-02-10 22:05:34 -080034 uint32_t outStride = 0;
Fan Xu574a6852018-11-02 13:22:42 -070035 // 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 Jiangc9d8d582019-02-10 22:05:34 -080038 int ret = GraphicBufferAllocator::get().allocate(width, height, format, layerCount, usage,
Fan Xu574a6852018-11-02 13:22:42 -070039 const_cast<const native_handle_t**>(
Tianyu Jiang1543d882019-02-04 10:53:53 -080040 &mBufferHandle),
Tianyu Jiangc9d8d582019-02-10 22:05:34 -080041 &outStride,
Fan Xu574a6852018-11-02 13:22:42 -070042 /*graphicBufferId=*/0,
43 /*requestor=*/"bufferhub");
44
Tianyu Jiang1543d882019-02-04 10:53:53 -080045 if (ret != OK || mBufferHandle == nullptr) {
Fan Xu19a3e2b2018-11-12 13:45:33 -080046 ALOGE("%s: Failed to allocate buffer: %s", __FUNCTION__, strerror(-ret));
Fan Xu574a6852018-11-02 13:22:42 -070047 return;
48 }
49
Tianyu Jiang1543d882019-02-04 10:53:53 -080050 mBufferDesc.width = width;
51 mBufferDesc.height = height;
Tianyu Jiangc9d8d582019-02-10 22:05:34 -080052 mBufferDesc.layers = layerCount;
Tianyu Jiang1543d882019-02-04 10:53:53 -080053 mBufferDesc.format = format;
54 mBufferDesc.usage = usage;
Tianyu Jiangc9d8d582019-02-10 22:05:34 -080055 mBufferDesc.stride = outStride;
Fan Xu574a6852018-11-02 13:22:42 -070056
Tianyu Jiangc9d8d582019-02-10 22:05:34 -080057 mMetadata = BufferHubMetadata::create(userMetadataSize);
Tianyu Jiang727ede42019-02-01 11:44:51 -080058 if (!mMetadata.isValid()) {
Fan Xu19a3e2b2018-11-12 13:45:33 -080059 ALOGE("%s: Failed to allocate metadata.", __FUNCTION__);
Fan Xu574a6852018-11-02 13:22:42 -070060 return;
61 }
Tianyu Jiang727ede42019-02-01 11:44:51 -080062 initializeMetadata();
Fan Xu574a6852018-11-02 13:22:42 -070063}
64
Fan Xu574a6852018-11-02 13:22:42 -070065BufferNode::~BufferNode() {
Fan Xuffde7862018-11-08 16:29:13 -080066 // Free the handle
Tianyu Jiang1543d882019-02-04 10:53:53 -080067 if (mBufferHandle != nullptr) {
68 status_t ret = GraphicBufferAllocator::get().free(mBufferHandle);
Fan Xu574a6852018-11-02 13:22:42 -070069 if (ret != OK) {
Fan Xu19a3e2b2018-11-12 13:45:33 -080070 ALOGE("%s: Failed to free handle; Got error: %d", __FUNCTION__, ret);
Fan Xu574a6852018-11-02 13:22:42 -070071 }
72 }
Fan Xuffde7862018-11-08 16:29:13 -080073
74 // Free the id, if valid
Fan Xu6b4b1e52018-12-18 14:03:44 -080075 if (mId >= 0) {
76 BufferHubIdGenerator::getInstance().freeId(mId);
Fan Xuffde7862018-11-08 16:29:13 -080077 }
Fan Xu574a6852018-11-02 13:22:42 -070078}
79
Tianyu Jiang727ede42019-02-01 11:44:51 -080080uint32_t BufferNode::getActiveClientsBitMask() const {
Tianyu Jiang1543d882019-02-04 10:53:53 -080081 return mActiveClientsBitMask->load(std::memory_order_acquire);
Fan Xu574a6852018-11-02 13:22:42 -070082}
83
Tianyu Jiang727ede42019-02-01 11:44:51 -080084uint32_t BufferNode::addNewActiveClientsBitToMask() {
85 uint32_t currentActiveClientsBitMask = getActiveClientsBitMask();
Tianyu Jiangc9d8d582019-02-10 22:05:34 -080086 uint32_t clientStateMask = 0U;
Tianyu Jiang1543d882019-02-04 10:53:53 -080087 uint32_t updatedActiveClientsBitMask = 0U;
Fan Xu574a6852018-11-02 13:22:42 -070088 do {
Tianyu Jiangc9d8d582019-02-10 22:05:34 -080089 clientStateMask =
Tianyu Jiang727ede42019-02-01 11:44:51 -080090 BufferHubDefs::findNextAvailableClientStateMask(currentActiveClientsBitMask);
Tianyu Jiangc9d8d582019-02-10 22:05:34 -080091 if (clientStateMask == 0U) {
Fan Xud34a80a2018-12-04 11:32:39 -080092 ALOGE("%s: reached the maximum number of channels per buffer node: %d.", __FUNCTION__,
93 BufferHubDefs::kMaxNumberOfClients);
Fan Xu574a6852018-11-02 13:22:42 -070094 errno = E2BIG;
Tianyu Jianga99f9112018-12-13 18:23:07 -080095 return 0U;
Fan Xu574a6852018-11-02 13:22:42 -070096 }
Tianyu Jiangc9d8d582019-02-10 22:05:34 -080097 updatedActiveClientsBitMask = currentActiveClientsBitMask | clientStateMask;
Tianyu Jiang1543d882019-02-04 10:53:53 -080098 } while (!(mActiveClientsBitMask->compare_exchange_weak(currentActiveClientsBitMask,
99 updatedActiveClientsBitMask,
100 std::memory_order_acq_rel,
101 std::memory_order_acquire)));
Tianyu Jiangc9d8d582019-02-10 22:05:34 -0800102 return clientStateMask;
Fan Xu574a6852018-11-02 13:22:42 -0700103}
104
Tianyu Jiang727ede42019-02-01 11:44:51 -0800105void BufferNode::removeClientsBitFromMask(const uint32_t& value) {
Tianyu Jiang1543d882019-02-04 10:53:53 -0800106 mActiveClientsBitMask->fetch_and(~value);
Fan Xu574a6852018-11-02 13:22:42 -0700107}
108
109} // namespace implementation
110} // namespace V1_0
111} // namespace bufferhub
112} // namespace frameworks
113} // namespace android