BufferQueueProducer.cpp revision 5b0cbcf9464dbcda9d19ae978911222806ec8bdc
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        // 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;
531    }
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);
541            return BAD_VALUE;
542    }
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);
568            return BAD_VALUE;
569        } 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);
572            return BAD_VALUE;
573        } else if (!mSlots[slot].mRequestBufferCalled) {
574            BQ_LOGE("queueBuffer: slot %d was queued without requesting "
575                    "a buffer", slot);
576            return BAD_VALUE;
577        }
578
579        BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64
580                " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
581                slot, mCore->mFrameCounter + 1, timestamp,
582                crop.left, crop.top, crop.right, crop.bottom,
583                transform, BufferItem::scalingModeName(scalingMode));
584
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);
592            return BAD_VALUE;
593        }
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;
604        item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
605        item.mTransformToDisplayInverse =
606                bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
607        item.mScalingMode = scalingMode;
608        item.mTimestamp = timestamp;
609        item.mIsAutoTimestamp = isAutoTimestamp;
610        item.mFrameNumber = mCore->mFrameCounter;
611        item.mSlot = slot;
612        item.mFence = fence;
613        item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
614
615        mStickyTransform = stickyTransform;
616
617        if (mCore->mQueue.empty()) {
618            // When the queue is empty, we can ignore mDequeueBufferCannotBlock
619            // and simply queue this buffer
620            mCore->mQueue.push_back(item);
621            listener = mCore->mConsumerListener;
622        } else {
623            // When the queue is not empty, we need to look at the front buffer
624            // state to see if we need to replace it
625            BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
626            if (front->mIsDroppable) {
627                // If the front queued buffer is still being tracked, we first
628                // mark it as freed
629                if (mCore->stillTracking(front)) {
630                    mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
631                    // Reset the frame number of the freed buffer so that it is
632                    // the first in line to be dequeued again
633                    mSlots[front->mSlot].mFrameNumber = 0;
634                }
635                // Overwrite the droppable buffer with the incoming one
636                *front = item;
637            } else {
638                mCore->mQueue.push_back(item);
639                listener = mCore->mConsumerListener;
640            }
641        }
642
643        mCore->mBufferHasBeenQueued = true;
644        mCore->mDequeueCondition.broadcast();
645
646        output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
647                mCore->mTransformHint, mCore->mQueue.size());
648
649        ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
650    } // Autolock scope
651
652    // Call back without lock held
653    if (listener != NULL) {
654        listener->onFrameAvailable();
655    }
656
657    return NO_ERROR;
658}
659
660void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
661    ATRACE_CALL();
662    BQ_LOGV("cancelBuffer: slot %d", slot);
663    Mutex::Autolock lock(mCore->mMutex);
664
665    if (mCore->mIsAbandoned) {
666        BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
667        return;
668    }
669
670    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
671        BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
672                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
673        return;
674    } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
675        BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
676                "(state = %d)", slot, mSlots[slot].mBufferState);
677        return;
678    } else if (fence == NULL) {
679        BQ_LOGE("cancelBuffer: fence is NULL");
680        return;
681    }
682
683    mSlots[slot].mBufferState = BufferSlot::FREE;
684    mSlots[slot].mFrameNumber = 0;
685    mSlots[slot].mFence = fence;
686    mCore->mDequeueCondition.broadcast();
687}
688
689int BufferQueueProducer::query(int what, int *outValue) {
690    ATRACE_CALL();
691    Mutex::Autolock lock(mCore->mMutex);
692
693    if (outValue == NULL) {
694        BQ_LOGE("query: outValue was NULL");
695        return BAD_VALUE;
696    }
697
698    if (mCore->mIsAbandoned) {
699        BQ_LOGE("query: BufferQueue has been abandoned");
700        return NO_INIT;
701    }
702
703    int value;
704    switch (what) {
705        case NATIVE_WINDOW_WIDTH:
706            value = mCore->mDefaultWidth;
707            break;
708        case NATIVE_WINDOW_HEIGHT:
709            value = mCore->mDefaultHeight;
710            break;
711        case NATIVE_WINDOW_FORMAT:
712            value = mCore->mDefaultBufferFormat;
713            break;
714        case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
715            value = mCore->getMinUndequeuedBufferCountLocked(false);
716            break;
717        case NATIVE_WINDOW_STICKY_TRANSFORM:
718            value = static_cast<int>(mStickyTransform);
719            break;
720        case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
721            value = (mCore->mQueue.size() > 1);
722            break;
723        case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
724            value = mCore->mConsumerUsageBits;
725            break;
726        default:
727            return BAD_VALUE;
728    }
729
730    BQ_LOGV("query: %d? %d", what, value);
731    *outValue = value;
732    return NO_ERROR;
733}
734
735status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
736        int api, bool producerControlledByApp, QueueBufferOutput *output) {
737    ATRACE_CALL();
738    Mutex::Autolock lock(mCore->mMutex);
739    mConsumerName = mCore->mConsumerName;
740    BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
741            producerControlledByApp ? "true" : "false");
742
743    if (mCore->mIsAbandoned) {
744        BQ_LOGE("connect(P): BufferQueue has been abandoned");
745        return NO_INIT;
746    }
747
748    if (mCore->mConsumerListener == NULL) {
749        BQ_LOGE("connect(P): BufferQueue has no consumer");
750        return NO_INIT;
751    }
752
753    if (output == NULL) {
754        BQ_LOGE("connect(P): output was NULL");
755        return BAD_VALUE;
756    }
757
758    if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
759        BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
760                mCore->mConnectedApi, api);
761        return BAD_VALUE;
762    }
763
764    int status = NO_ERROR;
765    switch (api) {
766        case NATIVE_WINDOW_API_EGL:
767        case NATIVE_WINDOW_API_CPU:
768        case NATIVE_WINDOW_API_MEDIA:
769        case NATIVE_WINDOW_API_CAMERA:
770            mCore->mConnectedApi = api;
771            output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
772                    mCore->mTransformHint, mCore->mQueue.size());
773
774            // Set up a death notification so that we can disconnect
775            // automatically if the remote producer dies
776            if (listener != NULL &&
777                    listener->asBinder()->remoteBinder() != NULL) {
778                status = listener->asBinder()->linkToDeath(
779                        static_cast<IBinder::DeathRecipient*>(this));
780                if (status != NO_ERROR) {
781                    BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
782                            strerror(-status), status);
783                }
784            }
785            mCore->mConnectedProducerListener = listener;
786            break;
787        default:
788            BQ_LOGE("connect(P): unknown API %d", api);
789            status = BAD_VALUE;
790            break;
791    }
792
793    mCore->mBufferHasBeenQueued = false;
794    mCore->mDequeueBufferCannotBlock =
795            mCore->mConsumerControlledByApp && producerControlledByApp;
796
797    return status;
798}
799
800status_t BufferQueueProducer::disconnect(int api) {
801    ATRACE_CALL();
802    BQ_LOGV("disconnect(P): api %d", api);
803
804    int status = NO_ERROR;
805    sp<IConsumerListener> listener;
806    { // Autolock scope
807        Mutex::Autolock lock(mCore->mMutex);
808        mCore->waitWhileAllocatingLocked();
809
810        if (mCore->mIsAbandoned) {
811            // It's not really an error to disconnect after the surface has
812            // been abandoned; it should just be a no-op.
813            return NO_ERROR;
814        }
815
816        switch (api) {
817            case NATIVE_WINDOW_API_EGL:
818            case NATIVE_WINDOW_API_CPU:
819            case NATIVE_WINDOW_API_MEDIA:
820            case NATIVE_WINDOW_API_CAMERA:
821                if (mCore->mConnectedApi == api) {
822                    mCore->freeAllBuffersLocked();
823
824                    // Remove our death notification callback if we have one
825                    if (mCore->mConnectedProducerListener != NULL) {
826                        sp<IBinder> token =
827                                mCore->mConnectedProducerListener->asBinder();
828                        // This can fail if we're here because of the death
829                        // notification, but we just ignore it
830                        token->unlinkToDeath(
831                                static_cast<IBinder::DeathRecipient*>(this));
832                    }
833                    mCore->mConnectedProducerListener = NULL;
834                    mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
835                    mCore->mSidebandStream.clear();
836                    mCore->mDequeueCondition.broadcast();
837                    listener = mCore->mConsumerListener;
838                } else {
839                    BQ_LOGE("disconnect(P): connected to another API "
840                            "(cur=%d req=%d)", mCore->mConnectedApi, api);
841                    status = BAD_VALUE;
842                }
843                break;
844            default:
845                BQ_LOGE("disconnect(P): unknown API %d", api);
846                status = BAD_VALUE;
847                break;
848        }
849    } // Autolock scope
850
851    // Call back without lock held
852    if (listener != NULL) {
853        listener->onBuffersReleased();
854    }
855
856    return status;
857}
858
859status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
860    sp<IConsumerListener> listener;
861    { // Autolock scope
862        Mutex::Autolock _l(mCore->mMutex);
863        mCore->mSidebandStream = stream;
864        listener = mCore->mConsumerListener;
865    } // Autolock scope
866
867    if (listener != NULL) {
868        listener->onSidebandStreamChanged();
869    }
870    return NO_ERROR;
871}
872
873void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
874        uint32_t height, uint32_t format, uint32_t usage) {
875    ATRACE_CALL();
876    while (true) {
877        Vector<int> freeSlots;
878        size_t newBufferCount = 0;
879        uint32_t allocWidth = 0;
880        uint32_t allocHeight = 0;
881        uint32_t allocFormat = 0;
882        uint32_t allocUsage = 0;
883        { // Autolock scope
884            Mutex::Autolock lock(mCore->mMutex);
885            mCore->waitWhileAllocatingLocked();
886
887            int currentBufferCount = 0;
888            for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
889                if (mSlots[slot].mGraphicBuffer != NULL) {
890                    ++currentBufferCount;
891                } else {
892                    if (mSlots[slot].mBufferState != BufferSlot::FREE) {
893                        BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
894                                slot);
895                        continue;
896                    }
897
898                    freeSlots.push_back(slot);
899                }
900            }
901
902            int maxBufferCount = mCore->getMaxBufferCountLocked(async);
903            BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
904                    currentBufferCount, maxBufferCount);
905            if (maxBufferCount <= currentBufferCount)
906                return;
907            newBufferCount = maxBufferCount - currentBufferCount;
908            if (freeSlots.size() < newBufferCount) {
909                BQ_LOGE("allocateBuffers: ran out of free slots");
910                return;
911            }
912            allocWidth = width > 0 ? width : mCore->mDefaultWidth;
913            allocHeight = height > 0 ? height : mCore->mDefaultHeight;
914            allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
915            allocUsage = usage | mCore->mConsumerUsageBits;
916
917            mCore->mIsAllocating = true;
918        } // Autolock scope
919
920        Vector<sp<GraphicBuffer> > buffers;
921        for (size_t i = 0; i <  newBufferCount; ++i) {
922            status_t result = NO_ERROR;
923            sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
924                    allocWidth, allocHeight, allocFormat, allocUsage, &result));
925            if (result != NO_ERROR) {
926                BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
927                        " %u, usage %u)", width, height, format, usage);
928                Mutex::Autolock lock(mCore->mMutex);
929                mCore->mIsAllocating = false;
930                mCore->mIsAllocatingCondition.broadcast();
931                return;
932            }
933            buffers.push_back(graphicBuffer);
934        }
935
936        { // Autolock scope
937            Mutex::Autolock lock(mCore->mMutex);
938            uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
939            uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
940            uint32_t checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
941            uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
942            if (checkWidth != allocWidth || checkHeight != allocHeight ||
943                checkFormat != allocFormat || checkUsage != allocUsage) {
944                // Something changed while we released the lock. Retry.
945                BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
946                mCore->mIsAllocating = false;
947                mCore->mIsAllocatingCondition.broadcast();
948                continue;
949            }
950
951            for (size_t i = 0; i < newBufferCount; ++i) {
952                int slot = freeSlots[i];
953                if (mSlots[slot].mBufferState != BufferSlot::FREE) {
954                    // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we
955                    // allocated.
956                    BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
957                            "Dropping allocated buffer.", slot);
958                    continue;
959                }
960                mCore->freeBufferLocked(slot); // Clean up the slot first
961                mSlots[slot].mGraphicBuffer = buffers[i];
962                mSlots[slot].mFrameNumber = 0;
963                mSlots[slot].mFence = Fence::NO_FENCE;
964                BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
965            }
966
967            mCore->mIsAllocating = false;
968            mCore->mIsAllocatingCondition.broadcast();
969        } // Autolock scope
970    }
971}
972
973void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
974    // If we're here, it means that a producer we were connected to died.
975    // We're guaranteed that we are still connected to it because we remove
976    // this callback upon disconnect. It's therefore safe to read mConnectedApi
977    // without synchronization here.
978    int api = mCore->mConnectedApi;
979    disconnect(api);
980}
981
982} // namespace android
983