Home | History | Annotate | Download | only in DisplayHardware
      1 /*
      2  **
      3  ** Copyright 2012 The Android Open Source Project
      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  */
     17 
     18 // #define LOG_NDEBUG 0
     19 #undef LOG_TAG
     20 #define LOG_TAG "FramebufferSurface"
     21 
     22 #include <errno.h>
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <string.h>
     26 
     27 #include <utils/String8.h>
     28 #include <log/log.h>
     29 
     30 #include <EGL/egl.h>
     31 
     32 #include <hardware/hardware.h>
     33 #include <gui/BufferItem.h>
     34 #include <gui/BufferQueue.h>
     35 #include <gui/Surface.h>
     36 
     37 #include <ui/GraphicBuffer.h>
     38 #include <ui/Rect.h>
     39 
     40 #include "FramebufferSurface.h"
     41 #include "HWComposer.h"
     42 #include "../SurfaceFlinger.h"
     43 
     44 // ----------------------------------------------------------------------------
     45 namespace android {
     46 // ----------------------------------------------------------------------------
     47 
     48 /*
     49  * This implements the (main) framebuffer management. This class is used
     50  * mostly by SurfaceFlinger, but also by command line GL application.
     51  *
     52  */
     53 
     54 FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,
     55         const sp<IGraphicBufferConsumer>& consumer) :
     56     ConsumerBase(consumer),
     57     mDisplayType(disp),
     58     mCurrentBufferSlot(-1),
     59     mCurrentBuffer(),
     60     mCurrentFence(Fence::NO_FENCE),
     61 #ifdef USE_HWC2
     62     mHwc(hwc),
     63     mHasPendingRelease(false),
     64     mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
     65     mPreviousBuffer()
     66 #else
     67     mHwc(hwc)
     68 #endif
     69 {
     70 #ifdef USE_HWC2
     71     ALOGV("Creating for display %d", disp);
     72 #endif
     73 
     74     mName = "FramebufferSurface";
     75     mConsumer->setConsumerName(mName);
     76     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
     77                                        GRALLOC_USAGE_HW_RENDER |
     78                                        GRALLOC_USAGE_HW_COMPOSER);
     79 #ifdef USE_HWC2
     80     const auto& activeConfig = mHwc.getActiveConfig(disp);
     81     mConsumer->setDefaultBufferSize(activeConfig->getWidth(),
     82             activeConfig->getHeight());
     83 #else
     84     mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
     85     mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
     86 #endif
     87     mConsumer->setMaxAcquiredBufferCount(
     88             SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
     89 }
     90 
     91 status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
     92     return NO_ERROR;
     93 }
     94 
     95 status_t FramebufferSurface::prepareFrame(CompositionType /*compositionType*/) {
     96     return NO_ERROR;
     97 }
     98 
     99 status_t FramebufferSurface::advanceFrame() {
    100 #ifdef USE_HWC2
    101     uint32_t slot = 0;
    102     sp<GraphicBuffer> buf;
    103     sp<Fence> acquireFence(Fence::NO_FENCE);
    104     android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
    105     status_t result = nextBuffer(slot, buf, acquireFence, dataspace);
    106     if (result != NO_ERROR) {
    107         ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
    108                 strerror(-result), result);
    109         return result;
    110     }
    111     result = mHwc.setClientTarget(mDisplayType, slot,
    112             acquireFence, buf, dataspace);
    113     if (result != NO_ERROR) {
    114         ALOGE("error posting framebuffer: %d", result);
    115     }
    116     return result;
    117 #else
    118     // Once we remove FB HAL support, we can call nextBuffer() from here
    119     // instead of using onFrameAvailable(). No real benefit, except it'll be
    120     // more like VirtualDisplaySurface.
    121     return NO_ERROR;
    122 #endif
    123 }
    124 
    125 #ifdef USE_HWC2
    126 status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,
    127         sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,
    128         android_dataspace_t& outDataspace) {
    129 #else
    130 status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
    131 #endif
    132     Mutex::Autolock lock(mMutex);
    133 
    134     BufferItem item;
    135     status_t err = acquireBufferLocked(&item, 0);
    136     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
    137 #ifdef USE_HWC2
    138         mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
    139                 &outSlot, &outBuffer);
    140 #else
    141         outBuffer = mCurrentBuffer;
    142 #endif
    143         return NO_ERROR;
    144     } else if (err != NO_ERROR) {
    145         ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
    146         return err;
    147     }
    148 
    149     // If the BufferQueue has freed and reallocated a buffer in mCurrentSlot
    150     // then we may have acquired the slot we already own.  If we had released
    151     // our current buffer before we call acquireBuffer then that release call
    152     // would have returned STALE_BUFFER_SLOT, and we would have called
    153     // freeBufferLocked on that slot.  Because the buffer slot has already
    154     // been overwritten with the new buffer all we have to do is skip the
    155     // releaseBuffer call and we should be in the same state we'd be in if we
    156     // had released the old buffer first.
    157     if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
    158         item.mSlot != mCurrentBufferSlot) {
    159 #ifdef USE_HWC2
    160         mHasPendingRelease = true;
    161         mPreviousBufferSlot = mCurrentBufferSlot;
    162         mPreviousBuffer = mCurrentBuffer;
    163 #else
    164         // Release the previous buffer.
    165         err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
    166                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
    167         if (err < NO_ERROR) {
    168             ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
    169             return err;
    170         }
    171 #endif
    172     }
    173     mCurrentBufferSlot = item.mSlot;
    174     mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
    175     mCurrentFence = item.mFence;
    176 
    177     outFence = item.mFence;
    178 #ifdef USE_HWC2
    179     mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
    180             &outSlot, &outBuffer);
    181     outDataspace = item.mDataSpace;
    182 #else
    183     outBuffer = mCurrentBuffer;
    184 #endif
    185     return NO_ERROR;
    186 }
    187 
    188 #ifndef USE_HWC2
    189 // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
    190 void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
    191     sp<GraphicBuffer> buf;
    192     sp<Fence> acquireFence;
    193     status_t err = nextBuffer(buf, acquireFence);
    194     if (err != NO_ERROR) {
    195         ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
    196                 strerror(-err), err);
    197         return;
    198     }
    199     err = mHwc.fbPost(mDisplayType, acquireFence, buf);
    200     if (err != NO_ERROR) {
    201         ALOGE("error posting framebuffer: %d", err);
    202     }
    203 }
    204 #endif
    205 
    206 void FramebufferSurface::freeBufferLocked(int slotIndex) {
    207     ConsumerBase::freeBufferLocked(slotIndex);
    208     if (slotIndex == mCurrentBufferSlot) {
    209         mCurrentBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
    210     }
    211 }
    212 
    213 void FramebufferSurface::onFrameCommitted() {
    214 #ifdef USE_HWC2
    215     if (mHasPendingRelease) {
    216         sp<Fence> fence = mHwc.getPresentFence(mDisplayType);
    217         if (fence->isValid()) {
    218             status_t result = addReleaseFence(mPreviousBufferSlot,
    219                     mPreviousBuffer, fence);
    220             ALOGE_IF(result != NO_ERROR, "onFrameCommitted: failed to add the"
    221                     " fence: %s (%d)", strerror(-result), result);
    222         }
    223         status_t result = releaseBufferLocked(mPreviousBufferSlot,
    224                 mPreviousBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
    225         ALOGE_IF(result != NO_ERROR, "onFrameCommitted: error releasing buffer:"
    226                 " %s (%d)", strerror(-result), result);
    227 
    228         mPreviousBuffer.clear();
    229         mHasPendingRelease = false;
    230     }
    231 #else
    232     sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
    233     if (fence->isValid() &&
    234             mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
    235         status_t err = addReleaseFence(mCurrentBufferSlot,
    236                 mCurrentBuffer, fence);
    237         ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
    238                 strerror(-err), err);
    239     }
    240 #endif
    241 }
    242 
    243 #ifndef USE_HWC2
    244 status_t FramebufferSurface::compositionComplete()
    245 {
    246     return mHwc.fbCompositionComplete();
    247 }
    248 #endif
    249 
    250 void FramebufferSurface::dumpAsString(String8& result) const {
    251     ConsumerBase::dumpState(result);
    252 }
    253 
    254 void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
    255 {
    256 #ifndef USE_HWC2
    257     mHwc.fbDump(result);
    258 #endif
    259     ConsumerBase::dumpLocked(result, prefix);
    260 }
    261 
    262 const sp<Fence>& FramebufferSurface::getClientTargetAcquireFence() const {
    263     return mCurrentFence;
    264 }
    265 
    266 // ----------------------------------------------------------------------------
    267 }; // namespace android
    268 // ----------------------------------------------------------------------------
    269