blob: 64a7944aeaf5342edd6d1570a0169b7f07726f5a [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include "include/private/dvr/buffer_hub_queue_producer.h"
2
Alex Vakulenko4fe60582017-02-02 11:35:59 -08003#include <inttypes.h>
4#include <log/log.h>
5
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08006namespace android {
7namespace dvr {
8
9BufferHubQueueProducer::BufferHubQueueProducer(
10 const std::shared_ptr<BufferHubQueueCore>& core)
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070011 : core_(core) {}
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080012
13status_t BufferHubQueueProducer::requestBuffer(int slot,
14 sp<GraphicBuffer>* buf) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -070015 ALOGD_IF(TRACE, "requestBuffer: slot=%d", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080016
17 std::unique_lock<std::mutex> lock(core_->mutex_);
18
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070019 if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
20 ALOGE("requestBuffer: BufferHubQueueProducer has no connected producer");
21 return NO_INIT;
22 }
23
24 if (slot < 0 || slot >= max_buffer_count_) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -080025 ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot,
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070026 max_buffer_count_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080027 return BAD_VALUE;
28 } else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -080029 ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)",
30 slot, core_->buffers_[slot].mBufferState.string());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080031 return BAD_VALUE;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070032 } else if (core_->buffers_[slot].mGraphicBuffer != nullptr) {
33 ALOGE("requestBuffer: slot %d is not empty.", slot);
34 return BAD_VALUE;
35 } else if (core_->buffers_[slot].mBufferProducer == nullptr) {
36 ALOGE("requestBuffer: slot %d is not dequeued.", slot);
37 return BAD_VALUE;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080038 }
39
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070040 const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
Corey Tabakacd52dd92017-04-07 18:03:57 -070041 sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070042
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070043 core_->buffers_[slot].mGraphicBuffer = graphic_buffer;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080044 core_->buffers_[slot].mRequestBufferCalled = true;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070045
46 *buf = graphic_buffer;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080047 return NO_ERROR;
48}
49
50status_t BufferHubQueueProducer::setMaxDequeuedBufferCount(
51 int max_dequeued_buffers) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -070052 ALOGD_IF(TRACE, "setMaxDequeuedBufferCount: max_dequeued_buffers=%d",
53 max_dequeued_buffers);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080054
55 std::unique_lock<std::mutex> lock(core_->mutex_);
56
57 if (max_dequeued_buffers <= 0 ||
58 max_dequeued_buffers >
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -070059 static_cast<int>(BufferHubQueue::kMaxQueueCapacity -
60 BufferHubQueueCore::kDefaultUndequeuedBuffers)) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -080061 ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]",
62 max_dequeued_buffers, BufferHubQueue::kMaxQueueCapacity);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080063 return BAD_VALUE;
64 }
65
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070066 // The new dequeued_buffers count should not be violated by the number
67 // of currently dequeued buffers.
68 int dequeued_count = 0;
69 for (const auto& buf : core_->buffers_) {
70 if (buf.mBufferState.isDequeued()) {
71 dequeued_count++;
72 }
73 }
74 if (dequeued_count > max_dequeued_buffers) {
75 ALOGE(
76 "setMaxDequeuedBufferCount: the requested dequeued_buffers"
77 "count (%d) exceeds the current dequeued buffer count (%d)",
78 max_dequeued_buffers, dequeued_count);
79 return BAD_VALUE;
80 }
81
82 max_dequeued_buffer_count_ = max_dequeued_buffers;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080083 return NO_ERROR;
84}
85
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070086status_t BufferHubQueueProducer::setAsyncMode(bool async) {
87 if (async) {
88 // TODO(b/36724099) BufferHubQueue's consumer end always acquires the buffer
89 // automatically and behaves differently from IGraphicBufferConsumer. Thus,
90 // android::BufferQueue's async mode (a.k.a. allocating an additional buffer
91 // to prevent dequeueBuffer from being blocking) technically does not apply
92 // here.
93 //
94 // In Daydream, non-blocking producer side dequeue is guaranteed by careful
95 // buffer consumer implementations. In another word, BufferHubQueue based
96 // dequeueBuffer should never block whether setAsyncMode(true) is set or
97 // not.
98 //
99 // See: IGraphicBufferProducer::setAsyncMode and
100 // BufferQueueProducer::setAsyncMode for more about original implementation.
101 ALOGW(
102 "BufferHubQueueProducer::setAsyncMode: BufferHubQueue should always be "
103 "asynchronous. This call makes no effact.");
104 return NO_ERROR;
105 }
106 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800107}
108
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700109status_t BufferHubQueueProducer::dequeueBuffer(
110 int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height,
111 PixelFormat format, uint32_t usage,
112 FrameEventHistoryDelta* /* out_timestamps */) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700113 ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%u", width,
114 height, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800115
116 status_t ret;
117 std::unique_lock<std::mutex> lock(core_->mutex_);
118
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700119 if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
120 ALOGE("dequeueBuffer: BufferQueue has no connected producer");
121 return NO_INIT;
122 }
123
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700124 const uint32_t kLayerCount = 1;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700125 if (static_cast<int32_t>(core_->producer_->capacity()) <
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700126 max_dequeued_buffer_count_ +
127 BufferHubQueueCore::kDefaultUndequeuedBuffers) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800128 // Lazy allocation. When the capacity of |core_->producer_| has not reach
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700129 // |max_dequeued_buffer_count_|, allocate new buffer.
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800130 // TODO(jwcai) To save memory, the really reasonable thing to do is to go
131 // over existing slots and find first existing one to dequeue.
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700132 ret = core_->AllocateBuffer(width, height, kLayerCount, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800133 if (ret < 0)
134 return ret;
135 }
136
137 size_t slot;
138 std::shared_ptr<BufferProducer> buffer_producer;
139
140 for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
Jiwen 'Steve' Caied654322017-03-13 17:04:43 -0700141 LocalHandle fence;
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700142 auto buffer_status =
Jiwen 'Steve' Caied654322017-03-13 17:04:43 -0700143 core_->producer_->Dequeue(core_->dequeue_timeout_ms_, &slot, &fence);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800144 if (!buffer_producer)
145 return NO_MEMORY;
146
Corey Tabaka9d8bd092017-04-25 16:47:44 -0700147 buffer_producer = buffer_status.take();
148
Corey Tabakacd52dd92017-04-07 18:03:57 -0700149 if (width == buffer_producer->width() &&
150 height == buffer_producer->height() &&
151 static_cast<uint32_t>(format) == buffer_producer->format()) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800152 // The producer queue returns a buffer producer matches the request.
153 break;
154 }
155
156 // Needs reallocation.
157 // TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800158 ALOGI(
Corey Tabakacd52dd92017-04-07 18:03:57 -0700159 "dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
160 "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800161 "re-allocattion.",
162 width, height, format, slot, buffer_producer->width(),
163 buffer_producer->height(), buffer_producer->format());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800164 // Mark the slot as reallocating, so that later we can set
165 // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
166 core_->buffers_[slot].mIsReallocating = true;
167
168 // Detach the old buffer once the allocation before allocating its
169 // replacement.
170 core_->DetachBuffer(slot);
171
172 // Allocate a new producer buffer with new buffer configs. Note that if
173 // there are already multiple buffers in the queue, the next one returned
174 // from |core_->producer_->Dequeue| may not be the new buffer we just
175 // reallocated. Retry up to BufferHubQueue::kMaxQueueCapacity times.
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700176 ret = core_->AllocateBuffer(width, height, kLayerCount, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800177 if (ret < 0)
178 return ret;
179 }
180
181 // With the BufferHub backed solution. Buffer slot returned from
182 // |core_->producer_->Dequeue| is guaranteed to avaiable for producer's use.
183 // It's either in free state (if the buffer has never been used before) or
184 // in queued state (if the buffer has been dequeued and queued back to
185 // BufferHubQueue).
186 // TODO(jwcai) Clean this up, make mBufferState compatible with BufferHub's
187 // model.
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700188 LOG_ALWAYS_FATAL_IF((!core_->buffers_[slot].mBufferState.isFree() &&
189 !core_->buffers_[slot].mBufferState.isQueued()),
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800190 "dequeueBuffer: slot %zu is not free or queued.", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800191
192 core_->buffers_[slot].mBufferState.freeQueued();
193 core_->buffers_[slot].mBufferState.dequeue();
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700194 ALOGD_IF(TRACE, "dequeueBuffer: slot=%zu", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800195
196 // TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we
197 // just need to exopose that through |BufferHubQueue| once we need fence.
198 *out_fence = Fence::NO_FENCE;
199 *out_slot = slot;
200 ret = NO_ERROR;
201
202 if (core_->buffers_[slot].mIsReallocating) {
203 ret |= BUFFER_NEEDS_REALLOCATION;
204 core_->buffers_[slot].mIsReallocating = false;
205 }
206
207 return ret;
208}
209
210status_t BufferHubQueueProducer::detachBuffer(int /* slot */) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800211 ALOGE("BufferHubQueueProducer::detachBuffer not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800212 return INVALID_OPERATION;
213}
214
215status_t BufferHubQueueProducer::detachNextBuffer(
216 sp<GraphicBuffer>* /* out_buffer */, sp<Fence>* /* out_fence */) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800217 ALOGE("BufferHubQueueProducer::detachNextBuffer not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800218 return INVALID_OPERATION;
219}
220
221status_t BufferHubQueueProducer::attachBuffer(
222 int* /* out_slot */, const sp<GraphicBuffer>& /* buffer */) {
223 // With this BufferHub backed implementation, we assume (for now) all buffers
224 // are allocated and owned by the BufferHub. Thus the attempt of transfering
225 // ownership of a buffer to the buffer queue is intentionally unsupported.
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800226 LOG_ALWAYS_FATAL("BufferHubQueueProducer::attachBuffer not supported.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800227 return INVALID_OPERATION;
228}
229
230status_t BufferHubQueueProducer::queueBuffer(int slot,
231 const QueueBufferInput& input,
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700232 QueueBufferOutput* output) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700233 ALOGD_IF(TRACE, "queueBuffer: slot %d", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800234
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700235 if (output == nullptr) {
236 return BAD_VALUE;
237 }
238
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800239 int64_t timestamp;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800240 bool is_auto_timestamp;
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700241 android_dataspace dataspace;
242 Rect crop(Rect::EMPTY_RECT);
243 int scaling_mode;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800244 uint32_t transform;
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700245 sp<Fence> fence;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800246
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700247 input.deflate(&timestamp, &is_auto_timestamp, &dataspace, &crop,
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800248 &scaling_mode, &transform, &fence);
249
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700250 // Check input scaling mode is valid.
251 switch (scaling_mode) {
252 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
253 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
254 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
255 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
256 break;
257 default:
258 ALOGE("queueBuffer: unknown scaling mode %d", scaling_mode);
259 return BAD_VALUE;
260 }
261
262 // Check input fence is valid.
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800263 if (fence == nullptr) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800264 ALOGE("queueBuffer: fence is NULL");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800265 return BAD_VALUE;
266 }
267
268 status_t ret;
269 std::unique_lock<std::mutex> lock(core_->mutex_);
270
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700271 if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
272 ALOGE("queueBuffer: BufferQueue has no connected producer");
273 return NO_INIT;
274 }
275
276 if (slot < 0 || slot >= max_buffer_count_) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800277 ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot,
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700278 max_buffer_count_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800279 return BAD_VALUE;
280 } else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800281 ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)",
282 slot, core_->buffers_[slot].mBufferState.string());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800283 return BAD_VALUE;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700284 } else if ((!core_->buffers_[slot].mRequestBufferCalled ||
285 core_->buffers_[slot].mGraphicBuffer == nullptr)) {
286 ALOGE(
287 "queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, "
288 "mGraphicBuffer=%p)",
289 slot, core_->buffers_[slot].mRequestBufferCalled,
290 core_->buffers_[slot].mGraphicBuffer.get());
291 return BAD_VALUE;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800292 }
293
294 // Post the buffer producer with timestamp in the metadata.
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700295 const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
296
297 // Check input crop is not out of boundary of current buffer.
298 Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
299 Rect cropped_rect(Rect::EMPTY_RECT);
300 crop.intersect(buffer_rect, &cropped_rect);
301 if (cropped_rect != crop) {
302 ALOGE("queueBuffer: slot %d has out-of-boundary crop.", slot);
303 return BAD_VALUE;
304 }
305
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800306 LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
307
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700308 BufferHubQueueCore::NativeBufferMetadata meta_data = {};
309 meta_data.timestamp = timestamp;
310 meta_data.is_auto_timestamp = static_cast<int32_t>(is_auto_timestamp);
311 meta_data.dataspace = static_cast<int32_t>(dataspace);
312 meta_data.crop_left = crop.left;
313 meta_data.crop_top = crop.top;
314 meta_data.crop_right = crop.right;
315 meta_data.crop_bottom = crop.bottom;
316 meta_data.scaling_mode = static_cast<int32_t>(scaling_mode);
317 meta_data.transform = static_cast<int32_t>(transform);
318
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800319 buffer_producer->Post(fence_fd, &meta_data, sizeof(meta_data));
320 core_->buffers_[slot].mBufferState.queue();
321
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700322 output->width = buffer_producer->width();
323 output->height = buffer_producer->height();
Corey Tabakacd52dd92017-04-07 18:03:57 -0700324 output->transformHint = 0; // default value, we don't use it yet.
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700325
326 // |numPendingBuffers| counts of the number of buffers that has been enqueued
327 // by the producer but not yet acquired by the consumer. Due to the nature
328 // of BufferHubQueue design, this is hard to trace from the producer's client
329 // side, but it's safe to assume it's zero.
330 output->numPendingBuffers = 0;
331
332 // Note that we are not setting nextFrameNumber here as it seems to be only
333 // used by surface flinger. See more at b/22802885, ag/791760.
334 output->nextFrameNumber = 0;
335
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800336 return NO_ERROR;
337}
338
339status_t BufferHubQueueProducer::cancelBuffer(int slot,
340 const sp<Fence>& fence) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700341 ALOGD_IF(TRACE, __FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800342
343 std::unique_lock<std::mutex> lock(core_->mutex_);
344
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700345 if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
346 ALOGE("cancelBuffer: BufferQueue has no connected producer");
347 return NO_INIT;
348 }
349
350 if (slot < 0 || slot >= max_buffer_count_) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800351 ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700352 max_buffer_count_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800353 return BAD_VALUE;
354 } else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800355 ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)",
356 slot, core_->buffers_[slot].mBufferState.string());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800357 return BAD_VALUE;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700358 } else if (fence == nullptr) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800359 ALOGE("cancelBuffer: fence is NULL");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800360 return BAD_VALUE;
361 }
362
363 auto buffer_producer = core_->buffers_[slot].mBufferProducer;
364 core_->producer_->Enqueue(buffer_producer, slot);
365 core_->buffers_[slot].mBufferState.cancel();
366 core_->buffers_[slot].mFence = fence;
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700367 ALOGD_IF(TRACE, "cancelBuffer: slot %d", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800368
369 return NO_ERROR;
370}
371
372status_t BufferHubQueueProducer::query(int what, int* out_value) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700373 ALOGD_IF(TRACE, __FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800374
375 std::unique_lock<std::mutex> lock(core_->mutex_);
376
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700377 if (out_value == nullptr) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800378 ALOGE("query: out_value was NULL");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800379 return BAD_VALUE;
380 }
381
382 int value = 0;
383 switch (what) {
384 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700385 // TODO(b/36187402) This should be the maximum number of buffers that this
386 // producer queue's consumer can acquire. Set to be at least one. Need to
387 // find a way to set from the consumer side.
388 value = BufferHubQueueCore::kDefaultUndequeuedBuffers;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800389 break;
390 case NATIVE_WINDOW_BUFFER_AGE:
391 value = 0;
392 break;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700393 case NATIVE_WINDOW_WIDTH:
394 value = core_->producer_->default_width();
395 break;
396 case NATIVE_WINDOW_HEIGHT:
397 value = core_->producer_->default_height();
398 break;
399 case NATIVE_WINDOW_FORMAT:
400 value = core_->producer_->default_format();
401 break;
402 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
403 // BufferHubQueue is always operating in async mode, thus semantically
404 // consumer can never be running behind. See BufferQueueCore.cpp core
405 // for more information about the original meaning of this flag.
406 value = 0;
407 break;
408 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
409 // TODO(jwcai) This is currently not implement as we don't need
410 // IGraphicBufferConsumer parity.
411 value = 0;
412 break;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800413 case NATIVE_WINDOW_DEFAULT_DATASPACE:
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700414 // TODO(jwcai) Return the default value android::BufferQueue is using as
415 // there is no way dvr::ConsumerQueue can set it.
416 value = 0; // HAL_DATASPACE_UNKNOWN
417 break;
418 case NATIVE_WINDOW_STICKY_TRANSFORM:
419 // TODO(jwcai) Return the default value android::BufferQueue is using as
420 // there is no way dvr::ConsumerQueue can set it.
421 value = 0;
422 break;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800423 default:
424 return BAD_VALUE;
425 }
426
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700427 ALOGD_IF(TRACE, "query: key=%d, v=%d", what, value);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800428 *out_value = value;
429 return NO_ERROR;
430}
431
432status_t BufferHubQueueProducer::connect(
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700433 const sp<IProducerListener>& /* listener */, int api,
434 bool /* producer_controlled_by_app */, QueueBufferOutput* output) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800435 // Consumer interaction are actually handled by buffer hub, and we need
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700436 // to maintain consumer operations here. We only need to perform basic input
437 // parameter checks here.
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700438 ALOGD_IF(TRACE, __FUNCTION__);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700439
440 if (output == nullptr) {
441 return BAD_VALUE;
442 }
443
444 std::unique_lock<std::mutex> lock(core_->mutex_);
445
446 if (core_->connected_api_ != BufferHubQueueCore::kNoConnectedApi) {
447 return BAD_VALUE;
448 }
449
450 switch (api) {
451 case NATIVE_WINDOW_API_EGL:
452 case NATIVE_WINDOW_API_CPU:
453 case NATIVE_WINDOW_API_MEDIA:
454 case NATIVE_WINDOW_API_CAMERA:
455 core_->connected_api_ = api;
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700456
457 output->width = core_->producer_->default_width();
458 output->height = core_->producer_->default_height();
459
460 // default values, we don't use them yet.
461 output->transformHint = 0;
462 output->numPendingBuffers = 0;
463 output->nextFrameNumber = 0;
464 output->bufferReplaced = false;
465
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700466 break;
467 default:
468 ALOGE("BufferHubQueueProducer::connect: unknow API %d", api);
469 return BAD_VALUE;
470 }
471
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800472 return NO_ERROR;
473}
474
Corey Tabakacd52dd92017-04-07 18:03:57 -0700475status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode /*mode*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800476 // Consumer interaction are actually handled by buffer hub, and we need
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700477 // to maintain consumer operations here. We only need to perform basic input
478 // parameter checks here.
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700479 ALOGD_IF(TRACE, __FUNCTION__);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700480
481 std::unique_lock<std::mutex> lock(core_->mutex_);
482
Wonsik Kim3e198b22017-04-07 15:43:16 -0700483 if (BufferHubQueueCore::kNoConnectedApi == core_->connected_api_) {
484 return NO_INIT;
485 } else if (api != core_->connected_api_) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700486 return BAD_VALUE;
487 }
488
489 core_->connected_api_ = BufferHubQueueCore::kNoConnectedApi;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800490 return NO_ERROR;
491}
492
493status_t BufferHubQueueProducer::setSidebandStream(
494 const sp<NativeHandle>& stream) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700495 if (stream != nullptr) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800496 // TODO(jwcai) Investigate how is is used, maybe use BufferHubBuffer's
497 // metadata.
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800498 ALOGE("SidebandStream is not currently supported.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800499 return INVALID_OPERATION;
500 }
501 return NO_ERROR;
502}
503
504void BufferHubQueueProducer::allocateBuffers(uint32_t /* width */,
505 uint32_t /* height */,
506 PixelFormat /* format */,
507 uint32_t /* usage */) {
508 // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
509 // of buffers permitted by the current BufferQueue configuration (aka
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700510 // |max_buffer_count_|).
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800511 ALOGE("BufferHubQueueProducer::allocateBuffers not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800512}
513
514status_t BufferHubQueueProducer::allowAllocation(bool /* allow */) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800515 ALOGE("BufferHubQueueProducer::allowAllocation not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800516 return INVALID_OPERATION;
517}
518
519status_t BufferHubQueueProducer::setGenerationNumber(
520 uint32_t generation_number) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700521 ALOGD_IF(TRACE, __FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800522
523 std::unique_lock<std::mutex> lock(core_->mutex_);
524 core_->generation_number_ = generation_number;
525 return NO_ERROR;
526}
527
528String8 BufferHubQueueProducer::getConsumerName() const {
529 // BufferHub based implementation could have one to many producer/consumer
530 // relationship, thus |getConsumerName| from the producer side does not
531 // make any sense.
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800532 ALOGE("BufferHubQueueProducer::getConsumerName not supported.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800533 return String8("BufferHubQueue::DummyConsumer");
534}
535
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700536status_t BufferHubQueueProducer::setSharedBufferMode(bool shared_buffer_mode) {
537 if (shared_buffer_mode) {
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700538 ALOGE(
539 "BufferHubQueueProducer::setSharedBufferMode(true) is not supported.");
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700540 // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow.
541 return INVALID_OPERATION;
542 }
543 // Setting to default should just work as a no-op.
544 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800545}
546
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700547status_t BufferHubQueueProducer::setAutoRefresh(bool auto_refresh) {
548 if (auto_refresh) {
549 ALOGE("BufferHubQueueProducer::setAutoRefresh(true) is not supported.");
550 return INVALID_OPERATION;
551 }
552 // Setting to default should just work as a no-op.
553 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800554}
555
556status_t BufferHubQueueProducer::setDequeueTimeout(nsecs_t timeout) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700557 ALOGD_IF(TRACE, __FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800558
559 std::unique_lock<std::mutex> lock(core_->mutex_);
560 core_->dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
561 return NO_ERROR;
562}
563
564status_t BufferHubQueueProducer::getLastQueuedBuffer(
565 sp<GraphicBuffer>* /* out_buffer */, sp<Fence>* /* out_fence */,
566 float /*out_transform_matrix*/[16]) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800567 ALOGE("BufferHubQueueProducer::getLastQueuedBuffer not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800568 return INVALID_OPERATION;
569}
570
571void BufferHubQueueProducer::getFrameTimestamps(
572 FrameEventHistoryDelta* /*outDelta*/) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800573 ALOGE("BufferHubQueueProducer::getFrameTimestamps not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800574}
575
576status_t BufferHubQueueProducer::getUniqueId(uint64_t* out_id) const {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700577 ALOGD_IF(TRACE, __FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800578
579 *out_id = core_->unique_id_;
580 return NO_ERROR;
581}
582
583IBinder* BufferHubQueueProducer::onAsBinder() {
584 // BufferHubQueueProducer is a non-binder implementation of
585 // IGraphicBufferProducer.
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700586 ALOGW("BufferHubQueueProducer::onAsBinder is not efficiently supported.");
587 return this;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800588}
589
590} // namespace dvr
591} // namespace android