• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright 2014 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  #include <inttypes.h>
18  
19  #define LOG_TAG "BufferQueueProducer"
20  #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21  //#define LOG_NDEBUG 0
22  
23  #define EGL_EGLEXT_PROTOTYPES
24  
25  #include <gui/BufferItem.h>
26  #include <gui/BufferQueueCore.h>
27  #include <gui/BufferQueueProducer.h>
28  #include <gui/IConsumerListener.h>
29  #include <gui/IGraphicBufferAlloc.h>
30  #include <gui/IProducerListener.h>
31  
32  #include <utils/Log.h>
33  #include <utils/Trace.h>
34  
35  namespace android {
36  
BufferQueueProducer(const sp<BufferQueueCore> & core)37  BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
38      mCore(core),
39      mSlots(core->mSlots),
40      mConsumerName(),
41      mStickyTransform(0),
42      mLastQueueBufferFence(Fence::NO_FENCE),
43      mCallbackMutex(),
44      mNextCallbackTicket(0),
45      mCurrentCallbackTicket(0),
46      mCallbackCondition() {}
47  
~BufferQueueProducer()48  BufferQueueProducer::~BufferQueueProducer() {}
49  
requestBuffer(int slot,sp<GraphicBuffer> * buf)50  status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
51      ATRACE_CALL();
52      BQ_LOGV("requestBuffer: slot %d", slot);
53      Mutex::Autolock lock(mCore->mMutex);
54  
55      if (mCore->mIsAbandoned) {
56          BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
57          return NO_INIT;
58      }
59  
60      if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
61          BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
62                  slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
63          return BAD_VALUE;
64      } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
65          BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
66                  "(state = %d)", slot, mSlots[slot].mBufferState);
67          return BAD_VALUE;
68      }
69  
70      mSlots[slot].mRequestBufferCalled = true;
71      *buf = mSlots[slot].mGraphicBuffer;
72      return NO_ERROR;
73  }
74  
setBufferCount(int bufferCount)75  status_t BufferQueueProducer::setBufferCount(int bufferCount) {
76      ATRACE_CALL();
77      BQ_LOGV("setBufferCount: count = %d", bufferCount);
78  
79      sp<IConsumerListener> listener;
80      { // Autolock scope
81          Mutex::Autolock lock(mCore->mMutex);
82          mCore->waitWhileAllocatingLocked();
83  
84          if (mCore->mIsAbandoned) {
85              BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
86              return NO_INIT;
87          }
88  
89          if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
90              BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
91                      bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
92              return BAD_VALUE;
93          }
94  
95          // There must be no dequeued buffers when changing the buffer count.
96          for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
97              if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
98                  BQ_LOGE("setBufferCount: buffer owned by producer");
99                  return BAD_VALUE;
100              }
101          }
102  
103          if (bufferCount == 0) {
104              mCore->mOverrideMaxBufferCount = 0;
105              mCore->mDequeueCondition.broadcast();
106              return NO_ERROR;
107          }
108  
109          const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
110          if (bufferCount < minBufferSlots) {
111              BQ_LOGE("setBufferCount: requested buffer count %d is less than "
112                      "minimum %d", bufferCount, minBufferSlots);
113              return BAD_VALUE;
114          }
115  
116          // Here we are guaranteed that the producer doesn't have any dequeued
117          // buffers and will release all of its buffer references. We don't
118          // clear the queue, however, so that currently queued buffers still
119          // get displayed.
120          mCore->freeAllBuffersLocked();
121          mCore->mOverrideMaxBufferCount = bufferCount;
122          mCore->mDequeueCondition.broadcast();
123          listener = mCore->mConsumerListener;
124      } // Autolock scope
125  
126      // Call back without lock held
127      if (listener != NULL) {
128          listener->onBuffersReleased();
129      }
130  
131      return NO_ERROR;
132  }
133  
waitForFreeSlotThenRelock(const char * caller,bool async,int * found,status_t * returnFlags) const134  status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
135          bool async, int* found, status_t* returnFlags) const {
136      bool tryAgain = true;
137      while (tryAgain) {
138          if (mCore->mIsAbandoned) {
139              BQ_LOGE("%s: BufferQueue has been abandoned", caller);
140              return NO_INIT;
141          }
142  
143          const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
144          if (async && mCore->mOverrideMaxBufferCount) {
145              // FIXME: Some drivers are manually setting the buffer count
146              // (which they shouldn't), so we do this extra test here to
147              // handle that case. This is TEMPORARY until we get this fixed.
148              if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
149                  BQ_LOGE("%s: async mode is invalid with buffer count override",
150                          caller);
151                  return BAD_VALUE;
152              }
153          }
154  
155          // Free up any buffers that are in slots beyond the max buffer count
156          for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
157              assert(mSlots[s].mBufferState == BufferSlot::FREE);
158              if (mSlots[s].mGraphicBuffer != NULL) {
159                  mCore->freeBufferLocked(s);
160                  *returnFlags |= RELEASE_ALL_BUFFERS;
161              }
162          }
163  
164          // Look for a free buffer to give to the client
165          *found = BufferQueueCore::INVALID_BUFFER_SLOT;
166          int dequeuedCount = 0;
167          int acquiredCount = 0;
168          for (int s = 0; s < maxBufferCount; ++s) {
169              switch (mSlots[s].mBufferState) {
170                  case BufferSlot::DEQUEUED:
171                      ++dequeuedCount;
172                      break;
173                  case BufferSlot::ACQUIRED:
174                      ++acquiredCount;
175                      break;
176                  case BufferSlot::FREE:
177                      // We return the oldest of the free buffers to avoid
178                      // stalling the producer if possible, since the consumer
179                      // may still have pending reads of in-flight buffers
180                      if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
181                              mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
182                          *found = s;
183                      }
184                      break;
185                  default:
186                      break;
187              }
188          }
189  
190          // Producers are not allowed to dequeue more than one buffer if they
191          // did not set a buffer count
192          if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
193              BQ_LOGE("%s: can't dequeue multiple buffers without setting the "
194                      "buffer count", caller);
195              return INVALID_OPERATION;
196          }
197  
198          // See whether a buffer has been queued since the last
199          // setBufferCount so we know whether to perform the min undequeued
200          // buffers check below
201          if (mCore->mBufferHasBeenQueued) {
202              // Make sure the producer is not trying to dequeue more buffers
203              // than allowed
204              const int newUndequeuedCount =
205                  maxBufferCount - (dequeuedCount + 1);
206              const int minUndequeuedCount =
207                  mCore->getMinUndequeuedBufferCountLocked(async);
208              if (newUndequeuedCount < minUndequeuedCount) {
209                  BQ_LOGE("%s: min undequeued buffer count (%d) exceeded "
210                          "(dequeued=%d undequeued=%d)",
211                          caller, minUndequeuedCount,
212                          dequeuedCount, newUndequeuedCount);
213                  return INVALID_OPERATION;
214              }
215          }
216  
217          // If we disconnect and reconnect quickly, we can be in a state where
218          // our slots are empty but we have many buffers in the queue. This can
219          // cause us to run out of memory if we outrun the consumer. Wait here if
220          // it looks like we have too many buffers queued up.
221          bool tooManyBuffers = mCore->mQueue.size()
222                              > static_cast<size_t>(maxBufferCount);
223          if (tooManyBuffers) {
224              BQ_LOGV("%s: queue size is %zu, waiting", caller,
225                      mCore->mQueue.size());
226          }
227  
228          // If no buffer is found, or if the queue has too many buffers
229          // outstanding, wait for a buffer to be acquired or released, or for the
230          // max buffer count to change.
231          tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
232                     tooManyBuffers;
233          if (tryAgain) {
234              // Return an error if we're in non-blocking mode (producer and
235              // consumer are controlled by the application).
236              // However, the consumer is allowed to briefly acquire an extra
237              // buffer (which could cause us to have to wait here), which is
238              // okay, since it is only used to implement an atomic acquire +
239              // release (e.g., in GLConsumer::updateTexImage())
240              if (mCore->mDequeueBufferCannotBlock &&
241                      (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
242                  return WOULD_BLOCK;
243              }
244              mCore->mDequeueCondition.wait(mCore->mMutex);
245          }
246      } // while (tryAgain)
247  
248      return NO_ERROR;
249  }
250  
dequeueBuffer(int * outSlot,sp<android::Fence> * outFence,bool async,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)251  status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
252          sp<android::Fence> *outFence, bool async,
253          uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
254      ATRACE_CALL();
255      { // Autolock scope
256          Mutex::Autolock lock(mCore->mMutex);
257          mConsumerName = mCore->mConsumerName;
258      } // Autolock scope
259  
260      BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
261              async ? "true" : "false", width, height, format, usage);
262  
263      if ((width && !height) || (!width && height)) {
264          BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
265          return BAD_VALUE;
266      }
267  
268      status_t returnFlags = NO_ERROR;
269      EGLDisplay eglDisplay = EGL_NO_DISPLAY;
270      EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
271      bool attachedByConsumer = false;
272  
273      { // Autolock scope
274          Mutex::Autolock lock(mCore->mMutex);
275          mCore->waitWhileAllocatingLocked();
276  
277          if (format == 0) {
278              format = mCore->mDefaultBufferFormat;
279          }
280  
281          // Enable the usage bits the consumer requested
282          usage |= mCore->mConsumerUsageBits;
283  
284          int found;
285          status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
286                  &found, &returnFlags);
287          if (status != NO_ERROR) {
288              return status;
289          }
290  
291          // This should not happen
292          if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
293              BQ_LOGE("dequeueBuffer: no available buffer slots");
294              return -EBUSY;
295          }
296  
297          *outSlot = found;
298          ATRACE_BUFFER_INDEX(found);
299  
300          attachedByConsumer = mSlots[found].mAttachedByConsumer;
301  
302          const bool useDefaultSize = !width && !height;
303          if (useDefaultSize) {
304              width = mCore->mDefaultWidth;
305              height = mCore->mDefaultHeight;
306          }
307  
308          mSlots[found].mBufferState = BufferSlot::DEQUEUED;
309  
310          const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
311          if ((buffer == NULL) ||
312                  (static_cast<uint32_t>(buffer->width) != width) ||
313                  (static_cast<uint32_t>(buffer->height) != height) ||
314                  (static_cast<uint32_t>(buffer->format) != format) ||
315                  ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
316          {
317              mSlots[found].mAcquireCalled = false;
318              mSlots[found].mGraphicBuffer = NULL;
319              mSlots[found].mRequestBufferCalled = false;
320              mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
321              mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
322              mSlots[found].mFence = Fence::NO_FENCE;
323  
324              returnFlags |= BUFFER_NEEDS_REALLOCATION;
325          }
326  
327          if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
328              BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
329                      "slot=%d w=%d h=%d format=%u",
330                      found, buffer->width, buffer->height, buffer->format);
331          }
332  
333          eglDisplay = mSlots[found].mEglDisplay;
334          eglFence = mSlots[found].mEglFence;
335          *outFence = mSlots[found].mFence;
336          mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
337          mSlots[found].mFence = Fence::NO_FENCE;
338      } // Autolock scope
339  
340      if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
341          status_t error;
342          BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
343          sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
344                      width, height, format, usage, &error));
345          if (graphicBuffer == NULL) {
346              BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
347              return error;
348          }
349  
350          { // Autolock scope
351              Mutex::Autolock lock(mCore->mMutex);
352  
353              if (mCore->mIsAbandoned) {
354                  BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
355                  return NO_INIT;
356              }
357  
358              mSlots[*outSlot].mFrameNumber = UINT32_MAX;
359              mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
360          } // Autolock scope
361      }
362  
363      if (attachedByConsumer) {
364          returnFlags |= BUFFER_NEEDS_REALLOCATION;
365      }
366  
367      if (eglFence != EGL_NO_SYNC_KHR) {
368          EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
369                  1000000000);
370          // If something goes wrong, log the error, but return the buffer without
371          // synchronizing access to it. It's too late at this point to abort the
372          // dequeue operation.
373          if (result == EGL_FALSE) {
374              BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
375                      eglGetError());
376          } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
377              BQ_LOGE("dequeueBuffer: timeout waiting for fence");
378          }
379          eglDestroySyncKHR(eglDisplay, eglFence);
380      }
381  
382      BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
383              *outSlot,
384              mSlots[*outSlot].mFrameNumber,
385              mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
386  
387      return returnFlags;
388  }
389  
detachBuffer(int slot)390  status_t BufferQueueProducer::detachBuffer(int slot) {
391      ATRACE_CALL();
392      ATRACE_BUFFER_INDEX(slot);
393      BQ_LOGV("detachBuffer(P): slot %d", slot);
394      Mutex::Autolock lock(mCore->mMutex);
395  
396      if (mCore->mIsAbandoned) {
397          BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned");
398          return NO_INIT;
399      }
400  
401      if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
402          BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
403                  slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
404          return BAD_VALUE;
405      } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
406          BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer "
407                  "(state = %d)", slot, mSlots[slot].mBufferState);
408          return BAD_VALUE;
409      } else if (!mSlots[slot].mRequestBufferCalled) {
410          BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested",
411                  slot);
412          return BAD_VALUE;
413      }
414  
415      mCore->freeBufferLocked(slot);
416      mCore->mDequeueCondition.broadcast();
417  
418      return NO_ERROR;
419  }
420  
detachNextBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence)421  status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
422          sp<Fence>* outFence) {
423      ATRACE_CALL();
424  
425      if (outBuffer == NULL) {
426          BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
427          return BAD_VALUE;
428      } else if (outFence == NULL) {
429          BQ_LOGE("detachNextBuffer: outFence must not be NULL");
430          return BAD_VALUE;
431      }
432  
433      Mutex::Autolock lock(mCore->mMutex);
434      mCore->waitWhileAllocatingLocked();
435  
436      if (mCore->mIsAbandoned) {
437          BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
438          return NO_INIT;
439      }
440  
441      // Find the oldest valid slot
442      int found = BufferQueueCore::INVALID_BUFFER_SLOT;
443      for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
444          if (mSlots[s].mBufferState == BufferSlot::FREE &&
445                  mSlots[s].mGraphicBuffer != NULL) {
446              if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
447                      mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
448                  found = s;
449              }
450          }
451      }
452  
453      if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
454          return NO_MEMORY;
455      }
456  
457      BQ_LOGV("detachNextBuffer detached slot %d", found);
458  
459      *outBuffer = mSlots[found].mGraphicBuffer;
460      *outFence = mSlots[found].mFence;
461      mCore->freeBufferLocked(found);
462  
463      return NO_ERROR;
464  }
465  
attachBuffer(int * outSlot,const sp<android::GraphicBuffer> & buffer)466  status_t BufferQueueProducer::attachBuffer(int* outSlot,
467          const sp<android::GraphicBuffer>& buffer) {
468      ATRACE_CALL();
469  
470      if (outSlot == NULL) {
471          BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
472          return BAD_VALUE;
473      } else if (buffer == NULL) {
474          BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
475          return BAD_VALUE;
476      }
477  
478      Mutex::Autolock lock(mCore->mMutex);
479      mCore->waitWhileAllocatingLocked();
480  
481      status_t returnFlags = NO_ERROR;
482      int found;
483      // TODO: Should we provide an async flag to attachBuffer? It seems
484      // unlikely that buffers which we are attaching to a BufferQueue will
485      // be asynchronous (droppable), but it may not be impossible.
486      status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false,
487              &found, &returnFlags);
488      if (status != NO_ERROR) {
489          return status;
490      }
491  
492      // This should not happen
493      if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
494          BQ_LOGE("attachBuffer(P): no available buffer slots");
495          return -EBUSY;
496      }
497  
498      *outSlot = found;
499      ATRACE_BUFFER_INDEX(*outSlot);
500      BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x",
501              *outSlot, returnFlags);
502  
503      mSlots[*outSlot].mGraphicBuffer = buffer;
504      mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED;
505      mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
506      mSlots[*outSlot].mFence = Fence::NO_FENCE;
507      mSlots[*outSlot].mRequestBufferCalled = true;
508  
509      return returnFlags;
510  }
511  
queueBuffer(int slot,const QueueBufferInput & input,QueueBufferOutput * output)512  status_t BufferQueueProducer::queueBuffer(int slot,
513          const QueueBufferInput &input, QueueBufferOutput *output) {
514      ATRACE_CALL();
515      ATRACE_BUFFER_INDEX(slot);
516  
517      int64_t timestamp;
518      bool isAutoTimestamp;
519      Rect crop;
520      int scalingMode;
521      uint32_t transform;
522      uint32_t stickyTransform;
523      bool async;
524      sp<Fence> fence;
525      input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
526              &async, &fence, &stickyTransform);
527  
528      if (fence == NULL) {
529          BQ_LOGE("queueBuffer: fence is NULL");
530          return BAD_VALUE;
531      }
532  
533      switch (scalingMode) {
534          case NATIVE_WINDOW_SCALING_MODE_FREEZE:
535          case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
536          case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
537          case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
538              break;
539          default:
540              BQ_LOGE("queueBuffer: unknown scaling mode %d", scalingMode);
541              return BAD_VALUE;
542      }
543  
544      sp<IConsumerListener> frameAvailableListener;
545      sp<IConsumerListener> frameReplacedListener;
546      int callbackTicket = 0;
547      BufferItem item;
548      { // Autolock scope
549          Mutex::Autolock lock(mCore->mMutex);
550  
551          if (mCore->mIsAbandoned) {
552              BQ_LOGE("queueBuffer: BufferQueue has been abandoned");
553              return NO_INIT;
554          }
555  
556          const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
557          if (async && mCore->mOverrideMaxBufferCount) {
558              // FIXME: Some drivers are manually setting the buffer count
559              // (which they shouldn't), so we do this extra test here to
560              // handle that case. This is TEMPORARY until we get this fixed.
561              if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
562                  BQ_LOGE("queueBuffer: async mode is invalid with "
563                          "buffer count override");
564                  return BAD_VALUE;
565              }
566          }
567  
568          if (slot < 0 || slot >= maxBufferCount) {
569              BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
570                      slot, maxBufferCount);
571              return BAD_VALUE;
572          } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
573              BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
574                      "(state = %d)", slot, mSlots[slot].mBufferState);
575              return BAD_VALUE;
576          } else if (!mSlots[slot].mRequestBufferCalled) {
577              BQ_LOGE("queueBuffer: slot %d was queued without requesting "
578                      "a buffer", slot);
579              return BAD_VALUE;
580          }
581  
582          BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64
583                  " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
584                  slot, mCore->mFrameCounter + 1, timestamp,
585                  crop.left, crop.top, crop.right, crop.bottom,
586                  transform, BufferItem::scalingModeName(scalingMode));
587  
588          const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
589          Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
590          Rect croppedRect;
591          crop.intersect(bufferRect, &croppedRect);
592          if (croppedRect != crop) {
593              BQ_LOGE("queueBuffer: crop rect is not contained within the "
594                      "buffer in slot %d", slot);
595              return BAD_VALUE;
596          }
597  
598          mSlots[slot].mFence = fence;
599          mSlots[slot].mBufferState = BufferSlot::QUEUED;
600          ++mCore->mFrameCounter;
601          mSlots[slot].mFrameNumber = mCore->mFrameCounter;
602  
603          item.mAcquireCalled = mSlots[slot].mAcquireCalled;
604          item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
605          item.mCrop = crop;
606          item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
607          item.mTransformToDisplayInverse =
608                  bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
609          item.mScalingMode = scalingMode;
610          item.mTimestamp = timestamp;
611          item.mIsAutoTimestamp = isAutoTimestamp;
612          item.mFrameNumber = mCore->mFrameCounter;
613          item.mSlot = slot;
614          item.mFence = fence;
615          item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
616  
617          mStickyTransform = stickyTransform;
618  
619          if (mCore->mQueue.empty()) {
620              // When the queue is empty, we can ignore mDequeueBufferCannotBlock
621              // and simply queue this buffer
622              mCore->mQueue.push_back(item);
623              frameAvailableListener = mCore->mConsumerListener;
624          } else {
625              // When the queue is not empty, we need to look at the front buffer
626              // state to see if we need to replace it
627              BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
628              if (front->mIsDroppable) {
629                  // If the front queued buffer is still being tracked, we first
630                  // mark it as freed
631                  if (mCore->stillTracking(front)) {
632                      mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
633                      // Reset the frame number of the freed buffer so that it is
634                      // the first in line to be dequeued again
635                      mSlots[front->mSlot].mFrameNumber = 0;
636                  }
637                  // Overwrite the droppable buffer with the incoming one
638                  *front = item;
639                  frameReplacedListener = mCore->mConsumerListener;
640              } else {
641                  mCore->mQueue.push_back(item);
642                  frameAvailableListener = mCore->mConsumerListener;
643              }
644          }
645  
646          mCore->mBufferHasBeenQueued = true;
647          mCore->mDequeueCondition.broadcast();
648  
649          output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
650                  mCore->mTransformHint, mCore->mQueue.size());
651  
652          ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
653  
654          // Take a ticket for the callback functions
655          callbackTicket = mNextCallbackTicket++;
656      } // Autolock scope
657  
658      // Wait without lock held
659      if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
660          // Waiting here allows for two full buffers to be queued but not a
661          // third. In the event that frames take varying time, this makes a
662          // small trade-off in favor of latency rather than throughput.
663          mLastQueueBufferFence->waitForever("Throttling EGL Production");
664          mLastQueueBufferFence = fence;
665      }
666  
667      // Don't send the GraphicBuffer through the callback, and don't send
668      // the slot number, since the consumer shouldn't need it
669      item.mGraphicBuffer.clear();
670      item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
671  
672      // Call back without the main BufferQueue lock held, but with the callback
673      // lock held so we can ensure that callbacks occur in order
674      {
675          Mutex::Autolock lock(mCallbackMutex);
676          while (callbackTicket != mCurrentCallbackTicket) {
677              mCallbackCondition.wait(mCallbackMutex);
678          }
679  
680          if (frameAvailableListener != NULL) {
681              frameAvailableListener->onFrameAvailable(item);
682          } else if (frameReplacedListener != NULL) {
683              frameReplacedListener->onFrameReplaced(item);
684          }
685  
686          ++mCurrentCallbackTicket;
687          mCallbackCondition.broadcast();
688      }
689  
690      return NO_ERROR;
691  }
692  
cancelBuffer(int slot,const sp<Fence> & fence)693  void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
694      ATRACE_CALL();
695      BQ_LOGV("cancelBuffer: slot %d", slot);
696      Mutex::Autolock lock(mCore->mMutex);
697  
698      if (mCore->mIsAbandoned) {
699          BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
700          return;
701      }
702  
703      if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
704          BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
705                  slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
706          return;
707      } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
708          BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
709                  "(state = %d)", slot, mSlots[slot].mBufferState);
710          return;
711      } else if (fence == NULL) {
712          BQ_LOGE("cancelBuffer: fence is NULL");
713          return;
714      }
715  
716      mSlots[slot].mBufferState = BufferSlot::FREE;
717      mSlots[slot].mFrameNumber = 0;
718      mSlots[slot].mFence = fence;
719      mCore->mDequeueCondition.broadcast();
720  }
721  
query(int what,int * outValue)722  int BufferQueueProducer::query(int what, int *outValue) {
723      ATRACE_CALL();
724      Mutex::Autolock lock(mCore->mMutex);
725  
726      if (outValue == NULL) {
727          BQ_LOGE("query: outValue was NULL");
728          return BAD_VALUE;
729      }
730  
731      if (mCore->mIsAbandoned) {
732          BQ_LOGE("query: BufferQueue has been abandoned");
733          return NO_INIT;
734      }
735  
736      int value;
737      switch (what) {
738          case NATIVE_WINDOW_WIDTH:
739              value = mCore->mDefaultWidth;
740              break;
741          case NATIVE_WINDOW_HEIGHT:
742              value = mCore->mDefaultHeight;
743              break;
744          case NATIVE_WINDOW_FORMAT:
745              value = mCore->mDefaultBufferFormat;
746              break;
747          case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
748              value = mCore->getMinUndequeuedBufferCountLocked(false);
749              break;
750          case NATIVE_WINDOW_STICKY_TRANSFORM:
751              value = static_cast<int>(mStickyTransform);
752              break;
753          case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
754              value = (mCore->mQueue.size() > 1);
755              break;
756          case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
757              value = mCore->mConsumerUsageBits;
758              break;
759          default:
760              return BAD_VALUE;
761      }
762  
763      BQ_LOGV("query: %d? %d", what, value);
764      *outValue = value;
765      return NO_ERROR;
766  }
767  
connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)768  status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
769          int api, bool producerControlledByApp, QueueBufferOutput *output) {
770      ATRACE_CALL();
771      Mutex::Autolock lock(mCore->mMutex);
772      mConsumerName = mCore->mConsumerName;
773      BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
774              producerControlledByApp ? "true" : "false");
775  
776      if (mCore->mIsAbandoned) {
777          BQ_LOGE("connect(P): BufferQueue has been abandoned");
778          return NO_INIT;
779      }
780  
781      if (mCore->mConsumerListener == NULL) {
782          BQ_LOGE("connect(P): BufferQueue has no consumer");
783          return NO_INIT;
784      }
785  
786      if (output == NULL) {
787          BQ_LOGE("connect(P): output was NULL");
788          return BAD_VALUE;
789      }
790  
791      if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
792          BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
793                  mCore->mConnectedApi, api);
794          return BAD_VALUE;
795      }
796  
797      int status = NO_ERROR;
798      switch (api) {
799          case NATIVE_WINDOW_API_EGL:
800          case NATIVE_WINDOW_API_CPU:
801          case NATIVE_WINDOW_API_MEDIA:
802          case NATIVE_WINDOW_API_CAMERA:
803              mCore->mConnectedApi = api;
804              output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
805                      mCore->mTransformHint, mCore->mQueue.size());
806  
807              // Set up a death notification so that we can disconnect
808              // automatically if the remote producer dies
809              if (listener != NULL &&
810                      listener->asBinder()->remoteBinder() != NULL) {
811                  status = listener->asBinder()->linkToDeath(
812                          static_cast<IBinder::DeathRecipient*>(this));
813                  if (status != NO_ERROR) {
814                      BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
815                              strerror(-status), status);
816                  }
817              }
818              mCore->mConnectedProducerListener = listener;
819              break;
820          default:
821              BQ_LOGE("connect(P): unknown API %d", api);
822              status = BAD_VALUE;
823              break;
824      }
825  
826      mCore->mBufferHasBeenQueued = false;
827      mCore->mDequeueBufferCannotBlock =
828              mCore->mConsumerControlledByApp && producerControlledByApp;
829  
830      return status;
831  }
832  
disconnect(int api)833  status_t BufferQueueProducer::disconnect(int api) {
834      ATRACE_CALL();
835      BQ_LOGV("disconnect(P): api %d", api);
836  
837      int status = NO_ERROR;
838      sp<IConsumerListener> listener;
839      { // Autolock scope
840          Mutex::Autolock lock(mCore->mMutex);
841          mCore->waitWhileAllocatingLocked();
842  
843          if (mCore->mIsAbandoned) {
844              // It's not really an error to disconnect after the surface has
845              // been abandoned; it should just be a no-op.
846              return NO_ERROR;
847          }
848  
849          switch (api) {
850              case NATIVE_WINDOW_API_EGL:
851              case NATIVE_WINDOW_API_CPU:
852              case NATIVE_WINDOW_API_MEDIA:
853              case NATIVE_WINDOW_API_CAMERA:
854                  if (mCore->mConnectedApi == api) {
855                      mCore->freeAllBuffersLocked();
856  
857                      // Remove our death notification callback if we have one
858                      if (mCore->mConnectedProducerListener != NULL) {
859                          sp<IBinder> token =
860                                  mCore->mConnectedProducerListener->asBinder();
861                          // This can fail if we're here because of the death
862                          // notification, but we just ignore it
863                          token->unlinkToDeath(
864                                  static_cast<IBinder::DeathRecipient*>(this));
865                      }
866                      mCore->mConnectedProducerListener = NULL;
867                      mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
868                      mCore->mSidebandStream.clear();
869                      mCore->mDequeueCondition.broadcast();
870                      listener = mCore->mConsumerListener;
871                  } else {
872                      BQ_LOGE("disconnect(P): connected to another API "
873                              "(cur=%d req=%d)", mCore->mConnectedApi, api);
874                      status = BAD_VALUE;
875                  }
876                  break;
877              default:
878                  BQ_LOGE("disconnect(P): unknown API %d", api);
879                  status = BAD_VALUE;
880                  break;
881          }
882      } // Autolock scope
883  
884      // Call back without lock held
885      if (listener != NULL) {
886          listener->onBuffersReleased();
887      }
888  
889      return status;
890  }
891  
setSidebandStream(const sp<NativeHandle> & stream)892  status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
893      sp<IConsumerListener> listener;
894      { // Autolock scope
895          Mutex::Autolock _l(mCore->mMutex);
896          mCore->mSidebandStream = stream;
897          listener = mCore->mConsumerListener;
898      } // Autolock scope
899  
900      if (listener != NULL) {
901          listener->onSidebandStreamChanged();
902      }
903      return NO_ERROR;
904  }
905  
allocateBuffers(bool async,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)906  void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
907          uint32_t height, uint32_t format, uint32_t usage) {
908      ATRACE_CALL();
909      while (true) {
910          Vector<int> freeSlots;
911          size_t newBufferCount = 0;
912          uint32_t allocWidth = 0;
913          uint32_t allocHeight = 0;
914          uint32_t allocFormat = 0;
915          uint32_t allocUsage = 0;
916          { // Autolock scope
917              Mutex::Autolock lock(mCore->mMutex);
918              mCore->waitWhileAllocatingLocked();
919  
920              int currentBufferCount = 0;
921              for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
922                  if (mSlots[slot].mGraphicBuffer != NULL) {
923                      ++currentBufferCount;
924                  } else {
925                      if (mSlots[slot].mBufferState != BufferSlot::FREE) {
926                          BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
927                                  slot);
928                          continue;
929                      }
930  
931                      freeSlots.push_back(slot);
932                  }
933              }
934  
935              int maxBufferCount = mCore->getMaxBufferCountLocked(async);
936              BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
937                      currentBufferCount, maxBufferCount);
938              if (maxBufferCount <= currentBufferCount)
939                  return;
940              newBufferCount = maxBufferCount - currentBufferCount;
941              if (freeSlots.size() < newBufferCount) {
942                  BQ_LOGE("allocateBuffers: ran out of free slots");
943                  return;
944              }
945              allocWidth = width > 0 ? width : mCore->mDefaultWidth;
946              allocHeight = height > 0 ? height : mCore->mDefaultHeight;
947              allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
948              allocUsage = usage | mCore->mConsumerUsageBits;
949  
950              mCore->mIsAllocating = true;
951          } // Autolock scope
952  
953          Vector<sp<GraphicBuffer> > buffers;
954          for (size_t i = 0; i <  newBufferCount; ++i) {
955              status_t result = NO_ERROR;
956              sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
957                      allocWidth, allocHeight, allocFormat, allocUsage, &result));
958              if (result != NO_ERROR) {
959                  BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
960                          " %u, usage %u)", width, height, format, usage);
961                  Mutex::Autolock lock(mCore->mMutex);
962                  mCore->mIsAllocating = false;
963                  mCore->mIsAllocatingCondition.broadcast();
964                  return;
965              }
966              buffers.push_back(graphicBuffer);
967          }
968  
969          { // Autolock scope
970              Mutex::Autolock lock(mCore->mMutex);
971              uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
972              uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
973              uint32_t checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
974              uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
975              if (checkWidth != allocWidth || checkHeight != allocHeight ||
976                  checkFormat != allocFormat || checkUsage != allocUsage) {
977                  // Something changed while we released the lock. Retry.
978                  BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
979                  mCore->mIsAllocating = false;
980                  mCore->mIsAllocatingCondition.broadcast();
981                  continue;
982              }
983  
984              for (size_t i = 0; i < newBufferCount; ++i) {
985                  int slot = freeSlots[i];
986                  if (mSlots[slot].mBufferState != BufferSlot::FREE) {
987                      // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we
988                      // allocated.
989                      BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
990                              "Dropping allocated buffer.", slot);
991                      continue;
992                  }
993                  mCore->freeBufferLocked(slot); // Clean up the slot first
994                  mSlots[slot].mGraphicBuffer = buffers[i];
995                  mSlots[slot].mFrameNumber = 0;
996                  mSlots[slot].mFence = Fence::NO_FENCE;
997                  BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
998              }
999  
1000              mCore->mIsAllocating = false;
1001              mCore->mIsAllocatingCondition.broadcast();
1002          } // Autolock scope
1003      }
1004  }
1005  
binderDied(const wp<android::IBinder> &)1006  void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
1007      // If we're here, it means that a producer we were connected to died.
1008      // We're guaranteed that we are still connected to it because we remove
1009      // this callback upon disconnect. It's therefore safe to read mConnectedApi
1010      // without synchronization here.
1011      int api = mCore->mConnectedApi;
1012      disconnect(api);
1013  }
1014  
1015  } // namespace android
1016