widget/gonk/nativewindow/GonkBufferQueueKK.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial