blob: 0f75a5c3d8b2e68e6b42f5934a351d0b95dd3fce [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include "include/private/dvr/buffer_hub_queue_producer.h"
2
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -07003#include <dvr/dvr_api.h>
Alex Vakulenko4fe60582017-02-02 11:35:59 -08004#include <inttypes.h>
5#include <log/log.h>
Mathias Agopian6a3c05b2017-04-27 20:06:55 -07006#include <system/window.h>
Alex Vakulenko4fe60582017-02-02 11:35:59 -08007
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08008namespace android {
9namespace dvr {
10
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070011/* static */
12sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() {
13 sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
Jiwen 'Steve' Cai6bffc672017-05-18 23:05:05 -070014 auto config = ProducerQueueConfigBuilder()
15 .SetMetadata<DvrNativeBufferMetadata>()
16 .Build();
17 producer->queue_ = ProducerQueue::Create(config, UsagePolicy{});
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070018 return producer;
19}
20
21/* static */
22sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
23 const std::shared_ptr<ProducerQueue>& queue) {
24 if (queue->metadata_size() != sizeof(DvrNativeBufferMetadata)) {
25 ALOGE(
26 "BufferHubQueueProducer::Create producer's metadata size is different "
27 "than the size of DvrNativeBufferMetadata");
28 return nullptr;
29 }
30
31 sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
32 producer->queue_ = queue;
33 return producer;
34}
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080035
36status_t BufferHubQueueProducer::requestBuffer(int slot,
37 sp<GraphicBuffer>* buf) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -070038 ALOGD_IF(TRACE, "requestBuffer: slot=%d", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080039
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070040 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080041
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070042 if (connected_api_ == kNoConnectedApi) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070043 ALOGE("requestBuffer: BufferHubQueueProducer has no connected producer");
44 return NO_INIT;
45 }
46
47 if (slot < 0 || slot >= max_buffer_count_) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -080048 ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot,
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070049 max_buffer_count_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080050 return BAD_VALUE;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070051 } else if (!buffers_[slot].mBufferState.isDequeued()) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -080052 ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)",
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070053 slot, buffers_[slot].mBufferState.string());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080054 return BAD_VALUE;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070055 } else if (buffers_[slot].mGraphicBuffer != nullptr) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070056 ALOGE("requestBuffer: slot %d is not empty.", slot);
57 return BAD_VALUE;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070058 } else if (buffers_[slot].mBufferProducer == nullptr) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070059 ALOGE("requestBuffer: slot %d is not dequeued.", slot);
60 return BAD_VALUE;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080061 }
62
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070063 const auto& buffer_producer = buffers_[slot].mBufferProducer;
Corey Tabakacd52dd92017-04-07 18:03:57 -070064 sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070065
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070066 buffers_[slot].mGraphicBuffer = graphic_buffer;
67 buffers_[slot].mRequestBufferCalled = true;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070068
69 *buf = graphic_buffer;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080070 return NO_ERROR;
71}
72
73status_t BufferHubQueueProducer::setMaxDequeuedBufferCount(
74 int max_dequeued_buffers) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -070075 ALOGD_IF(TRACE, "setMaxDequeuedBufferCount: max_dequeued_buffers=%d",
76 max_dequeued_buffers);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080077
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070078 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080079
80 if (max_dequeued_buffers <= 0 ||
81 max_dequeued_buffers >
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -070082 static_cast<int>(BufferHubQueue::kMaxQueueCapacity -
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070083 kDefaultUndequeuedBuffers)) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -080084 ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]",
85 max_dequeued_buffers, BufferHubQueue::kMaxQueueCapacity);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080086 return BAD_VALUE;
87 }
88
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070089 // The new dequeued_buffers count should not be violated by the number
90 // of currently dequeued buffers.
91 int dequeued_count = 0;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070092 for (const auto& buf : buffers_) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070093 if (buf.mBufferState.isDequeued()) {
94 dequeued_count++;
95 }
96 }
97 if (dequeued_count > max_dequeued_buffers) {
98 ALOGE(
99 "setMaxDequeuedBufferCount: the requested dequeued_buffers"
100 "count (%d) exceeds the current dequeued buffer count (%d)",
101 max_dequeued_buffers, dequeued_count);
102 return BAD_VALUE;
103 }
104
105 max_dequeued_buffer_count_ = max_dequeued_buffers;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800106 return NO_ERROR;
107}
108
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700109status_t BufferHubQueueProducer::setAsyncMode(bool async) {
110 if (async) {
111 // TODO(b/36724099) BufferHubQueue's consumer end always acquires the buffer
112 // automatically and behaves differently from IGraphicBufferConsumer. Thus,
113 // android::BufferQueue's async mode (a.k.a. allocating an additional buffer
114 // to prevent dequeueBuffer from being blocking) technically does not apply
115 // here.
116 //
117 // In Daydream, non-blocking producer side dequeue is guaranteed by careful
118 // buffer consumer implementations. In another word, BufferHubQueue based
119 // dequeueBuffer should never block whether setAsyncMode(true) is set or
120 // not.
121 //
122 // See: IGraphicBufferProducer::setAsyncMode and
123 // BufferQueueProducer::setAsyncMode for more about original implementation.
124 ALOGW(
125 "BufferHubQueueProducer::setAsyncMode: BufferHubQueue should always be "
126 "asynchronous. This call makes no effact.");
127 return NO_ERROR;
128 }
129 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800130}
131
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700132status_t BufferHubQueueProducer::dequeueBuffer(
133 int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height,
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700134 PixelFormat format, uint64_t usage,
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700135 FrameEventHistoryDelta* /* out_timestamps */) {
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700136 ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%llu", width,
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700137 height, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800138
139 status_t ret;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700140 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800141
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700142 if (connected_api_ == kNoConnectedApi) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700143 ALOGE("dequeueBuffer: BufferQueue has no connected producer");
144 return NO_INIT;
145 }
146
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700147 const uint32_t kLayerCount = 1;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700148 if (static_cast<int32_t>(queue_->capacity()) <
149 max_dequeued_buffer_count_ + kDefaultUndequeuedBuffers) {
150 // Lazy allocation. When the capacity of |queue_| has not reached
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700151 // |max_dequeued_buffer_count_|, allocate new buffer.
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800152 // TODO(jwcai) To save memory, the really reasonable thing to do is to go
153 // over existing slots and find first existing one to dequeue.
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700154 ret = AllocateBuffer(width, height, kLayerCount, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800155 if (ret < 0)
156 return ret;
157 }
158
159 size_t slot;
160 std::shared_ptr<BufferProducer> buffer_producer;
161
162 for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
Jiwen 'Steve' Caied654322017-03-13 17:04:43 -0700163 LocalHandle fence;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700164 auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
Corey Tabakab7ca5de2017-05-08 18:55:02 -0700165 if (!buffer_status)
166 return NO_MEMORY;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800167
Corey Tabaka9d8bd092017-04-25 16:47:44 -0700168 buffer_producer = buffer_status.take();
Jiwen 'Steve' Caib8508212017-05-08 16:02:36 -0700169 if (!buffer_producer)
170 return NO_MEMORY;
Corey Tabaka9d8bd092017-04-25 16:47:44 -0700171
Corey Tabakacd52dd92017-04-07 18:03:57 -0700172 if (width == buffer_producer->width() &&
173 height == buffer_producer->height() &&
174 static_cast<uint32_t>(format) == buffer_producer->format()) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800175 // The producer queue returns a buffer producer matches the request.
176 break;
177 }
178
179 // Needs reallocation.
180 // TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800181 ALOGI(
Corey Tabakacd52dd92017-04-07 18:03:57 -0700182 "dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
183 "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800184 "re-allocattion.",
185 width, height, format, slot, buffer_producer->width(),
186 buffer_producer->height(), buffer_producer->format());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800187 // Mark the slot as reallocating, so that later we can set
188 // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700189 buffers_[slot].mIsReallocating = true;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800190
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700191 // Remove the old buffer once the allocation before allocating its
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800192 // replacement.
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700193 RemoveBuffer(slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800194
195 // Allocate a new producer buffer with new buffer configs. Note that if
196 // there are already multiple buffers in the queue, the next one returned
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700197 // from |queue_->Dequeue| may not be the new buffer we just reallocated.
198 // Retry up to BufferHubQueue::kMaxQueueCapacity times.
199 ret = AllocateBuffer(width, height, kLayerCount, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800200 if (ret < 0)
201 return ret;
202 }
203
204 // With the BufferHub backed solution. Buffer slot returned from
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700205 // |queue_->Dequeue| is guaranteed to avaiable for producer's use.
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800206 // It's either in free state (if the buffer has never been used before) or
207 // in queued state (if the buffer has been dequeued and queued back to
208 // BufferHubQueue).
209 // TODO(jwcai) Clean this up, make mBufferState compatible with BufferHub's
210 // model.
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700211 LOG_ALWAYS_FATAL_IF((!buffers_[slot].mBufferState.isFree() &&
212 !buffers_[slot].mBufferState.isQueued()),
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800213 "dequeueBuffer: slot %zu is not free or queued.", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800214
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700215 buffers_[slot].mBufferState.freeQueued();
216 buffers_[slot].mBufferState.dequeue();
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700217 ALOGD_IF(TRACE, "dequeueBuffer: slot=%zu", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800218
219 // TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we
220 // just need to exopose that through |BufferHubQueue| once we need fence.
221 *out_fence = Fence::NO_FENCE;
222 *out_slot = slot;
223 ret = NO_ERROR;
224
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700225 if (buffers_[slot].mIsReallocating) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800226 ret |= BUFFER_NEEDS_REALLOCATION;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700227 buffers_[slot].mIsReallocating = false;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800228 }
229
230 return ret;
231}
232
233status_t BufferHubQueueProducer::detachBuffer(int /* slot */) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800234 ALOGE("BufferHubQueueProducer::detachBuffer not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800235 return INVALID_OPERATION;
236}
237
238status_t BufferHubQueueProducer::detachNextBuffer(
239 sp<GraphicBuffer>* /* out_buffer */, sp<Fence>* /* out_fence */) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800240 ALOGE("BufferHubQueueProducer::detachNextBuffer not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800241 return INVALID_OPERATION;
242}
243
244status_t BufferHubQueueProducer::attachBuffer(
245 int* /* out_slot */, const sp<GraphicBuffer>& /* buffer */) {
246 // With this BufferHub backed implementation, we assume (for now) all buffers
247 // are allocated and owned by the BufferHub. Thus the attempt of transfering
248 // ownership of a buffer to the buffer queue is intentionally unsupported.
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800249 LOG_ALWAYS_FATAL("BufferHubQueueProducer::attachBuffer not supported.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800250 return INVALID_OPERATION;
251}
252
253status_t BufferHubQueueProducer::queueBuffer(int slot,
254 const QueueBufferInput& input,
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700255 QueueBufferOutput* output) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700256 ALOGD_IF(TRACE, "queueBuffer: slot %d", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800257
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700258 if (output == nullptr) {
259 return BAD_VALUE;
260 }
261
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800262 int64_t timestamp;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800263 bool is_auto_timestamp;
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700264 android_dataspace dataspace;
265 Rect crop(Rect::EMPTY_RECT);
266 int scaling_mode;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800267 uint32_t transform;
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700268 sp<Fence> fence;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800269
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700270 input.deflate(&timestamp, &is_auto_timestamp, &dataspace, &crop,
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800271 &scaling_mode, &transform, &fence);
272
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700273 // Check input scaling mode is valid.
274 switch (scaling_mode) {
275 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
276 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
277 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
278 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
279 break;
280 default:
281 ALOGE("queueBuffer: unknown scaling mode %d", scaling_mode);
282 return BAD_VALUE;
283 }
284
285 // Check input fence is valid.
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800286 if (fence == nullptr) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800287 ALOGE("queueBuffer: fence is NULL");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800288 return BAD_VALUE;
289 }
290
291 status_t ret;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700292 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800293
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700294 if (connected_api_ == kNoConnectedApi) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700295 ALOGE("queueBuffer: BufferQueue has no connected producer");
296 return NO_INIT;
297 }
298
299 if (slot < 0 || slot >= max_buffer_count_) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800300 ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot,
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700301 max_buffer_count_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800302 return BAD_VALUE;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700303 } else if (!buffers_[slot].mBufferState.isDequeued()) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800304 ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)",
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700305 slot, buffers_[slot].mBufferState.string());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800306 return BAD_VALUE;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700307 } else if ((!buffers_[slot].mRequestBufferCalled ||
308 buffers_[slot].mGraphicBuffer == nullptr)) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700309 ALOGE(
310 "queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, "
311 "mGraphicBuffer=%p)",
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700312 slot, buffers_[slot].mRequestBufferCalled,
313 buffers_[slot].mGraphicBuffer.get());
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700314 return BAD_VALUE;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800315 }
316
317 // Post the buffer producer with timestamp in the metadata.
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700318 const auto& buffer_producer = buffers_[slot].mBufferProducer;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700319
320 // Check input crop is not out of boundary of current buffer.
321 Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
322 Rect cropped_rect(Rect::EMPTY_RECT);
323 crop.intersect(buffer_rect, &cropped_rect);
324 if (cropped_rect != crop) {
325 ALOGE("queueBuffer: slot %d has out-of-boundary crop.", slot);
326 return BAD_VALUE;
327 }
328
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800329 LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
330
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700331 DvrNativeBufferMetadata meta_data = {};
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700332 meta_data.timestamp = timestamp;
333 meta_data.is_auto_timestamp = static_cast<int32_t>(is_auto_timestamp);
334 meta_data.dataspace = static_cast<int32_t>(dataspace);
335 meta_data.crop_left = crop.left;
336 meta_data.crop_top = crop.top;
337 meta_data.crop_right = crop.right;
338 meta_data.crop_bottom = crop.bottom;
339 meta_data.scaling_mode = static_cast<int32_t>(scaling_mode);
340 meta_data.transform = static_cast<int32_t>(transform);
341
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800342 buffer_producer->Post(fence_fd, &meta_data, sizeof(meta_data));
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700343 buffers_[slot].mBufferState.queue();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800344
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700345 output->width = buffer_producer->width();
346 output->height = buffer_producer->height();
Corey Tabakacd52dd92017-04-07 18:03:57 -0700347 output->transformHint = 0; // default value, we don't use it yet.
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700348
349 // |numPendingBuffers| counts of the number of buffers that has been enqueued
350 // by the producer but not yet acquired by the consumer. Due to the nature
351 // of BufferHubQueue design, this is hard to trace from the producer's client
352 // side, but it's safe to assume it's zero.
353 output->numPendingBuffers = 0;
354
355 // Note that we are not setting nextFrameNumber here as it seems to be only
356 // used by surface flinger. See more at b/22802885, ag/791760.
357 output->nextFrameNumber = 0;
358
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800359 return NO_ERROR;
360}
361
362status_t BufferHubQueueProducer::cancelBuffer(int slot,
363 const sp<Fence>& fence) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700364 ALOGD_IF(TRACE, __FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800365
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700366 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800367
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700368 if (connected_api_ == kNoConnectedApi) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700369 ALOGE("cancelBuffer: BufferQueue has no connected producer");
370 return NO_INIT;
371 }
372
373 if (slot < 0 || slot >= max_buffer_count_) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800374 ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700375 max_buffer_count_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800376 return BAD_VALUE;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700377 } else if (!buffers_[slot].mBufferState.isDequeued()) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800378 ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)",
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700379 slot, buffers_[slot].mBufferState.string());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800380 return BAD_VALUE;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700381 } else if (fence == nullptr) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800382 ALOGE("cancelBuffer: fence is NULL");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800383 return BAD_VALUE;
384 }
385
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700386 auto buffer_producer = buffers_[slot].mBufferProducer;
387 queue_->Enqueue(buffer_producer, slot);
388 buffers_[slot].mBufferState.cancel();
389 buffers_[slot].mFence = fence;
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700390 ALOGD_IF(TRACE, "cancelBuffer: slot %d", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800391
392 return NO_ERROR;
393}
394
395status_t BufferHubQueueProducer::query(int what, int* out_value) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700396 ALOGD_IF(TRACE, __FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800397
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700398 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800399
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700400 if (out_value == nullptr) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800401 ALOGE("query: out_value was NULL");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800402 return BAD_VALUE;
403 }
404
405 int value = 0;
406 switch (what) {
407 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700408 // TODO(b/36187402) This should be the maximum number of buffers that this
409 // producer queue's consumer can acquire. Set to be at least one. Need to
410 // find a way to set from the consumer side.
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700411 value = kDefaultUndequeuedBuffers;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800412 break;
413 case NATIVE_WINDOW_BUFFER_AGE:
414 value = 0;
415 break;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700416 case NATIVE_WINDOW_WIDTH:
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700417 value = queue_->default_width();
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700418 break;
419 case NATIVE_WINDOW_HEIGHT:
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700420 value = queue_->default_height();
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700421 break;
422 case NATIVE_WINDOW_FORMAT:
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700423 value = queue_->default_format();
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700424 break;
425 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
426 // BufferHubQueue is always operating in async mode, thus semantically
427 // consumer can never be running behind. See BufferQueueCore.cpp core
428 // for more information about the original meaning of this flag.
429 value = 0;
430 break;
431 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
432 // TODO(jwcai) This is currently not implement as we don't need
433 // IGraphicBufferConsumer parity.
434 value = 0;
435 break;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800436 case NATIVE_WINDOW_DEFAULT_DATASPACE:
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700437 // TODO(jwcai) Return the default value android::BufferQueue is using as
438 // there is no way dvr::ConsumerQueue can set it.
439 value = 0; // HAL_DATASPACE_UNKNOWN
440 break;
441 case NATIVE_WINDOW_STICKY_TRANSFORM:
442 // TODO(jwcai) Return the default value android::BufferQueue is using as
443 // there is no way dvr::ConsumerQueue can set it.
444 value = 0;
445 break;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700446 case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
447 // In Daydream's implementation, the consumer end (i.e. VR Compostior)
448 // knows how to handle protected buffers.
449 value = 1;
450 break;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800451 default:
452 return BAD_VALUE;
453 }
454
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700455 ALOGD_IF(TRACE, "query: key=%d, v=%d", what, value);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800456 *out_value = value;
457 return NO_ERROR;
458}
459
460status_t BufferHubQueueProducer::connect(
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700461 const sp<IProducerListener>& /* listener */, int api,
462 bool /* producer_controlled_by_app */, QueueBufferOutput* output) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800463 // Consumer interaction are actually handled by buffer hub, and we need
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700464 // to maintain consumer operations here. We only need to perform basic input
465 // parameter checks here.
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700466 ALOGD_IF(TRACE, __FUNCTION__);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700467
468 if (output == nullptr) {
469 return BAD_VALUE;
470 }
471
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700472 std::unique_lock<std::mutex> lock(mutex_);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700473
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700474 if (connected_api_ != kNoConnectedApi) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700475 return BAD_VALUE;
476 }
477
478 switch (api) {
479 case NATIVE_WINDOW_API_EGL:
480 case NATIVE_WINDOW_API_CPU:
481 case NATIVE_WINDOW_API_MEDIA:
482 case NATIVE_WINDOW_API_CAMERA:
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700483 connected_api_ = api;
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700484
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700485 output->width = queue_->default_width();
486 output->height = queue_->default_height();
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700487
488 // default values, we don't use them yet.
489 output->transformHint = 0;
490 output->numPendingBuffers = 0;
491 output->nextFrameNumber = 0;
492 output->bufferReplaced = false;
493
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700494 break;
495 default:
496 ALOGE("BufferHubQueueProducer::connect: unknow API %d", api);
497 return BAD_VALUE;
498 }
499
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800500 return NO_ERROR;
501}
502
Corey Tabakacd52dd92017-04-07 18:03:57 -0700503status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode /*mode*/) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800504 // Consumer interaction are actually handled by buffer hub, and we need
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700505 // to maintain consumer operations here. We only need to perform basic input
506 // parameter checks here.
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700507 ALOGD_IF(TRACE, __FUNCTION__);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700508
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700509 std::unique_lock<std::mutex> lock(mutex_);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700510
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700511 if (kNoConnectedApi == connected_api_) {
Wonsik Kim3e198b22017-04-07 15:43:16 -0700512 return NO_INIT;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700513 } else if (api != connected_api_) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700514 return BAD_VALUE;
515 }
516
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700517 connected_api_ = kNoConnectedApi;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800518 return NO_ERROR;
519}
520
521status_t BufferHubQueueProducer::setSidebandStream(
522 const sp<NativeHandle>& stream) {
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700523 if (stream != nullptr) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800524 // TODO(jwcai) Investigate how is is used, maybe use BufferHubBuffer's
525 // metadata.
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800526 ALOGE("SidebandStream is not currently supported.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800527 return INVALID_OPERATION;
528 }
529 return NO_ERROR;
530}
531
532void BufferHubQueueProducer::allocateBuffers(uint32_t /* width */,
533 uint32_t /* height */,
534 PixelFormat /* format */,
Mathias Agopiancb496ac2017-05-22 14:21:00 -0700535 uint64_t /* usage */) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800536 // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
537 // of buffers permitted by the current BufferQueue configuration (aka
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700538 // |max_buffer_count_|).
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800539 ALOGE("BufferHubQueueProducer::allocateBuffers not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800540}
541
542status_t BufferHubQueueProducer::allowAllocation(bool /* allow */) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800543 ALOGE("BufferHubQueueProducer::allowAllocation not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800544 return INVALID_OPERATION;
545}
546
547status_t BufferHubQueueProducer::setGenerationNumber(
548 uint32_t generation_number) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700549 ALOGD_IF(TRACE, __FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800550
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700551 std::unique_lock<std::mutex> lock(mutex_);
552 generation_number_ = generation_number;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800553 return NO_ERROR;
554}
555
556String8 BufferHubQueueProducer::getConsumerName() const {
557 // BufferHub based implementation could have one to many producer/consumer
558 // relationship, thus |getConsumerName| from the producer side does not
559 // make any sense.
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800560 ALOGE("BufferHubQueueProducer::getConsumerName not supported.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800561 return String8("BufferHubQueue::DummyConsumer");
562}
563
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700564status_t BufferHubQueueProducer::setSharedBufferMode(bool shared_buffer_mode) {
565 if (shared_buffer_mode) {
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700566 ALOGE(
567 "BufferHubQueueProducer::setSharedBufferMode(true) is not supported.");
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700568 // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow.
569 return INVALID_OPERATION;
570 }
571 // Setting to default should just work as a no-op.
572 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800573}
574
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700575status_t BufferHubQueueProducer::setAutoRefresh(bool auto_refresh) {
576 if (auto_refresh) {
577 ALOGE("BufferHubQueueProducer::setAutoRefresh(true) is not supported.");
578 return INVALID_OPERATION;
579 }
580 // Setting to default should just work as a no-op.
581 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800582}
583
584status_t BufferHubQueueProducer::setDequeueTimeout(nsecs_t timeout) {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700585 ALOGD_IF(TRACE, __FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800586
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700587 std::unique_lock<std::mutex> lock(mutex_);
588 dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800589 return NO_ERROR;
590}
591
592status_t BufferHubQueueProducer::getLastQueuedBuffer(
593 sp<GraphicBuffer>* /* out_buffer */, sp<Fence>* /* out_fence */,
594 float /*out_transform_matrix*/[16]) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800595 ALOGE("BufferHubQueueProducer::getLastQueuedBuffer not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800596 return INVALID_OPERATION;
597}
598
599void BufferHubQueueProducer::getFrameTimestamps(
600 FrameEventHistoryDelta* /*outDelta*/) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800601 ALOGE("BufferHubQueueProducer::getFrameTimestamps not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800602}
603
604status_t BufferHubQueueProducer::getUniqueId(uint64_t* out_id) const {
Jiwen 'Steve' Cai25fd3fa2017-03-20 15:30:21 -0700605 ALOGD_IF(TRACE, __FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800606
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700607 *out_id = unique_id_;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800608 return NO_ERROR;
609}
610
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700611status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height,
612 uint32_t layer_count,
613 PixelFormat format,
614 uint64_t usage) {
Corey Tabakab7ca5de2017-05-08 18:55:02 -0700615 auto status =
Jiwen 'Steve' Cai8fa4e102017-05-24 23:16:54 -0700616 queue_->AllocateBuffer(width, height, layer_count, format, usage);
Corey Tabakab7ca5de2017-05-08 18:55:02 -0700617 if (!status) {
618 ALOGE(
619 "BufferHubQueueProducer::AllocateBuffer: Failed to allocate buffer: %s",
620 status.GetErrorMessage().c_str());
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700621 return NO_MEMORY;
622 }
623
Jiwen 'Steve' Cai8fa4e102017-05-24 23:16:54 -0700624 size_t slot = status.get();
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700625 auto buffer_producer = queue_->GetBuffer(slot);
626
627 LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr,
628 "Failed to get buffer producer at slot: %zu", slot);
629
630 buffers_[slot].mBufferProducer = buffer_producer;
631
632 return NO_ERROR;
633}
634
635status_t BufferHubQueueProducer::RemoveBuffer(size_t slot) {
Jiwen 'Steve' Caibb701db2017-05-23 11:15:33 -0700636 auto status = queue_->RemoveBuffer(slot);
Corey Tabakab7ca5de2017-05-08 18:55:02 -0700637 if (!status) {
Jiwen 'Steve' Caibb701db2017-05-23 11:15:33 -0700638 ALOGE("BufferHubQueueProducer::RemoveBuffer: Failed to remove buffer: %s",
Corey Tabakab7ca5de2017-05-08 18:55:02 -0700639 status.GetErrorMessage().c_str());
640 return INVALID_OPERATION;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700641 }
642
643 // Reset in memory objects related the the buffer.
644 buffers_[slot].mBufferProducer = nullptr;
645 buffers_[slot].mGraphicBuffer = nullptr;
646 buffers_[slot].mBufferState.detachProducer();
647 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800648}
649
650} // namespace dvr
651} // namespace android