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/BufferItem.h>
     31 #include <gui/IGraphicBufferAlloc.h>
     32 #include <gui/ISurfaceComposer.h>
     33 #include <gui/SurfaceComposerClient.h>
     34 #include <gui/ConsumerBase.h>
     35 
     36 #include <private/gui/ComposerService.h>
     37 
     38 #include <utils/Log.h>
     39 #include <utils/String8.h>
     40 #include <utils/Trace.h>
     41 
     42 // Macros for including the ConsumerBase name in log messages
     43 #define CB_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
     44 //#define CB_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
     45 //#define CB_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
     46 //#define CB_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
     47 #define CB_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
     48 
     49 namespace android {
     50 
     51 // Get an ID that's unique within this process.
     52 static int32_t createProcessUniqueId() {
     53     static volatile int32_t globalCounter = 0;
     54     return android_atomic_inc(&globalCounter);
     55 }
     56 
     57 ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
     58         mAbandoned(false),
     59         mConsumer(bufferQueue) {
     60     // Choose a name using the PID and a process-unique ID.
     61     mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
     62 
     63     // Note that we can't create an sp<...>(this) in a ctor that will not keep a
     64     // reference once the ctor ends, as that would cause the refcount of 'this'
     65     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
     66     // that's what we create.
     67     wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
     68     sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
     69 
     70     status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
     71     if (err != NO_ERROR) {
     72         CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
     73                 strerror(-err), err);
     74     } else {
     75         mConsumer->setConsumerName(mName);
     76     }
     77 }
     78 
     79 ConsumerBase::~ConsumerBase() {
     80     CB_LOGV("~ConsumerBase");
     81     Mutex::Autolock lock(mMutex);
     82 
     83     // Verify that abandon() has been called before we get here.  This should
     84     // be done by ConsumerBase::onLastStrongRef(), but it's possible for a
     85     // derived class to override that method and not call
     86     // ConsumerBase::onLastStrongRef().
     87     LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~ConsumerBase was called, but the "
     88         "consumer is not abandoned!", mName.string());
     89 }
     90 
     91 void ConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) {
     92     abandon();
     93 }
     94 
     95 void ConsumerBase::freeBufferLocked(int slotIndex) {
     96     CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
     97     mSlots[slotIndex].mGraphicBuffer = 0;
     98     mSlots[slotIndex].mFence = Fence::NO_FENCE;
     99     mSlots[slotIndex].mFrameNumber = 0;
    100 }
    101 
    102 void ConsumerBase::onFrameAvailable(const BufferItem& item) {
    103     CB_LOGV("onFrameAvailable");
    104 
    105     sp<FrameAvailableListener> listener;
    106     { // scope for the lock
    107         Mutex::Autolock lock(mMutex);
    108         listener = mFrameAvailableListener.promote();
    109     }
    110 
    111     if (listener != NULL) {
    112         CB_LOGV("actually calling onFrameAvailable");
    113         listener->onFrameAvailable(item);
    114     }
    115 }
    116 
    117 void ConsumerBase::onFrameReplaced(const BufferItem &item) {
    118     CB_LOGV("onFrameReplaced");
    119 
    120     sp<FrameAvailableListener> listener;
    121     {
    122         Mutex::Autolock lock(mMutex);
    123         listener = mFrameAvailableListener.promote();
    124     }
    125 
    126     if (listener != NULL) {
    127         CB_LOGV("actually calling onFrameReplaced");
    128         listener->onFrameReplaced(item);
    129     }
    130 }
    131 
    132 void ConsumerBase::onBuffersReleased() {
    133     Mutex::Autolock lock(mMutex);
    134 
    135     CB_LOGV("onBuffersReleased");
    136 
    137     if (mAbandoned) {
    138         // Nothing to do if we're already abandoned.
    139         return;
    140     }
    141 
    142     uint64_t mask = 0;
    143     mConsumer->getReleasedBuffers(&mask);
    144     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    145         if (mask & (1ULL << i)) {
    146             freeBufferLocked(i);
    147         }
    148     }
    149 }
    150 
    151 void ConsumerBase::onSidebandStreamChanged() {
    152 }
    153 
    154 void ConsumerBase::abandon() {
    155     CB_LOGV("abandon");
    156     Mutex::Autolock lock(mMutex);
    157 
    158     if (!mAbandoned) {
    159         abandonLocked();
    160         mAbandoned = true;
    161     }
    162 }
    163 
    164 void ConsumerBase::abandonLocked() {
    165     CB_LOGV("abandonLocked");
    166     if (mAbandoned) {
    167         CB_LOGE("abandonLocked: ConsumerBase is abandoned!");
    168         return;
    169     }
    170     for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    171         freeBufferLocked(i);
    172     }
    173     // disconnect from the BufferQueue
    174     mConsumer->consumerDisconnect();
    175     mConsumer.clear();
    176 }
    177 
    178 bool ConsumerBase::isAbandoned() {
    179     Mutex::Autolock _l(mMutex);
    180     return mAbandoned;
    181 }
    182 
    183 void ConsumerBase::setFrameAvailableListener(
    184         const wp<FrameAvailableListener>& listener) {
    185     CB_LOGV("setFrameAvailableListener");
    186     Mutex::Autolock lock(mMutex);
    187     mFrameAvailableListener = listener;
    188 }
    189 
    190 status_t ConsumerBase::detachBuffer(int slot) {
    191     CB_LOGV("detachBuffer");
    192     Mutex::Autolock lock(mMutex);
    193 
    194     if (mAbandoned) {
    195         CB_LOGE("detachBuffer: ConsumerBase is abandoned!");
    196         return NO_INIT;
    197     }
    198 
    199     status_t result = mConsumer->detachBuffer(slot);
    200     if (result != NO_ERROR) {
    201         CB_LOGE("Failed to detach buffer: %d", result);
    202         return result;
    203     }
    204 
    205     freeBufferLocked(slot);
    206 
    207     return result;
    208 }
    209 
    210 status_t ConsumerBase::setDefaultBufferSize(uint32_t width, uint32_t height) {
    211     Mutex::Autolock _l(mMutex);
    212     if (mAbandoned) {
    213         CB_LOGE("setDefaultBufferSize: ConsumerBase is abandoned!");
    214         return NO_INIT;
    215     }
    216     return mConsumer->setDefaultBufferSize(width, height);
    217 }
    218 
    219 status_t ConsumerBase::setDefaultBufferFormat(PixelFormat defaultFormat) {
    220     Mutex::Autolock _l(mMutex);
    221     if (mAbandoned) {
    222         CB_LOGE("setDefaultBufferFormat: ConsumerBase is abandoned!");
    223         return NO_INIT;
    224     }
    225     return mConsumer->setDefaultBufferFormat(defaultFormat);
    226 }
    227 
    228 status_t ConsumerBase::setDefaultBufferDataSpace(
    229         android_dataspace defaultDataSpace) {
    230     Mutex::Autolock _l(mMutex);
    231     if (mAbandoned) {
    232         CB_LOGE("setDefaultBufferDataSpace: ConsumerBase is abandoned!");
    233         return NO_INIT;
    234     }
    235     return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
    236 }
    237 
    238 status_t ConsumerBase::getOccupancyHistory(bool forceFlush,
    239         std::vector<OccupancyTracker::Segment>* outHistory) {
    240     Mutex::Autolock _l(mMutex);
    241     if (mAbandoned) {
    242         CB_LOGE("getOccupancyHistory: ConsumerBase is abandoned!");
    243         return NO_INIT;
    244     }
    245     return mConsumer->getOccupancyHistory(forceFlush, outHistory);
    246 }
    247 
    248 status_t ConsumerBase::discardFreeBuffers() {
    249     Mutex::Autolock _l(mMutex);
    250     if (mAbandoned) {
    251         CB_LOGE("discardFreeBuffers: ConsumerBase is abandoned!");
    252         return NO_INIT;
    253     }
    254     return mConsumer->discardFreeBuffers();
    255 }
    256 
    257 void ConsumerBase::dump(String8& result) const {
    258     dump(result, "");
    259 }
    260 
    261 void ConsumerBase::dump(String8& result, const char* prefix) const {
    262     Mutex::Autolock _l(mMutex);
    263     dumpLocked(result, prefix);
    264 }
    265 
    266 void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
    267     result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
    268 
    269     if (!mAbandoned) {
    270         mConsumer->dump(result, prefix);
    271     }
    272 }
    273 
    274 status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
    275         nsecs_t presentWhen, uint64_t maxFrameNumber) {
    276     if (mAbandoned) {
    277         CB_LOGE("acquireBufferLocked: ConsumerBase is abandoned!");
    278         return NO_INIT;
    279     }
    280 
    281     status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
    282     if (err != NO_ERROR) {
    283         return err;
    284     }
    285 
    286     if (item->mGraphicBuffer != NULL) {
    287         mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
    288     }
    289 
    290     mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
    291     mSlots[item->mSlot].mFence = item->mFence;
    292 
    293     CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
    294             item->mSlot, item->mFrameNumber);
    295 
    296     return OK;
    297 }
    298 
    299 status_t ConsumerBase::addReleaseFence(int slot,
    300         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
    301     Mutex::Autolock lock(mMutex);
    302     return addReleaseFenceLocked(slot, graphicBuffer, fence);
    303 }
    304 
    305 status_t ConsumerBase::addReleaseFenceLocked(int slot,
    306         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
    307     CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
    308 
    309     // If consumer no longer tracks this graphicBuffer, we can safely
    310     // drop this fence, as it will never be received by the producer.
    311     if (!stillTracking(slot, graphicBuffer)) {
    312         return OK;
    313     }
    314 
    315     if (!mSlots[slot].mFence.get()) {
    316         mSlots[slot].mFence = fence;
    317     } else {
    318         sp<Fence> mergedFence = Fence::merge(
    319                 String8::format("%.28s:%d", mName.string(), slot),
    320                 mSlots[slot].mFence, fence);
    321         if (!mergedFence.get()) {
    322             CB_LOGE("failed to merge release fences");
    323             // synchronization is broken, the best we can do is hope fences
    324             // signal in order so the new fence will act like a union
    325             mSlots[slot].mFence = fence;
    326             return BAD_VALUE;
    327         }
    328         mSlots[slot].mFence = mergedFence;
    329     }
    330 
    331     return OK;
    332 }
    333 
    334 status_t ConsumerBase::releaseBufferLocked(
    335         int slot, const sp<GraphicBuffer> graphicBuffer,
    336         EGLDisplay display, EGLSyncKHR eglFence) {
    337     if (mAbandoned) {
    338         CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");
    339         return NO_INIT;
    340     }
    341     // If consumer no longer tracks this graphicBuffer (we received a new
    342     // buffer on the same slot), the buffer producer is definitely no longer
    343     // tracking it.
    344     if (!stillTracking(slot, graphicBuffer)) {
    345         return OK;
    346     }
    347 
    348     CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
    349             slot, mSlots[slot].mFrameNumber);
    350     status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
    351             display, eglFence, mSlots[slot].mFence);
    352     if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
    353         freeBufferLocked(slot);
    354     }
    355 
    356     mSlots[slot].mFence = Fence::NO_FENCE;
    357 
    358     return err;
    359 }
    360 
    361 bool ConsumerBase::stillTracking(int slot,
    362         const sp<GraphicBuffer> graphicBuffer) {
    363     if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
    364         return false;
    365     }
    366     return (mSlots[slot].mGraphicBuffer != NULL &&
    367             mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
    368 }
    369 
    370 } // namespace android
    371