widget/gonk/nativewindow/GonkBufferQueueJB.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
-rwxr-xr-x

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>
    27 #include "mozilla/layers/GrallocTextureClient.h"
    28 #include "mozilla/layers/ImageBridgeChild.h"
    30 #include "GonkBufferQueueJB.h"
    32 // Macros for including the GonkBufferQueue name in log messages
    33 #define ST_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
    34 #define ST_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
    35 #define ST_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
    36 #define ST_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
    37 #define ST_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
    39 #define ATRACE_BUFFER_INDEX(index)
    41 using namespace mozilla;
    42 using namespace mozilla::gfx;
    43 using namespace mozilla::layers;
    45 namespace android {
    47 // Get an ID that's unique within this process.
    48 static int32_t createProcessUniqueId() {
    49     static volatile int32_t globalCounter = 0;
    50     return android_atomic_inc(&globalCounter);
    51 }
    53 static const char* scalingModeName(int scalingMode) {
    54     switch (scalingMode) {
    55         case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
    56         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
    57         case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
    58         default: return "Unknown";
    59     }
    60 }
    62 class nsProxyReleaseTask : public Task
    63 {
    64 public:
    65     nsProxyReleaseTask(TextureClient* aClient)
    66         : mTextureClient(aClient) {
    67     }
    69     virtual void Run() MOZ_OVERRIDE
    70     {
    71         mTextureClient = nullptr;
    72     }
    74 private:
    75     mozilla::RefPtr<TextureClient> mTextureClient;
    76 };
    78 GonkBufferQueue::GonkBufferQueue(bool allowSynchronousMode,
    79         const sp<IGraphicBufferAlloc>& allocator) :
    80     mDefaultWidth(1),
    81     mDefaultHeight(1),
    82     mMaxAcquiredBufferCount(1),
    83     mDefaultMaxBufferCount(2),
    84     mOverrideMaxBufferCount(0),
    85     mSynchronousMode(true), // GonkBufferQueue always works in sync mode.
    86     mAllowSynchronousMode(allowSynchronousMode),
    87     mConnectedApi(NO_CONNECTED_API),
    88     mAbandoned(false),
    89     mFrameCounter(0),
    90     mBufferHasBeenQueued(false),
    91     mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
    92     mConsumerUsageBits(0),
    93     mTransformHint(0)
    94 {
    95     // Choose a name using the PID and a process-unique ID.
    96     mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
    98     ST_LOGV("GonkBufferQueue");
    99 }
   101 GonkBufferQueue::~GonkBufferQueue() {
   102     ST_LOGV("~GonkBufferQueue");
   103 }
   105 status_t GonkBufferQueue::setDefaultMaxBufferCountLocked(int count) {
   106     if (count < 2 || count > NUM_BUFFER_SLOTS)
   107         return BAD_VALUE;
   109     mDefaultMaxBufferCount = count;
   110     mDequeueCondition.broadcast();
   112     return NO_ERROR;
   113 }
   115 bool GonkBufferQueue::isSynchronousMode() const {
   116     Mutex::Autolock lock(mMutex);
   117     return mSynchronousMode;
   118 }
   120 void GonkBufferQueue::setConsumerName(const String8& name) {
   121     Mutex::Autolock lock(mMutex);
   122     mConsumerName = name;
   123 }
   125 status_t GonkBufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
   126     Mutex::Autolock lock(mMutex);
   127     mDefaultBufferFormat = defaultFormat;
   128     return NO_ERROR;
   129 }
   131 status_t GonkBufferQueue::setConsumerUsageBits(uint32_t usage) {
   132     Mutex::Autolock lock(mMutex);
   133     mConsumerUsageBits = usage;
   134     return NO_ERROR;
   135 }
   137 status_t GonkBufferQueue::setTransformHint(uint32_t hint) {
   138     ST_LOGV("setTransformHint: %02x", hint);
   139     Mutex::Autolock lock(mMutex);
   140     mTransformHint = hint;
   141     return NO_ERROR;
   142 }
   144 TemporaryRef<TextureClient>
   145 GonkBufferQueue::getTextureClientFromBuffer(ANativeWindowBuffer* buffer)
   146 {
   147     Mutex::Autolock _l(mMutex);
   148     if (buffer == NULL) {
   149         ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer");
   150         return nullptr;
   151     }
   153     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
   154         if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
   155             return mSlots[i].mTextureClient;
   156         }
   157     }
   158     ST_LOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
   159     return nullptr;
   160 }
   162 int GonkBufferQueue::getSlotFromTextureClientLocked(
   163         TextureClient* client) const
   164 {
   165     if (client == NULL) {
   166         ST_LOGE("getSlotFromBufferLocked: encountered NULL buffer");
   167         return BAD_VALUE;
   168     }
   170     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
   171         if (mSlots[i].mTextureClient == client) {
   172             return i;
   173         }
   174     }
   175     ST_LOGE("getSlotFromBufferLocked: unknown TextureClient: %p", client);
   176     return BAD_VALUE;
   177 }
   180 status_t GonkBufferQueue::setBufferCount(int bufferCount) {
   181     ST_LOGV("setBufferCount: count=%d", bufferCount);
   183     sp<ConsumerListener> listener;
   184     {
   185         Mutex::Autolock lock(mMutex);
   187         if (mAbandoned) {
   188             ST_LOGE("setBufferCount: GonkBufferQueue has been abandoned!");
   189             return NO_INIT;
   190         }
   191         if (bufferCount > NUM_BUFFER_SLOTS) {
   192             ST_LOGE("setBufferCount: bufferCount too large (max %d)",
   193                     NUM_BUFFER_SLOTS);
   194             return BAD_VALUE;
   195         }
   197         // Error out if the user has dequeued buffers
   198         int maxBufferCount = getMaxBufferCountLocked();
   199         for (int i=0 ; i<maxBufferCount; i++) {
   200             if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
   201                 ST_LOGE("setBufferCount: client owns some buffers");
   202                 return -EINVAL;
   203             }
   204         }
   206         const int minBufferSlots = getMinMaxBufferCountLocked();
   207         if (bufferCount == 0) {
   208             mOverrideMaxBufferCount = 0;
   209             mDequeueCondition.broadcast();
   210             return NO_ERROR;
   211         }
   213         if (bufferCount < minBufferSlots) {
   214             ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
   215                     "minimum (%d)", bufferCount, minBufferSlots);
   216             return BAD_VALUE;
   217         }
   219         // here we're guaranteed that the client doesn't have dequeued buffers
   220         // and will release all of its buffer references.
   221         //
   222         // XXX: Should this use drainQueueAndFreeBuffersLocked instead?
   223         freeAllBuffersLocked();
   224         mOverrideMaxBufferCount = bufferCount;
   225         mBufferHasBeenQueued = false;
   226         mDequeueCondition.broadcast();
   227         listener = mConsumerListener;
   228     } // scope for lock
   230     if (listener != NULL) {
   231         listener->onBuffersReleased();
   232     }
   234     return NO_ERROR;
   235 }
   237 int GonkBufferQueue::query(int what, int* outValue)
   238 {
   239     Mutex::Autolock lock(mMutex);
   241     if (mAbandoned) {
   242         ST_LOGE("query: GonkBufferQueue has been abandoned!");
   243         return NO_INIT;
   244     }
   246     int value;
   247     switch (what) {
   248     case NATIVE_WINDOW_WIDTH:
   249         value = mDefaultWidth;
   250         break;
   251     case NATIVE_WINDOW_HEIGHT:
   252         value = mDefaultHeight;
   253         break;
   254     case NATIVE_WINDOW_FORMAT:
   255         value = mDefaultBufferFormat;
   256         break;
   257     case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
   258         value = getMinUndequeuedBufferCountLocked();
   259         break;
   260     case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
   261         value = (mQueue.size() >= 2);
   262         break;
   263     default:
   264         return BAD_VALUE;
   265     }
   266     outValue[0] = value;
   267     return NO_ERROR;
   268 }
   270 status_t GonkBufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
   271     ST_LOGV("requestBuffer: slot=%d", slot);
   272     Mutex::Autolock lock(mMutex);
   273     if (mAbandoned) {
   274         ST_LOGE("requestBuffer: GonkBufferQueue has been abandoned!");
   275         return NO_INIT;
   276     }
   277     int maxBufferCount = getMaxBufferCountLocked();
   278     if (slot < 0 || maxBufferCount <= slot) {
   279         ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
   280                 maxBufferCount, slot);
   281         return BAD_VALUE;
   282     } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
   283         // XXX: I vaguely recall there was some reason this can be valid, but
   284         // for the life of me I can't recall under what circumstances that's
   285         // the case.
   286         ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
   287                 slot, mSlots[slot].mBufferState);
   288         return BAD_VALUE;
   289     }
   290     mSlots[slot].mRequestBufferCalled = true;
   291     *buf = mSlots[slot].mGraphicBuffer;
   292     return NO_ERROR;
   293 }
   295 status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
   296         uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
   297     ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
   299     if ((w && !h) || (!w && h)) {
   300         ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
   301         return BAD_VALUE;
   302     }
   304     status_t returnFlags(OK);
   305     int buf = INVALID_BUFFER_SLOT;
   307     { // Scope for the lock
   308         Mutex::Autolock lock(mMutex);
   310         if (format == 0) {
   311             format = mDefaultBufferFormat;
   312         }
   313         // turn on usage bits the consumer requested
   314         usage |= mConsumerUsageBits;
   316         int found = -1;
   317         int dequeuedCount = 0;
   318         bool tryAgain = true;
   319         while (tryAgain) {
   320             if (mAbandoned) {
   321                 ST_LOGE("dequeueBuffer: GonkBufferQueue has been abandoned!");
   322                 return NO_INIT;
   323             }
   325             const int maxBufferCount = getMaxBufferCountLocked();
   327             // Free up any buffers that are in slots beyond the max buffer
   328             // count.
   329             //for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
   330             //    assert(mSlots[i].mBufferState == BufferSlot::FREE);
   331             //    if (mSlots[i].mGraphicBuffer != NULL) {
   332             //        freeBufferLocked(i);
   333             //        returnFlags |= IGraphicBufferProducer::RELEASE_ALL_BUFFERS;
   334             //    }
   335             //}
   337             // look for a free buffer to give to the client
   338             found = INVALID_BUFFER_SLOT;
   339             dequeuedCount = 0;
   340             for (int i = 0; i < maxBufferCount; i++) {
   341                 const int state = mSlots[i].mBufferState;
   342                 if (state == BufferSlot::DEQUEUED) {
   343                     dequeuedCount++;
   344                 }
   346                 if (state == BufferSlot::FREE) {
   347                     /* We return the oldest of the free buffers to avoid
   348                      * stalling the producer if possible.  This is because
   349                      * the consumer may still have pending reads of the
   350                      * buffers in flight.
   351                      */
   352                     if ((found < 0) ||
   353                             mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
   354                         found = i;
   355                     }
   356                 }
   357             }
   359             // clients are not allowed to dequeue more than one buffer
   360             // if they didn't set a buffer count.
   361             if (!mOverrideMaxBufferCount && dequeuedCount) {
   362                 ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
   363                         "setting the buffer count");
   364                 return -EINVAL;
   365             }
   367             // See whether a buffer has been queued since the last
   368             // setBufferCount so we know whether to perform the min undequeued
   369             // buffers check below.
   370             if (mBufferHasBeenQueued) {
   371                 // make sure the client is not trying to dequeue more buffers
   372                 // than allowed.
   373                 const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
   374                 const int minUndequeuedCount = getMinUndequeuedBufferCountLocked();
   375                 if (newUndequeuedCount < minUndequeuedCount) {
   376                     ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
   377                             "exceeded (dequeued=%d undequeudCount=%d)",
   378                             minUndequeuedCount, dequeuedCount,
   379                             newUndequeuedCount);
   380                     return -EBUSY;
   381                 }
   382             }
   384             // If no buffer is found, wait for a buffer to be released or for
   385             // the max buffer count to change.
   386             tryAgain = found == INVALID_BUFFER_SLOT;
   387             if (tryAgain) {
   388                 mDequeueCondition.wait(mMutex);
   389             }
   390         }
   393         if (found == INVALID_BUFFER_SLOT) {
   394             // This should not happen.
   395             ST_LOGE("dequeueBuffer: no available buffer slots");
   396             return -EBUSY;
   397         }
   399         buf = found;
   400         *outBuf = found;
   402         const bool useDefaultSize = !w && !h;
   403         if (useDefaultSize) {
   404             // use the default size
   405             w = mDefaultWidth;
   406             h = mDefaultHeight;
   407         }
   409         mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
   411         const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
   412         if ((buffer == NULL) ||
   413             (uint32_t(buffer->width)  != w) ||
   414             (uint32_t(buffer->height) != h) ||
   415             (uint32_t(buffer->format) != format) ||
   416             ((uint32_t(buffer->usage) & usage) != usage))
   417         {
   418             mSlots[buf].mAcquireCalled = false;
   419             mSlots[buf].mGraphicBuffer = NULL;
   420             mSlots[buf].mRequestBufferCalled = false;
   421             mSlots[buf].mFence = Fence::NO_FENCE;
   422             if (mSlots[buf].mTextureClient) {
   423               mSlots[buf].mTextureClient->ClearRecycleCallback();
   424               // release TextureClient in ImageBridge thread
   425               nsProxyReleaseTask* task = new nsProxyReleaseTask(mSlots[buf].mTextureClient);
   426               mSlots[buf].mTextureClient = NULL;
   427               ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task);
   428             }
   429             returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
   430         }
   432         *outFence = mSlots[buf].mFence;
   433         mSlots[buf].mFence = Fence::NO_FENCE;
   434     }  // end lock scope
   436     sp<GraphicBuffer> graphicBuffer;
   437     if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
   438         RefPtr<GrallocTextureClientOGL> textureClient =
   439             new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
   440                                         gfx::SurfaceFormat::UNKNOWN,
   441                                         gfx::BackendType::NONE,
   442                                         TEXTURE_DEALLOCATE_CLIENT);
   443         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
   444         bool result = textureClient->AllocateGralloc(IntSize(w, h), format, usage);
   445         sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
   446         if (!result || !graphicBuffer.get()) {
   447             ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
   448             return -ENOMEM;
   449         }
   451         { // Scope for the lock
   452             Mutex::Autolock lock(mMutex);
   454             if (mAbandoned) {
   455                 ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
   456                 return NO_INIT;
   457             }
   459             mSlots[buf].mGraphicBuffer = graphicBuffer;
   460             mSlots[buf].mTextureClient = textureClient;
   461             ST_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
   462                     mSlots[buf].mGraphicBuffer->handle);
   463             //mSlots[*outBuf].mGraphicBuffer = graphicBuffer;
   464         }
   465     }
   467     ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
   468             mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
   470     return returnFlags;
   471 }
   473 status_t GonkBufferQueue::setSynchronousMode(bool enabled) {
   474     return NO_ERROR;
   475 }
   477 status_t GonkBufferQueue::queueBuffer(int buf,
   478         const QueueBufferInput& input, QueueBufferOutput* output) {
   480     Rect crop;
   481     uint32_t transform;
   482     int scalingMode;
   483     int64_t timestamp;
   484     sp<Fence> fence;
   486     input.deflate(&timestamp, &crop, &scalingMode, &transform, &fence);
   488 #if ANDROID_VERSION >= 18
   489     if (fence == NULL) {
   490         ST_LOGE("queueBuffer: fence is NULL");
   491         return BAD_VALUE;
   492     }
   493 #endif
   495     ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
   496             "scale=%s",
   497             buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
   498             transform, scalingModeName(scalingMode));
   500     sp<ConsumerListener> listener;
   502     { // scope for the lock
   503         Mutex::Autolock lock(mMutex);
   504         if (mAbandoned) {
   505             ST_LOGE("queueBuffer: GonkBufferQueue has been abandoned!");
   506             return NO_INIT;
   507         }
   508         int maxBufferCount = getMaxBufferCountLocked();
   509         if (buf < 0 || buf >= maxBufferCount) {
   510             ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
   511                     maxBufferCount, buf);
   512             return -EINVAL;
   513         } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
   514             ST_LOGE("queueBuffer: slot %d is not owned by the client "
   515                     "(state=%d)", buf, mSlots[buf].mBufferState);
   516             return -EINVAL;
   517         } else if (!mSlots[buf].mRequestBufferCalled) {
   518             ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
   519                     "buffer", buf);
   520             return -EINVAL;
   521         }
   523         const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
   524         Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
   525         Rect croppedCrop;
   526         crop.intersect(bufferRect, &croppedCrop);
   527         if (croppedCrop != crop) {
   528             ST_LOGE("queueBuffer: crop rect is not contained within the "
   529                     "buffer in slot %d", buf);
   530             return -EINVAL;
   531         }
   533         if (mSynchronousMode) {
   534             // In synchronous mode we queue all buffers in a FIFO.
   535             mQueue.push_back(buf);
   537             // Synchronous mode always signals that an additional frame should
   538             // be consumed.
   539             listener = mConsumerListener;
   540         } else {
   541             // In asynchronous mode we only keep the most recent buffer.
   542             if (mQueue.empty()) {
   543                 mQueue.push_back(buf);
   545                 // Asynchronous mode only signals that a frame should be
   546                 // consumed if no previous frame was pending. If a frame were
   547                 // pending then the consumer would have already been notified.
   548                 listener = mConsumerListener;
   549             } else {
   550                 Fifo::iterator front(mQueue.begin());
   551                 // buffer currently queued is freed
   552                 mSlots[*front].mBufferState = BufferSlot::FREE;
   553                 // and we record the new buffer index in the queued list
   554                 *front = buf;
   555             }
   556         }
   558         mSlots[buf].mTimestamp = timestamp;
   559         mSlots[buf].mCrop = crop;
   560         mSlots[buf].mTransform = transform;
   561         mSlots[buf].mFence = fence;
   563         switch (scalingMode) {
   564             case NATIVE_WINDOW_SCALING_MODE_FREEZE:
   565             case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
   566             case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
   567                 break;
   568             default:
   569                 ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode);
   570                 scalingMode = mSlots[buf].mScalingMode;
   571                 break;
   572         }
   574         mSlots[buf].mBufferState = BufferSlot::QUEUED;
   575         mSlots[buf].mScalingMode = scalingMode;
   576         mFrameCounter++;
   577         mSlots[buf].mFrameNumber = mFrameCounter;
   579         mBufferHasBeenQueued = true;
   580         mDequeueCondition.broadcast();
   582         output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
   583                 mQueue.size());
   584     } // scope for the lock
   586     // call back without lock held
   587     if (listener != 0) {
   588         listener->onFrameAvailable();
   589     }
   590     return NO_ERROR;
   591 }
   593 #if ANDROID_VERSION == 17
   594 void GonkBufferQueue::cancelBuffer(int buf, sp<Fence> fence) {
   595 #else
   596 void GonkBufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
   597 #endif
   599     ST_LOGV("cancelBuffer: slot=%d", buf);
   600     Mutex::Autolock lock(mMutex);
   602     if (mAbandoned) {
   603         ST_LOGW("cancelBuffer: GonkBufferQueue has been abandoned!");
   604         return;
   605     }
   607     int maxBufferCount = getMaxBufferCountLocked();
   608     if (buf < 0 || buf >= maxBufferCount) {
   609         ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
   610                 maxBufferCount, buf);
   611         return;
   612     } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
   613         ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
   614                 buf, mSlots[buf].mBufferState);
   615         return;
   616 #if ANDROID_VERSION >= 18
   617     } else if (fence == NULL) {
   618         ST_LOGE("cancelBuffer: fence is NULL");
   619         return;
   620 #endif
   621     }
   622     mSlots[buf].mBufferState = BufferSlot::FREE;
   623     mSlots[buf].mFrameNumber = 0;
   624     mSlots[buf].mFence = fence;
   625     mDequeueCondition.broadcast();
   626 }
   628 status_t GonkBufferQueue::connect(int api, QueueBufferOutput* output) {
   629     ST_LOGV("connect: api=%d", api);
   630     Mutex::Autolock lock(mMutex);
   632     if (mAbandoned) {
   633         ST_LOGE("connect: GonkBufferQueue has been abandoned!");
   634         return NO_INIT;
   635     }
   637     if (mConsumerListener == NULL) {
   638         ST_LOGE("connect: GonkBufferQueue has no consumer!");
   639         return NO_INIT;
   640     }
   642     int err = NO_ERROR;
   643     switch (api) {
   644         case NATIVE_WINDOW_API_EGL:
   645         case NATIVE_WINDOW_API_CPU:
   646         case NATIVE_WINDOW_API_MEDIA:
   647         case NATIVE_WINDOW_API_CAMERA:
   648             if (mConnectedApi != NO_CONNECTED_API) {
   649                 ST_LOGE("connect: already connected (cur=%d, req=%d)",
   650                         mConnectedApi, api);
   651                 err = -EINVAL;
   652             } else {
   653                 mConnectedApi = api;
   654                 output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
   655                         mQueue.size());
   656             }
   657             break;
   658         default:
   659             err = -EINVAL;
   660             break;
   661     }
   663     mBufferHasBeenQueued = false;
   665     return err;
   666 }
   668 status_t GonkBufferQueue::disconnect(int api) {
   669     ST_LOGV("disconnect: api=%d", api);
   671     int err = NO_ERROR;
   672     sp<ConsumerListener> listener;
   674     { // Scope for the lock
   675         Mutex::Autolock lock(mMutex);
   677         if (mAbandoned) {
   678             // it is not really an error to disconnect after the surface
   679             // has been abandoned, it should just be a no-op.
   680             return NO_ERROR;
   681         }
   683         switch (api) {
   684             case NATIVE_WINDOW_API_EGL:
   685             case NATIVE_WINDOW_API_CPU:
   686             case NATIVE_WINDOW_API_MEDIA:
   687             case NATIVE_WINDOW_API_CAMERA:
   688                 if (mConnectedApi == api) {
   689                     freeAllBuffersLocked();
   690                     mConnectedApi = NO_CONNECTED_API;
   691                     mDequeueCondition.broadcast();
   692                     listener = mConsumerListener;
   693                 } else {
   694                     ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
   695                             mConnectedApi, api);
   696                     err = -EINVAL;
   697                 }
   698                 break;
   699             default:
   700                 ST_LOGE("disconnect: unknown API %d", api);
   701                 err = -EINVAL;
   702                 break;
   703         }
   704     }
   706     if (listener != NULL) {
   707         listener->onBuffersReleased();
   708     }
   710     return err;
   711 }
   713 void GonkBufferQueue::dump(String8& result) const
   714 {
   715     char buffer[1024];
   716     GonkBufferQueue::dump(result, "", buffer, 1024);
   717 }
   719 void GonkBufferQueue::dump(String8& result, const char* prefix,
   720         char* buffer, size_t SIZE) const
   721 {
   722     Mutex::Autolock _l(mMutex);
   724     String8 fifo;
   725     int fifoSize = 0;
   726     Fifo::const_iterator i(mQueue.begin());
   727     while (i != mQueue.end()) {
   728        snprintf(buffer, SIZE, "%02d ", *i++);
   729        fifoSize++;
   730        fifo.append(buffer);
   731     }
   733     int maxBufferCount = getMaxBufferCountLocked();
   735     snprintf(buffer, SIZE,
   736             "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
   737             "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
   738             prefix, maxBufferCount, mSynchronousMode, mDefaultWidth,
   739             mDefaultHeight, mDefaultBufferFormat, mTransformHint,
   740             fifoSize, fifo.string());
   741     result.append(buffer);
   744     struct {
   745         const char * operator()(int state) const {
   746             switch (state) {
   747                 case BufferSlot::DEQUEUED: return "DEQUEUED";
   748                 case BufferSlot::QUEUED: return "QUEUED";
   749                 case BufferSlot::FREE: return "FREE";
   750                 case BufferSlot::ACQUIRED: return "ACQUIRED";
   751                 default: return "Unknown";
   752             }
   753         }
   754     } stateName;
   756     for (int i=0 ; i<maxBufferCount ; i++) {
   757         const BufferSlot& slot(mSlots[i]);
   758         snprintf(buffer, SIZE,
   759                 "%s%s[%02d] "
   760                 "state=%-8s, crop=[%d,%d,%d,%d], "
   761                 "xform=0x%02x, time=%#llx, scale=%s",
   762                 prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
   763                 stateName(slot.mBufferState),
   764                 slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
   765                 slot.mCrop.bottom, slot.mTransform, slot.mTimestamp,
   766                 scalingModeName(slot.mScalingMode)
   767         );
   768         result.append(buffer);
   770         const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
   771         if (buf != NULL) {
   772             snprintf(buffer, SIZE,
   773                     ", %p [%4ux%4u:%4u,%3X]",
   774                     buf->handle, buf->width, buf->height, buf->stride,
   775                     buf->format);
   776             result.append(buffer);
   777         }
   778         result.append("\n");
   779     }
   780 }
   782 void GonkBufferQueue::freeAllBuffersLocked()
   783 {
   784     ALOGW_IF(!mQueue.isEmpty(),
   785             "freeAllBuffersLocked called but mQueue is not empty");
   786     mQueue.clear();
   787     mBufferHasBeenQueued = false;
   788     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
   789         mSlots[i].mGraphicBuffer = 0;
   790         if (mSlots[i].mTextureClient) {
   791           mSlots[i].mTextureClient->ClearRecycleCallback();
   792           // release TextureClient in ImageBridge thread
   793           nsProxyReleaseTask* task = new nsProxyReleaseTask(mSlots[i].mTextureClient);
   794           mSlots[i].mTextureClient = NULL;
   795           ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task);
   796         }
   797         if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
   798             mSlots[i].mNeedsCleanupOnRelease = true;
   799         }
   800         mSlots[i].mBufferState = BufferSlot::FREE;
   801         mSlots[i].mFrameNumber = 0;
   802         mSlots[i].mAcquireCalled = false;
   803         // destroy fence as GonkBufferQueue now takes ownership
   804         mSlots[i].mFence = Fence::NO_FENCE;
   805     }
   806 }
   808 status_t GonkBufferQueue::acquireBuffer(BufferItem *buffer) {
   809     Mutex::Autolock _l(mMutex);
   811     // Check that the consumer doesn't currently have the maximum number of
   812     // buffers acquired.  We allow the max buffer count to be exceeded by one
   813     // buffer, so that the consumer can successfully set up the newly acquired
   814     // buffer before releasing the old one.
   815     int numAcquiredBuffers = 0;
   816     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
   817         if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
   818             numAcquiredBuffers++;
   819         }
   820     }
   821     if (numAcquiredBuffers >= mMaxAcquiredBufferCount+1) {
   822         ST_LOGE("acquireBuffer: max acquired buffer count reached: %d (max=%d)",
   823                 numAcquiredBuffers, mMaxAcquiredBufferCount);
   824         return INVALID_OPERATION;
   825     }
   827     // check if queue is empty
   828     // In asynchronous mode the list is guaranteed to be one buffer
   829     // deep, while in synchronous mode we use the oldest buffer.
   830     if (!mQueue.empty()) {
   831         Fifo::iterator front(mQueue.begin());
   832         int buf = *front;
   834         // In android, when the buffer is aquired by BufferConsumer,
   835         // BufferQueue releases a reference to the buffer and
   836         // it's ownership moves to the BufferConsumer.
   837         // In b2g, GonkBufferQueue continues to have a buffer ownership.
   838         // It is necessary to free buffer via ImageBridgeChild.
   840         //if (mSlots[buf].mAcquireCalled) {
   841         //    buffer->mGraphicBuffer = NULL;
   842         //} else {
   843         //    buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
   844         //}
   845         buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
   846         buffer->mCrop = mSlots[buf].mCrop;
   847         buffer->mTransform = mSlots[buf].mTransform;
   848         buffer->mScalingMode = mSlots[buf].mScalingMode;
   849         buffer->mFrameNumber = mSlots[buf].mFrameNumber;
   850         buffer->mTimestamp = mSlots[buf].mTimestamp;
   851         buffer->mBuf = buf;
   852         buffer->mFence = mSlots[buf].mFence;
   854         mSlots[buf].mAcquireCalled = true;
   855         mSlots[buf].mNeedsCleanupOnRelease = false;
   856         mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
   857         mSlots[buf].mFence = Fence::NO_FENCE;
   859         mQueue.erase(front);
   860         mDequeueCondition.broadcast();
   861     } else {
   862         return NO_BUFFER_AVAILABLE;
   863     }
   865     return NO_ERROR;
   866 }
   868 status_t GonkBufferQueue::releaseBuffer(int buf, const sp<Fence>& fence) {
   869     Mutex::Autolock _l(mMutex);
   871 #if ANDROID_VERSION == 17
   872     if (buf == INVALID_BUFFER_SLOT) {
   873 #else
   874     if (buf == INVALID_BUFFER_SLOT || fence == NULL) {
   875 #endif
   876         return BAD_VALUE;
   877     }
   879     mSlots[buf].mFence = fence;
   881     // The buffer can now only be released if its in the acquired state
   882     if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
   883         mSlots[buf].mBufferState = BufferSlot::FREE;
   884     } else if (mSlots[buf].mNeedsCleanupOnRelease) {
   885         ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
   886         mSlots[buf].mNeedsCleanupOnRelease = false;
   887         return STALE_BUFFER_SLOT;
   888     } else {
   889         ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState);
   890         return -EINVAL;
   891     }
   893     mDequeueCondition.broadcast();
   894     return NO_ERROR;
   895 }
   897 status_t GonkBufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
   898     ST_LOGV("consumerConnect");
   899     Mutex::Autolock lock(mMutex);
   901     if (mAbandoned) {
   902         ST_LOGE("consumerConnect: GonkBufferQueue has been abandoned!");
   903         return NO_INIT;
   904     }
   905     if (consumerListener == NULL) {
   906         ST_LOGE("consumerConnect: consumerListener may not be NULL");
   907         return BAD_VALUE;
   908     }
   910     mConsumerListener = consumerListener;
   912     return NO_ERROR;
   913 }
   915 status_t GonkBufferQueue::consumerDisconnect() {
   916     ST_LOGV("consumerDisconnect");
   917     Mutex::Autolock lock(mMutex);
   919     if (mConsumerListener == NULL) {
   920         ST_LOGE("consumerDisconnect: No consumer is connected!");
   921         return -EINVAL;
   922     }
   924     mAbandoned = true;
   925     mConsumerListener = NULL;
   926     mQueue.clear();
   927     freeAllBuffersLocked();
   928     mDequeueCondition.broadcast();
   929     return NO_ERROR;
   930 }
   932 status_t GonkBufferQueue::getReleasedBuffers(uint32_t* slotMask) {
   933     ST_LOGV("getReleasedBuffers");
   934     Mutex::Autolock lock(mMutex);
   936     if (mAbandoned) {
   937         ST_LOGE("getReleasedBuffers: GonkBufferQueue has been abandoned!");
   938         return NO_INIT;
   939     }
   941     uint32_t mask = 0;
   942     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
   943         if (!mSlots[i].mAcquireCalled) {
   944             mask |= 1 << i;
   945         }
   946     }
   947     *slotMask = mask;
   949     ST_LOGV("getReleasedBuffers: returning mask %#x", mask);
   950     return NO_ERROR;
   951 }
   953 status_t GonkBufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
   954 {
   955     ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
   956     if (!w || !h) {
   957         ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
   958                 w, h);
   959         return BAD_VALUE;
   960     }
   962     Mutex::Autolock lock(mMutex);
   963     mDefaultWidth = w;
   964     mDefaultHeight = h;
   965     return NO_ERROR;
   966 }
   968 status_t GonkBufferQueue::setDefaultMaxBufferCount(int bufferCount) {
   969     Mutex::Autolock lock(mMutex);
   970     return setDefaultMaxBufferCountLocked(bufferCount);
   971 }
   973 status_t GonkBufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
   974     Mutex::Autolock lock(mMutex);
   975     if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) {
   976         ST_LOGE("setMaxAcquiredBufferCount: invalid count specified: %d",
   977                 maxAcquiredBuffers);
   978         return BAD_VALUE;
   979     }
   980     if (mConnectedApi != NO_CONNECTED_API) {
   981         return INVALID_OPERATION;
   982     }
   983     mMaxAcquiredBufferCount = maxAcquiredBuffers;
   984     return NO_ERROR;
   985 }
   987 int GonkBufferQueue::getMinMaxBufferCountLocked() const {
   988     return getMinUndequeuedBufferCountLocked() + 1;
   989 }
   991 int GonkBufferQueue::getMinUndequeuedBufferCountLocked() const {
   992     return mSynchronousMode ? mMaxAcquiredBufferCount :
   993             mMaxAcquiredBufferCount + 1;
   994 }
   996 int GonkBufferQueue::getMaxBufferCountLocked() const {
   997     int minMaxBufferCount = getMinMaxBufferCountLocked();
   999     int maxBufferCount = mDefaultMaxBufferCount;
  1000     if (maxBufferCount < minMaxBufferCount) {
  1001         maxBufferCount = minMaxBufferCount;
  1003     if (mOverrideMaxBufferCount != 0) {
  1004         assert(mOverrideMaxBufferCount >= minMaxBufferCount);
  1005         maxBufferCount = mOverrideMaxBufferCount;
  1008     // Any buffers that are dequeued by the producer or sitting in the queue
  1009     // waiting to be consumed need to have their slots preserved.  Such
  1010     // buffers will temporarily keep the max buffer count up until the slots
  1011     // no longer need to be preserved.
  1012     for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
  1013         BufferSlot::BufferState state = mSlots[i].mBufferState;
  1014         if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
  1015             maxBufferCount = i + 1;
  1019     return maxBufferCount;
  1022 GonkBufferQueue::ProxyConsumerListener::ProxyConsumerListener(
  1023         const wp<GonkBufferQueue::ConsumerListener>& consumerListener):
  1024         mConsumerListener(consumerListener) {}
  1026 GonkBufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
  1028 void GonkBufferQueue::ProxyConsumerListener::onFrameAvailable() {
  1029     sp<GonkBufferQueue::ConsumerListener> listener(mConsumerListener.promote());
  1030     if (listener != NULL) {
  1031         listener->onFrameAvailable();
  1035 void GonkBufferQueue::ProxyConsumerListener::onBuffersReleased() {
  1036     sp<GonkBufferQueue::ConsumerListener> listener(mConsumerListener.promote());
  1037     if (listener != NULL) {
  1038         listener->onBuffersReleased();
  1042 }; // namespace android

mercurial