1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * Copyright (C) 2012 The Android Open Source Project
4  * Copyright (C) 2013 Mozilla Foundation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #define LOG_TAG "GonkBufferQueue"
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 //#define LOG_NDEBUG 0
22 
23 #define GL_GLEXT_PROTOTYPES
24 #define EGL_EGLEXT_PROTOTYPES
25 
26 #include <utils/Log.h>
27 #include <utils/Trace.h>
28 #include <utils/CallStack.h>
29 #include <cutils/compiler.h>
30 
31 #include "mozilla/layers/GrallocTextureClient.h"
32 #include "mozilla/layers/ImageBridgeChild.h"
33 #include "GonkBufferQueueKK.h"
34 
35 #define ATRACE_BUFFER_INDEX(index)
36 
37 using namespace mozilla;
38 using namespace mozilla::gfx;
39 using namespace mozilla::layers;
40 
41 namespace android {
42 
43 // Get an ID that's unique within this process.
createProcessUniqueId()44 static int32_t createProcessUniqueId() {
45     static volatile int32_t globalCounter = 0;
46     return android_atomic_inc(&globalCounter);
47 }
48 
scalingModeName(int scalingMode)49 static const char* scalingModeName(int scalingMode) {
50     switch (scalingMode) {
51         case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
52         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
53         case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
54         default: return "Unknown";
55     }
56 }
57 
GonkBufferQueue(bool allowSynchronousMode,const sp<IGraphicBufferAlloc> & allocator)58 GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode,
59         const sp<IGraphicBufferAlloc>& allocator) :
60     mDefaultWidth(1),
61     mDefaultHeight(1),
62     mMaxAcquiredBufferCount(1),
63     mDefaultMaxBufferCount(2),
64     mOverrideMaxBufferCount(0),
65     mSynchronousMode(true),
66     mConsumerControlledByApp(false),
67     mDequeueBufferCannotBlock(false),
68     mUseAsyncBuffer(true),
69     mConnectedApi(NO_CONNECTED_API),
70     mAbandoned(false),
71     mFrameCounter(0),
72     mBufferHasBeenQueued(false),
73     mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
74     mConsumerUsageBits(0),
75     mTransformHint(0)
76 {
77     // Choose a name using the PID and a process-unique ID.
78     mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
79 
80     ALOGV("GonkBufferQueue");
81 }
82 
~GonkBufferQueue()83 GonkBufferQueue::~GonkBufferQueue() {
84     ALOGV("~GonkBufferQueue");
85 }
86 
setDefaultMaxBufferCountLocked(int count)87 status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) {
88     if (count < 2 || count > NUM_BUFFER_SLOTS)
89         return BAD_VALUE;
90 
91     mDefaultMaxBufferCount = count;
92     mDequeueCondition.broadcast();
93 
94     return NO_ERROR;
95 }
96 
setConsumerName(const String8 & name)97 void GonkBufferQueue::setConsumerName(const String8& name) {
98     Mutex::Autolock lock(mMutex);
99     mConsumerName = name;
100 }
101 
setDefaultBufferFormat(uint32_t defaultFormat)102 status_t GonkBufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
103     Mutex::Autolock lock(mMutex);
104     mDefaultBufferFormat = defaultFormat;
105     return NO_ERROR;
106 }
107 
setConsumerUsageBits(uint32_t usage)108 status_t GonkBufferQueue::setConsumerUsageBits(uint32_t usage) {
109     Mutex::Autolock lock(mMutex);
110     mConsumerUsageBits = usage;
111     return NO_ERROR;
112 }
113 
setTransformHint(uint32_t hint)114 status_t GonkBufferQueue::setTransformHint(uint32_t hint) {
115     ALOGV("setTransformHint: %02x", hint);
116     Mutex::Autolock lock(mMutex);
117     mTransformHint = hint;
118     return NO_ERROR;
119 }
120 
121 already_AddRefed<TextureClient>
getTextureClientFromBuffer(ANativeWindowBuffer * buffer)122 GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer)
123 {
124     Mutex::Autolock _l(mMutex);
125     if (buffer == NULL) {
126         ALOGE("getSlotFromBufferLocked: encountered NULL buffer");
127         return nullptr;
128     }
129 
130     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
131         if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
132              RefPtr<TextureClient> client(mSlots[i].mTextureClient);
133              return client.forget();
134         }
135     }
136     ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
137     return nullptr;
138 }
139 
getSlotFromTextureClientLocked(TextureClient * client) const140 int GonkBufferQueue::getSlotFromTextureClientLocked(
141         TextureClient* client) const
142 {
143     if (client == NULL) {
144         ALOGE("getSlotFromBufferLocked: encountered NULL buffer");
145         return BAD_VALUE;
146     }
147 
148     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
149         if (mSlots[i].mTextureClient == client) {
150             return i;
151         }
152     }
153     ALOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client);
154     return BAD_VALUE;
155 }
156 
setBufferCount(int bufferCount)157 status_t GonkBufferQueue::setBufferCount(int bufferCount) {
158     ALOGV("setBufferCount: count=%d", bufferCount);
159 
160     sp<IConsumerListener> listener;
161     {
162         Mutex::Autolock lock(mMutex);
163 
164         if (mAbandoned) {
165             ALOGE("setBufferCount: GonkBufferQueue has been abandoned!");
166             return NO_INIT;
167         }
168         if (bufferCount > NUM_BUFFER_SLOTS) {
169             ALOGE("setBufferCount: bufferCount too large (max %d)",
170                     NUM_BUFFER_SLOTS);
171             return BAD_VALUE;
172         }
173 
174         // Error out if the user has dequeued buffers
175         for (int i=0 ; i<NUM_BUFFER_SLOTS; i++) {
176             if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
177                 ALOGE("setBufferCount: client owns some buffers");
178                 return -EINVAL;
179             }
180         }
181 
182         if (bufferCount == 0) {
183             mOverrideMaxBufferCount = 0;
184             mDequeueCondition.broadcast();
185             return NO_ERROR;
186         }
187 
188         // fine to assume async to false before we're setting the buffer count
189         const int minBufferSlots = getMinMaxBufferCountLocked(false);
190         if (bufferCount < minBufferSlots) {
191             ALOGE("setBufferCount: requested buffer count (%d) is less than "
192                     "minimum (%d)", bufferCount, minBufferSlots);
193             return BAD_VALUE;
194         }
195 
196         // here we're guaranteed that the client doesn't have dequeued buffers
197         // and will release all of its buffer references.  We don't clear the
198         // queue, however, so currently queued buffers still get displayed.
199         // XXX: Should this use drainQueueAndFreeBuffersLocked instead?
200         freeAllBuffersLocked();
201         mOverrideMaxBufferCount = bufferCount;
202         mDequeueCondition.broadcast();
203         listener = mConsumerListener;
204     } // scope for lock
205 
206     if (listener != NULL) {
207         listener->onBuffersReleased();
208     }
209 
210     return NO_ERROR;
211 }
212 
query(int what,int * outValue)213 int GonkBufferQueue::query(int what, int* outValue)
214 {
215     ATRACE_CALL();
216     Mutex::Autolock lock(mMutex);
217 
218     if (mAbandoned) {
219         ALOGE("query: GonkBufferQueue has been abandoned!");
220         return NO_INIT;
221     }
222 
223     int value;
224     switch (what) {
225     case NATIVE_WINDOW_WIDTH:
226         value = mDefaultWidth;
227         break;
228     case NATIVE_WINDOW_HEIGHT:
229         value = mDefaultHeight;
230         break;
231     case NATIVE_WINDOW_FORMAT:
232         value = mDefaultBufferFormat;
233         break;
234     case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
235         value = getMinUndequeuedBufferCount(false);
236         break;
237     case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
238         value = (mQueue.size() >= 2);
239         break;
240     case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
241         value = mConsumerUsageBits;
242         break;
243     default:
244         return BAD_VALUE;
245     }
246     outValue[0] = value;
247     return NO_ERROR;
248 }
249 
requestBuffer(int slot,sp<GraphicBuffer> * buf)250 status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
251     ATRACE_CALL();
252     ALOGV("requestBuffer: slot=%d", slot);
253     Mutex::Autolock lock(mMutex);
254     if (mAbandoned) {
255         ALOGE("requestBuffer: GonkBufferQueue has been abandoned!");
256         return NO_INIT;
257     }
258     if (slot < 0 || slot >= NUM_BUFFER_SLOTS) {
259         ALOGE("requestBuffer: slot index out of range [0, %d]: %d",
260                 NUM_BUFFER_SLOTS, slot);
261         return BAD_VALUE;
262     } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
263         ALOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
264                 slot, mSlots[slot].mBufferState);
265         return BAD_VALUE;
266     }
267     mSlots[slot].mRequestBufferCalled = true;
268     *buf = mSlots[slot].mGraphicBuffer;
269     return NO_ERROR;
270 }
271 
dequeueBuffer(int * outBuf,sp<Fence> * outFence,bool async,uint32_t w,uint32_t h,uint32_t format,uint32_t usage)272 status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async,
273             uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
274     ATRACE_CALL();
275     ALOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
276 
277     if ((w && !h) || (!w && h)) {
278         ALOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
279         return BAD_VALUE;
280     }
281 
282     status_t returnFlags(OK);
283     int buf = INVALID_BUFFER_SLOT;
284 
285     { // Scope for the lock
286         Mutex::Autolock lock(mMutex);
287 
288         if (format == 0) {
289             format = mDefaultBufferFormat;
290         }
291         // turn on usage bits the consumer requested
292         usage |= mConsumerUsageBits;
293 
294         int found = -1;
295         bool tryAgain = true;
296         while (tryAgain) {
297             if (mAbandoned) {
298                 ALOGE("dequeueBuffer: GonkBufferQueue has been abandoned!");
299                 return NO_INIT;
300             }
301 
302             const int maxBufferCount = getMaxBufferCountLocked(async);
303             if (async && mOverrideMaxBufferCount) {
304                 // FIXME: some drivers are manually setting the buffer-count (which they
305                 // shouldn't), so we do this extra test here to handle that case.
306                 // This is TEMPORARY, until we get this fixed.
307                 if (mOverrideMaxBufferCount < maxBufferCount) {
308                     ALOGE("dequeueBuffer: async mode is invalid with buffercount override");
309                     return BAD_VALUE;
310                 }
311             }
312 
313             // Free up any buffers that are in slots beyond the max buffer
314             // count.
315             //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
316             //    assert(mSlots[i].mBufferState == BufferSlot::FREE);
317             //    if (mSlots[i].mGraphicBuffer != NULL) {
318             //        freeBufferLocked(i);
319             //        returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
320             //    }
321             //}
322 
323             // look for a free buffer to give to the client
324             found = INVALID_BUFFER_SLOT;
325             int dequeuedCount = 0;
326             int acquiredCount = 0;
327             for (int i = 0; i < maxBufferCount; i++) {
328                 const int state = mSlots[i].mBufferState;
329                 switch (state) {
330                     case BufferSlot::DEQUEUED:
331                     dequeuedCount++;
332                         break;
333                     case BufferSlot::ACQUIRED:
334                         acquiredCount++;
335                         break;
336                     case BufferSlot::FREE:
337                     /* We return the oldest of the free buffers to avoid
338                      * stalling the producer if possible.  This is because
339                      * the consumer may still have pending reads of the
340                      * buffers in flight.
341                      */
342                     if ((found < 0) ||
343                             mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
344                         found = i;
345                     }
346                         break;
347                 }
348             }
349 
350             // clients are not allowed to dequeue more than one buffer
351             // if they didn't set a buffer count.
352             if (!mOverrideMaxBufferCount && dequeuedCount) {
353                 ALOGE("dequeueBuffer: can't dequeue multiple buffers without "
354                         "setting the buffer count");
355                 return -EINVAL;
356             }
357 
358             // See whether a buffer has been queued since the last
359             // setBufferCount so we know whether to perform the min undequeued
360             // buffers check below.
361             if (mBufferHasBeenQueued) {
362                 // make sure the client is not trying to dequeue more buffers
363                 // than allowed.
364                 const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
365                 const int minUndequeuedCount = getMinUndequeuedBufferCount(async);
366                 if (newUndequeuedCount < minUndequeuedCount) {
367                     ALOGE("dequeueBuffer: min undequeued buffer count (%d) "
368                             "exceeded (dequeued=%d undequeudCount=%d)",
369                             minUndequeuedCount, dequeuedCount,
370                             newUndequeuedCount);
371                     return -EBUSY;
372                 }
373             }
374 
375             // If no buffer is found, wait for a buffer to be released or for
376             // the max buffer count to change.
377             tryAgain = found == INVALID_BUFFER_SLOT;
378             if (tryAgain) {
379                 // return an error if we're in "cannot block" mode (producer and consumer
380                 // are controlled by the application) -- however, the consumer is allowed
381                 // to acquire briefly an extra buffer (which could cause us to have to wait here)
382                 // and that's okay because we know the wait will be brief (it happens
383                 // if we dequeue a buffer while the consumer has acquired one but not released
384                 // the old one yet -- for e.g.: see GLConsumer::updateTexImage()).
385                 if (mDequeueBufferCannotBlock && (acquiredCount <= mMaxAcquiredBufferCount)) {
386                     ALOGE("dequeueBuffer: would block! returning an error instead.");
387                     return WOULD_BLOCK;
388                 }
389                 mDequeueCondition.wait(mMutex);
390             }
391         }
392 
393 
394         if (found == INVALID_BUFFER_SLOT) {
395             // This should not happen.
396             ALOGE("dequeueBuffer: no available buffer slots");
397             return -EBUSY;
398         }
399 
400         buf = found;
401         *outBuf = found;
402 
403         const bool useDefaultSize = !w && !h;
404         if (useDefaultSize) {
405             // use the default size
406             w = mDefaultWidth;
407             h = mDefaultHeight;
408         }
409 
410         mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
411 
412         const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
413         if ((buffer == NULL) ||
414             (uint32_t(buffer->width)  != w) ||
415             (uint32_t(buffer->height) != h) ||
416             (uint32_t(buffer->format) != format) ||
417             ((uint32_t(buffer->usage) & usage) != usage))
418         {
419             mSlots[buf].mAcquireCalled = false;
420             mSlots[buf].mGraphicBuffer = NULL;
421             mSlots[buf].mRequestBufferCalled = false;
422             mSlots[buf].mFence = Fence::NO_FENCE;
423             if (mSlots[buf].mTextureClient) {
424               mSlots[buf].mTextureClient->ClearRecycleCallback();
425               // release TextureClient in ImageBridge thread
426               RefPtr<TextureClientReleaseTask> task =
427                 MakeAndAddRef<TextureClientReleaseTask>(mSlots[buf].mTextureClient);
428               mSlots[buf].mTextureClient = NULL;
429               ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget());
430             }
431             returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
432         }
433 
434 
435         if (CC_UNLIKELY(mSlots[buf].mFence == NULL)) {
436             ALOGE("dequeueBuffer: about to return a NULL fence from mSlot. "
437                     "buf=%d, w=%d, h=%d, format=%d",
438                     buf, buffer->width, buffer->height, buffer->format);
439         }
440         *outFence = mSlots[buf].mFence;
441         mSlots[buf].mFence = Fence::NO_FENCE;
442     }  // end lock scope
443 
444     if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
445 
446         RefPtr<LayersIPCChannel> allocator = ImageBridgeChild::GetSingleton();
447         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
448         GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w, h), format,
449                                                                  gfx::BackendType::NONE, usage,
450                                                                  allocator);
451         if (!texData) {
452             return -ENOMEM;
453         }
454 
455         RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator);
456 
457         { // Scope for the lock
458             Mutex::Autolock lock(mMutex);
459 
460             if (mAbandoned) {
461                 ALOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
462                 return NO_INIT;
463             }
464 
465             mSlots[buf].mGraphicBuffer = texData->GetGraphicBuffer();
466             mSlots[buf].mTextureClient = textureClient;
467             ALOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
468                     mSlots[buf].mGraphicBuffer->handle);
469 
470         }
471 
472     }
473 
474     ALOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outBuf,
475             mSlots[*outBuf].mFrameNumber,
476             mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
477 
478     return returnFlags;
479 }
480 
setSynchronousMode(bool enabled)481 status_t GonkBufferQueue::setSynchronousMode(bool enabled) {
482     ALOGV("setSynchronousMode: enabled=%d", enabled);
483     Mutex::Autolock lock(mMutex);
484 
485     if (mAbandoned) {
486         ALOGE("setSynchronousMode: BufferQueue has been abandoned!");
487         return NO_INIT;
488     }
489 
490     if (mSynchronousMode != enabled) {
491         mSynchronousMode = enabled;
492         mDequeueCondition.broadcast();
493     }
494     return OK;
495 }
496 
queueBuffer(int buf,const QueueBufferInput & input,QueueBufferOutput * output)497 status_t GonkBufferQueue::queueBuffer(int buf,
498         const QueueBufferInput& input, QueueBufferOutput* output) {
499     ATRACE_CALL();
500 
501     Rect crop;
502     uint32_t transform;
503     int scalingMode;
504     int64_t timestamp;
505     bool isAutoTimestamp;
506     bool async;
507     sp<Fence> fence;
508 
509     input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
510              &async, &fence);
511 
512     if (fence == NULL) {
513         ALOGE("queueBuffer: fence is NULL");
514         return BAD_VALUE;
515     }
516 
517     ALOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
518             "scale=%s",
519             buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
520             transform, scalingModeName(scalingMode));
521 
522     switch (scalingMode) {
523         case NATIVE_WINDOW_SCALING_MODE_FREEZE:
524         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
525         case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
526         case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
527             break;
528         default:
529             ALOGE("unknown scaling mode: %d", scalingMode);
530             return -EINVAL;
531     }
532 
533     sp<IConsumerListener> listener;
534 
535     { // scope for the lock
536         Mutex::Autolock lock(mMutex);
537 
538         if (mAbandoned) {
539             ALOGE("queueBuffer: GonkBufferQueue has been abandoned!");
540             return NO_INIT;
541         }
542 
543         const int maxBufferCount = getMaxBufferCountLocked(async);
544         if (async && mOverrideMaxBufferCount) {
545             // FIXME: some drivers are manually setting the buffer-count (which they
546             // shouldn't), so we do this extra test here to handle that case.
547             // This is TEMPORARY, until we get this fixed.
548             if (mOverrideMaxBufferCount < maxBufferCount) {
549                 ALOGE("queueBuffer: async mode is invalid with buffercount override");
550                 return BAD_VALUE;
551             }
552         }
553         if (buf < 0 || buf >= maxBufferCount) {
554             ALOGE("queueBuffer: slot index out of range [0, %d]: %d",
555                     maxBufferCount, buf);
556             return -EINVAL;
557         } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
558             ALOGE("queueBuffer: slot %d is not owned by the client "
559                     "(state=%d)", buf, mSlots[buf].mBufferState);
560             return -EINVAL;
561         } else if (!mSlots[buf].mRequestBufferCalled) {
562             ALOGE("queueBuffer: slot %d was enqueued without requesting a "
563                     "buffer", buf);
564             return -EINVAL;
565         }
566 
567         ALOGV("queueBuffer: slot=%d/%llu time=%#llx crop=[%d,%d,%d,%d] "
568                 "tr=%#x scale=%s",
569                 buf, mFrameCounter + 1, timestamp,
570                 crop.left, crop.top, crop.right, crop.bottom,
571                 transform, scalingModeName(scalingMode));
572 
573         const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
574         Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
575         Rect croppedCrop;
576         crop.intersect(bufferRect, &croppedCrop);
577         if (croppedCrop != crop) {
578             ALOGE("queueBuffer: crop rect is not contained within the "
579                     "buffer in slot %d", buf);
580             return -EINVAL;
581         }
582 
583         mSlots[buf].mFence = fence;
584         mSlots[buf].mBufferState = BufferSlot::QUEUED;
585         mFrameCounter++;
586         mSlots[buf].mFrameNumber = mFrameCounter;
587 
588         BufferItem item;
589         item.mAcquireCalled = mSlots[buf].mAcquireCalled;
590         item.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
591         item.mCrop = crop;
592         item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
593         item.mTransformToDisplayInverse = bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
594         item.mScalingMode = scalingMode;
595         item.mTimestamp = timestamp;
596         item.mIsAutoTimestamp = isAutoTimestamp;
597         item.mFrameNumber = mFrameCounter;
598         item.mBuf = buf;
599         item.mFence = fence;
600         item.mIsDroppable = mDequeueBufferCannotBlock || async;
601 
602         if (mQueue.empty()) {
603             // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and
604             // simply queue this buffer.
605             mQueue.push_back(item);
606         } else {
607             // when the queue is not empty, we need to look at the front buffer
608             // state and see if we need to replace it.
609             Fifo::iterator front(mQueue.begin());
610             if (front->mIsDroppable || !mSynchronousMode) {
611                 // buffer slot currently queued is marked free if still tracked
612                 if (stillTracking(front)) {
613                     mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
614                     // reset the frame number of the freed buffer so that it is the first in
615                     // line to be dequeued again.
616                     mSlots[front->mBuf].mFrameNumber = 0;
617                 }
618                 // and we record the new buffer in the queued list
619                 *front = item;
620             } else {
621                 mQueue.push_back(item);
622             }
623         }
624         // always signals that an additional frame should be consumed
625         // to handle max acquired buffer count reached case.
626         listener = mConsumerListener;
627 
628         mBufferHasBeenQueued = true;
629         mDequeueCondition.broadcast();
630 
631         output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
632                 mQueue.size());
633 
634     } // scope for the lock
635 
636     // call back without lock held
637     if (listener != 0) {
638         listener->onFrameAvailable();
639     }
640     return NO_ERROR;
641 }
642 
cancelBuffer(int buf,const sp<Fence> & fence)643 void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
644     ATRACE_CALL();
645     ALOGV("cancelBuffer: slot=%d", buf);
646     Mutex::Autolock lock(mMutex);
647 
648     if (mAbandoned) {
649         ALOGW("cancelBuffer: GonkBufferQueue has been abandoned!");
650         return;
651     }
652 
653     if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
654         ALOGE("cancelBuffer: slot index out of range [0, %d]: %d",
655                 NUM_BUFFER_SLOTS, buf);
656         return;
657     } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
658         ALOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
659                 buf, mSlots[buf].mBufferState);
660         return;
661     } else if (fence == NULL) {
662         ALOGE("cancelBuffer: fence is NULL");
663         return;
664     }
665     mSlots[buf].mBufferState = BufferSlot::FREE;
666     mSlots[buf].mFrameNumber = 0;
667     mSlots[buf].mFence = fence;
668     mDequeueCondition.broadcast();
669 }
670 
671 
connect(const sp<IBinder> & token,int api,bool producerControlledByApp,QueueBufferOutput * output)672 status_t GonkBufferQueue::connect(const sp<IBinder>& token,
673         int api, bool producerControlledByApp, QueueBufferOutput* output) {
674     ATRACE_CALL();
675     ALOGV("connect: api=%d producerControlledByApp=%s", api,
676             producerControlledByApp ? "true" : "false");
677     Mutex::Autolock lock(mMutex);
678 
679 retry:
680     if (mAbandoned) {
681         ALOGE("connect: GonkBufferQueue has been abandoned!");
682         return NO_INIT;
683     }
684 
685     if (mConsumerListener == NULL) {
686         ALOGE("connect: GonkBufferQueue has no consumer!");
687         return NO_INIT;
688     }
689 
690     if (mConnectedApi != NO_CONNECTED_API) {
691         ALOGE("connect: already connected (cur=%d, req=%d)",
692                 mConnectedApi, api);
693         return -EINVAL;
694     }
695 
696     // If we disconnect and reconnect quickly, we can be in a state where our slots are
697     // empty but we have many buffers in the queue.  This can cause us to run out of
698     // memory if we outrun the consumer.  Wait here if it looks like we have too many
699     // buffers queued up.
700     int maxBufferCount = getMaxBufferCountLocked(false);    // worst-case, i.e. largest value
701     if (mQueue.size() > (size_t) maxBufferCount) {
702         // TODO: make this bound tighter?
703         ALOGV("queue size is %d, waiting", mQueue.size());
704         mDequeueCondition.wait(mMutex);
705         goto retry;
706     }
707 
708     int err = NO_ERROR;
709     switch (api) {
710         case NATIVE_WINDOW_API_EGL:
711         case NATIVE_WINDOW_API_CPU:
712         case NATIVE_WINDOW_API_MEDIA:
713         case NATIVE_WINDOW_API_CAMERA:
714             mConnectedApi = api;
715             output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
716 
717             // set-up a death notification so that we can disconnect
718             // automatically when/if the remote producer dies.
719             if (token != NULL && token->remoteBinder() != NULL) {
720                 status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
721                 if (err == NO_ERROR) {
722                     mConnectedProducerToken = token;
723                 } else {
724                     ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err);
725                 }
726             }
727             break;
728         default:
729             err = -EINVAL;
730             break;
731     }
732 
733     mBufferHasBeenQueued = false;
734     mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp;
735 
736     return err;
737 }
738 
binderDied(const wp<IBinder> & who)739 void GonkBufferQueue::binderDied(const wp<IBinder>& who) {
740     // If we're here, it means that a producer we were connected to died.
741     // We're GUARANTEED that we still are connected to it because it has no other way
742     // to get disconnected -- or -- we wouldn't be here because we're removing this
743     // callback upon disconnect. Therefore, it's okay to read mConnectedApi without
744     // synchronization here.
745     int api = mConnectedApi;
746     this->disconnect(api);
747 }
748 
disconnect(int api)749 status_t GonkBufferQueue::disconnect(int api) {
750     ATRACE_CALL();
751     ALOGV("disconnect: api=%d", api);
752 
753     int err = NO_ERROR;
754     sp<IConsumerListener> listener;
755 
756     { // Scope for the lock
757         Mutex::Autolock lock(mMutex);
758 
759         if (mAbandoned) {
760             // it is not really an error to disconnect after the surface
761             // has been abandoned, it should just be a no-op.
762             return NO_ERROR;
763         }
764 
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                 if (mConnectedApi == api) {
771                     freeAllBuffersLocked();
772                     mConnectedApi = NO_CONNECTED_API;
773                     mDequeueCondition.broadcast();
774                     listener = mConsumerListener;
775                 } else {
776                     ALOGE("disconnect: connected to another api (cur=%d, req=%d)",
777                             mConnectedApi, api);
778                     err = -EINVAL;
779                 }
780                 break;
781             default:
782                 ALOGE("disconnect: unknown API %d", api);
783                 err = -EINVAL;
784                 break;
785         }
786     }
787 
788     if (listener != NULL) {
789         listener->onBuffersReleased();
790     }
791 
792     return err;
793 }
794 
dumpToString(String8 & result,const char * prefix) const795 void GonkBufferQueue::dumpToString(String8& result, const char* prefix) const {
796     Mutex::Autolock _l(mMutex);
797 
798     String8 fifo;
799     int fifoSize = 0;
800     Fifo::const_iterator i(mQueue.begin());
801     while (i != mQueue.end()) {
802         fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
803                 "xform=0x%02x, time=%#llx, scale=%s\n",
804                 i->mBuf, i->mGraphicBuffer.get(),
805                 i->mCrop.left, i->mCrop.top, i->mCrop.right,
806                 i->mCrop.bottom, i->mTransform, i->mTimestamp,
807                 scalingModeName(i->mScalingMode)
808                 );
809         i++;
810         fifoSize++;
811     }
812 
813 
814     result.appendFormat(
815             "%s-BufferQueue mMaxAcquiredBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
816             "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
817             prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, mDefaultWidth,
818             mDefaultHeight, mDefaultBufferFormat, mTransformHint,
819             fifoSize, fifo.string());
820 
821     struct {
822         const char * operator()(int state) const {
823             switch (state) {
824                 case BufferSlot::DEQUEUED: return "DEQUEUED";
825                 case BufferSlot::QUEUED: return "QUEUED";
826                 case BufferSlot::FREE: return "FREE";
827                 case BufferSlot::ACQUIRED: return "ACQUIRED";
828                 default: return "Unknown";
829             }
830         }
831     } stateName;
832 
833     // just trim the free buffers to not spam the dump
834     int maxBufferCount = 0;
835     for (int i=NUM_BUFFER_SLOTS-1 ; i>=0 ; i--) {
836         const BufferSlot& slot(mSlots[i]);
837         if ((slot.mBufferState != BufferSlot::FREE) || (slot.mGraphicBuffer != NULL)) {
838             maxBufferCount = i+1;
839             break;
840         }
841     }
842 
843     for (int i=0 ; i<maxBufferCount ; i++) {
844         const BufferSlot& slot(mSlots[i]);
845         const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
846         result.appendFormat(
847             "%s%s[%02d:%p] state=%-8s",
848                 prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, buf.get(),
849                 stateName(slot.mBufferState)
850         );
851 
852         if (buf != NULL) {
853             result.appendFormat(
854                     ", %p [%4ux%4u:%4u,%3X]",
855                     buf->handle, buf->width, buf->height, buf->stride,
856                     buf->format);
857         }
858         result.append("\n");
859     }
860 }
861 
freeAllBuffersLocked()862 void GonkBufferQueue::freeAllBuffersLocked()
863 {
864     ALOGW_IF(!mQueue.isEmpty(),
865             "freeAllBuffersLocked called but mQueue is not empty");
866     mQueue.clear();
867     mBufferHasBeenQueued = false;
868     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
869         mSlots[i].mGraphicBuffer = 0;
870         if (mSlots[i].mTextureClient) {
871           mSlots[i].mTextureClient->ClearRecycleCallback();
872           // release TextureClient in ImageBridge thread
873           RefPtr<TextureClientReleaseTask> task =
874             MakeAndAddRef<TextureClientReleaseTask>(mSlots[i].mTextureClient);
875           mSlots[i].mTextureClient = NULL;
876           ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(task.forget());
877         }
878         if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
879             mSlots[i].mNeedsCleanupOnRelease = true;
880         }
881         mSlots[i].mBufferState = BufferSlot::FREE;
882         mSlots[i].mFrameNumber = 0;
883         mSlots[i].mAcquireCalled = false;
884         // destroy fence as GonkBufferQueue now takes ownership
885         mSlots[i].mFence = Fence::NO_FENCE;
886     }
887 }
888 
acquireBuffer(BufferItem * buffer,nsecs_t expectedPresent)889 status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer, nsecs_t expectedPresent) {
890     ATRACE_CALL();
891     Mutex::Autolock _l(mMutex);
892 
893     // Check that the consumer doesn't currently have the maximum number of
894     // buffers acquired.  We allow the max buffer count to be exceeded by one
895     // buffer, so that the consumer can successfully set up the newly acquired
896     // buffer before releasing the old one.
897     int numAcquiredBuffers = 0;
898     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
899         if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
900             numAcquiredBuffers++;
901         }
902     }
903     if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) {
904         ALOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)",
905                 numAcquiredBuffers, mMaxAcquiredBufferCount);
906         return INVALID_OPERATION;
907     }
908 
909     // check if queue is empty
910     // In asynchronous mode the list is guaranteed to be one buffer
911     // deep, while in synchronous mode we use the oldest buffer.
912     if (mQueue.empty()) {
913         return NO_BUFFER_AVAILABLE;
914     }
915 
916     Fifo::iterator front(mQueue.begin());
917 
918     // If expectedPresent is specified, we may not want to return a buffer yet.
919     // If it's specified and there's more than one buffer queued, we may
920     // want to drop a buffer.
921     if (expectedPresent != 0) {
922         const int MAX_REASONABLE_NSEC = 1000000000ULL;  // 1 second
923 
924         // The "expectedPresent" argument indicates when the buffer is expected
925         // to be presented on-screen.  If the buffer's desired-present time
926         // is earlier (less) than expectedPresent, meaning it'll be displayed
927         // on time or possibly late if we show it ASAP, we acquire and return
928         // it.  If we don't want to display it until after the expectedPresent
929         // time, we return PRESENT_LATER without acquiring it.
930         //
931         // To be safe, we don't defer acquisition if expectedPresent is
932         // more than one second in the future beyond the desired present time
933         // (i.e. we'd be holding the buffer for a long time).
934         //
935         // NOTE: code assumes monotonic time values from the system clock are
936         // positive.
937 
938         // Start by checking to see if we can drop frames.  We skip this check
939         // if the timestamps are being auto-generated by Surface -- if the
940         // app isn't generating timestamps explicitly, they probably don't
941         // want frames to be discarded based on them.
942         while (mQueue.size() > 1 && !mQueue[0].mIsAutoTimestamp) {
943             // If entry[1] is timely, drop entry[0] (and repeat).  We apply
944             // an additional criteria here: we only drop the earlier buffer if
945             // our desiredPresent falls within +/- 1 second of the expected
946             // present.  Otherwise, bogus desiredPresent times (e.g. 0 or
947             // a small relative timestamp), which normally mean "ignore the
948             // timestamp and acquire immediately", would cause us to drop
949             // frames.
950             //
951             // We may want to add an additional criteria: don't drop the
952             // earlier buffer if entry[1]'s fence hasn't signaled yet.
953             //
954             // (Vector front is [0], back is [size()-1])
955             const BufferItem& bi(mQueue[1]);
956             nsecs_t desiredPresent = bi.mTimestamp;
957             if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
958                     desiredPresent > expectedPresent) {
959                 // This buffer is set to display in the near future, or
960                 // desiredPresent is garbage.  Either way we don't want to
961                 // drop the previous buffer just to get this on screen sooner.
962                 ALOGV("pts nodrop: des=%lld expect=%lld (%lld) now=%lld",
963                         desiredPresent, expectedPresent, desiredPresent - expectedPresent,
964                         systemTime(CLOCK_MONOTONIC));
965                 break;
966             }
967             ALOGV("pts drop: queue1des=%lld expect=%lld size=%d",
968                     desiredPresent, expectedPresent, mQueue.size());
969             if (stillTracking(front)) {
970                 // front buffer is still in mSlots, so mark the slot as free
971                 mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
972             }
973             mQueue.erase(front);
974             front = mQueue.begin();
975         }
976 
977         // See if the front buffer is due.
978         nsecs_t desiredPresent = front->mTimestamp;
979         if (desiredPresent > expectedPresent &&
980                 desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
981             ALOGV("pts defer: des=%lld expect=%lld (%lld) now=%lld",
982                     desiredPresent, expectedPresent, desiredPresent - expectedPresent,
983                     systemTime(CLOCK_MONOTONIC));
984             return PRESENT_LATER;
985         }
986 
987         ALOGV("pts accept: des=%lld expect=%lld (%lld) now=%lld",
988                 desiredPresent, expectedPresent, desiredPresent - expectedPresent,
989                 systemTime(CLOCK_MONOTONIC));
990     }
991 
992     int buf = front->mBuf;
993     buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
994     buffer->mFrameNumber = mSlots[buf].mFrameNumber;
995     buffer->mBuf = buf;
996     buffer->mFence = mSlots[buf].mFence;
997     ATRACE_BUFFER_INDEX(buf);
998 
999     ALOGV("acquireBuffer: acquiring { slot=%d/%llu, buffer=%p }",
1000             front->mBuf, front->mFrameNumber,
1001             front->mGraphicBuffer->handle);
1002     // if front buffer still being tracked update slot state
1003     if (stillTracking(front)) {
1004         mSlots[buf].mAcquireCalled = true;
1005         mSlots[buf].mNeedsCleanupOnRelease = false;
1006         mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
1007         mSlots[buf].mFence = Fence::NO_FENCE;
1008     }
1009 
1010     // If the buffer has previously been acquired by the consumer, set
1011     // mGraphicBuffer to NULL to avoid unnecessarily remapping this
1012     // buffer on the consumer side.
1013     //if (buffer->mAcquireCalled) {
1014     //    buffer->mGraphicBuffer = NULL;
1015     //}
1016 
1017     mQueue.erase(front);
1018     mDequeueCondition.broadcast();
1019 
1020     return NO_ERROR;
1021 }
1022 
releaseBuffer(int buf,uint64_t frameNumber,const sp<Fence> & fence)1023 status_t GonkBufferQueue::releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& fence) {
1024     ATRACE_CALL();
1025 
1026     if (buf == INVALID_BUFFER_SLOT || fence == NULL) {
1027         return BAD_VALUE;
1028     }
1029 
1030     Mutex::Autolock _l(mMutex);
1031 
1032     // If the frame number has changed because buffer has been reallocated,
1033     // we can ignore this releaseBuffer for the old buffer.
1034     //if (frameNumber != mSlots[buf].mFrameNumber) {
1035     //    return STALE_BUFFER_SLOT;
1036     //}
1037 
1038 
1039     // Internal state consistency checks:
1040     // Make sure this buffers hasn't been queued while we were owning it (acquired)
1041     Fifo::iterator front(mQueue.begin());
1042     Fifo::const_iterator const end(mQueue.end());
1043     while (front != end) {
1044         if (front->mBuf == buf) {
1045             LOG_ALWAYS_FATAL("[%s] received new buffer(#%lld) on slot #%d that has not yet been "
1046                     "acquired", mConsumerName.string(), frameNumber, buf);
1047             break; // never reached
1048         }
1049         front++;
1050     }
1051 
1052     // The buffer can now only be released if its in the acquired state
1053     if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
1054         mSlots[buf].mFence = fence;
1055         mSlots[buf].mBufferState = BufferSlot::FREE;
1056     } else if (mSlots[buf].mNeedsCleanupOnRelease) {
1057         ALOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
1058         mSlots[buf].mNeedsCleanupOnRelease = false;
1059         return STALE_BUFFER_SLOT;
1060     } else {
1061         ALOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState);
1062         return -EINVAL;
1063     }
1064 
1065     mDequeueCondition.broadcast();
1066     return NO_ERROR;
1067 }
1068 
consumerConnect(const sp<IConsumerListener> & consumerListener,bool controlledByApp)1069 status_t GonkBufferQueue::consumerConnect(const sp<IConsumerListener>& consumerListener,
1070         bool controlledByApp) {
1071     ALOGV("consumerConnect controlledByApp=%s",
1072             controlledByApp ? "true" : "false");
1073     Mutex::Autolock lock(mMutex);
1074 
1075     if (mAbandoned) {
1076         ALOGE("consumerConnect: GonkBufferQueue has been abandoned!");
1077         return NO_INIT;
1078     }
1079     if (consumerListener == NULL) {
1080         ALOGE("consumerConnect: consumerListener may not be NULL");
1081         return BAD_VALUE;
1082     }
1083 
1084     mConsumerListener = consumerListener;
1085     mConsumerControlledByApp = controlledByApp;
1086 
1087     return NO_ERROR;
1088 }
1089 
consumerDisconnect()1090 status_t GonkBufferQueue::consumerDisconnect() {
1091     ALOGV("consumerDisconnect");
1092     Mutex::Autolock lock(mMutex);
1093 
1094     if (mConsumerListener == NULL) {
1095         ALOGE("consumerDisconnect: No consumer is connected!");
1096         return -EINVAL;
1097     }
1098 
1099     mAbandoned = true;
1100     mConsumerListener = NULL;
1101     mQueue.clear();
1102     freeAllBuffersLocked();
1103     mDequeueCondition.broadcast();
1104     return NO_ERROR;
1105 }
1106 
getReleasedBuffers(uint32_t * slotMask)1107 status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) {
1108     ALOGV("getReleasedBuffers");
1109     Mutex::Autolock lock(mMutex);
1110 
1111     if (mAbandoned) {
1112         ALOGE("getReleasedBuffers: GonkBufferQueue has been abandoned!");
1113         return NO_INIT;
1114     }
1115 
1116     uint32_t mask = 0;
1117     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
1118         if (!mSlots[i].mAcquireCalled) {
1119             mask |= 1 << i;
1120         }
1121     }
1122 
1123     // Remove buffers in flight (on the queue) from the mask where acquire has
1124     // been called, as the consumer will not receive the buffer address, so
1125     // it should not free these slots.
1126     Fifo::iterator front(mQueue.begin());
1127     while (front != mQueue.end()) {
1128         if (front->mAcquireCalled)
1129             mask &= ~(1 << front->mBuf);
1130         front++;
1131     }
1132 
1133     *slotMask = mask;
1134 
1135     ALOGV("getReleasedBuffers: returning mask %#x", mask);
1136     return NO_ERROR;
1137 }
1138 
setDefaultBufferSize(uint32_t w,uint32_t h)1139 status_t GonkBufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) {
1140     ALOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
1141     if (!w || !h) {
1142         ALOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
1143                 w, h);
1144         return BAD_VALUE;
1145     }
1146 
1147     Mutex::Autolock lock(mMutex);
1148     mDefaultWidth = w;
1149     mDefaultHeight = h;
1150     return NO_ERROR;
1151 }
1152 
setDefaultMaxBufferCount(int bufferCount)1153 status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) {
1154     ATRACE_CALL();
1155     Mutex::Autolock lock(mMutex);
1156     return setDefaultMaxBufferCountLocked(bufferCount);
1157 }
1158 
disableAsyncBuffer()1159 status_t GonkBufferQueue::disableAsyncBuffer() {
1160     ATRACE_CALL();
1161     Mutex::Autolock lock(mMutex);
1162     if (mConsumerListener != NULL) {
1163         ALOGE("disableAsyncBuffer: consumer already connected!");
1164         return INVALID_OPERATION;
1165     }
1166     mUseAsyncBuffer = false;
1167     return NO_ERROR;
1168 }
1169 
setMaxAcquiredBufferCount(int maxAcquiredBuffers)1170 status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
1171     ATRACE_CALL();
1172     Mutex::Autolock lock(mMutex);
1173     if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) {
1174         ALOGE("setMaxAcquiredBufferCount: invalid count specified: %d",
1175                 maxAcquiredBuffers);
1176         return BAD_VALUE;
1177     }
1178     if (mConnectedApi != NO_CONNECTED_API) {
1179         return INVALID_OPERATION;
1180     }
1181     mMaxAcquiredBufferCount = maxAcquiredBuffers;
1182     return NO_ERROR;
1183 }
1184 
getMinUndequeuedBufferCount(bool async) const1185 int GonkBufferQueue::getMinUndequeuedBufferCount(bool async) const {
1186     // if dequeueBuffer is allowed to error out, we don't have to
1187     // add an extra buffer.
1188     if (!mUseAsyncBuffer)
1189         return mMaxAcquiredBufferCount;
1190 
1191     // we're in async mode, or we want to prevent the app to
1192     // deadlock itself, we throw-in an extra buffer to guarantee it.
1193     if (mDequeueBufferCannotBlock || async || !mSynchronousMode)
1194         return mMaxAcquiredBufferCount + 1;
1195 
1196     return mMaxAcquiredBufferCount;
1197 }
1198 
getMinMaxBufferCountLocked(bool async) const1199 int GonkBufferQueue::getMinMaxBufferCountLocked(bool async) const {
1200     return getMinUndequeuedBufferCount(async) + 1;
1201 }
1202 
getMaxBufferCountLocked(bool async) const1203 int GonkBufferQueue::getMaxBufferCountLocked(bool async) const {
1204     int minMaxBufferCount = getMinMaxBufferCountLocked(async);
1205 
1206     int maxBufferCount = mDefaultMaxBufferCount;
1207     if (maxBufferCount < minMaxBufferCount) {
1208         maxBufferCount = minMaxBufferCount;
1209     }
1210     if (mOverrideMaxBufferCount != 0) {
1211         assert(mOverrideMaxBufferCount >= minMaxBufferCount);
1212         maxBufferCount = mOverrideMaxBufferCount;
1213     }
1214 
1215     // Any buffers that are dequeued by the producer or sitting in the queue
1216     // waiting to be consumed need to have their slots preserved.  Such
1217     // buffers will temporarily keep the max buffer count up until the slots
1218     // no longer need to be preserved.
1219     for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
1220         BufferSlot::BufferState state = mSlots[i].mBufferState;
1221         if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
1222             maxBufferCount = i + 1;
1223         }
1224     }
1225 
1226     return maxBufferCount;
1227 }
1228 
stillTracking(const BufferItem * item) const1229 bool GonkBufferQueue::stillTracking(const BufferItem *item) const {
1230     const BufferSlot &slot = mSlots[item->mBuf];
1231 
1232     ALOGV("stillTracking?: item: { slot=%d/%llu, buffer=%p }, "
1233             "slot: { slot=%d/%llu, buffer=%p }",
1234             item->mBuf, item->mFrameNumber,
1235             (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0),
1236             item->mBuf, slot.mFrameNumber,
1237             (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0));
1238 
1239     // Compare item with its original buffer slot.  We can check the slot
1240     // as the buffer would not be moved to a different slot by the producer.
1241     return (slot.mGraphicBuffer != NULL &&
1242             item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle);
1243 }
1244 
ProxyConsumerListener(const wp<ConsumerListener> & consumerListener)1245 GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener(
1246         const wp<ConsumerListener>& consumerListener):
1247         mConsumerListener(consumerListener) {}
1248 
~ProxyConsumerListener()1249 GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
1250 
onFrameAvailable()1251 void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() {
1252     sp<ConsumerListener> listener(mConsumerListener.promote());
1253     if (listener != NULL) {
1254         listener->onFrameAvailable();
1255     }
1256 }
1257 
onBuffersReleased()1258 void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() {
1259     sp<ConsumerListener> listener(mConsumerListener.promote());
1260     if (listener != NULL) {
1261         listener->onBuffersReleased();
1262     }
1263 }
1264 
1265 }; // namespace android
1266