blob: ef2a7e8260c9f5516e8ca20b38f9416d65c2b63b [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,
Dan Stozadd883c02014-11-18 10:24:03 -0800248 uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) {
Dan Stoza289ade12014-02-28 11:17:17 -0800249 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) ||
Dan Stozadd883c02014-11-18 10:24:03 -0800309 (buffer->format != format) ||
Dan Stoza289ade12014-02-28 11:17:17 -0800310 ((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(
Dan Stozadd883c02014-11-18 10:24:03 -0800339 width, height, format, usage, &error));
Dan Stoza289ade12014-02-28 11:17:17 -0800340 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");
Jesse Hall5b0cbcf2014-10-18 21:47:04 -0700525 // Temporary workaround for b/17946343: soldier-on instead of returning an error. This
526 // prevents the client from dying, at the risk of visible corruption due to hwcomposer
527 // reading the buffer before the producer is done rendering it. Unless the buffer is the
528 // last frame of an animation, the corruption will be transient.
529 fence = Fence::NO_FENCE;
530 // return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800531 }
532
533 switch (scalingMode) {
534 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
535 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
536 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
537 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
538 break;
539 default:
540 BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800541 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800542 }
543
544 sp<IConsumerListener> listener;
545 { // Autolock scope
546 Mutex::Autolock lock(mCore->mMutex);
547
548 if (mCore->mIsAbandoned) {
549 BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
550 return NO_INIT;
551 }
552
553 const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
554 if (async && mCore->mOverrideMaxBufferCount) {
555 // FIXME: Some drivers are manually setting the buffer count
556 // (which they shouldn't), so we do this extra test here to
557 // handle that case. This is TEMPORARY until we get this fixed.
558 if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
559 BQ_LOGE("queueBuffer: async mode is invalid with "
560 "buffer count override");
561 return BAD_VALUE;
562 }
563 }
564
565 if (slot < 0 || slot >= maxBufferCount) {
566 BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
567 slot, maxBufferCount);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800568 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800569 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
570 BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
571 "(state = %d)", slot, mSlots[slot].mBufferState);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800572 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800573 } else if (!mSlots[slot].mRequestBufferCalled) {
574 BQ_LOGE("queueBuffer: slot %d was queued without requesting "
575 "a buffer", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800576 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800577 }
578
Mark Salyzyn8f515ce2014-06-09 14:32:04 -0700579 BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64
580 " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
Dan Stoza289ade12014-02-28 11:17:17 -0800581 slot, mCore->mFrameCounter + 1, timestamp,
Dan Stozadd883c02014-11-18 10:24:03 -0800582 crop.left, crop.top, crop.right, crop.bottom, transform,
583 BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));
Dan Stoza289ade12014-02-28 11:17:17 -0800584
585 const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
586 Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
587 Rect croppedRect;
588 crop.intersect(bufferRect, &croppedRect);
589 if (croppedRect != crop) {
590 BQ_LOGE("queueBuffer: crop rect is not contained within the "
591 "buffer in slot %d", slot);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800592 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800593 }
594
595 mSlots[slot].mFence = fence;
596 mSlots[slot].mBufferState = BufferSlot::QUEUED;
597 ++mCore->mFrameCounter;
598 mSlots[slot].mFrameNumber = mCore->mFrameCounter;
599
600 BufferItem item;
601 item.mAcquireCalled = mSlots[slot].mAcquireCalled;
602 item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
603 item.mCrop = crop;
Dan Stozadd883c02014-11-18 10:24:03 -0800604 item.mTransform = transform &
605 ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
Dan Stoza289ade12014-02-28 11:17:17 -0800606 item.mTransformToDisplayInverse =
Dan Stozadd883c02014-11-18 10:24:03 -0800607 (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
608 item.mScalingMode = static_cast<uint32_t>(scalingMode);
Dan Stoza289ade12014-02-28 11:17:17 -0800609 item.mTimestamp = timestamp;
610 item.mIsAutoTimestamp = isAutoTimestamp;
611 item.mFrameNumber = mCore->mFrameCounter;
612 item.mSlot = slot;
613 item.mFence = fence;
614 item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
615
Ruben Brunk1681d952014-06-27 15:51:55 -0700616 mStickyTransform = stickyTransform;
617
Dan Stoza289ade12014-02-28 11:17:17 -0800618 if (mCore->mQueue.empty()) {
619 // When the queue is empty, we can ignore mDequeueBufferCannotBlock
620 // and simply queue this buffer
621 mCore->mQueue.push_back(item);
622 listener = mCore->mConsumerListener;
623 } else {
624 // When the queue is not empty, we need to look at the front buffer
625 // state to see if we need to replace it
626 BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
627 if (front->mIsDroppable) {
628 // If the front queued buffer is still being tracked, we first
629 // mark it as freed
630 if (mCore->stillTracking(front)) {
631 mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
632 // Reset the frame number of the freed buffer so that it is
633 // the first in line to be dequeued again
634 mSlots[front->mSlot].mFrameNumber = 0;
635 }
636 // Overwrite the droppable buffer with the incoming one
637 *front = item;
638 } else {
639 mCore->mQueue.push_back(item);
640 listener = mCore->mConsumerListener;
641 }
642 }
643
644 mCore->mBufferHasBeenQueued = true;
645 mCore->mDequeueCondition.broadcast();
646
647 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
Dan Stozadd883c02014-11-18 10:24:03 -0800648 mCore->mTransformHint,
649 static_cast<uint32_t>(mCore->mQueue.size()));
Dan Stoza289ade12014-02-28 11:17:17 -0800650
651 ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
652 } // Autolock scope
653
654 // Call back without lock held
655 if (listener != NULL) {
656 listener->onFrameAvailable();
657 }
658
659 return NO_ERROR;
660}
661
662void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
663 ATRACE_CALL();
664 BQ_LOGV("cancelBuffer: slot %d", slot);
665 Mutex::Autolock lock(mCore->mMutex);
666
667 if (mCore->mIsAbandoned) {
668 BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
669 return;
670 }
671
Dan Stoza3e96f192014-03-03 10:16:19 -0800672 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
Dan Stoza289ade12014-02-28 11:17:17 -0800673 BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
Dan Stoza3e96f192014-03-03 10:16:19 -0800674 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
Dan Stoza289ade12014-02-28 11:17:17 -0800675 return;
676 } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
677 BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
678 "(state = %d)", slot, mSlots[slot].mBufferState);
679 return;
680 } else if (fence == NULL) {
681 BQ_LOGE("cancelBuffer: fence is NULL");
682 return;
683 }
684
685 mSlots[slot].mBufferState = BufferSlot::FREE;
686 mSlots[slot].mFrameNumber = 0;
687 mSlots[slot].mFence = fence;
688 mCore->mDequeueCondition.broadcast();
689}
690
691int BufferQueueProducer::query(int what, int *outValue) {
692 ATRACE_CALL();
693 Mutex::Autolock lock(mCore->mMutex);
694
695 if (outValue == NULL) {
696 BQ_LOGE("query: outValue was NULL");
697 return BAD_VALUE;
698 }
699
700 if (mCore->mIsAbandoned) {
701 BQ_LOGE("query: BufferQueue has been abandoned");
702 return NO_INIT;
703 }
704
705 int value;
706 switch (what) {
707 case NATIVE_WINDOW_WIDTH:
Dan Stozadd883c02014-11-18 10:24:03 -0800708 value = static_cast<int32_t>(mCore->mDefaultWidth);
Dan Stoza289ade12014-02-28 11:17:17 -0800709 break;
710 case NATIVE_WINDOW_HEIGHT:
Dan Stozadd883c02014-11-18 10:24:03 -0800711 value = static_cast<int32_t>(mCore->mDefaultHeight);
Dan Stoza289ade12014-02-28 11:17:17 -0800712 break;
713 case NATIVE_WINDOW_FORMAT:
Dan Stozadd883c02014-11-18 10:24:03 -0800714 value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
Dan Stoza289ade12014-02-28 11:17:17 -0800715 break;
716 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
717 value = mCore->getMinUndequeuedBufferCountLocked(false);
718 break;
Ruben Brunk1681d952014-06-27 15:51:55 -0700719 case NATIVE_WINDOW_STICKY_TRANSFORM:
Dan Stozadd883c02014-11-18 10:24:03 -0800720 value = static_cast<int32_t>(mStickyTransform);
Ruben Brunk1681d952014-06-27 15:51:55 -0700721 break;
Dan Stoza289ade12014-02-28 11:17:17 -0800722 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
723 value = (mCore->mQueue.size() > 1);
724 break;
725 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
Dan Stozadd883c02014-11-18 10:24:03 -0800726 value = static_cast<int32_t>(mCore->mConsumerUsageBits);
Dan Stoza289ade12014-02-28 11:17:17 -0800727 break;
728 default:
729 return BAD_VALUE;
730 }
731
732 BQ_LOGV("query: %d? %d", what, value);
733 *outValue = value;
734 return NO_ERROR;
735}
736
Dan Stozaf0eaf252014-03-21 13:05:51 -0700737status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
Dan Stoza289ade12014-02-28 11:17:17 -0800738 int api, bool producerControlledByApp, QueueBufferOutput *output) {
739 ATRACE_CALL();
740 Mutex::Autolock lock(mCore->mMutex);
741 mConsumerName = mCore->mConsumerName;
742 BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
743 producerControlledByApp ? "true" : "false");
744
Dan Stozaae3c3682014-04-18 15:43:35 -0700745 if (mCore->mIsAbandoned) {
746 BQ_LOGE("connect(P): BufferQueue has been abandoned");
747 return NO_INIT;
748 }
Dan Stoza289ade12014-02-28 11:17:17 -0800749
Dan Stozaae3c3682014-04-18 15:43:35 -0700750 if (mCore->mConsumerListener == NULL) {
751 BQ_LOGE("connect(P): BufferQueue has no consumer");
752 return NO_INIT;
753 }
Dan Stoza289ade12014-02-28 11:17:17 -0800754
Dan Stozaae3c3682014-04-18 15:43:35 -0700755 if (output == NULL) {
756 BQ_LOGE("connect(P): output was NULL");
757 return BAD_VALUE;
758 }
Dan Stoza289ade12014-02-28 11:17:17 -0800759
Dan Stozaae3c3682014-04-18 15:43:35 -0700760 if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
761 BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
762 mCore->mConnectedApi, api);
763 return BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800764 }
765
766 int status = NO_ERROR;
767 switch (api) {
768 case NATIVE_WINDOW_API_EGL:
769 case NATIVE_WINDOW_API_CPU:
770 case NATIVE_WINDOW_API_MEDIA:
771 case NATIVE_WINDOW_API_CAMERA:
772 mCore->mConnectedApi = api;
773 output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
Dan Stozadd883c02014-11-18 10:24:03 -0800774 mCore->mTransformHint,
775 static_cast<uint32_t>(mCore->mQueue.size()));
Dan Stoza289ade12014-02-28 11:17:17 -0800776
777 // Set up a death notification so that we can disconnect
778 // automatically if the remote producer dies
Dan Stozaf0eaf252014-03-21 13:05:51 -0700779 if (listener != NULL &&
Marco Nelissen097ca272014-11-14 08:01:01 -0800780 IInterface::asBinder(listener)->remoteBinder() != NULL) {
781 status = IInterface::asBinder(listener)->linkToDeath(
Dan Stoza289ade12014-02-28 11:17:17 -0800782 static_cast<IBinder::DeathRecipient*>(this));
Dan Stozaf0eaf252014-03-21 13:05:51 -0700783 if (status != NO_ERROR) {
Dan Stoza289ade12014-02-28 11:17:17 -0800784 BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
785 strerror(-status), status);
786 }
787 }
Dan Stozaf0eaf252014-03-21 13:05:51 -0700788 mCore->mConnectedProducerListener = listener;
Dan Stoza289ade12014-02-28 11:17:17 -0800789 break;
790 default:
791 BQ_LOGE("connect(P): unknown API %d", api);
792 status = BAD_VALUE;
793 break;
794 }
795
796 mCore->mBufferHasBeenQueued = false;
797 mCore->mDequeueBufferCannotBlock =
798 mCore->mConsumerControlledByApp && producerControlledByApp;
799
800 return status;
801}
802
803status_t BufferQueueProducer::disconnect(int api) {
804 ATRACE_CALL();
805 BQ_LOGV("disconnect(P): api %d", api);
806
807 int status = NO_ERROR;
808 sp<IConsumerListener> listener;
809 { // Autolock scope
810 Mutex::Autolock lock(mCore->mMutex);
Antoine Labour78014f32014-07-15 21:17:03 -0700811 mCore->waitWhileAllocatingLocked();
Dan Stoza289ade12014-02-28 11:17:17 -0800812
813 if (mCore->mIsAbandoned) {
814 // It's not really an error to disconnect after the surface has
815 // been abandoned; it should just be a no-op.
816 return NO_ERROR;
817 }
818
819 switch (api) {
820 case NATIVE_WINDOW_API_EGL:
821 case NATIVE_WINDOW_API_CPU:
822 case NATIVE_WINDOW_API_MEDIA:
823 case NATIVE_WINDOW_API_CAMERA:
824 if (mCore->mConnectedApi == api) {
825 mCore->freeAllBuffersLocked();
826
827 // Remove our death notification callback if we have one
Dan Stozaf0eaf252014-03-21 13:05:51 -0700828 if (mCore->mConnectedProducerListener != NULL) {
829 sp<IBinder> token =
Marco Nelissen097ca272014-11-14 08:01:01 -0800830 IInterface::asBinder(mCore->mConnectedProducerListener);
Dan Stoza289ade12014-02-28 11:17:17 -0800831 // This can fail if we're here because of the death
832 // notification, but we just ignore it
833 token->unlinkToDeath(
834 static_cast<IBinder::DeathRecipient*>(this));
835 }
Dan Stozaf0eaf252014-03-21 13:05:51 -0700836 mCore->mConnectedProducerListener = NULL;
Dan Stoza289ade12014-02-28 11:17:17 -0800837 mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
Jesse Hall399184a2014-03-03 15:42:54 -0800838 mCore->mSidebandStream.clear();
Dan Stoza289ade12014-02-28 11:17:17 -0800839 mCore->mDequeueCondition.broadcast();
840 listener = mCore->mConsumerListener;
Michael Lentine45e2fc22014-08-08 10:30:44 -0700841 } else {
842 BQ_LOGE("disconnect(P): connected to another API "
Dan Stoza289ade12014-02-28 11:17:17 -0800843 "(cur=%d req=%d)", mCore->mConnectedApi, api);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800844 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800845 }
846 break;
847 default:
848 BQ_LOGE("disconnect(P): unknown API %d", api);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800849 status = BAD_VALUE;
Dan Stoza289ade12014-02-28 11:17:17 -0800850 break;
851 }
852 } // Autolock scope
853
854 // Call back without lock held
855 if (listener != NULL) {
856 listener->onBuffersReleased();
857 }
858
859 return status;
860}
861
Jesse Hall399184a2014-03-03 15:42:54 -0800862status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
Wonsik Kimafe30812014-03-31 23:16:08 +0900863 sp<IConsumerListener> listener;
864 { // Autolock scope
865 Mutex::Autolock _l(mCore->mMutex);
866 mCore->mSidebandStream = stream;
867 listener = mCore->mConsumerListener;
868 } // Autolock scope
869
870 if (listener != NULL) {
871 listener->onSidebandStreamChanged();
872 }
Jesse Hall399184a2014-03-03 15:42:54 -0800873 return NO_ERROR;
874}
875
Dan Stoza29a3e902014-06-20 13:13:57 -0700876void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
Dan Stozadd883c02014-11-18 10:24:03 -0800877 uint32_t height, PixelFormat format, uint32_t usage) {
Antoine Labour78014f32014-07-15 21:17:03 -0700878 ATRACE_CALL();
879 while (true) {
880 Vector<int> freeSlots;
881 size_t newBufferCount = 0;
882 uint32_t allocWidth = 0;
883 uint32_t allocHeight = 0;
Dan Stozadd883c02014-11-18 10:24:03 -0800884 PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
Antoine Labour78014f32014-07-15 21:17:03 -0700885 uint32_t allocUsage = 0;
886 { // Autolock scope
887 Mutex::Autolock lock(mCore->mMutex);
888 mCore->waitWhileAllocatingLocked();
Dan Stoza29a3e902014-06-20 13:13:57 -0700889
Antoine Labour78014f32014-07-15 21:17:03 -0700890 int currentBufferCount = 0;
891 for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
892 if (mSlots[slot].mGraphicBuffer != NULL) {
893 ++currentBufferCount;
894 } else {
895 if (mSlots[slot].mBufferState != BufferSlot::FREE) {
896 BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
897 slot);
898 continue;
899 }
Dan Stoza29a3e902014-06-20 13:13:57 -0700900
Antoine Labour11f14872014-07-25 18:14:42 -0700901 freeSlots.push_back(slot);
Antoine Labour78014f32014-07-15 21:17:03 -0700902 }
903 }
904
905 int maxBufferCount = mCore->getMaxBufferCountLocked(async);
906 BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
907 currentBufferCount, maxBufferCount);
908 if (maxBufferCount <= currentBufferCount)
909 return;
Dan Stozadd883c02014-11-18 10:24:03 -0800910 newBufferCount =
911 static_cast<size_t>(maxBufferCount - currentBufferCount);
Antoine Labour78014f32014-07-15 21:17:03 -0700912 if (freeSlots.size() < newBufferCount) {
913 BQ_LOGE("allocateBuffers: ran out of free slots");
914 return;
915 }
916 allocWidth = width > 0 ? width : mCore->mDefaultWidth;
917 allocHeight = height > 0 ? height : mCore->mDefaultHeight;
918 allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
919 allocUsage = usage | mCore->mConsumerUsageBits;
920
921 mCore->mIsAllocating = true;
922 } // Autolock scope
923
Dan Stozadd883c02014-11-18 10:24:03 -0800924 Vector<sp<GraphicBuffer>> buffers;
Antoine Labour78014f32014-07-15 21:17:03 -0700925 for (size_t i = 0; i < newBufferCount; ++i) {
926 status_t result = NO_ERROR;
927 sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
928 allocWidth, allocHeight, allocFormat, allocUsage, &result));
929 if (result != NO_ERROR) {
930 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
931 " %u, usage %u)", width, height, format, usage);
932 Mutex::Autolock lock(mCore->mMutex);
933 mCore->mIsAllocating = false;
934 mCore->mIsAllocatingCondition.broadcast();
935 return;
936 }
937 buffers.push_back(graphicBuffer);
938 }
939
940 { // Autolock scope
941 Mutex::Autolock lock(mCore->mMutex);
942 uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
943 uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
Dan Stozadd883c02014-11-18 10:24:03 -0800944 PixelFormat checkFormat = format != 0 ?
945 format : mCore->mDefaultBufferFormat;
Antoine Labour78014f32014-07-15 21:17:03 -0700946 uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
947 if (checkWidth != allocWidth || checkHeight != allocHeight ||
948 checkFormat != allocFormat || checkUsage != allocUsage) {
949 // Something changed while we released the lock. Retry.
950 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
951 mCore->mIsAllocating = false;
952 mCore->mIsAllocatingCondition.broadcast();
Dan Stoza29a3e902014-06-20 13:13:57 -0700953 continue;
954 }
955
Antoine Labour78014f32014-07-15 21:17:03 -0700956 for (size_t i = 0; i < newBufferCount; ++i) {
957 int slot = freeSlots[i];
958 if (mSlots[slot].mBufferState != BufferSlot::FREE) {
959 // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we
960 // allocated.
961 BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
962 "Dropping allocated buffer.", slot);
963 continue;
964 }
965 mCore->freeBufferLocked(slot); // Clean up the slot first
966 mSlots[slot].mGraphicBuffer = buffers[i];
967 mSlots[slot].mFrameNumber = 0;
968 mSlots[slot].mFence = Fence::NO_FENCE;
969 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
970 }
Dan Stoza29a3e902014-06-20 13:13:57 -0700971
Antoine Labour78014f32014-07-15 21:17:03 -0700972 mCore->mIsAllocating = false;
973 mCore->mIsAllocatingCondition.broadcast();
974 } // Autolock scope
Dan Stoza29a3e902014-06-20 13:13:57 -0700975 }
976}
977
Dan Stoza289ade12014-02-28 11:17:17 -0800978void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
979 // If we're here, it means that a producer we were connected to died.
980 // We're guaranteed that we are still connected to it because we remove
981 // this callback upon disconnect. It's therefore safe to read mConnectedApi
982 // without synchronization here.
983 int api = mCore->mConnectedApi;
984 disconnect(api);
985}
986
987} // namespace android