diff options
8 files changed, 65 insertions, 26 deletions
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index e16abef3d7..cdc16edb97 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -235,8 +235,7 @@ void DisplayDevice::swapBuffers(HWComposer& hwc) const { void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const { if (hwc.initCheck() == NO_ERROR) { - sp<Fence> fence = hwc.getAndResetReleaseFence(mType); - mDisplaySurface->onFrameCommitted(fence); + mDisplaySurface->onFrameCommitted(); } } diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h index bc717a956d..2eca3cbfbf 100644 --- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h @@ -49,10 +49,9 @@ public: virtual status_t advanceFrame() = 0; // onFrameCommitted is called after the frame has been committed to the - // hardware composer and a release fence is available for the buffer. - // Further operations on the buffer can be queued as long as they wait for - // the fence to signal. - virtual void onFrameCommitted(const sp<Fence>& fence) = 0; + // hardware composer. The surface collects the release fence for this + // frame's buffer. + virtual void onFrameCommitted() = 0; virtual void dump(String8& result) const = 0; diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index c35ac956c8..1936893c85 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -140,7 +140,8 @@ void FramebufferSurface::freeBufferLocked(int slotIndex) { } } -void FramebufferSurface::onFrameCommitted(const sp<Fence>& fence) { +void FramebufferSurface::onFrameCommitted() { + sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType); if (fence->isValid() && mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) { status_t err = addReleaseFence(mCurrentBufferSlot, fence); diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 164f81f273..2fde789b4e 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -43,7 +43,7 @@ public: virtual status_t compositionComplete(); virtual status_t advanceFrame(); - virtual void onFrameCommitted(const sp<Fence>& fence); + virtual void onFrameCommitted(); // Implementation of DisplaySurface::dump(). Note that ConsumerBase also // has a non-virtual dump() with the same signature. diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 9d32410932..497593bba1 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -657,15 +657,12 @@ status_t HWComposer::commit() { mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW); } - // For virtual displays, the framebufferTarget buffer also serves as - // the HWC output buffer, so we need to copy the buffer handle and - // dup() the acquire fence. for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) { DisplayData& disp(mDisplayData[i]); - if (disp.framebufferTarget) { - mLists[i]->outbuf = disp.framebufferTarget->handle; + if (disp.outbufHandle) { + mLists[i]->outbuf = disp.outbufHandle; mLists[i]->outbufAcquireFenceFd = - dup(disp.framebufferTarget->acquireFenceFd); + disp.outbufAcquireFence->dup(); } } @@ -706,17 +703,15 @@ status_t HWComposer::acquire(int disp) { void HWComposer::disconnectDisplay(int disp) { LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY); - if (disp >= HWC_NUM_DISPLAY_TYPES) { - // nothing to do for these yet - return; - } DisplayData& dd(mDisplayData[disp]); - if (dd.list != NULL) { - free(dd.list); - dd.list = NULL; - dd.framebufferTarget = NULL; // points into dd.list - dd.fbTargetHandle = NULL; - } + free(dd.list); + dd.list = NULL; + dd.framebufferTarget = NULL; // points into dd.list + dd.fbTargetHandle = NULL; + dd.outbufHandle = NULL; + dd.lastRetireFence = Fence::NO_FENCE; + dd.lastDisplayFence = Fence::NO_FENCE; + dd.outbufAcquireFence = Fence::NO_FENCE; } int HWComposer::getVisualID() const { @@ -765,6 +760,25 @@ void HWComposer::fbDump(String8& result) { } } +status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence, + const sp<GraphicBuffer>& buf) { + if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) + return BAD_INDEX; + if (id < VIRTUAL_DISPLAY_ID_BASE) + return INVALID_OPERATION; + + DisplayData& disp(mDisplayData[id]); + disp.outbufHandle = buf->handle; + disp.outbufAcquireFence = acquireFence; + return NO_ERROR; +} + +sp<Fence> HWComposer::getLastRetireFence(int32_t id) { + if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) + return Fence::NO_FENCE; + return mDisplayData[id].lastRetireFence; +} + /* * Helper template to implement a concrete HWCLayer * This holds the pointer to the concrete hwc layer type @@ -1071,6 +1085,7 @@ HWComposer::DisplayData::DisplayData() capacity(0), list(NULL), framebufferTarget(NULL), fbTargetHandle(0), lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE), + outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE), events(0) {} diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 346526aae4..58f7e8fff0 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -128,6 +128,17 @@ public: int fbCompositionComplete(); void fbDump(String8& result); + // Set the output buffer and acquire fence for a virtual display. + // Returns INVALID_OPERATION if id is not a virtual display. + status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence, + const sp<GraphicBuffer>& buf); + + // Get the retire fence for the last committed frame. This fence will + // signal when the h/w composer is completely finished with the frame. + // For physical displays, it is no longer being displayed. For virtual + // displays, writes to the output buffer are complete. + sp<Fence> getLastRetireFence(int32_t id); + /* * Interface to hardware composer's layers functionality. * This abstracts the HAL interface to layers which can evolve in @@ -306,6 +317,8 @@ private: sp<Fence> lastRetireFence; // signals when the last set op retires sp<Fence> lastDisplayFence; // signals when the last set op takes // effect on screen + buffer_handle_t outbufHandle; + sp<Fence> outbufAcquireFence; // protected by mEventControlLock int32_t events; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 255b77f655..b28500e8f4 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -70,9 +70,21 @@ status_t VirtualDisplaySurface::advanceFrame() { return mHwc.fbPost(mDisplayId, fence, mAcquiredBuffer); } -void VirtualDisplaySurface::onFrameCommitted(const sp<Fence>& fence) { +void VirtualDisplaySurface::onFrameCommitted() { Mutex::Autolock lock(mMutex); if (mAcquiredBuffer != NULL) { + // fbFence signals when reads from the framebuffer are finished + // outFence signals when writes to the output buffer are finished + // It's unlikely that there will be an implementation where fbFence + // signals after outFence (in fact they'll typically be the same + // sync_pt), but just to be pedantic we merge them so the sink will + // be sure to wait until both are complete. + sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId); + sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId); + sp<Fence> fence = Fence::merge( + String8::format("HWC done: %.21s", mName.string()), + fbFence, outFence); + status_t result = mSource->releaseBuffer(fence); ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": " "failed to release buffer: %d", mName.string(), result); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 13476800fe..61bafedde5 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -58,7 +58,7 @@ public: virtual status_t compositionComplete(); virtual status_t advanceFrame(); - virtual void onFrameCommitted(const sp<Fence>& fence); + virtual void onFrameCommitted(); virtual void dump(String8& result) const; private: |