blob: a53775fa75a5d4f9941e9233fc611f3e316f6b14 [file] [log] [blame]
Dan Stoza289ade12014-02-28 11:17:17 -08001/*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mark Salyzyn8f515ce2014-06-09 14:32:04 -070017#include <inttypes.h>
18
Dan Stoza3e96f192014-03-03 10:16:19 -080019#define LOG_TAG "BufferQueueProducer"
20#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21//#define LOG_NDEBUG 0
22
Dan Stoza289ade12014-02-28 11:17:17 -080023#define EGL_EGLEXT_PROTOTYPES
24
25#include <gui/BufferItem.h>
26#include <gui/BufferQueueCore.h>
27#include <gui/BufferQueueProducer.h>
28#include <gui/IConsumerListener.h>
29#include <gui/IGraphicBufferAlloc.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070030#include <gui/IProducerListener.h>
Dan Stoza289ade12014-02-28 11:17:17 -080031
32#include <utils/Log.h>
33#include <utils/Trace.h>
34
35namespace android {
36
37BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
38 mCore(core),
39 mSlots(core->mSlots),
Ruben Brunk1681d952014-06-27 15:51:55 -070040 mConsumerName(),
41 mStickyTransform(0) {}
Dan Stoza289ade12014-02-28 11:17:17 -080042
43BufferQueueProducer::~BufferQueueProducer() {}
44
45status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
46 ATRACE_CALL();
47 BQ_LOGV("requestBuffer: slot %d", slot);
48 Mutex::Autolock lock(mCore->mMutex);
49
50 if (mCore->mIsAbandoned) {
51 BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
52 return NO_INIT;
53 }
54
Dan Stoza3e96f192014-03-03 10:16:19 -080055 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -080056 BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -080057 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -080058 return BAD_VALUE;
59 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
60 BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
61 "(state = %d)", slot, mSlots[slot].mBufferState);
62 return BAD_VALUE;
63 }
64
65 mSlots[slot].mRequestBufferCalled = true;
66 *buf = mSlots[slot].mGraphicBuffer;
67 return NO_ERROR;
68}
69
70status_t BufferQueueProducer::setBufferCount(int bufferCount) {
71 ATRACE_CALL();
72 BQ_LOGV("setBufferCount: count = %d", bufferCount);
73
74 sp<IConsumerListener> listener;
75 { // Autolock scope
76 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -070077 mCore->waitWhileAllocatingLocked();
Dan Stoza289ade12014-02-28 11:17:17 -080078
79 if (mCore->mIsAbandoned) {
80 BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
81 return NO_INIT;
82 }
83
Dan Stoza3e96f192014-03-03 10:16:19 -080084 if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -080085 BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -080086 bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -080087 return BAD_VALUE;
88 }
89
90 // There must be no dequeued buffers when changing the buffer count.
Dan Stoza3e96f192014-03-03 10:16:19 -080091 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
Dan Stoza289ade12014-02-28 11:17:17 -080092 if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
93 BQ_LOGE("setBufferCount: buffer owned by producer");
Dan Stoza9f3053d2014-03-06 15:14:33 -080094 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -080095 }
96 }
97
98 if (bufferCount == 0) {
99 mCore->mOverrideMaxBufferCount = 0;
100 mCore->mDequeueCondition.broadcast();
101 return NO_ERROR;
102 }
103
104 const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
105 if (bufferCount < minBufferSlots) {
106 BQ_LOGE("setBufferCount: requested buffer count %d is less than "
107 "minimum %d", bufferCount, minBufferSlots);
108 return BAD_VALUE;
109 }
110
111 // Here we are guaranteed that the producer doesn't have any dequeued
112 // buffers and will release all of its buffer references. We don't
113 // clear the queue, however, so that currently queued buffers still
114 // get displayed.
115 mCore->freeAllBuffersLocked();
116 mCore->mOverrideMaxBufferCount = bufferCount;
117 mCore->mDequeueCondition.broadcast();
118 listener = mCore->mConsumerListener;
119 } // Autolock scope
120
121 // Call back without lock held
122 if (listener != NULL) {
123 listener->onBuffersReleased();
124 }
125
126 return NO_ERROR;
127}
128
Dan Stoza9f3053d2014-03-06 15:14:33 -0800129status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
130 bool async, int* found, status_t* returnFlags) const {
131 bool tryAgain = true;
132 while (tryAgain) {
133 if (mCore->mIsAbandoned) {
134 BQ_LOGE("%s: BufferQueue has been abandoned", caller);
135 return NO_INIT;
136 }
137
138 const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
139 if (async && mCore->mOverrideMaxBufferCount) {
140 // FIXME: Some drivers are manually setting the buffer count
141 // (which they shouldn't), so we do this extra test here to
142 // handle that case. This is TEMPORARY until we get this fixed.
143 if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
144 BQ_LOGE("%s: async mode is invalid with buffer count override",
145 caller);
146 return BAD_VALUE;
147 }
148 }
149
150 // Free up any buffers that are in slots beyond the max buffer count
151 for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
152 assert(mSlots[s].mBufferState == BufferSlot::FREE);
153 if (mSlots[s].mGraphicBuffer != NULL) {
154 mCore->freeBufferLocked(s);
155 *returnFlags |= RELEASE_ALL_BUFFERS;
156 }
157 }
158
159 // Look for a free buffer to give to the client
160 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
161 int dequeuedCount = 0;
162 int acquiredCount = 0;
163 for (int s = 0; s < maxBufferCount; ++s) {
164 switch (mSlots[s].mBufferState) {
165 case BufferSlot::DEQUEUED:
166 ++dequeuedCount;
167 break;
168 case BufferSlot::ACQUIRED:
169 ++acquiredCount;
170 break;
171 case BufferSlot::FREE:
172 // We return the oldest of the free buffers to avoid
173 // stalling the producer if possible, since the consumer
174 // may still have pending reads of in-flight buffers
175 if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
176 mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
177 *found = s;
178 }
179 break;
180 default:
181 break;
182 }
183 }
184
185 // Producers are not allowed to dequeue more than one buffer if they
186 // did not set a buffer count
187 if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
188 BQ_LOGE("%s: can't dequeue multiple buffers without setting the "
189 "buffer count", caller);
190 return INVALID_OPERATION;
191 }
192
193 // See whether a buffer has been queued since the last
194 // setBufferCount so we know whether to perform the min undequeued
195 // buffers check below
196 if (mCore->mBufferHasBeenQueued) {
197 // Make sure the producer is not trying to dequeue more buffers
198 // than allowed
199 const int newUndequeuedCount =
200 maxBufferCount - (dequeuedCount + 1);
201 const int minUndequeuedCount =
202 mCore->getMinUndequeuedBufferCountLocked(async);
203 if (newUndequeuedCount < minUndequeuedCount) {
204 BQ_LOGE("%s: min undequeued buffer count (%d) exceeded "
205 "(dequeued=%d undequeued=%d)",
206 caller, minUndequeuedCount,
207 dequeuedCount, newUndequeuedCount);
208 return INVALID_OPERATION;
209 }
210 }
211
Dan Stozaae3c3682014-04-18 15:43:35 -0700212 // If we disconnect and reconnect quickly, we can be in a state where
213 // our slots are empty but we have many buffers in the queue. This can
214 // cause us to run out of memory if we outrun the consumer. Wait here if
215 // it looks like we have too many buffers queued up.
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700216 bool tooManyBuffers = mCore->mQueue.size()
217 > static_cast<size_t>(maxBufferCount);
Dan Stozaae3c3682014-04-18 15:43:35 -0700218 if (tooManyBuffers) {
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700219 BQ_LOGV("%s: queue size is %zu, waiting", caller,
Dan Stozaae3c3682014-04-18 15:43:35 -0700220 mCore->mQueue.size());
221 }
222
223 // If no buffer is found, or if the queue has too many buffers
224 // outstanding, wait for a buffer to be acquired or released, or for the
225 // max buffer count to change.
226 tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
227 tooManyBuffers;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800228 if (tryAgain) {
229 // Return an error if we're in non-blocking mode (producer and
230 // consumer are controlled by the application).
231 // However, the consumer is allowed to briefly acquire an extra
232 // buffer (which could cause us to have to wait here), which is
233 // okay, since it is only used to implement an atomic acquire +
234 // release (e.g., in GLConsumer::updateTexImage())
235 if (mCore->mDequeueBufferCannotBlock &&
236 (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
237 return WOULD_BLOCK;
238 }
239 mCore->mDequeueCondition.wait(mCore->mMutex);
240 }
241 } // while (tryAgain)
242
243 return NO_ERROR;
244}
245
Dan Stoza289ade12014-02-28 11:17:17 -0800246status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
247 sp<android::Fence> *outFence, bool async,
248 uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
249 ATRACE_CALL();
250 { // Autolock scope
251 Mutex::Autolock lock(mCore->mMutex);
252 mConsumerName = mCore->mConsumerName;
253 } // Autolock scope
254
255 BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
256 async ? "true" : "false", width, height, format, usage);
257
258 if ((width && !height) || (!width && height)) {
259 BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
260 return BAD_VALUE;
261 }
262
263 status_t returnFlags = NO_ERROR;
264 EGLDisplay eglDisplay = EGL_NO_DISPLAY;
265 EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800266 bool attachedByConsumer = false;
Dan Stoza289ade12014-02-28 11:17:17 -0800267
268 { // Autolock scope
269 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -0700270 mCore->waitWhileAllocatingLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800271
272 if (format == 0) {
273 format = mCore->mDefaultBufferFormat;
274 }
275
276 // Enable the usage bits the consumer requested
277 usage |= mCore->mConsumerUsageBits;
278
Dan Stoza9f3053d2014-03-06 15:14:33 -0800279 int found;
280 status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
281 &found, &returnFlags);
282 if (status != NO_ERROR) {
283 return status;
284 }
Dan Stoza289ade12014-02-28 11:17:17 -0800285
286 // This should not happen
287 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
288 BQ_LOGE("dequeueBuffer: no available buffer slots");
289 return -EBUSY;
290 }
291
292 *outSlot = found;
293 ATRACE_BUFFER_INDEX(found);
294
Dan Stoza9f3053d2014-03-06 15:14:33 -0800295 attachedByConsumer = mSlots[found].mAttachedByConsumer;
296
Dan Stoza289ade12014-02-28 11:17:17 -0800297 const bool useDefaultSize = !width && !height;
298 if (useDefaultSize) {
299 width = mCore->mDefaultWidth;
300 height = mCore->mDefaultHeight;
301 }
302
303 mSlots[found].mBufferState = BufferSlot::DEQUEUED;
304
305 const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
306 if ((buffer == NULL) ||
307 (static_cast<uint32_t>(buffer->width) != width) ||
308 (static_cast<uint32_t>(buffer->height) != height) ||
309 (static_cast<uint32_t>(buffer->format) != format) ||
310 ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
311 {
312 mSlots[found].mAcquireCalled = false;
313 mSlots[found].mGraphicBuffer = NULL;
314 mSlots[found].mRequestBufferCalled = false;
315 mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
316 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
317 mSlots[found].mFence = Fence::NO_FENCE;
318
319 returnFlags |= BUFFER_NEEDS_REALLOCATION;
320 }
321
322 if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
323 BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
324 "slot=%d w=%d h=%d format=%u",
325 found, buffer->width, buffer->height, buffer->format);
326 }
327
328 eglDisplay = mSlots[found].mEglDisplay;
329 eglFence = mSlots[found].mEglFence;
330 *outFence = mSlots[found].mFence;
331 mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
332 mSlots[found].mFence = Fence::NO_FENCE;
333 } // Autolock scope
334
335 if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
336 status_t error;
Dan Stoza29a3e902014-06-20 13:13:57 -0700337 BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
Dan Stoza289ade12014-02-28 11:17:17 -0800338 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
339 width, height, format, usage, &error));
340 if (graphicBuffer == NULL) {
341 BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
342 return error;
343 }
344
345 { // Autolock scope
346 Mutex::Autolock lock(mCore->mMutex);
347
348 if (mCore->mIsAbandoned) {
349 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
350 return NO_INIT;
351 }
352
Dan Stoza9f3053d2014-03-06 15:14:33 -0800353 mSlots[*outSlot].mFrameNumber = UINT32_MAX;
Dan Stoza289ade12014-02-28 11:17:17 -0800354 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
355 } // Autolock scope
356 }
357
Dan Stoza9f3053d2014-03-06 15:14:33 -0800358 if (attachedByConsumer) {
359 returnFlags |= BUFFER_NEEDS_REALLOCATION;
360 }
361
Dan Stoza289ade12014-02-28 11:17:17 -0800362 if (eglFence != EGL_NO_SYNC_KHR) {
363 EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
364 1000000000);
365 // If something goes wrong, log the error, but return the buffer without
366 // synchronizing access to it. It's too late at this point to abort the
367 // dequeue operation.
368 if (result == EGL_FALSE) {
369 BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
370 eglGetError());
371 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
372 BQ_LOGE("dequeueBuffer: timeout waiting for fence");
373 }
374 eglDestroySyncKHR(eglDisplay, eglFence);
375 }
376
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700377 BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
378 *outSlot,
Dan Stoza289ade12014-02-28 11:17:17 -0800379 mSlots[*outSlot].mFrameNumber,
380 mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
381
382 return returnFlags;
383}
384
Dan Stoza9f3053d2014-03-06 15:14:33 -0800385status_t BufferQueueProducer::detachBuffer(int slot) {
386 ATRACE_CALL();
387 ATRACE_BUFFER_INDEX(slot);
388 BQ_LOGV("detachBuffer(P): slot %d", slot);
389 Mutex::Autolock lock(mCore->mMutex);
390
391 if (mCore->mIsAbandoned) {
392 BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned");
393 return NO_INIT;
394 }
395
396 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
397 BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
398 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
399 return BAD_VALUE;
400 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
401 BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer "
402 "(state = %d)", slot, mSlots[slot].mBufferState);
403 return BAD_VALUE;
404 } else if (!mSlots[slot].mRequestBufferCalled) {
405 BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested",
406 slot);
407 return BAD_VALUE;
408 }
409
410 mCore->freeBufferLocked(slot);
411 mCore->mDequeueCondition.broadcast();
412
413 return NO_ERROR;
414}
415
Dan Stozad9822a32014-03-28 15:25:31 -0700416status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
417 sp<Fence>* outFence) {
418 ATRACE_CALL();
419
420 if (outBuffer == NULL) {
421 BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
422 return BAD_VALUE;
423 } else if (outFence == NULL) {
424 BQ_LOGE("detachNextBuffer: outFence must not be NULL");
425 return BAD_VALUE;
426 }
427
428 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -0700429 mCore->waitWhileAllocatingLocked();
Dan Stozad9822a32014-03-28 15:25:31 -0700430
431 if (mCore->mIsAbandoned) {
432 BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
433 return NO_INIT;
434 }
435
436 // Find the oldest valid slot
437 int found = BufferQueueCore::INVALID_BUFFER_SLOT;
438 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
439 if (mSlots[s].mBufferState == BufferSlot::FREE &&
440 mSlots[s].mGraphicBuffer != NULL) {
441 if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
442 mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
443 found = s;
444 }
445 }
446 }
447
448 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
449 return NO_MEMORY;
450 }
451
452 BQ_LOGV("detachNextBuffer detached slot %d", found);
453
454 *outBuffer = mSlots[found].mGraphicBuffer;
455 *outFence = mSlots[found].mFence;
456 mCore->freeBufferLocked(found);
457
458 return NO_ERROR;
459}
460
Dan Stoza9f3053d2014-03-06 15:14:33 -0800461status_t BufferQueueProducer::attachBuffer(int* outSlot,
462 const sp<android::GraphicBuffer>& buffer) {
463 ATRACE_CALL();
464
465 if (outSlot == NULL) {
466 BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
467 return BAD_VALUE;
468 } else if (buffer == NULL) {
469 BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
470 return BAD_VALUE;
471 }
472
473 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -0700474 mCore->waitWhileAllocatingLocked();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800475
476 status_t returnFlags = NO_ERROR;
477 int found;
478 // TODO: Should we provide an async flag to attachBuffer? It seems
479 // unlikely that buffers which we are attaching to a BufferQueue will
480 // be asynchronous (droppable), but it may not be impossible.
481 status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false,
482 &found, &returnFlags);
483 if (status != NO_ERROR) {
484 return status;
485 }
486
487 // This should not happen
488 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
489 BQ_LOGE("attachBuffer(P): no available buffer slots");
490 return -EBUSY;
491 }
492
493 *outSlot = found;
494 ATRACE_BUFFER_INDEX(*outSlot);
495 BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x",
496 *outSlot, returnFlags);
497
498 mSlots[*outSlot].mGraphicBuffer = buffer;
499 mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED;
500 mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
501 mSlots[*outSlot].mFence = Fence::NO_FENCE;
Dan Stoza2443c792014-03-24 15:03:46 -0700502 mSlots[*outSlot].mRequestBufferCalled = true;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800503
504 return returnFlags;
505}
506
Dan Stoza289ade12014-02-28 11:17:17 -0800507status_t BufferQueueProducer::queueBuffer(int slot,
508 const QueueBufferInput &input, QueueBufferOutput *output) {
509 ATRACE_CALL();
510 ATRACE_BUFFER_INDEX(slot);
511
512 int64_t timestamp;
513 bool isAutoTimestamp;
514 Rect crop;
515 int scalingMode;
516 uint32_t transform;
Ruben Brunk1681d952014-06-27 15:51:55 -0700517 uint32_t stickyTransform;
Dan Stoza289ade12014-02-28 11:17:17 -0800518 bool async;
519 sp<Fence> fence;
520 input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
Ruben Brunk1681d952014-06-27 15:51:55 -0700521 &async, &fence, &stickyTransform);
Dan Stoza289ade12014-02-28 11:17:17 -0800522
523 if (fence == NULL) {
524 BQ_LOGE("queueBuffer: fence is NULL");
525 return BAD_VALUE;
526 }
527
528 switch (scalingMode) {
529 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
530 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
531 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
532 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
533 break;
534 default:
535 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800536 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800537 }
538
539 sp<IConsumerListener> listener;
540 { // Autolock scope
541 Mutex::Autolock lock(mCore->mMutex);
542
543 if (mCore->mIsAbandoned) {
544 BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
545 return NO_INIT;
546 }
547
548 const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
549 if (async && mCore->mOverrideMaxBufferCount) {
550 // FIXME: Some drivers are manually setting the buffer count
551 // (which they shouldn't), so we do this extra test here to
552 // handle that case. This is TEMPORARY until we get this fixed.
553 if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
554 BQ_LOGE("queueBuffer: async mode is invalid with "
555 "buffer count override");
556 return BAD_VALUE;
557 }
558 }
559
560 if (slot < 0 || slot >= maxBufferCount) {
561 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
562 slot, maxBufferCount);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800563 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800564 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
565 BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
566 "(state = %d)", slot, mSlots[slot].mBufferState);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800567 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800568 } else if (!mSlots[slot].mRequestBufferCalled) {
569 BQ_LOGE("queueBuffer: slot %d was queued without requesting "
570 "a buffer", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800571 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800572 }
573
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700574 BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64
575 " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
Dan Stoza289ade12014-02-28 11:17:17 -0800576 slot, mCore->mFrameCounter + 1, timestamp,
577 crop.left, crop.top, crop.right, crop.bottom,
578 transform, BufferItem::scalingModeName(scalingMode));
579
580 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
581 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
582 Rect croppedRect;
583 crop.intersect(bufferRect, &croppedRect);
584 if (croppedRect != crop) {
585 BQ_LOGE("queueBuffer: crop rect is not contained within the "
586 "buffer in slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800587 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800588 }
589
590 mSlots[slot].mFence = fence;
591 mSlots[slot].mBufferState = BufferSlot::QUEUED;
592 ++mCore->mFrameCounter;
593 mSlots[slot].mFrameNumber = mCore->mFrameCounter;
594
595 BufferItem item;
596 item.mAcquireCalled = mSlots[slot].mAcquireCalled;
597 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
598 item.mCrop = crop;
599 item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
600 item.mTransformToDisplayInverse =
601 bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
602 item.mScalingMode = scalingMode;
603 item.mTimestamp = timestamp;
604 item.mIsAutoTimestamp = isAutoTimestamp;
605 item.mFrameNumber = mCore->mFrameCounter;
606 item.mSlot = slot;
607 item.mFence = fence;
608 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
609
Ruben Brunk1681d952014-06-27 15:51:55 -0700610 mStickyTransform = stickyTransform;
611
Dan Stoza289ade12014-02-28 11:17:17 -0800612 if (mCore->mQueue.empty()) {
613 // When the queue is empty, we can ignore mDequeueBufferCannotBlock
614 // and simply queue this buffer
615 mCore->mQueue.push_back(item);
616 listener = mCore->mConsumerListener;
617 } else {
618 // When the queue is not empty, we need to look at the front buffer
619 // state to see if we need to replace it
620 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
621 if (front->mIsDroppable) {
622 // If the front queued buffer is still being tracked, we first
623 // mark it as freed
624 if (mCore->stillTracking(front)) {
625 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
626 // Reset the frame number of the freed buffer so that it is
627 // the first in line to be dequeued again
628 mSlots[front->mSlot].mFrameNumber = 0;
629 }
630 // Overwrite the droppable buffer with the incoming one
631 *front = item;
632 } else {
633 mCore->mQueue.push_back(item);
634 listener = mCore->mConsumerListener;
635 }
636 }
637
638 mCore->mBufferHasBeenQueued = true;
639 mCore->mDequeueCondition.broadcast();
640
641 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
642 mCore->mTransformHint, mCore->mQueue.size());
643
644 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
645 } // Autolock scope
646
647 // Call back without lock held
648 if (listener != NULL) {
649 listener->onFrameAvailable();
650 }
651
652 return NO_ERROR;
653}
654
655void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
656 ATRACE_CALL();
657 BQ_LOGV("cancelBuffer: slot %d", slot);
658 Mutex::Autolock lock(mCore->mMutex);
659
660 if (mCore->mIsAbandoned) {
661 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
662 return;
663 }
664
Dan Stoza3e96f192014-03-03 10:16:19 -0800665 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800666 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -0800667 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -0800668 return;
669 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
670 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
671 "(state = %d)", slot, mSlots[slot].mBufferState);
672 return;
673 } else if (fence == NULL) {
674 BQ_LOGE("cancelBuffer: fence is NULL");
675 return;
676 }
677
678 mSlots[slot].mBufferState = BufferSlot::FREE;
679 mSlots[slot].mFrameNumber = 0;
680 mSlots[slot].mFence = fence;
681 mCore->mDequeueCondition.broadcast();
682}
683
684int BufferQueueProducer::query(int what, int *outValue) {
685 ATRACE_CALL();
686 Mutex::Autolock lock(mCore->mMutex);
687
688 if (outValue == NULL) {
689 BQ_LOGE("query: outValue was NULL");
690 return BAD_VALUE;
691 }
692
693 if (mCore->mIsAbandoned) {
694 BQ_LOGE("query: BufferQueue has been abandoned");
695 return NO_INIT;
696 }
697
698 int value;
699 switch (what) {
700 case NATIVE_WINDOW_WIDTH:
701 value = mCore->mDefaultWidth;
702 break;
703 case NATIVE_WINDOW_HEIGHT:
704 value = mCore->mDefaultHeight;
705 break;
706 case NATIVE_WINDOW_FORMAT:
707 value = mCore->mDefaultBufferFormat;
708 break;
709 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
710 value = mCore->getMinUndequeuedBufferCountLocked(false);
711 break;
Ruben Brunk1681d952014-06-27 15:51:55 -0700712 case NATIVE_WINDOW_STICKY_TRANSFORM:
713 value = static_cast<int>(mStickyTransform);
714 break;
Dan Stoza289ade12014-02-28 11:17:17 -0800715 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
716 value = (mCore->mQueue.size() > 1);
717 break;
718 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
719 value = mCore->mConsumerUsageBits;
720 break;
721 default:
722 return BAD_VALUE;
723 }
724
725 BQ_LOGV("query: %d? %d", what, value);
726 *outValue = value;
727 return NO_ERROR;
728}
729
Dan Stozaf0eaf252014-03-21 13:05:51 -0700730status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
Dan Stoza289ade12014-02-28 11:17:17 -0800731 int api, bool producerControlledByApp, QueueBufferOutput *output) {
732 ATRACE_CALL();
733 Mutex::Autolock lock(mCore->mMutex);
734 mConsumerName = mCore->mConsumerName;
735 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
736 producerControlledByApp ? "true" : "false");
737
Dan Stozaae3c3682014-04-18 15:43:35 -0700738 if (mCore->mIsAbandoned) {
739 BQ_LOGE("connect(P): BufferQueue has been abandoned");
740 return NO_INIT;
741 }
Dan Stoza289ade12014-02-28 11:17:17 -0800742
Dan Stozaae3c3682014-04-18 15:43:35 -0700743 if (mCore->mConsumerListener == NULL) {
744 BQ_LOGE("connect(P): BufferQueue has no consumer");
745 return NO_INIT;
746 }
Dan Stoza289ade12014-02-28 11:17:17 -0800747
Dan Stozaae3c3682014-04-18 15:43:35 -0700748 if (output == NULL) {
749 BQ_LOGE("connect(P): output was NULL");
750 return BAD_VALUE;
751 }
Dan Stoza289ade12014-02-28 11:17:17 -0800752
Dan Stozaae3c3682014-04-18 15:43:35 -0700753 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
754 BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
755 mCore->mConnectedApi, api);
756 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800757 }
758
759 int status = NO_ERROR;
760 switch (api) {
761 case NATIVE_WINDOW_API_EGL:
762 case NATIVE_WINDOW_API_CPU:
763 case NATIVE_WINDOW_API_MEDIA:
764 case NATIVE_WINDOW_API_CAMERA:
765 mCore->mConnectedApi = api;
766 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
767 mCore->mTransformHint, mCore->mQueue.size());
768
769 // Set up a death notification so that we can disconnect
770 // automatically if the remote producer dies
Dan Stozaf0eaf252014-03-21 13:05:51 -0700771 if (listener != NULL &&
772 listener->asBinder()->remoteBinder() != NULL) {
773 status = listener->asBinder()->linkToDeath(
Dan Stoza289ade12014-02-28 11:17:17 -0800774 static_cast<IBinder::DeathRecipient*>(this));
Dan Stozaf0eaf252014-03-21 13:05:51 -0700775 if (status != NO_ERROR) {
Dan Stoza289ade12014-02-28 11:17:17 -0800776 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
777 strerror(-status), status);
778 }
779 }
Dan Stozaf0eaf252014-03-21 13:05:51 -0700780 mCore->mConnectedProducerListener = listener;
Dan Stoza289ade12014-02-28 11:17:17 -0800781 break;
782 default:
783 BQ_LOGE("connect(P): unknown API %d", api);
784 status = BAD_VALUE;
785 break;
786 }
787
788 mCore->mBufferHasBeenQueued = false;
789 mCore->mDequeueBufferCannotBlock =
790 mCore->mConsumerControlledByApp && producerControlledByApp;
791
792 return status;
793}
794
795status_t BufferQueueProducer::disconnect(int api) {
796 ATRACE_CALL();
797 BQ_LOGV("disconnect(P): api %d", api);
798
799 int status = NO_ERROR;
800 sp<IConsumerListener> listener;
801 { // Autolock scope
802 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -0700803 mCore->waitWhileAllocatingLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800804
805 if (mCore->mIsAbandoned) {
806 // It's not really an error to disconnect after the surface has
807 // been abandoned; it should just be a no-op.
808 return NO_ERROR;
809 }
810
811 switch (api) {
812 case NATIVE_WINDOW_API_EGL:
813 case NATIVE_WINDOW_API_CPU:
814 case NATIVE_WINDOW_API_MEDIA:
815 case NATIVE_WINDOW_API_CAMERA:
816 if (mCore->mConnectedApi == api) {
817 mCore->freeAllBuffersLocked();
818
819 // Remove our death notification callback if we have one
Dan Stozaf0eaf252014-03-21 13:05:51 -0700820 if (mCore->mConnectedProducerListener != NULL) {
821 sp<IBinder> token =
822 mCore->mConnectedProducerListener->asBinder();
Dan Stoza289ade12014-02-28 11:17:17 -0800823 // This can fail if we're here because of the death
824 // notification, but we just ignore it
825 token->unlinkToDeath(
826 static_cast<IBinder::DeathRecipient*>(this));
827 }
Dan Stozaf0eaf252014-03-21 13:05:51 -0700828 mCore->mConnectedProducerListener = NULL;
Dan Stoza289ade12014-02-28 11:17:17 -0800829 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
Jesse Hall399184a2014-03-03 15:42:54 -0800830 mCore->mSidebandStream.clear();
Dan Stoza289ade12014-02-28 11:17:17 -0800831 mCore->mDequeueCondition.broadcast();
832 listener = mCore->mConsumerListener;
833 } else {
834 BQ_LOGE("disconnect(P): connected to another API "
835 "(cur=%d req=%d)", mCore->mConnectedApi, api);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800836 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800837 }
838 break;
839 default:
840 BQ_LOGE("disconnect(P): unknown API %d", api);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800841 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800842 break;
843 }
844 } // Autolock scope
845
846 // Call back without lock held
847 if (listener != NULL) {
848 listener->onBuffersReleased();
849 }
850
851 return status;
852}
853
Jesse Hall399184a2014-03-03 15:42:54 -0800854status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
Wonsik Kimafe30812014-03-31 23:16:08 +0900855 sp<IConsumerListener> listener;
856 { // Autolock scope
857 Mutex::Autolock _l(mCore->mMutex);
858 mCore->mSidebandStream = stream;
859 listener = mCore->mConsumerListener;
860 } // Autolock scope
861
862 if (listener != NULL) {
863 listener->onSidebandStreamChanged();
864 }
Jesse Hall399184a2014-03-03 15:42:54 -0800865 return NO_ERROR;
866}
867
Dan Stoza29a3e902014-06-20 13:13:57 -0700868void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
869 uint32_t height, uint32_t format, uint32_t usage) {
Antoine Labour78014f32014-07-15 21:17:03 -0700870 ATRACE_CALL();
871 while (true) {
872 Vector<int> freeSlots;
873 size_t newBufferCount = 0;
874 uint32_t allocWidth = 0;
875 uint32_t allocHeight = 0;
876 uint32_t allocFormat = 0;
877 uint32_t allocUsage = 0;
878 { // Autolock scope
879 Mutex::Autolock lock(mCore->mMutex);
880 mCore->waitWhileAllocatingLocked();
Dan Stoza29a3e902014-06-20 13:13:57 -0700881
Antoine Labour78014f32014-07-15 21:17:03 -0700882 int currentBufferCount = 0;
883 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
884 if (mSlots[slot].mGraphicBuffer != NULL) {
885 ++currentBufferCount;
886 } else {
887 if (mSlots[slot].mBufferState != BufferSlot::FREE) {
888 BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
889 slot);
890 continue;
891 }
Dan Stoza29a3e902014-06-20 13:13:57 -0700892
Antoine Labour11f14872014-07-25 18:14:42 -0700893 freeSlots.push_back(slot);
Antoine Labour78014f32014-07-15 21:17:03 -0700894 }
895 }
896
897 int maxBufferCount = mCore->getMaxBufferCountLocked(async);
898 BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
899 currentBufferCount, maxBufferCount);
900 if (maxBufferCount <= currentBufferCount)
901 return;
902 newBufferCount = maxBufferCount - currentBufferCount;
903 if (freeSlots.size() < newBufferCount) {
904 BQ_LOGE("allocateBuffers: ran out of free slots");
905 return;
906 }
907 allocWidth = width > 0 ? width : mCore->mDefaultWidth;
908 allocHeight = height > 0 ? height : mCore->mDefaultHeight;
909 allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
910 allocUsage = usage | mCore->mConsumerUsageBits;
911
912 mCore->mIsAllocating = true;
913 } // Autolock scope
914
915 Vector<sp<GraphicBuffer> > buffers;
916 for (size_t i = 0; i < newBufferCount; ++i) {
917 status_t result = NO_ERROR;
918 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
919 allocWidth, allocHeight, allocFormat, allocUsage, &result));
920 if (result != NO_ERROR) {
921 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
922 " %u, usage %u)", width, height, format, usage);
923 Mutex::Autolock lock(mCore->mMutex);
924 mCore->mIsAllocating = false;
925 mCore->mIsAllocatingCondition.broadcast();
926 return;
927 }
928 buffers.push_back(graphicBuffer);
929 }
930
931 { // Autolock scope
932 Mutex::Autolock lock(mCore->mMutex);
933 uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
934 uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
935 uint32_t checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
936 uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
937 if (checkWidth != allocWidth || checkHeight != allocHeight ||
938 checkFormat != allocFormat || checkUsage != allocUsage) {
939 // Something changed while we released the lock. Retry.
940 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
941 mCore->mIsAllocating = false;
942 mCore->mIsAllocatingCondition.broadcast();
Dan Stoza29a3e902014-06-20 13:13:57 -0700943 continue;
944 }
945
Antoine Labour78014f32014-07-15 21:17:03 -0700946 for (size_t i = 0; i < newBufferCount; ++i) {
947 int slot = freeSlots[i];
948 if (mSlots[slot].mBufferState != BufferSlot::FREE) {
949 // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we
950 // allocated.
951 BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
952 "Dropping allocated buffer.", slot);
953 continue;
954 }
955 mCore->freeBufferLocked(slot); // Clean up the slot first
956 mSlots[slot].mGraphicBuffer = buffers[i];
957 mSlots[slot].mFrameNumber = 0;
958 mSlots[slot].mFence = Fence::NO_FENCE;
959 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
960 }
Dan Stoza29a3e902014-06-20 13:13:57 -0700961
Antoine Labour78014f32014-07-15 21:17:03 -0700962 mCore->mIsAllocating = false;
963 mCore->mIsAllocatingCondition.broadcast();
964 } // Autolock scope
Dan Stoza29a3e902014-06-20 13:13:57 -0700965 }
966}
967
Dan Stoza289ade12014-02-28 11:17:17 -0800968void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
969 // If we're here, it means that a producer we were connected to died.
970 // We're guaranteed that we are still connected to it because we remove
971 // this callback upon disconnect. It's therefore safe to read mConnectedApi
972 // without synchronization here.
973 int api = mCore->mConnectedApi;
974 disconnect(api);
975}
976
977} // namespace android