From 42c4db1c6e009c629de7c10c43b4c33c6004c14a Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 22 Dec 2011 19:25:19 -0800 Subject: [PATCH] libhwcomposer: Check the number of open overlay channels When performing the setup for bypass operations, check the number of bypass channels that are in open state. If the count does not match the number of bypass layers, close all the bypass channels. This is done to prevent the overlay channels from going into an inconsistent/undefined state. Change-Id: If471a4b4437e25642586616461c5d745f15b3287 CRs-fixed: 323676 --- libhwcomposer/hwcomposer.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index f83901c..8a50baa 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -243,7 +243,8 @@ void unlockPreviousBypassBuffers(hwc_context_t* ctx) { void closeBypass(hwc_context_t* ctx) { unlockPreviousBypassBuffers(ctx); for (int index = 0 ; index < MAX_BYPASS_LAYERS; index++) { - ctx->mOvUI[index]->closeChannel(); + if (overlay::CLOSED != ctx->mOvUI[index]->isChannelUP()) + ctx->mOvUI[index]->closeChannel(); } #ifdef DEBUG LOGE("%s", __FUNCTION__); @@ -608,6 +609,24 @@ inline static bool isBypassEfficient(const framebuffer_device_t* fbDev, } bool setupBypass(hwc_context_t* ctx, hwc_layer_list_t* list) { + int currentBypassLayerCount = list->numHwLayers; + // Check the number of open bypass channels + + int openBypassChannels = 0; + for (int index = 0; index < MAX_BYPASS_LAYERS; index++) { + if (overlay::UP == ctx->mOvUI[index]->isChannelUP()) { + openBypassChannels++; + } + } + if (openBypassChannels && (openBypassChannels != currentBypassLayerCount)) { + // Number of overlay channels that are open is not the same as + // the number of bypass channels. We could run into an issue + // where the channels could potentially move into an incorrect/inconsistent + // stste. Return a failure so that the channels can be closed and re-opened + // with the correct states. + return false; + } + for (int index = 0 ; index < list->numHwLayers; index++) { if(prepareBypass(ctx, &(list->hwLayers[index]), index, list->numHwLayers - 1) != 0) { @@ -926,6 +945,7 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { #ifdef COMPOSITION_BYPASS //Check if bypass is feasible + bool unsetBypass = false; if(isBypassDoable(dev, yuvBufferCount, list) && isBypassEfficient(hwcModule->fbDevice, list, ctx)) { //Setup bypass @@ -934,13 +954,22 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { setBypassLayerFlags(ctx, list); list->flags |= HWC_SKIP_COMPOSITION; ctx->bypassState = BYPASS_ON; + } else { + unsetBypass = true; } } else { + unsetBypass = true; + } + + if (unsetBypass) { unlockPreviousBypassBuffers(ctx); unsetBypassLayerFlags(list); unsetBypassBufferLockState(ctx); if(ctx->bypassState == BYPASS_ON) { ctx->bypassState = BYPASS_OFF_PENDING; + } else if (BYPASS_OFF == ctx->bypassState) { + // If bypass is off, close any open overlay channels. + closeBypass(ctx); } } #endif