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 <hardware/hardware.h> 31 #include <gui/BufferItem.h> 32 #include <gui/BufferQueue.h> 33 #include <gui/Surface.h> 34 35 #include <ui/DebugUtils.h> 36 #include <ui/GraphicBuffer.h> 37 #include <ui/Rect.h> 38 39 #include "FramebufferSurface.h" 40 #include "HWComposer.h" 41 #include "../SurfaceFlinger.h" 42 43 // ---------------------------------------------------------------------------- 44 namespace android { 45 // ---------------------------------------------------------------------------- 46 47 using ui::Dataspace; 48 49 /* 50 * This implements the (main) framebuffer management. This class is used 51 * mostly by SurfaceFlinger, but also by command line GL application. 52 * 53 */ 54 55 FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId, 56 const sp<IGraphicBufferConsumer>& consumer) 57 : ConsumerBase(consumer), 58 mDisplayId(displayId), 59 mCurrentBufferSlot(-1), 60 mCurrentBuffer(), 61 mCurrentFence(Fence::NO_FENCE), 62 mHwc(hwc), 63 mHasPendingRelease(false), 64 mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), 65 mPreviousBuffer() { 66 ALOGV("Creating for display %s", to_string(displayId).c_str()); 67 68 mName = "FramebufferSurface"; 69 mConsumer->setConsumerName(mName); 70 mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB | 71 GRALLOC_USAGE_HW_RENDER | 72 GRALLOC_USAGE_HW_COMPOSER); 73 const auto& activeConfig = mHwc.getActiveConfig(displayId); 74 mConsumer->setDefaultBufferSize(activeConfig->getWidth(), 75 activeConfig->getHeight()); 76 mConsumer->setMaxAcquiredBufferCount( 77 SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1); 78 } 79 80 void FramebufferSurface::resizeBuffers(const uint32_t width, const uint32_t height) { 81 mConsumer->setDefaultBufferSize(width, height); 82 } 83 84 status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) { 85 return NO_ERROR; 86 } 87 88 status_t FramebufferSurface::prepareFrame(CompositionType /*compositionType*/) { 89 return NO_ERROR; 90 } 91 92 status_t FramebufferSurface::advanceFrame() { 93 uint32_t slot = 0; 94 sp<GraphicBuffer> buf; 95 sp<Fence> acquireFence(Fence::NO_FENCE); 96 Dataspace dataspace = Dataspace::UNKNOWN; 97 status_t result = nextBuffer(slot, buf, acquireFence, dataspace); 98 mDataSpace = dataspace; 99 if (result != NO_ERROR) { 100 ALOGE("error latching next FramebufferSurface buffer: %s (%d)", 101 strerror(-result), result); 102 } 103 return result; 104 } 105 106 status_t FramebufferSurface::nextBuffer(uint32_t& outSlot, 107 sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence, 108 Dataspace& outDataspace) { 109 Mutex::Autolock lock(mMutex); 110 111 BufferItem item; 112 status_t err = acquireBufferLocked(&item, 0); 113 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 114 mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer); 115 return NO_ERROR; 116 } else if (err != NO_ERROR) { 117 ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err); 118 return err; 119 } 120 121 // If the BufferQueue has freed and reallocated a buffer in mCurrentSlot 122 // then we may have acquired the slot we already own. If we had released 123 // our current buffer before we call acquireBuffer then that release call 124 // would have returned STALE_BUFFER_SLOT, and we would have called 125 // freeBufferLocked on that slot. Because the buffer slot has already 126 // been overwritten with the new buffer all we have to do is skip the 127 // releaseBuffer call and we should be in the same state we'd be in if we 128 // had released the old buffer first. 129 if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT && 130 item.mSlot != mCurrentBufferSlot) { 131 mHasPendingRelease = true; 132 mPreviousBufferSlot = mCurrentBufferSlot; 133 mPreviousBuffer = mCurrentBuffer; 134 } 135 mCurrentBufferSlot = item.mSlot; 136 mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer; 137 mCurrentFence = item.mFence; 138 139 outFence = item.mFence; 140 mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer); 141 outDataspace = static_cast<Dataspace>(item.mDataSpace); 142 status_t result = mHwc.setClientTarget(mDisplayId, outSlot, outFence, outBuffer, outDataspace); 143 if (result != NO_ERROR) { 144 ALOGE("error posting framebuffer: %d", result); 145 return result; 146 } 147 148 return NO_ERROR; 149 } 150 151 void FramebufferSurface::freeBufferLocked(int slotIndex) { 152 ConsumerBase::freeBufferLocked(slotIndex); 153 if (slotIndex == mCurrentBufferSlot) { 154 mCurrentBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; 155 } 156 } 157 158 void FramebufferSurface::onFrameCommitted() { 159 if (mHasPendingRelease) { 160 sp<Fence> fence = mHwc.getPresentFence(mDisplayId); 161 if (fence->isValid()) { 162 status_t result = addReleaseFence(mPreviousBufferSlot, 163 mPreviousBuffer, fence); 164 ALOGE_IF(result != NO_ERROR, "onFrameCommitted: failed to add the" 165 " fence: %s (%d)", strerror(-result), result); 166 } 167 status_t result = releaseBufferLocked(mPreviousBufferSlot, mPreviousBuffer); 168 ALOGE_IF(result != NO_ERROR, "onFrameCommitted: error releasing buffer:" 169 " %s (%d)", strerror(-result), result); 170 171 mPreviousBuffer.clear(); 172 mHasPendingRelease = false; 173 } 174 } 175 176 void FramebufferSurface::dumpAsString(String8& result) const { 177 Mutex::Autolock lock(mMutex); 178 result.appendFormat(" FramebufferSurface: dataspace: %s(%d)\n", 179 dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(), 180 mDataSpace); 181 ConsumerBase::dumpLocked(result, " "); 182 } 183 184 void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const 185 { 186 ConsumerBase::dumpLocked(result, prefix); 187 } 188 189 const sp<Fence>& FramebufferSurface::getClientTargetAcquireFence() const { 190 return mCurrentFence; 191 } 192 193 // ---------------------------------------------------------------------------- 194 }; // namespace android 195 // ---------------------------------------------------------------------------- 196