From cb098e76e82b432eb937f8aa884bc1522f43c1fd Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Thu, 16 Jun 2011 15:35:56 -0700 Subject: [PATCH] Handle overlay setup failure Separate overlay setup and overlay play. On setup failure, mark the layer to use C2D if enabled. Else mark the layer to use GPU. CRs-fixed: 292398 (cherry picked from commit b1459b0b1106ed66810b1c5a09878fae353c123c) Change-Id: Id4c27384193612ab13e87d18492b0fef662eb8b4 --- libhwcomposer/hwcomposer.cpp | 167 +++++++++++++++++++++-------------- 1 file changed, 100 insertions(+), 67 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index c3d8f29..3ec53fa 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -41,6 +41,8 @@ /*****************************************************************************/ #define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) // Enum containing the supported composition types enum { @@ -181,6 +183,88 @@ static int hwc_updateOverlayStatus(hwc_context_t* ctx, int layerType) { return 0; } +/* + * Configures mdp pipes + */ +static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { + int ret = 0; + if (LIKELY(ctx && ctx->mOverlayLibObject)) { + private_hwc_module_t* hwcModule = + reinterpret_cast(ctx->device.common.module); + if (UNLIKELY(!hwcModule)) { + LOGE("prepareOverlay null module "); + return -1; + } + + private_handle_t *hnd = (private_handle_t *)layer->handle; + overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; + int orientation = 0; + if (OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus()) + ovLibObject->getOrientation(orientation); + + if ((OVERLAY_CHANNEL_DOWN == ovLibObject->getChannelStatus()) + || (layer->transform != orientation) || + (hnd->flags & private_handle_t::PRIV_FLAGS_FORMAT_CHANGED)) { + // Overlay channel is not started, or we have an orientation change + // or there is a format change, call setSource to open the overlay + // if necessary + ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, + layer->transform, (ovLibObject->getHDMIStatus()?true:false), + false); + if (!ret) { + LOGE("prepareOverlay setSource failed"); + return -1; + } + // Reset this flag so that we don't keep opening and closing channels + // unnecessarily + hnd->flags &= ~private_handle_t::PRIV_FLAGS_FORMAT_CHANGED; + } else { + // The overlay goemetry may have changed, we only need to update the + // overlay + ret = ovLibObject->updateOverlaySource(hnd->width, hnd->height, + hnd->format, layer->transform); + if (!ret) { + LOGE("prepareOverlay updateOverlaySource failed"); + return -1; + } + } + + hwc_rect_t sourceCrop = layer->sourceCrop; + ret = ovLibObject->setCrop(sourceCrop.left, sourceCrop.top, + (sourceCrop.right - sourceCrop.left), + (sourceCrop.bottom - sourceCrop.top)); + if (!ret) { + LOGE("prepareOverlay setCrop failed"); + return -1; + } + + if (layer->flags == HWC_USE_ORIGINAL_RESOLUTION) { + framebuffer_device_t* fbDev = hwcModule->fbDevice; + ret = ovLibObject->setPosition(0, 0, + fbDev->width, fbDev->height); + } else { + hwc_rect_t displayFrame = layer->displayFrame; + ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top, + (displayFrame.right - displayFrame.left), + (displayFrame.bottom - displayFrame.top)); + } + if (!ret) { + LOGE("prepareOverlay setPosition failed"); + return -1; + } + + ovLibObject->getOrientation(orientation); + if (orientation != layer->transform) + ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform); + if (!ret) { + LOGE("prepareOverlay setParameter failed transform %x", + layer->transform); + return -1; + } + } + return 0; +} + static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { hwc_context_t* ctx = (hwc_context_t*)(dev); @@ -220,8 +304,19 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { // If there is a single Fullscreen layer, we can bypass it - TBD // If there is only one video/camera buffer, we can bypass itn if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { - list->hwLayers[i].compositionType = HWC_USE_OVERLAY; - list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; + if(prepareOverlay(ctx, &(list->hwLayers[i])) == 0) { + list->hwLayers[i].compositionType = HWC_USE_OVERLAY; + list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; + } else if (hwcModule->compositionType & (COMPOSITION_TYPE_C2D)) { + //Fail safe path: If drawing with overlay fails, + //Use C2D if available. + list->hwLayers[i].compositionType = HWC_USE_COPYBIT; + yuvBufferCount = 0; + } else { + //If C2D is not enabled fall back to GPU. + list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; + yuvBufferCount = 0; + } } else if (list->hwLayers[i].flags == HWC_USE_ORIGINAL_RESOLUTION) { list->hwLayers[i].compositionType = HWC_USE_OVERLAY; list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; @@ -371,83 +466,22 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { - int ret = 0; - if (ctx && ctx->mOverlayLibObject) { + if (ctx && ctx->mOverlayLibObject) { private_hwc_module_t* hwcModule = reinterpret_cast(ctx->device.common.module); if (!hwcModule) { LOGE("drawLayerUsingLayer null module "); return -1; } - private_handle_t *hnd = (private_handle_t *)layer->handle; overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; - int orientation = 0; - if (OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus()) - ovLibObject->getOrientation(orientation); - - if ((OVERLAY_CHANNEL_DOWN == ovLibObject->getChannelStatus()) - || (layer->transform != orientation) || - (hnd->flags & private_handle_t::PRIV_FLAGS_FORMAT_CHANGED)) { - // Overlay channel is not started, or we have an orientation change or there is a - // format change, call setSource to open the overlay if necessary - ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform, - (ovLibObject->getHDMIStatus()?true:false), false); - if (!ret) { - LOGE("drawLayerUsingOverlay setSource failed"); - return -1; - } - // Reset this flag so that we don't keep opening and closing channels unnecessarily - hnd->flags &= ~private_handle_t::PRIV_FLAGS_FORMAT_CHANGED; - } else { - // The overlay goemetry may have changed, we only need to update the overlay - ret = ovLibObject->updateOverlaySource(hnd->width, hnd->height, hnd->format, - layer->transform); - if (!ret) { - LOGE("drawLayerUsingOverlay updateOverlaySource failed"); - return -1; - } - } - - hwc_rect_t sourceCrop = layer->sourceCrop; - ret = ovLibObject->setCrop(sourceCrop.left, sourceCrop.top, - (sourceCrop.right - sourceCrop.left), - (sourceCrop.bottom-sourceCrop.top)); - if (!ret) { - LOGE("drawLayerUsingOverlay setCrop failed"); - return -1; - } - - if (layer->flags == HWC_USE_ORIGINAL_RESOLUTION) { - framebuffer_device_t* fbDev = hwcModule->fbDevice; - ret = ovLibObject->setPosition(0, 0, - fbDev->width, fbDev->height); - } else { - hwc_rect_t displayFrame = layer->displayFrame; - ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top, - (displayFrame.right - displayFrame.left), - (displayFrame.bottom-displayFrame.top)); - } - if (!ret) { - LOGE("drawLayerUsingOverlay setPosition failed"); - return -1; - } - - ovLibObject->getOrientation(orientation); - if (orientation != layer->transform) - ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform); - if (!ret) { - LOGE("drawLayerUsingOverlay setParameter failed transform %x", layer->transform); - return -1; - } - + int ret = 0; ret = ovLibObject->queueBuffer(hnd); if (!ret) { LOGE("drawLayerUsingOverlay queueBuffer failed"); return -1; } - return 0; } - return -1; + return 0; } static int hwc_set(hwc_composer_device_t *dev, @@ -472,7 +506,6 @@ static int hwc_set(hwc_composer_device_t *dev, if (list->hwLayers[i].flags == HWC_SKIP_LAYER) { continue; } - if (list->hwLayers[i].compositionType == HWC_USE_OVERLAY) { drawLayerUsingOverlay(ctx, &(list->hwLayers[i])); } else if (list->flags & HWC_SKIP_COMPOSITION) {