blob: f36e1697cbadc29eb833e506088520ab171fe58e [file] [log] [blame]
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -07001#include <private/dvr/producer_buffer.h>
2
3using android::pdx::LocalChannelHandle;
4using android::pdx::LocalHandle;
5using android::pdx::Status;
6
7namespace android {
8namespace dvr {
9
10ProducerBuffer::ProducerBuffer(uint32_t width, uint32_t height, uint32_t format,
11 uint64_t usage, size_t user_metadata_size)
12 : BASE(BufferHubRPC::kClientPath) {
13 ATRACE_NAME("ProducerBuffer::ProducerBuffer");
14 ALOGD_IF(TRACE,
15 "ProducerBuffer::ProducerBuffer: fd=%d width=%u height=%u format=%u "
16 "usage=%" PRIx64 " user_metadata_size=%zu",
17 event_fd(), width, height, format, usage, user_metadata_size);
18
19 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
20 width, height, format, usage, user_metadata_size);
21 if (!status) {
22 ALOGE(
23 "ProducerBuffer::ProducerBuffer: Failed to create producer buffer: %s",
24 status.GetErrorMessage().c_str());
25 Close(-status.error());
26 return;
27 }
28
29 const int ret = ImportBuffer();
30 if (ret < 0) {
31 ALOGE(
32 "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s",
33 strerror(-ret));
34 Close(ret);
35 }
36}
37
38ProducerBuffer::ProducerBuffer(uint64_t usage, size_t size)
39 : BASE(BufferHubRPC::kClientPath) {
40 ATRACE_NAME("ProducerBuffer::ProducerBuffer");
41 ALOGD_IF(TRACE, "ProducerBuffer::ProducerBuffer: usage=%" PRIx64 " size=%zu",
42 usage, size);
43 const int width = static_cast<int>(size);
44 const int height = 1;
45 const int format = HAL_PIXEL_FORMAT_BLOB;
46 const size_t user_metadata_size = 0;
47
48 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
49 width, height, format, usage, user_metadata_size);
50 if (!status) {
51 ALOGE("ProducerBuffer::ProducerBuffer: Failed to create blob: %s",
52 status.GetErrorMessage().c_str());
53 Close(-status.error());
54 return;
55 }
56
57 const int ret = ImportBuffer();
58 if (ret < 0) {
59 ALOGE(
60 "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s",
61 strerror(-ret));
62 Close(ret);
63 }
64}
65
66ProducerBuffer::ProducerBuffer(LocalChannelHandle channel)
67 : BASE(std::move(channel)) {
68 const int ret = ImportBuffer();
69 if (ret < 0) {
70 ALOGE(
71 "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s",
72 strerror(-ret));
73 Close(ret);
74 }
75}
76
77int ProducerBuffer::LocalPost(const DvrNativeBufferMetadata* meta,
78 const LocalHandle& ready_fence) {
79 if (const int error = CheckMetadata(meta->user_metadata_size))
80 return error;
81
82 // Check invalid state transition.
Tianyu Jiange2cdec92018-10-30 17:40:58 -070083 uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -070084 if (!BufferHubDefs::IsBufferGained(buffer_state)) {
85 ALOGE("ProducerBuffer::LocalPost: not gained, id=%d state=%" PRIx64 ".",
86 id(), buffer_state);
87 return -EBUSY;
88 }
89
90 // Copy the canonical metadata.
91 void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
92 memcpy(metadata_ptr, meta, sizeof(DvrNativeBufferMetadata));
93 // Copy extra user requested metadata.
94 if (meta->user_metadata_ptr && meta->user_metadata_size) {
95 void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
96 memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
97 }
98
99 // Send out the acquire fence through the shared epoll fd. Note that during
100 // posting no consumer is not expected to be polling on the fence.
101 if (const int error = UpdateSharedFence(ready_fence, shared_acquire_fence_))
102 return error;
103
104 // Set the producer bit atomically to transit into posted state.
Tianyu Jiang63dd7c32018-10-30 18:35:06 -0700105 // The producer state bit mask is kFirstClientBitMask for now.
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700106 BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL,
Tianyu Jiang63dd7c32018-10-30 18:35:06 -0700107 BufferHubDefs::kFirstClientBitMask);
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700108 return 0;
109}
110
111int ProducerBuffer::Post(const LocalHandle& ready_fence, const void* meta,
112 size_t user_metadata_size) {
113 ATRACE_NAME("ProducerBuffer::Post");
114
115 // Populate cononical metadata for posting.
116 DvrNativeBufferMetadata canonical_meta;
117 canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta);
118 canonical_meta.user_metadata_size = user_metadata_size;
119
120 if (const int error = LocalPost(&canonical_meta, ready_fence))
121 return error;
122
123 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
124 BorrowedFence(ready_fence.Borrow())));
125}
126
127int ProducerBuffer::PostAsync(const DvrNativeBufferMetadata* meta,
128 const LocalHandle& ready_fence) {
129 ATRACE_NAME("ProducerBuffer::PostAsync");
130
131 if (const int error = LocalPost(meta, ready_fence))
132 return error;
133
134 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode));
135}
136
137int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta,
Tianyu5465d6c2018-08-14 13:03:10 -0700138 LocalHandle* out_fence, bool gain_posted_buffer) {
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700139 uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700140 ALOGD_IF(TRACE, "ProducerBuffer::LocalGain: buffer=%d, state=%" PRIx64 ".",
141 id(), buffer_state);
142
143 if (!out_meta)
144 return -EINVAL;
145
Tianyu5465d6c2018-08-14 13:03:10 -0700146 if (BufferHubDefs::IsBufferGained(buffer_state)) {
147 // We don't want to log error when gaining a newly allocated
148 // buffer.
149 ALOGI("ProducerBuffer::LocalGain: already gained id=%d.", id());
150 return -EALREADY;
151 }
152 if (BufferHubDefs::IsBufferAcquired(buffer_state) ||
153 (BufferHubDefs::IsBufferPosted(buffer_state) && !gain_posted_buffer)) {
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700154 ALOGE("ProducerBuffer::LocalGain: not released id=%d state=%" PRIx64 ".",
155 id(), buffer_state);
156 return -EBUSY;
157 }
158
159 // Canonical metadata is undefined on Gain. Except for user_metadata and
160 // release_fence_mask. Fill in the user_metadata_ptr in address space of the
161 // local process.
162 if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) {
163 out_meta->user_metadata_size =
164 metadata_header_->metadata.user_metadata_size;
165 out_meta->user_metadata_ptr =
166 reinterpret_cast<uint64_t>(user_metadata_ptr_);
167 } else {
168 out_meta->user_metadata_size = 0;
169 out_meta->user_metadata_ptr = 0;
170 }
171
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700172 uint64_t fence_state = fence_state_->load(std::memory_order_acquire);
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700173 // If there is an release fence from consumer, we need to return it.
174 if (fence_state & BufferHubDefs::kConsumerStateMask) {
175 *out_fence = shared_release_fence_.Duplicate();
176 out_meta->release_fence_mask =
177 fence_state & BufferHubDefs::kConsumerStateMask;
178 }
179
180 // Clear out all bits and the buffer is now back to gained state.
181 buffer_state_->store(0ULL);
182 return 0;
183}
184
Tianyu5465d6c2018-08-14 13:03:10 -0700185int ProducerBuffer::Gain(LocalHandle* release_fence, bool gain_posted_buffer) {
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700186 ATRACE_NAME("ProducerBuffer::Gain");
187
188 DvrNativeBufferMetadata meta;
Tianyu5465d6c2018-08-14 13:03:10 -0700189 if (const int error = LocalGain(&meta, release_fence, gain_posted_buffer))
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700190 return error;
191
192 auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
193 if (!status)
194 return -status.error();
195 return 0;
196}
197
198int ProducerBuffer::GainAsync(DvrNativeBufferMetadata* out_meta,
Tianyu5465d6c2018-08-14 13:03:10 -0700199 LocalHandle* release_fence,
200 bool gain_posted_buffer) {
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700201 ATRACE_NAME("ProducerBuffer::GainAsync");
202
Tianyu5465d6c2018-08-14 13:03:10 -0700203 if (const int error = LocalGain(out_meta, release_fence, gain_posted_buffer))
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700204 return error;
205
206 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
207}
208
209int ProducerBuffer::GainAsync() {
210 DvrNativeBufferMetadata meta;
211 LocalHandle fence;
212 return GainAsync(&meta, &fence);
213}
214
215std::unique_ptr<ProducerBuffer> ProducerBuffer::Import(
216 LocalChannelHandle channel) {
217 ALOGD_IF(TRACE, "ProducerBuffer::Import: channel=%d", channel.value());
218 return ProducerBuffer::Create(std::move(channel));
219}
220
221std::unique_ptr<ProducerBuffer> ProducerBuffer::Import(
222 Status<LocalChannelHandle> status) {
223 return Import(status ? status.take()
224 : LocalChannelHandle{nullptr, -status.error()});
225}
226
227Status<LocalChannelHandle> ProducerBuffer::Detach() {
Fan Xuddb90db2018-10-03 10:09:14 -0700228 // TODO(b/112338294) remove after migrate producer buffer to binder
229 ALOGW("ProducerBuffer::Detach: not supported operation during migration");
230 return {};
231
Fan Xub0eec512018-10-30 11:33:15 -0700232 // TODO(b/112338294) Keep here for reference. Remove it after new logic is
233 // written.
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700234 /* uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700235 if (!BufferHubDefs::IsBufferGained(buffer_state)) {
236 // Can only detach a ProducerBuffer when it's in gained state.
237 ALOGW("ProducerBuffer::Detach: The buffer (id=%d, state=0x%" PRIx64
238 ") is not in gained state.",
239 id(), buffer_state);
240 return {};
241 }
242
243 Status<LocalChannelHandle> status =
244 InvokeRemoteMethod<BufferHubRPC::ProducerBufferDetach>();
245 ALOGE_IF(!status,
246 "ProducerBuffer::Detach: Failed to detach buffer (id=%d): %s.", id(),
247 status.GetErrorMessage().c_str());
Fan Xub0eec512018-10-30 11:33:15 -0700248 return status; */
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700249}
250
251} // namespace dvr
252} // namespace android