BufferQueue.cpp revision 74ff8c23f44f1546d0c7004302f4c7ba726ff4c0
1/*
2 * Copyright (C) 2012 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#define LOG_TAG "BufferQueue"
18//#define LOG_NDEBUG 0
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21#define GL_GLEXT_PROTOTYPES
22#define EGL_EGLEXT_PROTOTYPES
23
24#include <EGL/egl.h>
25#include <EGL/eglext.h>
26
27#include <gui/BufferQueue.h>
28#include <gui/ISurfaceComposer.h>
29#include <private/gui/ComposerService.h>
30
31#include <utils/Log.h>
32#include <gui/SurfaceTexture.h>
33#include <utils/Trace.h>
34
35// This compile option causes SurfaceTexture to return the buffer that is currently
36// attached to the GL texture from dequeueBuffer when no other buffers are
37// available.  It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do
38// implicit cross-process synchronization to prevent the buffer from being
39// written to before the buffer has (a) been detached from the GL texture and
40// (b) all GL reads from the buffer have completed.
41
42// During refactoring, do not support dequeuing the current buffer
43#undef ALLOW_DEQUEUE_CURRENT_BUFFER
44
45#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
46#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER    true
47#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
48#else
49#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER    false
50#endif
51
52// Macros for including the BufferQueue name in log messages
53#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
54#define ST_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
55#define ST_LOGI(x, ...) ALOGI("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
56#define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
57#define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
58
59#define ATRACE_BUFFER_INDEX(index)                                            \
60    char ___traceBuf[1024];                                                   \
61    snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), (index));   \
62    android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf);
63
64namespace android {
65
66// Get an ID that's unique within this process.
67static int32_t createProcessUniqueId() {
68    static volatile int32_t globalCounter = 0;
69    return android_atomic_inc(&globalCounter);
70}
71
72BufferQueue::BufferQueue( bool allowSynchronousMode ) :
73    mDefaultWidth(1),
74    mDefaultHeight(1),
75    mPixelFormat(PIXEL_FORMAT_RGBA_8888),
76    mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
77    mClientBufferCount(0),
78    mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
79    mNextTransform(0),
80    mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
81    mSynchronousMode(false),
82    mAllowSynchronousMode(allowSynchronousMode),
83    mConnectedApi(NO_CONNECTED_API),
84    mAbandoned(false),
85    mFrameCounter(0),
86    mBufferHasBeenQueued(false)
87{
88    // Choose a name using the PID and a process-unique ID.
89    mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
90
91    ST_LOGV("BufferQueue");
92    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
93    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
94    mNextCrop.makeInvalid();
95}
96
97BufferQueue::~BufferQueue() {
98    ST_LOGV("~BufferQueue");
99}
100
101status_t BufferQueue::setBufferCountServerLocked(int bufferCount) {
102    if (bufferCount > NUM_BUFFER_SLOTS)
103        return BAD_VALUE;
104
105    // special-case, nothing to do
106    if (bufferCount == mBufferCount)
107        return OK;
108
109    if (!mClientBufferCount &&
110        bufferCount >= mBufferCount) {
111        // easy, we just have more buffers
112        mBufferCount = bufferCount;
113        mServerBufferCount = bufferCount;
114        mDequeueCondition.broadcast();
115    } else {
116        // we're here because we're either
117        // - reducing the number of available buffers
118        // - or there is a client-buffer-count in effect
119
120        // less than 2 buffers is never allowed
121        if (bufferCount < 2)
122            return BAD_VALUE;
123
124        // when there is non client-buffer-count in effect, the client is not
125        // allowed to dequeue more than one buffer at a time,
126        // so the next time they dequeue a buffer, we know that they don't
127        // own one. the actual resizing will happen during the next
128        // dequeueBuffer.
129
130        mServerBufferCount = bufferCount;
131    }
132    return OK;
133}
134
135bool BufferQueue::isSynchronousMode() const {
136    Mutex::Autolock lock(mMutex);
137    return mSynchronousMode;
138}
139
140void BufferQueue::setConsumerName(const String8& name) {
141    Mutex::Autolock lock(mMutex);
142    mConsumerName = name;
143}
144
145void BufferQueue::setFrameAvailableListener(
146        const sp<FrameAvailableListener>& listener) {
147    ST_LOGV("setFrameAvailableListener");
148    Mutex::Autolock lock(mMutex);
149    mFrameAvailableListener = listener;
150}
151
152status_t BufferQueue::setBufferCount(int bufferCount) {
153    ST_LOGV("setBufferCount: count=%d", bufferCount);
154    Mutex::Autolock lock(mMutex);
155
156    if (mAbandoned) {
157        ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
158        return NO_INIT;
159    }
160    if (bufferCount > NUM_BUFFER_SLOTS) {
161        ST_LOGE("setBufferCount: bufferCount larger than slots available");
162        return BAD_VALUE;
163    }
164
165    // Error out if the user has dequeued buffers
166    for (int i=0 ; i<mBufferCount ; i++) {
167        if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
168            ST_LOGE("setBufferCount: client owns some buffers");
169            return -EINVAL;
170        }
171    }
172
173    const int minBufferSlots = mSynchronousMode ?
174            MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
175    if (bufferCount == 0) {
176        mClientBufferCount = 0;
177        bufferCount = (mServerBufferCount >= minBufferSlots) ?
178                mServerBufferCount : minBufferSlots;
179        return setBufferCountServerLocked(bufferCount);
180    }
181
182    if (bufferCount < minBufferSlots) {
183        ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
184                "minimum (%d)", bufferCount, minBufferSlots);
185        return BAD_VALUE;
186    }
187
188    // here we're guaranteed that the client doesn't have dequeued buffers
189    // and will release all of its buffer references.
190    freeAllBuffersLocked();
191    mBufferCount = bufferCount;
192    mClientBufferCount = bufferCount;
193    mBufferHasBeenQueued = false;
194    mQueue.clear();
195    mDequeueCondition.broadcast();
196    return OK;
197}
198
199int BufferQueue::query(int what, int* outValue)
200{
201    ATRACE_CALL();
202    Mutex::Autolock lock(mMutex);
203
204    if (mAbandoned) {
205        ST_LOGE("query: SurfaceTexture has been abandoned!");
206        return NO_INIT;
207    }
208
209    int value;
210    switch (what) {
211    case NATIVE_WINDOW_WIDTH:
212        value = mDefaultWidth;
213        break;
214    case NATIVE_WINDOW_HEIGHT:
215        value = mDefaultHeight;
216        break;
217    case NATIVE_WINDOW_FORMAT:
218        value = mPixelFormat;
219        break;
220    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
221        value = mSynchronousMode ?
222                (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
223        break;
224    default:
225        return BAD_VALUE;
226    }
227    outValue[0] = value;
228    return NO_ERROR;
229}
230
231status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
232    ATRACE_CALL();
233    ST_LOGV("requestBuffer: slot=%d", slot);
234    Mutex::Autolock lock(mMutex);
235    if (mAbandoned) {
236        ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
237        return NO_INIT;
238    }
239    if (slot < 0 || mBufferCount <= slot) {
240        ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
241                mBufferCount, slot);
242        return BAD_VALUE;
243    }
244    mSlots[slot].mRequestBufferCalled = true;
245    *buf = mSlots[slot].mGraphicBuffer;
246    return NO_ERROR;
247}
248
249status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
250        uint32_t format, uint32_t usage) {
251    ATRACE_CALL();
252    ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
253
254    if ((w && !h) || (!w && h)) {
255        ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
256        return BAD_VALUE;
257    }
258
259    status_t returnFlags(OK);
260    EGLDisplay dpy = EGL_NO_DISPLAY;
261    EGLSyncKHR fence = EGL_NO_SYNC_KHR;
262
263    { // Scope for the lock
264        Mutex::Autolock lock(mMutex);
265
266        int found = -1;
267        int foundSync = -1;
268        int dequeuedCount = 0;
269        bool tryAgain = true;
270        while (tryAgain) {
271            if (mAbandoned) {
272                ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
273                return NO_INIT;
274            }
275
276            // We need to wait for the FIFO to drain if the number of buffer
277            // needs to change.
278            //
279            // The condition "number of buffers needs to change" is true if
280            // - the client doesn't care about how many buffers there are
281            // - AND the actual number of buffer is different from what was
282            //   set in the last setBufferCountServer()
283            //                         - OR -
284            //   setBufferCountServer() was set to a value incompatible with
285            //   the synchronization mode (for instance because the sync mode
286            //   changed since)
287            //
288            // As long as this condition is true AND the FIFO is not empty, we
289            // wait on mDequeueCondition.
290
291            const int minBufferCountNeeded = mSynchronousMode ?
292                    MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
293
294            const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
295                    ((mServerBufferCount != mBufferCount) ||
296                            (mServerBufferCount < minBufferCountNeeded));
297
298            if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
299                // wait for the FIFO to drain
300                mDequeueCondition.wait(mMutex);
301                // NOTE: we continue here because we need to reevaluate our
302                // whole state (eg: we could be abandoned or disconnected)
303                continue;
304            }
305
306            if (numberOfBuffersNeedsToChange) {
307                // here we're guaranteed that mQueue is empty
308                freeAllBuffersLocked();
309                mBufferCount = mServerBufferCount;
310                if (mBufferCount < minBufferCountNeeded)
311                    mBufferCount = minBufferCountNeeded;
312                mBufferHasBeenQueued = false;
313                returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
314            }
315
316            // look for a free buffer to give to the client
317            found = INVALID_BUFFER_SLOT;
318            foundSync = INVALID_BUFFER_SLOT;
319            dequeuedCount = 0;
320            for (int i = 0; i < mBufferCount; i++) {
321                const int state = mSlots[i].mBufferState;
322                if (state == BufferSlot::DEQUEUED) {
323                    dequeuedCount++;
324                }
325
326                // this logic used to be if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER)
327                // but dequeuing the current buffer is disabled.
328                if (false) {
329                    // This functionality has been temporarily removed so
330                    // BufferQueue and SurfaceTexture can be refactored into
331                    // separate objects
332                } else {
333                    if (state == BufferSlot::FREE) {
334                        /* We return the oldest of the free buffers to avoid
335                         * stalling the producer if possible.  This is because
336                         * the consumer may still have pending reads of the
337                         * buffers in flight.
338                         */
339                        bool isOlder = mSlots[i].mFrameNumber <
340                                mSlots[found].mFrameNumber;
341                        if (found < 0 || isOlder) {
342                            foundSync = i;
343                            found = i;
344                        }
345                    }
346                }
347            }
348
349            // clients are not allowed to dequeue more than one buffer
350            // if they didn't set a buffer count.
351            if (!mClientBufferCount && dequeuedCount) {
352                ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
353                        "setting the buffer count");
354                return -EINVAL;
355            }
356
357            // See whether a buffer has been queued since the last
358            // setBufferCount so we know whether to perform the
359            // MIN_UNDEQUEUED_BUFFERS check below.
360            if (mBufferHasBeenQueued) {
361                // make sure the client is not trying to dequeue more buffers
362                // than allowed.
363                const int avail = mBufferCount - (dequeuedCount+1);
364                if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
365                    ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
366                            "(dequeued=%d)",
367                            MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
368                            dequeuedCount);
369                    return -EBUSY;
370                }
371            }
372
373            // if no buffer is found, wait for a buffer to be released
374            tryAgain = found == INVALID_BUFFER_SLOT;
375            if (tryAgain) {
376                mDequeueCondition.wait(mMutex);
377            }
378        }
379
380
381        if (found == INVALID_BUFFER_SLOT) {
382            // This should not happen.
383            ST_LOGE("dequeueBuffer: no available buffer slots");
384            return -EBUSY;
385        }
386
387        const int buf = found;
388        *outBuf = found;
389
390        ATRACE_BUFFER_INDEX(buf);
391
392        const bool useDefaultSize = !w && !h;
393        if (useDefaultSize) {
394            // use the default size
395            w = mDefaultWidth;
396            h = mDefaultHeight;
397        }
398
399        const bool updateFormat = (format != 0);
400        if (!updateFormat) {
401            // keep the current (or default) format
402            format = mPixelFormat;
403        }
404
405        // buffer is now in DEQUEUED (but can also be current at the same time,
406        // if we're in synchronous mode)
407        mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
408
409        const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
410        if ((buffer == NULL) ||
411            (uint32_t(buffer->width)  != w) ||
412            (uint32_t(buffer->height) != h) ||
413            (uint32_t(buffer->format) != format) ||
414            ((uint32_t(buffer->usage) & usage) != usage))
415        {
416            usage |= GraphicBuffer::USAGE_HW_TEXTURE;
417            status_t error;
418            sp<GraphicBuffer> graphicBuffer(
419                    mGraphicBufferAlloc->createGraphicBuffer(
420                            w, h, format, usage, &error));
421            if (graphicBuffer == 0) {
422                ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
423                        "failed");
424                return error;
425            }
426            if (updateFormat) {
427                mPixelFormat = format;
428            }
429
430            mSlots[buf].mAcquireCalled = false;
431            mSlots[buf].mGraphicBuffer = graphicBuffer;
432            mSlots[buf].mRequestBufferCalled = false;
433            mSlots[buf].mFence = EGL_NO_SYNC_KHR;
434            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
435
436
437
438
439            returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
440        }
441
442        dpy = mSlots[buf].mEglDisplay;
443        fence = mSlots[buf].mFence;
444        mSlots[buf].mFence = EGL_NO_SYNC_KHR;
445    }  // end lock scope
446
447    if (fence != EGL_NO_SYNC_KHR) {
448        EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
449        // If something goes wrong, log the error, but return the buffer without
450        // synchronizing access to it.  It's too late at this point to abort the
451        // dequeue operation.
452        if (result == EGL_FALSE) {
453            ALOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
454        } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
455            ALOGE("dequeueBuffer: timeout waiting for fence");
456        }
457        eglDestroySyncKHR(dpy, fence);
458
459    }
460
461    ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
462            mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
463
464    return returnFlags;
465}
466
467status_t BufferQueue::setSynchronousMode(bool enabled) {
468    ATRACE_CALL();
469    ST_LOGV("setSynchronousMode: enabled=%d", enabled);
470    Mutex::Autolock lock(mMutex);
471
472    if (mAbandoned) {
473        ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
474        return NO_INIT;
475    }
476
477    status_t err = OK;
478    if (!mAllowSynchronousMode && enabled)
479        return err;
480
481    if (!enabled) {
482        // going to asynchronous mode, drain the queue
483        err = drainQueueLocked();
484        if (err != NO_ERROR)
485            return err;
486    }
487
488    if (mSynchronousMode != enabled) {
489        // - if we're going to asynchronous mode, the queue is guaranteed to be
490        // empty here
491        // - if the client set the number of buffers, we're guaranteed that
492        // we have at least 3 (because we don't allow less)
493        mSynchronousMode = enabled;
494        mDequeueCondition.broadcast();
495    }
496    return err;
497}
498
499status_t BufferQueue::queueBuffer(int buf, int64_t timestamp,
500        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
501    ATRACE_CALL();
502    ATRACE_BUFFER_INDEX(buf);
503
504    ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
505
506    sp<FrameAvailableListener> listener;
507
508    { // scope for the lock
509        Mutex::Autolock lock(mMutex);
510        if (mAbandoned) {
511            ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
512            return NO_INIT;
513        }
514        if (buf < 0 || buf >= mBufferCount) {
515            ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
516                    mBufferCount, buf);
517            return -EINVAL;
518        } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
519            ST_LOGE("queueBuffer: slot %d is not owned by the client "
520                    "(state=%d)", buf, mSlots[buf].mBufferState);
521            return -EINVAL;
522        } else if (!mSlots[buf].mRequestBufferCalled) {
523            ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
524                    "buffer", buf);
525            return -EINVAL;
526        }
527
528        if (mSynchronousMode) {
529            // In synchronous mode we queue all buffers in a FIFO.
530            mQueue.push_back(buf);
531
532            // Synchronous mode always signals that an additional frame should
533            // be consumed.
534            listener = mFrameAvailableListener;
535        } else {
536            // In asynchronous mode we only keep the most recent buffer.
537            if (mQueue.empty()) {
538                mQueue.push_back(buf);
539
540                // Asynchronous mode only signals that a frame should be
541                // consumed if no previous frame was pending. If a frame were
542                // pending then the consumer would have already been notified.
543                listener = mFrameAvailableListener;
544            } else {
545                Fifo::iterator front(mQueue.begin());
546                // buffer currently queued is freed
547                mSlots[*front].mBufferState = BufferSlot::FREE;
548                // and we record the new buffer index in the queued list
549                *front = buf;
550            }
551        }
552
553        mSlots[buf].mBufferState = BufferSlot::QUEUED;
554        mSlots[buf].mCrop = mNextCrop;
555        mSlots[buf].mTransform = mNextTransform;
556        mSlots[buf].mScalingMode = mNextScalingMode;
557        mSlots[buf].mTimestamp = timestamp;
558        mFrameCounter++;
559        mSlots[buf].mFrameNumber = mFrameCounter;
560
561        mBufferHasBeenQueued = true;
562        mDequeueCondition.broadcast();
563
564        *outWidth = mDefaultWidth;
565        *outHeight = mDefaultHeight;
566        *outTransform = 0;
567
568        ATRACE_INT(mConsumerName.string(), mQueue.size());
569    } // scope for the lock
570
571    // call back without lock held
572    if (listener != 0) {
573        listener->onFrameAvailable();
574    }
575    return OK;
576}
577
578void BufferQueue::cancelBuffer(int buf) {
579    ATRACE_CALL();
580    ST_LOGV("cancelBuffer: slot=%d", buf);
581    Mutex::Autolock lock(mMutex);
582
583    if (mAbandoned) {
584        ST_LOGW("cancelBuffer: BufferQueue has been abandoned!");
585        return;
586    }
587
588    if (buf < 0 || buf >= mBufferCount) {
589        ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
590                mBufferCount, buf);
591        return;
592    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
593        ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
594                buf, mSlots[buf].mBufferState);
595        return;
596    }
597    mSlots[buf].mBufferState = BufferSlot::FREE;
598    mSlots[buf].mFrameNumber = 0;
599    mDequeueCondition.broadcast();
600}
601
602status_t BufferQueue::setCrop(const Rect& crop) {
603    ATRACE_CALL();
604    ST_LOGV("setCrop: crop=[%d,%d,%d,%d]", crop.left, crop.top, crop.right,
605            crop.bottom);
606
607    Mutex::Autolock lock(mMutex);
608    if (mAbandoned) {
609        ST_LOGE("setCrop: BufferQueue has been abandoned!");
610        return NO_INIT;
611    }
612    mNextCrop = crop;
613    return OK;
614}
615
616status_t BufferQueue::setTransform(uint32_t transform) {
617    ATRACE_CALL();
618    ST_LOGV("setTransform: xform=%#x", transform);
619    Mutex::Autolock lock(mMutex);
620    if (mAbandoned) {
621        ST_LOGE("setTransform: BufferQueue has been abandoned!");
622        return NO_INIT;
623    }
624    mNextTransform = transform;
625    return OK;
626}
627
628status_t BufferQueue::setScalingMode(int mode) {
629    ATRACE_CALL();
630    ST_LOGV("setScalingMode: mode=%d", mode);
631
632    switch (mode) {
633        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
634        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
635            break;
636        default:
637            ST_LOGE("unknown scaling mode: %d", mode);
638            return BAD_VALUE;
639    }
640
641    Mutex::Autolock lock(mMutex);
642    mNextScalingMode = mode;
643    return OK;
644}
645
646status_t BufferQueue::connect(int api,
647        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
648    ATRACE_CALL();
649    ST_LOGV("connect: api=%d", api);
650    Mutex::Autolock lock(mMutex);
651
652    if (mAbandoned) {
653        ST_LOGE("connect: BufferQueue has been abandoned!");
654        return NO_INIT;
655    }
656
657    int err = NO_ERROR;
658    switch (api) {
659        case NATIVE_WINDOW_API_EGL:
660        case NATIVE_WINDOW_API_CPU:
661        case NATIVE_WINDOW_API_MEDIA:
662        case NATIVE_WINDOW_API_CAMERA:
663            if (mConnectedApi != NO_CONNECTED_API) {
664                ST_LOGE("connect: already connected (cur=%d, req=%d)",
665                        mConnectedApi, api);
666                err = -EINVAL;
667            } else {
668                mConnectedApi = api;
669                *outWidth = mDefaultWidth;
670                *outHeight = mDefaultHeight;
671                *outTransform = 0;
672            }
673            break;
674        default:
675            err = -EINVAL;
676            break;
677    }
678
679    mBufferHasBeenQueued = false;
680
681    return err;
682}
683
684status_t BufferQueue::disconnect(int api) {
685    ATRACE_CALL();
686    ST_LOGV("disconnect: api=%d", api);
687    Mutex::Autolock lock(mMutex);
688
689    if (mAbandoned) {
690        // it is not really an error to disconnect after the surface
691        // has been abandoned, it should just be a no-op.
692        return NO_ERROR;
693    }
694
695    int err = NO_ERROR;
696    switch (api) {
697        case NATIVE_WINDOW_API_EGL:
698        case NATIVE_WINDOW_API_CPU:
699        case NATIVE_WINDOW_API_MEDIA:
700        case NATIVE_WINDOW_API_CAMERA:
701            if (mConnectedApi == api) {
702                drainQueueAndFreeBuffersLocked();
703                mConnectedApi = NO_CONNECTED_API;
704                mNextCrop.makeInvalid();
705                mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
706                mNextTransform = 0;
707                mDequeueCondition.broadcast();
708            } else {
709                ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
710                        mConnectedApi, api);
711                err = -EINVAL;
712            }
713            break;
714        default:
715            ST_LOGE("disconnect: unknown API %d", api);
716            err = -EINVAL;
717            break;
718    }
719    return err;
720}
721
722void BufferQueue::dump(String8& result) const
723{
724    char buffer[1024];
725    BufferQueue::dump(result, "", buffer, 1024);
726}
727
728void BufferQueue::dump(String8& result, const char* prefix,
729        char* buffer, size_t SIZE) const
730{
731    Mutex::Autolock _l(mMutex);
732    snprintf(buffer, SIZE,
733            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x}\n"
734            ,prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
735            mNextCrop.bottom, mNextTransform
736    );
737    result.append(buffer);
738
739    String8 fifo;
740    int fifoSize = 0;
741    Fifo::const_iterator i(mQueue.begin());
742    while (i != mQueue.end()) {
743       snprintf(buffer, SIZE, "%02d ", *i++);
744       fifoSize++;
745       fifo.append(buffer);
746    }
747
748    snprintf(buffer, SIZE,
749            "%s-BufferQueue mBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
750            "mPixelFormat=%d, FIFO(%d)={%s}\n",
751            prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
752            mDefaultHeight, mPixelFormat, fifoSize, fifo.string());
753    result.append(buffer);
754
755
756    struct {
757        const char * operator()(int state) const {
758            switch (state) {
759                case BufferSlot::DEQUEUED: return "DEQUEUED";
760                case BufferSlot::QUEUED: return "QUEUED";
761                case BufferSlot::FREE: return "FREE";
762                case BufferSlot::ACQUIRED: return "ACQUIRED";
763                default: return "Unknown";
764            }
765        }
766    } stateName;
767
768    for (int i=0 ; i<mBufferCount ; i++) {
769        const BufferSlot& slot(mSlots[i]);
770        snprintf(buffer, SIZE,
771                "%s%s[%02d] "
772                "state=%-8s, crop=[%d,%d,%d,%d], "
773                "transform=0x%02x, timestamp=%lld",
774                prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
775                stateName(slot.mBufferState),
776                slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
777                slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
778        );
779        result.append(buffer);
780
781        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
782        if (buf != NULL) {
783            snprintf(buffer, SIZE,
784                    ", %p [%4ux%4u:%4u,%3X]",
785                    buf->handle, buf->width, buf->height, buf->stride,
786                    buf->format);
787            result.append(buffer);
788        }
789        result.append("\n");
790    }
791}
792
793void BufferQueue::freeBufferLocked(int i) {
794    mSlots[i].mGraphicBuffer = 0;
795    mSlots[i].mBufferState = BufferSlot::FREE;
796    mSlots[i].mFrameNumber = 0;
797    mSlots[i].mAcquireCalled = false;
798
799    // destroy fence as BufferQueue now takes ownership
800    if (mSlots[i].mFence != EGL_NO_SYNC_KHR) {
801        eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence);
802        mSlots[i].mFence = EGL_NO_SYNC_KHR;
803    }
804}
805
806void BufferQueue::freeAllBuffersLocked() {
807    ALOGW_IF(!mQueue.isEmpty(),
808            "freeAllBuffersLocked called but mQueue is not empty");
809    mQueue.clear();
810    mBufferHasBeenQueued = false;
811    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
812        freeBufferLocked(i);
813    }
814}
815
816status_t BufferQueue::acquire(BufferItem *buffer) {
817    ATRACE_CALL();
818    Mutex::Autolock _l(mMutex);
819    // check if queue is empty
820    // In asynchronous mode the list is guaranteed to be one buffer
821    // deep, while in synchronous mode we use the oldest buffer.
822    if (!mQueue.empty()) {
823        Fifo::iterator front(mQueue.begin());
824        int buf = *front;
825
826        ATRACE_BUFFER_INDEX(buf);
827
828        if (mSlots[buf].mAcquireCalled) {
829            buffer->mGraphicBuffer = NULL;
830        }
831        else {
832            buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
833        }
834        buffer->mCrop = mSlots[buf].mCrop;
835        buffer->mTransform = mSlots[buf].mTransform;
836        buffer->mScalingMode = mSlots[buf].mScalingMode;
837        buffer->mFrameNumber = mSlots[buf].mFrameNumber;
838        buffer->mTimestamp = mSlots[buf].mTimestamp;
839        buffer->mBuf = buf;
840        mSlots[buf].mAcquireCalled = true;
841
842        mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
843        mQueue.erase(front);
844        mDequeueCondition.broadcast();
845
846        ATRACE_INT(mConsumerName.string(), mQueue.size());
847    }
848    else {
849        return -EINVAL; //should be a better return code
850    }
851
852    return OK;
853}
854
855status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
856        EGLSyncKHR fence) {
857    ATRACE_CALL();
858    ATRACE_BUFFER_INDEX(buf);
859
860    Mutex::Autolock _l(mMutex);
861
862    if (buf == INVALID_BUFFER_SLOT) {
863        return -EINVAL;
864    }
865
866    mSlots[buf].mEglDisplay = display;
867    mSlots[buf].mFence = fence;
868
869    // The current buffer becomes FREE if it was still in the queued
870    // state. If it has already been given to the client
871    // (synchronous mode), then it stays in DEQUEUED state.
872    if (mSlots[buf].mBufferState == BufferSlot::QUEUED
873            || mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
874        mSlots[buf].mBufferState = BufferSlot::FREE;
875    }
876    mDequeueCondition.broadcast();
877
878    return OK;
879}
880
881status_t BufferQueue::consumerDisconnect() {
882    Mutex::Autolock lock(mMutex);
883    // Once the SurfaceTexture disconnects, the BufferQueue
884    // is considered abandoned
885    mAbandoned = true;
886    freeAllBuffersLocked();
887    mDequeueCondition.broadcast();
888    return OK;
889}
890
891status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
892{
893    ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
894    if (!w || !h) {
895        ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
896                w, h);
897        return BAD_VALUE;
898    }
899
900    Mutex::Autolock lock(mMutex);
901    mDefaultWidth = w;
902    mDefaultHeight = h;
903    return OK;
904}
905
906status_t BufferQueue::setBufferCountServer(int bufferCount) {
907    ATRACE_CALL();
908    Mutex::Autolock lock(mMutex);
909    return setBufferCountServerLocked(bufferCount);
910}
911
912void BufferQueue::freeAllBuffersExceptHeadLocked() {
913    ALOGW_IF(!mQueue.isEmpty(),
914            "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
915    int head = -1;
916    if (!mQueue.empty()) {
917        Fifo::iterator front(mQueue.begin());
918        head = *front;
919    }
920    mBufferHasBeenQueued = false;
921    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
922        if (i != head) {
923            freeBufferLocked(i);
924        }
925    }
926}
927
928status_t BufferQueue::drainQueueLocked() {
929    while (mSynchronousMode && !mQueue.isEmpty()) {
930        mDequeueCondition.wait(mMutex);
931        if (mAbandoned) {
932            ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!");
933            return NO_INIT;
934        }
935        if (mConnectedApi == NO_CONNECTED_API) {
936            ST_LOGE("drainQueueLocked: BufferQueue is not connected!");
937            return NO_INIT;
938        }
939    }
940    return NO_ERROR;
941}
942
943status_t BufferQueue::drainQueueAndFreeBuffersLocked() {
944    status_t err = drainQueueLocked();
945    if (err == NO_ERROR) {
946        if (mSynchronousMode) {
947            freeAllBuffersLocked();
948        } else {
949            freeAllBuffersExceptHeadLocked();
950        }
951    }
952    return err;
953}
954
955}; // namespace android
956