From ec13dead1baa6ffb18efd08f33aef9be52707b49 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Mon, 8 Oct 2012 14:54:45 -0700 Subject: [PATCH] hwc: always make forward progress in fimd set() If the FIMD's set() fails for any reason, post a black screen to ensure forward progress, and try setting the HDMI contents anyway. If the black screen fails something has gone horribly wrong, so terminate the runtime. Bug: 7304464 Change-Id: I6d7333574286e3a87c990c2476c5d987613067d8 Signed-off-by: Greg Hackmann --- libhwc/hwc.cpp | 55 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/libhwc/hwc.cpp b/libhwc/hwc.cpp index f2164f2..3b15e7c 100644 --- a/libhwc/hwc.cpp +++ b/libhwc/hwc.cpp @@ -1345,6 +1345,20 @@ static int exynos5_post_fimd(exynos5_hwc_composer_device_1_t *pdev, return win_data.fence; } +static int exynos5_clear_fimd(exynos5_hwc_composer_device_1_t *pdev) +{ + struct s3c_fb_win_config_data win_data; + memset(&win_data, 0, sizeof(win_data)); + + int ret = ioctl(pdev->fd, S3CFB_WIN_CONFIG, &win_data); + LOG_ALWAYS_FATAL_IF(ret < 0, + "ioctl S3CFB_WIN_CONFIG failed to clear screen: %s", + strerror(errno)); + // the causes of an empty config failing are all unrecoverable + + return win_data.fence; +} + static int exynos5_set_fimd(exynos5_hwc_composer_device_1_t *pdev, hwc_display_contents_1_t* contents) { @@ -1352,6 +1366,7 @@ static int exynos5_set_fimd(exynos5_hwc_composer_device_1_t *pdev, return 0; hwc_layer_1_t *fb_layer = NULL; + int err = 0; if (pdev->bufs.fb_window != NO_FB_NEEDED) { for (size_t i = 0; i < contents->numHwLayers; i++) { @@ -1365,16 +1380,22 @@ static int exynos5_set_fimd(exynos5_hwc_composer_device_1_t *pdev, if (CC_UNLIKELY(!fb_layer)) { ALOGE("framebuffer target expected, but not provided"); - return -EINVAL; + err = -EINVAL; + } else { + ALOGV("framebuffer target buffer:"); + dump_layer(fb_layer); } + } - ALOGV("framebuffer target buffer:"); - dump_layer(fb_layer); + int fence; + if (!err) { + fence = exynos5_post_fimd(pdev, contents); + if (fence < 0) + err = fence; } - int fence = exynos5_post_fimd(pdev, contents); - if (fence < 0) - return fence; + if (err) + fence = exynos5_clear_fimd(pdev); for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { if (pdev->bufs.overlay_map[i] != -1 && @@ -1389,7 +1410,7 @@ static int exynos5_set_fimd(exynos5_hwc_composer_device_1_t *pdev, } close(fence); - return 0; + return err; } static int exynos5_set_hdmi(exynos5_hwc_composer_device_1_t *pdev, @@ -1476,20 +1497,18 @@ static int exynos5_set(struct hwc_composer_device_1 *dev, (exynos5_hwc_composer_device_1_t *)dev; hwc_display_contents_1_t *fimd_contents = displays[HWC_DISPLAY_PRIMARY]; hwc_display_contents_1_t *hdmi_contents = displays[HWC_DISPLAY_EXTERNAL]; + int fimd_err = 0, hdmi_err = 0; - if (fimd_contents) { - int err = exynos5_set_fimd(pdev, fimd_contents); - if (err) - return err; - } + if (fimd_contents) + fimd_err = exynos5_set_fimd(pdev, fimd_contents); - if (hdmi_contents) { - int err = exynos5_set_hdmi(pdev, hdmi_contents); - if (err) - return err; - } + if (hdmi_contents) + hdmi_err = exynos5_set_hdmi(pdev, hdmi_contents); - return 0; + if (fimd_err) + return fimd_err; + + return hdmi_err; } static void exynos5_registerProcs(struct hwc_composer_device_1* dev, -- 2.20.1