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
This commit is contained in:
Ramakrishna Prasad N 2012-05-03 18:46:47 +05:30 committed by Andrew Sutherland
parent 6b64b4881e
commit b942708b15

View File

@ -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<private_hwc_module_t*>(
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) {