3 ** Copyright 2012 The Android Open Source Project
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
9 ** http://www.apache.org/licenses/LICENSE-2.0
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.
18 // #define LOG_NDEBUG 0
20 #define LOG_TAG "FramebufferSurface"
27 #include <cutils/log.h>
29 #include <utils/String8.h>
35 #include <hardware/hardware.h>
36 #include <gui/BufferItem.h>
37 #include <gui/GraphicBufferAlloc.h>
38 #include <gui/Surface.h>
39 #include <ui/GraphicBuffer.h>
41 #include "FramebufferSurface.h"
42 #include "HWComposer.h"
44 #ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS
45 #define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2)
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
53 * This implements the (main) framebuffer management. This class is used
54 * mostly by SurfaceFlinger, but also by command line GL application.
58 FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,
59 const sp<IGraphicBufferConsumer>& consumer) :
60 ConsumerBase(consumer),
62 mCurrentBufferSlot(-1),
65 mCurrentFence(Fence::NO_FENCE),
67 mHasPendingRelease(false),
68 mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
76 ALOGV("Creating for display %d", disp);
79 mName = "FramebufferSurface";
80 mConsumer->setConsumerName(mName);
81 mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
82 GRALLOC_USAGE_HW_RENDER |
83 GRALLOC_USAGE_HW_COMPOSER);
85 const auto& activeConfig = mHwc.getActiveConfig(disp);
86 mConsumer->setDefaultBufferSize(activeConfig->getWidth(),
87 activeConfig->getHeight());
89 mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
90 mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
92 mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1);
95 status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
99 status_t FramebufferSurface::prepareFrame(CompositionType /*compositionType*/) {
103 status_t FramebufferSurface::advanceFrame() {
105 sp<GraphicBuffer> buf;
106 sp<Fence> acquireFence(Fence::NO_FENCE);
107 android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
108 status_t result = nextBuffer(buf, acquireFence, dataspace);
109 if (result != NO_ERROR) {
110 ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
111 strerror(-result), result);
114 result = mHwc.setClientTarget(mDisplayType, acquireFence, buf, dataspace);
115 if (result != NO_ERROR) {
116 ALOGE("error posting framebuffer: %d", result);
120 // Once we remove FB HAL support, we can call nextBuffer() from here
121 // instead of using onFrameAvailable(). No real benefit, except it'll be
122 // more like VirtualDisplaySurface.
128 status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer,
129 sp<Fence>& outFence, android_dataspace_t& outDataspace) {
131 status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
133 Mutex::Autolock lock(mMutex);
136 status_t err = acquireBufferLocked(&item, 0);
137 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
138 outBuffer = mCurrentBuffer;
140 } else if (err != NO_ERROR) {
141 ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
145 // If the BufferQueue has freed and reallocated a buffer in mCurrentSlot
146 // then we may have acquired the slot we already own. If we had released
147 // our current buffer before we call acquireBuffer then that release call
148 // would have returned STALE_BUFFER_SLOT, and we would have called
149 // freeBufferLocked on that slot. Because the buffer slot has already
150 // been overwritten with the new buffer all we have to do is skip the
151 // releaseBuffer call and we should be in the same state we'd be in if we
152 // had released the old buffer first.
153 if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
154 item.mSlot != mCurrentBufferSlot) {
156 mHasPendingRelease = true;
157 mPreviousBufferSlot = mCurrentBufferSlot;
158 mPreviousBuffer = mCurrentBuffer;
160 // Release the previous buffer.
161 err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
162 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
163 if (err < NO_ERROR) {
164 ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
169 mCurrentBufferSlot = item.mSlot;
170 mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
172 mCurrentFence = item.mFence;
175 outFence = item.mFence;
176 outBuffer = mCurrentBuffer;
178 outDataspace = item.mDataSpace;
184 // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
185 void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
186 sp<GraphicBuffer> buf;
187 sp<Fence> acquireFence;
188 status_t err = nextBuffer(buf, acquireFence);
189 if (err != NO_ERROR) {
190 ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
191 strerror(-err), err);
194 err = mHwc.fbPost(mDisplayType, acquireFence, buf);
195 if (err != NO_ERROR) {
196 ALOGE("error posting framebuffer: %d", err);
201 void FramebufferSurface::freeBufferLocked(int slotIndex) {
202 ConsumerBase::freeBufferLocked(slotIndex);
203 if (slotIndex == mCurrentBufferSlot) {
204 mCurrentBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
208 void FramebufferSurface::onFrameCommitted() {
210 if (mHasPendingRelease) {
211 sp<Fence> fence = mHwc.getRetireFence(mDisplayType);
212 if (fence->isValid()) {
213 status_t result = addReleaseFence(mPreviousBufferSlot,
214 mPreviousBuffer, fence);
215 ALOGE_IF(result != NO_ERROR, "onFrameCommitted: failed to add the"
216 " fence: %s (%d)", strerror(-result), result);
218 status_t result = releaseBufferLocked(mPreviousBufferSlot,
219 mPreviousBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
220 ALOGE_IF(result != NO_ERROR, "onFrameCommitted: error releasing buffer:"
221 " %s (%d)", strerror(-result), result);
223 mPreviousBuffer.clear();
224 mHasPendingRelease = false;
227 sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
228 if (fence->isValid() &&
229 mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
230 status_t err = addReleaseFence(mCurrentBufferSlot,
231 mCurrentBuffer, fence);
232 ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
233 strerror(-err), err);
239 status_t FramebufferSurface::compositionComplete()
241 return mHwc.fbCompositionComplete();
245 void FramebufferSurface::dumpAsString(String8& result) const {
246 ConsumerBase::dump(result);
249 void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
254 ConsumerBase::dumpLocked(result, prefix);
258 const sp<Fence>& FramebufferSurface::getClientTargetAcquireFence() const {
259 return mCurrentFence;
263 // ----------------------------------------------------------------------------
264 }; // namespace android
265 // ----------------------------------------------------------------------------