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