BufferQueueProducer.cpp revision 78014f32da6d0ebf52fb34ebb7663863000520a0
1/*
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
17#include <inttypes.h>
18
19#define LOG_TAG "BufferQueueProducer"
20#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21//#define LOG_NDEBUG 0
22
23#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>
30#include <gui/IProducerListener.h>
31
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),
40    mConsumerName(),
41    mStickyTransform(0) {}
42
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
55    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
56        BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
57                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
58        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);
77        mCore->waitWhileAllocatingLocked();
78
79        if (mCore->mIsAbandoned) {
80            BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
81            return NO_INIT;
82        }
83
84        if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
85            BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
86                    bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
87            return BAD_VALUE;
88        }
89
90        // There must be no dequeued buffers when changing the buffer count.
91        for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
92            if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
93                BQ_LOGE("setBufferCount: buffer owned by producer");
94                return BAD_VALUE;
95            }
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
129status_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
212        // 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.
216        bool tooManyBuffers = mCore->mQueue.size()
217                            > static_cast<size_t>(maxBufferCount);
218        if (tooManyBuffers) {
219            BQ_LOGV("%s: queue size is %zu, waiting", caller,
220                    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;
228        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
246status_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;
266    bool attachedByConsumer = false;
267
268    { // Autolock scope
269        Mutex::Autolock lock(mCore->mMutex);
270        mCore->waitWhileAllocatingLocked();
271
272        if (format == 0) {
273            format = mCore->mDefaultBufferFormat;
274        }
275
276        // Enable the usage bits the consumer requested
277        usage |= mCore->mConsumerUsageBits;
278
279        int found;
280        status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
281                &found, &returnFlags);
282        if (status != NO_ERROR) {
283            return status;
284        }
285
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
295        attachedByConsumer = mSlots[found].mAttachedByConsumer;
296
297        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;
337        BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
338        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
353            mSlots[*outSlot].mFrameNumber = UINT32_MAX;
354            mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
355        } // Autolock scope
356    }
357
358    if (attachedByConsumer) {
359        returnFlags |= BUFFER_NEEDS_REALLOCATION;
360    }
361
362    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
377    BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
378            *outSlot,
379            mSlots[*outSlot].mFrameNumber,
380            mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
381
382    return returnFlags;
383}
384
385status_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
416status_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);
429    mCore->waitWhileAllocatingLocked();
430
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
461status_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);
474    mCore->waitWhileAllocatingLocked();
475
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;
502    mSlots[*outSlot].mRequestBufferCalled = true;
503
504    return returnFlags;
505}
506
507status_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;
517    uint32_t stickyTransform;
518    bool async;
519    sp<Fence> fence;
520    input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
521            &async, &fence, &stickyTransform);
522
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);
536            return BAD_VALUE;
537    }
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);
563            return BAD_VALUE;
564        } 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);
567            return BAD_VALUE;
568        } else if (!mSlots[slot].mRequestBufferCalled) {
569            BQ_LOGE("queueBuffer: slot %d was queued without requesting "
570                    "a buffer", slot);
571            return BAD_VALUE;
572        }
573
574        BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64
575                " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
576                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);
587            return BAD_VALUE;
588        }
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
610        mStickyTransform = stickyTransform;
611
612        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
665    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
666        BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
667                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
668        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;
712        case NATIVE_WINDOW_STICKY_TRANSFORM:
713            value = static_cast<int>(mStickyTransform);
714            break;
715        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
730status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
731        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
738    if (mCore->mIsAbandoned) {
739        BQ_LOGE("connect(P): BufferQueue has been abandoned");
740        return NO_INIT;
741    }
742
743    if (mCore->mConsumerListener == NULL) {
744        BQ_LOGE("connect(P): BufferQueue has no consumer");
745        return NO_INIT;
746    }
747
748    if (output == NULL) {
749        BQ_LOGE("connect(P): output was NULL");
750        return BAD_VALUE;
751    }
752
753    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;
757    }
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
771            if (listener != NULL &&
772                    listener->asBinder()->remoteBinder() != NULL) {
773                status = listener->asBinder()->linkToDeath(
774                        static_cast<IBinder::DeathRecipient*>(this));
775                if (status != NO_ERROR) {
776                    BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
777                            strerror(-status), status);
778                }
779            }
780            mCore->mConnectedProducerListener = listener;
781            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);
803        mCore->waitWhileAllocatingLocked();
804
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
820                    if (mCore->mConnectedProducerListener != NULL) {
821                        sp<IBinder> token =
822                                mCore->mConnectedProducerListener->asBinder();
823                        // 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                    }
828                    mCore->mConnectedProducerListener = NULL;
829                    mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
830                    mCore->mSidebandStream.clear();
831                    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);
836                    status = BAD_VALUE;
837                }
838                break;
839            default:
840                BQ_LOGE("disconnect(P): unknown API %d", api);
841                status = BAD_VALUE;
842                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
854status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
855    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    }
865    return NO_ERROR;
866}
867
868void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
869        uint32_t height, uint32_t format, uint32_t usage) {
870    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();
881
882            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                    }
892
893                    freeSlots.push_front(slot);
894                }
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();
943                continue;
944            }
945
946            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            }
961
962            mCore->mIsAllocating = false;
963            mCore->mIsAllocatingCondition.broadcast();
964        } // Autolock scope
965    }
966}
967
968void 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
978