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     }
    110     return result;
    111 #else
    112     // Once we remove FB HAL support, we can call nextBuffer() from here
    113     // instead of using onFrameAvailable(). No real benefit, except it'll be
    114     // more like VirtualDisplaySurface.
    115     return NO_ERROR;
    116 #endif
    117 }
    118 
    119 #ifdef USE_HWC2
    120 status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,
    121         sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,
    122         android_dataspace_t& outDataspace) {
    123 #else
    124 status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
    125 #endif
    126     Mutex::Autolock lock(mMutex);
    127 
    128     BufferItem item;
    129     status_t err = acquireBufferLocked(&item, 0);
    130     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
    131 #ifdef USE_HWC2
    132         mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
    133                 &outSlot, &outBuffer);
    134 #else
    135         outBuffer = mCurrentBuffer;
    136 #endif
    137         return NO_ERROR;
    138     } else if (err != NO_ERROR) {
    139         ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
    140         return err;
    141     }
    142 
    143     // If the BufferQueue has freed and reallocated a buffer in mCurrentSlot
    144     // then we may have acquired the slot we already own.  If we had released
    145     // our current buffer before we call acquireBuffer then that release call
    146     // would have returned STALE_BUFFER_SLOT, and we would have called
    147     // freeBufferLocked on that slot.  Because the buffer slot has already
    148     // been overwritten with the new buffer all we have to do is skip the
    149     // releaseBuffer call and we should be in the same state we'd be in if we
    150     // had released the old buffer first.
    151     if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
    152         item.mSlot != mCurrentBufferSlot) {
    153 #ifdef USE_HWC2
    154         mHasPendingRelease = true;
    155         mPreviousBufferSlot = mCurrentBufferSlot;
    156         mPreviousBuffer = mCurrentBuffer;
    157 #else
    158         // Release the previous buffer.
    159         err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
    160                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
    161         if (err < NO_ERROR) {
    162             ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
    163             return err;
    164         }
    165 #endif
    166     }
    167     mCurrentBufferSlot = item.mSlot;
    168     mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
    169     mCurrentFence = item.mFence;
    170 
    171     outFence = item.mFence;
    172 #ifdef USE_HWC2
    173     mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
    174             &outSlot, &outBuffer);
    175     outDataspace = item.mDataSpace;
    176     status_t result =
    177             mHwc.setClientTarget(mDisplayType, outSlot, outFence, outBuffer, outDataspace);
    178     if (result != NO_ERROR) {
    179         ALOGE("error posting framebuffer: %d", result);
    180         return result;
    181     }
    182 #else
    183     outBuffer = mCurrentBuffer;
    184 #endif
    185 
    186     return NO_ERROR;
    187 }
    188 
    189 #ifndef USE_HWC2
    190 // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
    191 void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
    192     sp<GraphicBuffer> buf;
    193     sp<Fence> acquireFence;
    194     status_t err = nextBuffer(buf, acquireFence);
    195     if (err != NO_ERROR) {
    196         ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
    197                 strerror(-err), err);
    198         return;
    199     }
    200     err = mHwc.fbPost(mDisplayType, acquireFence, buf);
    201     if (err != NO_ERROR) {
    202         ALOGE("error posting framebuffer: %d", err);
    203     }
    204 }
    205 #endif
    206 
    207 void FramebufferSurface::freeBufferLocked(int slotIndex) {
    208     ConsumerBase::freeBufferLocked(slotIndex);
    209     if (slotIndex == mCurrentBufferSlot) {
    210         mCurrentBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
    211     }
    212 }
    213 
    214 void FramebufferSurface::onFrameCommitted() {
    215 #ifdef USE_HWC2
    216     if (mHasPendingRelease) {
    217         sp<Fence> fence = mHwc.getPresentFence(mDisplayType);
    218         if (fence->isValid()) {
    219             status_t result = addReleaseFence(mPreviousBufferSlot,
    220                     mPreviousBuffer, fence);
    221             ALOGE_IF(result != NO_ERROR, "onFrameCommitted: failed to add the"
    222                     " fence: %s (%d)", strerror(-result), result);
    223         }
    224         status_t result = releaseBufferLocked(mPreviousBufferSlot,
    225                 mPreviousBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
    226         ALOGE_IF(result != NO_ERROR, "onFrameCommitted: error releasing buffer:"
    227                 " %s (%d)", strerror(-result), result);
    228 
    229         mPreviousBuffer.clear();
    230         mHasPendingRelease = false;
    231     }
    232 #else
    233     sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
    234     if (fence->isValid() &&
    235             mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
    236         status_t err = addReleaseFence(mCurrentBufferSlot,
    237                 mCurrentBuffer, fence);
    238         ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
    239                 strerror(-err), err);
    240     }
    241 #endif
    242 }
    243 
    244 #ifndef USE_HWC2
    245 status_t FramebufferSurface::compositionComplete()
    246 {
    247     return mHwc.fbCompositionComplete();
    248 }
    249 #endif
    250 
    251 void FramebufferSurface::dumpAsString(String8& result) const {
    252     ConsumerBase::dumpState(result);
    253 }
    254 
    255 void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
    256 {
    257 #ifndef USE_HWC2
    258     mHwc.fbDump(result);
    259 #endif
    260     ConsumerBase::dumpLocked(result, prefix);
    261 }
    262 
    263 const sp<Fence>& FramebufferSurface::getClientTargetAcquireFence() const {
    264     return mCurrentFence;
    265 }
    266 
    267 // ----------------------------------------------------------------------------
    268 }; // namespace android
    269 // ----------------------------------------------------------------------------
    270