michael@0: /* michael@0: ** michael@0: ** Copyright 2012 The Android Open Source Project michael@0: ** michael@0: ** Licensed under the Apache License Version 2.0(the "License"); michael@0: ** you may not use this file except in compliance with the License. michael@0: ** You may obtain a copy of the License at michael@0: ** michael@0: ** http://www.apache.org/licenses/LICENSE-2.0 michael@0: ** michael@0: ** Unless required by applicable law or agreed to in writing software michael@0: ** distributed under the License is distributed on an "AS IS" BASIS michael@0: ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. michael@0: ** See the License for the specific language governing permissions and michael@0: ** limitations under the License. michael@0: */ michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include michael@0: michael@0: #include michael@0: michael@0: #include michael@0: michael@0: #include michael@0: michael@0: #include michael@0: #if ANDROID_VERSION == 17 michael@0: #include michael@0: #endif michael@0: #include michael@0: michael@0: #include "FramebufferSurface.h" michael@0: #include "GraphicBufferAlloc.h" michael@0: michael@0: #ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS michael@0: #define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2) michael@0: #endif michael@0: michael@0: // ---------------------------------------------------------------------------- michael@0: namespace android { michael@0: // ---------------------------------------------------------------------------- michael@0: michael@0: /* michael@0: * This implements the (main) framebuffer management. This class michael@0: * was adapted from the version in SurfaceFlinger michael@0: */ michael@0: FramebufferSurface::FramebufferSurface(int disp, uint32_t width, uint32_t height, uint32_t format, michael@0: sp& bq) : michael@0: #if ANDROID_VERSION >= 19 michael@0: ConsumerBase(bq, true), michael@0: #else michael@0: ConsumerBase(bq), michael@0: #endif michael@0: mDisplayType(disp), michael@0: mCurrentBufferSlot(-1), michael@0: mCurrentBuffer(0), michael@0: lastHandle(0) michael@0: { michael@0: mName = "FramebufferSurface"; michael@0: michael@0: #if ANDROID_VERSION >= 19 michael@0: sp consumer = mConsumer; michael@0: #else michael@0: sp consumer = mBufferQueue; michael@0: consumer->setSynchronousMode(true); michael@0: #endif michael@0: consumer->setConsumerName(mName); michael@0: consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB | michael@0: GRALLOC_USAGE_HW_RENDER | michael@0: GRALLOC_USAGE_HW_COMPOSER); michael@0: consumer->setDefaultBufferFormat(format); michael@0: consumer->setDefaultBufferSize(width, height); michael@0: consumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS); michael@0: } michael@0: michael@0: status_t FramebufferSurface::nextBuffer(sp& outBuffer, sp& outFence) { michael@0: Mutex::Autolock lock(mMutex); michael@0: michael@0: BufferQueue::BufferItem item; michael@0: #if ANDROID_VERSION >= 19 michael@0: status_t err = acquireBufferLocked(&item, 0); michael@0: #else michael@0: status_t err = acquireBufferLocked(&item); michael@0: #endif michael@0: if (err == BufferQueue::NO_BUFFER_AVAILABLE) { michael@0: outBuffer = mCurrentBuffer; michael@0: return NO_ERROR; michael@0: } else if (err != NO_ERROR) { michael@0: ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err); michael@0: return err; michael@0: } michael@0: michael@0: // If the BufferQueue has freed and reallocated a buffer in mCurrentSlot michael@0: // then we may have acquired the slot we already own. If we had released michael@0: // our current buffer before we call acquireBuffer then that release call michael@0: // would have returned STALE_BUFFER_SLOT, and we would have called michael@0: // freeBufferLocked on that slot. Because the buffer slot has already michael@0: // been overwritten with the new buffer all we have to do is skip the michael@0: // releaseBuffer call and we should be in the same state we'd be in if we michael@0: // had released the old buffer first. michael@0: if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT && michael@0: item.mBuf != mCurrentBufferSlot) { michael@0: // Release the previous buffer. michael@0: #if ANDROID_VERSION >= 19 michael@0: err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer, michael@0: EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); michael@0: #else michael@0: err = releaseBufferLocked(mCurrentBufferSlot, EGL_NO_DISPLAY, michael@0: EGL_NO_SYNC_KHR); michael@0: #endif michael@0: if (err != NO_ERROR && err != BufferQueue::STALE_BUFFER_SLOT) { michael@0: ALOGE("error releasing buffer: %s (%d)", strerror(-err), err); michael@0: return err; michael@0: } michael@0: } michael@0: mCurrentBufferSlot = item.mBuf; michael@0: mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer; michael@0: outFence = item.mFence; michael@0: outBuffer = mCurrentBuffer; michael@0: return NO_ERROR; michael@0: } michael@0: michael@0: // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl. michael@0: void FramebufferSurface::onFrameAvailable() { michael@0: sp buf; michael@0: sp acquireFence; michael@0: status_t err = nextBuffer(buf, acquireFence); michael@0: if (err != NO_ERROR) { michael@0: ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)", michael@0: strerror(-err), err); michael@0: return; michael@0: } michael@0: if (acquireFence.get() && acquireFence->isValid()) michael@0: mPrevFBAcquireFence = new Fence(acquireFence->dup()); michael@0: else michael@0: mPrevFBAcquireFence = Fence::NO_FENCE; michael@0: michael@0: lastHandle = buf->handle; michael@0: } michael@0: michael@0: void FramebufferSurface::freeBufferLocked(int slotIndex) { michael@0: ConsumerBase::freeBufferLocked(slotIndex); michael@0: if (slotIndex == mCurrentBufferSlot) { michael@0: mCurrentBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; michael@0: } michael@0: } michael@0: michael@0: status_t FramebufferSurface::setReleaseFenceFd(int fenceFd) { michael@0: status_t err = NO_ERROR; michael@0: if (fenceFd >= 0) { michael@0: sp fence(new Fence(fenceFd)); michael@0: if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) { michael@0: #if ANDROID_VERSION >= 19 michael@0: status_t err = addReleaseFence(mCurrentBufferSlot, mCurrentBuffer, fence); michael@0: #else michael@0: status_t err = addReleaseFence(mCurrentBufferSlot, fence); michael@0: #endif michael@0: ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)", michael@0: strerror(-err), err); michael@0: } michael@0: } michael@0: return err; michael@0: } michael@0: michael@0: int FramebufferSurface::GetPrevFBAcquireFd() { michael@0: return mPrevFBAcquireFence->dup(); michael@0: } michael@0: michael@0: status_t FramebufferSurface::setUpdateRectangle(const Rect& r) michael@0: { michael@0: return INVALID_OPERATION; michael@0: } michael@0: michael@0: status_t FramebufferSurface::compositionComplete() michael@0: { michael@0: return NO_ERROR; michael@0: } michael@0: michael@0: void FramebufferSurface::dump(String8& result) { michael@0: ConsumerBase::dump(result); michael@0: } michael@0: michael@0: void FramebufferSurface::dump(String8& result, const char* prefix) { michael@0: ConsumerBase::dump(result); michael@0: } michael@0: michael@0: // ---------------------------------------------------------------------------- michael@0: }; // namespace android michael@0: // ----------------------------------------------------------------------------