From b942708b157228d61b3192851fdde5fa87f6148c Mon Sep 17 00:00:00 2001 From: Ramakrishna Prasad N Date: Thu, 3 May 2012 18:46:47 +0530 Subject: [PATCH] libhwcomposer: Wait for framebuffer post complete before releasing composition buffers on bypass failure. When bypass fails, MDP keeps reading the last submitted buffers until the next VSYNC i.e., until PAN_DISPLAY is called on framebuffer. So the previous buffers can be released only after PAN_DISPLAY IOCTL call returns. CRs-fixed: 348953 (cherry picked from commit c3a7ed7db39609e8f4d7ce0d6a56e82303ddb7f1) Conflicts: libhwcomposer/hwcomposer.cpp Change-Id: I5fb5a9eb275006a3158a111aad1eafac79973095 --- libhwcomposer/hwcomposer.cpp | 85 ++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index bd5771f..38a39fb 100644 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -604,23 +604,10 @@ void closeExtraPipes(hwc_context_t* ctx) { int pipes_used = ctx->nPipesUsed; //Unused pipes must be of higher z-order + //Note that MDP on closechannel call just marks the + //pipes for closure. The pipes are actually closed + //on next VSYNC for (int i = pipes_used ; i < MAX_BYPASS_LAYERS; i++) { - private_handle_t *hnd = (private_handle_t*) ctx->previousBypassHandle[i]; - if (hnd) { - if (!private_handle_t::validate(hnd)) { - if (GENLOCK_FAILURE == genlock_unlock_buffer(hnd)) { - LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); - } else { - ctx->previousBypassHandle[i] = NULL; - ctx->bypassBufferLockState[i] = BYPASS_BUFFER_UNLOCKED; - hnd->flags &= ~private_handle_t::PRIV_FLAGS_HWC_LOCK; - } - } else { - LOGE("%s: Unregistering invalid gralloc handle %p.", - __FUNCTION__, hnd); - ctx->previousBypassHandle[i] = NULL; - } - } ctx->mOvUI[i]->closeChannel(); ctx->layerindex[i] = -1; } @@ -725,6 +712,8 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer, const int flag if(ctx && (ctx->bypassState != BYPASS_OFF)) { ctx->nPipesUsed = 0; closeExtraPipes(ctx); + unlockPreviousBypassBuffers(ctx); + unsetBypassBufferLockState(ctx); ctx->bypassState = BYPASS_OFF; } #endif @@ -1645,6 +1634,8 @@ static int hwc_set(hwc_composer_device_t *dev, private_hwc_module_t* hwcModule = reinterpret_cast( dev->common.module); + framebuffer_device_t *fbDev = hwcModule->fbDevice; + if (!hwcModule) { LOGE("hwc_set invalid module"); #ifdef COMPOSITION_BYPASS @@ -1655,6 +1646,14 @@ static int hwc_set(hwc_composer_device_t *dev, unlockPreviousOverlayBuffer(ctx); return -1; } +#ifdef COMPOSITION_BYPASS + if(!list){ + //Device in suspended state. Close all the MDP pipes + ctx->nPipesUsed = 0; + } + closeExtraPipes(ctx); +#endif + int ret = 0; if (list) { @@ -1678,10 +1677,6 @@ static int hwc_set(hwc_composer_device_t *dev, } } } else { - //Device in suspended state. Close all the MDP pipes -#ifdef COMPOSITION_BYPASS - ctx->nPipesUsed = 0; -#endif ctx->hwcOverlayStatus = HWC_OVERLAY_PREPARE_TO_CLOSE; unlockPreviousOverlayBuffer(ctx); } @@ -1689,29 +1684,45 @@ static int hwc_set(hwc_composer_device_t *dev, bool canSkipComposition = list && list->flags & HWC_SKIP_COMPOSITION; + + //Draw External-only layers + if(ExtDispOnly::draw(ctx, list) != overlay::NO_ERROR) { + ExtDispOnly::close(); + } + +#if BYPASS_DEBUG + if(canSkipComposition) + LOGE("%s: skipping eglSwapBuffer call", __FUNCTION__); +#endif + // Do not call eglSwapBuffers if we the skip composition flag is set on the list. + if (dpy && sur && !canSkipComposition) { +#ifdef COMPOSITION_BYPASS + if(ctx->bypassState == BYPASS_OFF_PENDING) + fbDev->perform(fbDev, EVENT_RESET_POSTBUFFER, NULL); +#endif + EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); + if (!sucess) { + ret = HWC_EGL_ERROR; + } else { +#ifdef COMPOSITION_BYPASS + if(ctx->bypassState == BYPASS_OFF_PENDING) { + fbDev->perform(fbDev, EVENT_WAIT_POSTBUFFER, NULL); + ctx->bypassState = BYPASS_OFF; + } +#endif + CALC_FPS(); + } + } + + // Unlock the previously locked buffer, since the overlay has completed reading the buffer + unlockPreviousOverlayBuffer(ctx); + #ifdef COMPOSITION_BYPASS unlockPreviousBypassBuffers(ctx); storeLockedBypassHandle(list, ctx); // We have stored the handles, unset the current lock states in the context. unsetBypassBufferLockState(ctx); - closeExtraPipes(ctx); -#if BYPASS_DEBUG - if(canSkipComposition) - LOGE("%s: skipping eglSwapBuffer call", __FUNCTION__); #endif -#endif - // Do not call eglSwapBuffers if we the skip composition flag is set on the list. - if (dpy && sur && !canSkipComposition) { - EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); - if (!sucess) { - ret = HWC_EGL_ERROR; - } - } else { - CALC_FPS(); - } - - // Unlock the previously locked buffer, since the overlay has completed reading the buffer - unlockPreviousOverlayBuffer(ctx); #if defined HDMI_DUAL_DISPLAY if(ctx->pendingHDMI) {