Home | History | Annotate | Download | only in gui
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <inttypes.h>
     18 
     19 #define LOG_TAG "ConsumerBase"
     20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
     21 //#define LOG_NDEBUG 0
     22 
     23 #define EGL_EGLEXT_PROTOTYPES
     24 
     25 #include <EGL/egl.h>
     26 #include <EGL/eglext.h>
     27 
     28 #include <hardware/hardware.h>
     29 
     30 #include <gui/IGraphicBufferAlloc.h>
     31 #include <gui/ISurfaceComposer.h>
     32 #include <gui/SurfaceComposerClient.h>
     33 #include <gui/ConsumerBase.h>
     34 
     35 #include <private/gui/ComposerService.h>
     36 
     37 #include <utils/Log.h>
     38 #include <utils/String8.h>
     39 #include <utils/Trace.h>
     40 
     41 // Macros for including the ConsumerBase name in log messages
     42 #define CB_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
     43 #define CB_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
     44 #define CB_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
     45 #define CB_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
     46 #define CB_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
     47 
     48 namespace android {
     49 
     50 // Get an ID that's unique within this process.
     51 static int32_t createProcessUniqueId() {
     52     static volatile int32_t globalCounter = 0;
     53     return android_atomic_inc(&globalCounter);
     54 }
     55 
     56 ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
     57         mAbandoned(false),
     58         mConsumer(bufferQueue) {
     59     // Choose a name using the PID and a process-unique ID.
     60     mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
     61 
     62     // Note that we can't create an sp<...>(this) in a ctor that will not keep a
     63     // reference once the ctor ends, as that would cause the refcount of 'this'
     64     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
     65     // that's what we create.
     66     wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
     67     sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
     68 
     69     status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
     70     if (err != NO_ERROR) {
     71         CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
     72                 strerror(-err), err);
     73     } else {
     74         mConsumer->setConsumerName(mName);
     75     }
     76 }
     77 
     78 ConsumerBase::~ConsumerBase() {
     79     CB_LOGV("~ConsumerBase");
     80     Mutex::Autolock lock(mMutex);
     81 
     82     // Verify that abandon() has been called before we get here.  This should
     83     // be done by ConsumerBase::onLastStrongRef(), but it's possible for a
     84     // derived class to override that method and not call
     85     // ConsumerBase::onLastStrongRef().
     86     LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~ConsumerBase was called, but the "
     87         "consumer is not abandoned!", mName.string());
     88 }
     89 
     90 void ConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) {
     91     abandon();
     92 }
     93 
     94 void ConsumerBase::freeBufferLocked(int slotIndex) {
     95     CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
     96     mSlots[slotIndex].mGraphicBuffer = 0;
     97     mSlots[slotIndex].mFence = Fence::NO_FENCE;
     98     mSlots[slotIndex].mFrameNumber = 0;
     99 }
    100 
    101 void ConsumerBase::onFrameAvailable(const BufferItem& item) {
    102     CB_LOGV("onFrameAvailable");
    103 
    104     sp<FrameAvailableListener> listener;
    105     { // scope for the lock
    106         Mutex::Autolock lock(mMutex);
    107         listener = mFrameAvailableListener.promote();
    108     }
    109 
    110     if (listener != NULL) {
    111         CB_LOGV("actually calling onFrameAvailable");
    112         listener->onFrameAvailable(item);
    113     }
    114 }
    115 
    116 void ConsumerBase::onBuffersReleased() {
    117     Mutex::Autolock lock(mMutex);
    118 
    119     CB_LOGV("onBuffersReleased");
    120 
    121     if (mAbandoned) {
    122         // Nothing to do if we're already abandoned.
    123         return;
    124     }
    125 
    126     uint64_t mask = 0;
    127     mConsumer->getReleasedBuffers(&mask);
    128     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    129         if (mask & (1ULL << i)) {
    130             freeBufferLocked(i);
    131         }
    132     }
    133 }
    134 
    135 void ConsumerBase::onSidebandStreamChanged() {
    136 }
    137 
    138 void ConsumerBase::abandon() {
    139     CB_LOGV("abandon");
    140     Mutex::Autolock lock(mMutex);
    141 
    142     if (!mAbandoned) {
    143         abandonLocked();
    144         mAbandoned = true;
    145     }
    146 }
    147 
    148 void ConsumerBase::abandonLocked() {
    149 	CB_LOGV("abandonLocked");
    150     for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    151         freeBufferLocked(i);
    152     }
    153     // disconnect from the BufferQueue
    154     mConsumer->consumerDisconnect();
    155     mConsumer.clear();
    156 }
    157 
    158 void ConsumerBase::setFrameAvailableListener(
    159         const wp<FrameAvailableListener>& listener) {
    160     CB_LOGV("setFrameAvailableListener");
    161     Mutex::Autolock lock(mMutex);
    162     mFrameAvailableListener = listener;
    163 }
    164 
    165 void ConsumerBase::dump(String8& result) const {
    166     dump(result, "");
    167 }
    168 
    169 void ConsumerBase::dump(String8& result, const char* prefix) const {
    170     Mutex::Autolock _l(mMutex);
    171     dumpLocked(result, prefix);
    172 }
    173 
    174 void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
    175     result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
    176 
    177     if (!mAbandoned) {
    178         mConsumer->dump(result, prefix);
    179     }
    180 }
    181 
    182 status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item,
    183         nsecs_t presentWhen) {
    184     status_t err = mConsumer->acquireBuffer(item, presentWhen);
    185     if (err != NO_ERROR) {
    186         return err;
    187     }
    188 
    189     if (item->mGraphicBuffer != NULL) {
    190         mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
    191     }
    192 
    193     mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
    194     mSlots[item->mBuf].mFence = item->mFence;
    195 
    196     CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
    197             item->mBuf, item->mFrameNumber);
    198 
    199     return OK;
    200 }
    201 
    202 status_t ConsumerBase::addReleaseFence(int slot,
    203         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
    204     Mutex::Autolock lock(mMutex);
    205     return addReleaseFenceLocked(slot, graphicBuffer, fence);
    206 }
    207 
    208 status_t ConsumerBase::addReleaseFenceLocked(int slot,
    209         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
    210     CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
    211 
    212     // If consumer no longer tracks this graphicBuffer, we can safely
    213     // drop this fence, as it will never be received by the producer.
    214     if (!stillTracking(slot, graphicBuffer)) {
    215         return OK;
    216     }
    217 
    218     if (!mSlots[slot].mFence.get()) {
    219         mSlots[slot].mFence = fence;
    220     } else {
    221         sp<Fence> mergedFence = Fence::merge(
    222                 String8::format("%.28s:%d", mName.string(), slot),
    223                 mSlots[slot].mFence, fence);
    224         if (!mergedFence.get()) {
    225             CB_LOGE("failed to merge release fences");
    226             // synchronization is broken, the best we can do is hope fences
    227             // signal in order so the new fence will act like a union
    228             mSlots[slot].mFence = fence;
    229             return BAD_VALUE;
    230         }
    231         mSlots[slot].mFence = mergedFence;
    232     }
    233 
    234     return OK;
    235 }
    236 
    237 status_t ConsumerBase::releaseBufferLocked(
    238         int slot, const sp<GraphicBuffer> graphicBuffer,
    239         EGLDisplay display, EGLSyncKHR eglFence) {
    240     // If consumer no longer tracks this graphicBuffer (we received a new
    241     // buffer on the same slot), the buffer producer is definitely no longer
    242     // tracking it.
    243     if (!stillTracking(slot, graphicBuffer)) {
    244         return OK;
    245     }
    246 
    247     CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
    248             slot, mSlots[slot].mFrameNumber);
    249     status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
    250             display, eglFence, mSlots[slot].mFence);
    251     if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
    252         freeBufferLocked(slot);
    253     }
    254 
    255     mSlots[slot].mFence = Fence::NO_FENCE;
    256 
    257     return err;
    258 }
    259 
    260 bool ConsumerBase::stillTracking(int slot,
    261         const sp<GraphicBuffer> graphicBuffer) {
    262     if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
    263         return false;
    264     }
    265     return (mSlots[slot].mGraphicBuffer != NULL &&
    266             mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
    267 }
    268 
    269 } // namespace android
    270