widget/gonk/nativewindow/GonkConsumerBaseKK.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) 2010 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 "GonkConsumerBase"
    19 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
    20 //#define LOG_NDEBUG 0
    22 #define EGL_EGLEXT_PROTOTYPES
    24 #include <hardware/hardware.h>
    26 #include <gui/IGraphicBufferAlloc.h>
    27 #include <utils/Log.h>
    28 #include <utils/String8.h>
    30 #include "GonkConsumerBaseKK.h"
    32 // Macros for including the GonkConsumerBase name in log messages
    33 #define CB_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
    34 #define CB_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
    35 #define CB_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
    36 #define CB_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
    37 #define CB_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
    39 namespace android {
    41 // Get an ID that's unique within this process.
    42 static int32_t createProcessUniqueId() {
    43     static volatile int32_t globalCounter = 0;
    44     return android_atomic_inc(&globalCounter);
    45 }
    47 GonkConsumerBase::GonkConsumerBase(const sp<GonkBufferQueue>& bufferQueue, bool controlledByApp) :
    48         mAbandoned(false),
    49         mConsumer(bufferQueue) {
    50     // Choose a name using the PID and a process-unique ID.
    51     mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
    53     // Note that we can't create an sp<...>(this) in a ctor that will not keep a
    54     // reference once the ctor ends, as that would cause the refcount of 'this'
    55     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
    56     // that's what we create.
    57     wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
    58     sp<IConsumerListener> proxy = new GonkBufferQueue::ProxyConsumerListener(listener);
    60     status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
    61     if (err != NO_ERROR) {
    62         CB_LOGE("GonkConsumerBase: error connecting to GonkBufferQueue: %s (%d)",
    63                 strerror(-err), err);
    64     } else {
    65         mConsumer->setConsumerName(mName);
    66     }
    67 }
    69 GonkConsumerBase::~GonkConsumerBase() {
    70     CB_LOGV("~GonkConsumerBase");
    71     Mutex::Autolock lock(mMutex);
    73     // Verify that abandon() has been called before we get here.  This should
    74     // be done by GonkConsumerBase::onLastStrongRef(), but it's possible for a
    75     // derived class to override that method and not call
    76     // GonkConsumerBase::onLastStrongRef().
    77     LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~GonkConsumerBase was called, but the "
    78         "consumer is not abandoned!", mName.string());
    79 }
    81 void GonkConsumerBase::onLastStrongRef(const void* id) {
    82     abandon();
    83 }
    85 void GonkConsumerBase::freeBufferLocked(int slotIndex) {
    86     CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
    87     mSlots[slotIndex].mGraphicBuffer = 0;
    88     mSlots[slotIndex].mFence = Fence::NO_FENCE;
    89     mSlots[slotIndex].mFrameNumber = 0;
    90 }
    92 // Used for refactoring, should not be in final interface
    93 sp<GonkBufferQueue> GonkConsumerBase::getBufferQueue() const {
    94     Mutex::Autolock lock(mMutex);
    95     return mConsumer;
    96 }
    98 void GonkConsumerBase::onFrameAvailable() {
    99     CB_LOGV("onFrameAvailable");
   101     sp<FrameAvailableListener> listener;
   102     { // scope for the lock
   103         Mutex::Autolock lock(mMutex);
   104         listener = mFrameAvailableListener.promote();
   105     }
   107     if (listener != NULL) {
   108         CB_LOGV("actually calling onFrameAvailable");
   109         listener->onFrameAvailable();
   110     }
   111 }
   113 void GonkConsumerBase::onBuffersReleased() {
   114     Mutex::Autolock lock(mMutex);
   116     CB_LOGV("onBuffersReleased");
   118     if (mAbandoned) {
   119         // Nothing to do if we're already abandoned.
   120         return;
   121     }
   123     uint32_t mask = 0;
   124     mConsumer->getReleasedBuffers(&mask);
   125     for (int i = 0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) {
   126         if (mask & (1 << i)) {
   127             freeBufferLocked(i);
   128         }
   129     }
   130 }
   132 void GonkConsumerBase::abandon() {
   133     CB_LOGV("abandon");
   134     Mutex::Autolock lock(mMutex);
   136     if (!mAbandoned) {
   137         abandonLocked();
   138         mAbandoned = true;
   139     }
   140 }
   142 void GonkConsumerBase::abandonLocked() {
   143 	CB_LOGV("abandonLocked");
   144     for (int i =0; i < GonkBufferQueue::NUM_BUFFER_SLOTS; i++) {
   145         freeBufferLocked(i);
   146     }
   147     // disconnect from the BufferQueue
   148     mConsumer->consumerDisconnect();
   149     mConsumer.clear();
   150 }
   152 void GonkConsumerBase::setFrameAvailableListener(
   153         const wp<FrameAvailableListener>& listener) {
   154     CB_LOGV("setFrameAvailableListener");
   155     Mutex::Autolock lock(mMutex);
   156     mFrameAvailableListener = listener;
   157 }
   159 void GonkConsumerBase::dump(String8& result) const {
   160     dump(result, "");
   161 }
   163 void GonkConsumerBase::dump(String8& result, const char* prefix) const {
   164     Mutex::Autolock _l(mMutex);
   165     dumpLocked(result, prefix);
   166 }
   168 void GonkConsumerBase::dumpLocked(String8& result, const char* prefix) const {
   169     result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
   171     if (!mAbandoned) {
   172         mConsumer->dump(result, prefix);
   173     }
   174 }
   176 status_t GonkConsumerBase::acquireBufferLocked(IGonkGraphicBufferConsumer::BufferItem *item,
   177         nsecs_t presentWhen) {
   178     status_t err = mConsumer->acquireBuffer(item, presentWhen);
   179     if (err != NO_ERROR) {
   180         return err;
   181     }
   183     if (item->mGraphicBuffer != NULL) {
   184         mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
   185     }
   187     mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
   188     mSlots[item->mBuf].mFence = item->mFence;
   190     CB_LOGV("acquireBufferLocked: -> slot=%d", item->mBuf);
   192     return OK;
   193 }
   195 status_t GonkConsumerBase::addReleaseFence(int slot,
   196         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
   197     Mutex::Autolock lock(mMutex);
   198     return addReleaseFenceLocked(slot, graphicBuffer, fence);
   199 }
   201 status_t GonkConsumerBase::addReleaseFenceLocked(int slot,
   202         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
   203     CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
   205     // If consumer no longer tracks this graphicBuffer, we can safely
   206     // drop this fence, as it will never be received by the producer.
   207     if (!stillTracking(slot, graphicBuffer)) {
   208         return OK;
   209     }
   211     if (!mSlots[slot].mFence.get()) {
   212         mSlots[slot].mFence = fence;
   213     } else {
   214         sp<Fence> mergedFence = Fence::merge(
   215                 String8::format("%.28s:%d", mName.string(), slot),
   216                 mSlots[slot].mFence, fence);
   217         if (!mergedFence.get()) {
   218             CB_LOGE("failed to merge release fences");
   219             // synchronization is broken, the best we can do is hope fences
   220             // signal in order so the new fence will act like a union
   221             mSlots[slot].mFence = fence;
   222             return BAD_VALUE;
   223         }
   224         mSlots[slot].mFence = mergedFence;
   225     }
   227     return OK;
   228 }
   230 status_t GonkConsumerBase::releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) {
   231     // If consumer no longer tracks this graphicBuffer (we received a new
   232     // buffer on the same slot), the buffer producer is definitely no longer
   233     // tracking it.
   234     if (!stillTracking(slot, graphicBuffer)) {
   235         return OK;
   236     }
   238     CB_LOGV("releaseBufferLocked: slot=%d/%llu",
   239             slot, mSlots[slot].mFrameNumber);
   240     status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber, mSlots[slot].mFence);
   241     if (err == GonkBufferQueue::STALE_BUFFER_SLOT) {
   242         freeBufferLocked(slot);
   243     }
   245     mSlots[slot].mFence = Fence::NO_FENCE;
   247     return err;
   248 }
   250 bool GonkConsumerBase::stillTracking(int slot,
   251         const sp<GraphicBuffer> graphicBuffer) {
   252     if (slot < 0 || slot >= GonkBufferQueue::NUM_BUFFER_SLOTS) {
   253         return false;
   254     }
   255     return (mSlots[slot].mGraphicBuffer != NULL &&
   256             mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
   257 }
   259 } // namespace android

mercurial