blob: 3730e7df6c955363e397682352da8e30591e5c7b [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.
83 uint64_t buffer_state = buffer_state_->load();
84 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.
105 BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL,
106 BufferHubDefs::kProducerStateBit);
107 return 0;
108}
109
110int ProducerBuffer::Post(const LocalHandle& ready_fence, const void* meta,
111 size_t user_metadata_size) {
112 ATRACE_NAME("ProducerBuffer::Post");
113
114 // Populate cononical metadata for posting.
115 DvrNativeBufferMetadata canonical_meta;
116 canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta);
117 canonical_meta.user_metadata_size = user_metadata_size;
118
119 if (const int error = LocalPost(&canonical_meta, ready_fence))
120 return error;
121
122 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
123 BorrowedFence(ready_fence.Borrow())));
124}
125
126int ProducerBuffer::PostAsync(const DvrNativeBufferMetadata* meta,
127 const LocalHandle& ready_fence) {
128 ATRACE_NAME("ProducerBuffer::PostAsync");
129
130 if (const int error = LocalPost(meta, ready_fence))
131 return error;
132
133 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode));
134}
135
136int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta,
Tianyu5465d6c2018-08-14 13:03:10 -0700137 LocalHandle* out_fence, bool gain_posted_buffer) {
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700138 uint64_t buffer_state = buffer_state_->load();
139 ALOGD_IF(TRACE, "ProducerBuffer::LocalGain: buffer=%d, state=%" PRIx64 ".",
140 id(), buffer_state);
141
142 if (!out_meta)
143 return -EINVAL;
144
Tianyu5465d6c2018-08-14 13:03:10 -0700145 if (BufferHubDefs::IsBufferGained(buffer_state)) {
146 // We don't want to log error when gaining a newly allocated
147 // buffer.
148 ALOGI("ProducerBuffer::LocalGain: already gained id=%d.", id());
149 return -EALREADY;
150 }
151 if (BufferHubDefs::IsBufferAcquired(buffer_state) ||
152 (BufferHubDefs::IsBufferPosted(buffer_state) && !gain_posted_buffer)) {
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700153 ALOGE("ProducerBuffer::LocalGain: not released id=%d state=%" PRIx64 ".",
154 id(), buffer_state);
155 return -EBUSY;
156 }
157
158 // Canonical metadata is undefined on Gain. Except for user_metadata and
159 // release_fence_mask. Fill in the user_metadata_ptr in address space of the
160 // local process.
161 if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) {
162 out_meta->user_metadata_size =
163 metadata_header_->metadata.user_metadata_size;
164 out_meta->user_metadata_ptr =
165 reinterpret_cast<uint64_t>(user_metadata_ptr_);
166 } else {
167 out_meta->user_metadata_size = 0;
168 out_meta->user_metadata_ptr = 0;
169 }
170
171 uint64_t fence_state = fence_state_->load();
172 // If there is an release fence from consumer, we need to return it.
173 if (fence_state & BufferHubDefs::kConsumerStateMask) {
174 *out_fence = shared_release_fence_.Duplicate();
175 out_meta->release_fence_mask =
176 fence_state & BufferHubDefs::kConsumerStateMask;
177 }
178
179 // Clear out all bits and the buffer is now back to gained state.
180 buffer_state_->store(0ULL);
181 return 0;
182}
183
Tianyu5465d6c2018-08-14 13:03:10 -0700184int ProducerBuffer::Gain(LocalHandle* release_fence, bool gain_posted_buffer) {
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700185 ATRACE_NAME("ProducerBuffer::Gain");
186
187 DvrNativeBufferMetadata meta;
Tianyu5465d6c2018-08-14 13:03:10 -0700188 if (const int error = LocalGain(&meta, release_fence, gain_posted_buffer))
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700189 return error;
190
191 auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
192 if (!status)
193 return -status.error();
194 return 0;
195}
196
197int ProducerBuffer::GainAsync(DvrNativeBufferMetadata* out_meta,
Tianyu5465d6c2018-08-14 13:03:10 -0700198 LocalHandle* release_fence,
199 bool gain_posted_buffer) {
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700200 ATRACE_NAME("ProducerBuffer::GainAsync");
201
Tianyu5465d6c2018-08-14 13:03:10 -0700202 if (const int error = LocalGain(out_meta, release_fence, gain_posted_buffer))
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700203 return error;
204
205 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
206}
207
208int ProducerBuffer::GainAsync() {
209 DvrNativeBufferMetadata meta;
210 LocalHandle fence;
211 return GainAsync(&meta, &fence);
212}
213
214std::unique_ptr<ProducerBuffer> ProducerBuffer::Import(
215 LocalChannelHandle channel) {
216 ALOGD_IF(TRACE, "ProducerBuffer::Import: channel=%d", channel.value());
217 return ProducerBuffer::Create(std::move(channel));
218}
219
220std::unique_ptr<ProducerBuffer> ProducerBuffer::Import(
221 Status<LocalChannelHandle> status) {
222 return Import(status ? status.take()
223 : LocalChannelHandle{nullptr, -status.error()});
224}
225
226Status<LocalChannelHandle> ProducerBuffer::Detach() {
Fan Xuddb90db2018-10-03 10:09:14 -0700227 // TODO(b/112338294) remove after migrate producer buffer to binder
228 ALOGW("ProducerBuffer::Detach: not supported operation during migration");
229 return {};
230
Fan Xub0eec512018-10-30 11:33:15 -0700231 // TODO(b/112338294) Keep here for reference. Remove it after new logic is
232 // written.
233 /* uint64_t buffer_state = buffer_state_->load();
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700234 if (!BufferHubDefs::IsBufferGained(buffer_state)) {
235 // Can only detach a ProducerBuffer when it's in gained state.
236 ALOGW("ProducerBuffer::Detach: The buffer (id=%d, state=0x%" PRIx64
237 ") is not in gained state.",
238 id(), buffer_state);
239 return {};
240 }
241
242 Status<LocalChannelHandle> status =
243 InvokeRemoteMethod<BufferHubRPC::ProducerBufferDetach>();
244 ALOGE_IF(!status,
245 "ProducerBuffer::Detach: Failed to detach buffer (id=%d): %s.", id(),
246 status.GetErrorMessage().c_str());
Fan Xub0eec512018-10-30 11:33:15 -0700247 return status; */
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700248}
249
250} // namespace dvr
251} // namespace android