hwc: keep gscaler streaming on between frames
authorGreg Hackmann <ghackmann@google.com>
Wed, 3 Oct 2012 23:28:19 +0000 (16:28 -0700)
committerGreg Hackmann <ghackmann@google.com>
Thu, 4 Oct 2012 18:00:47 +0000 (11:00 -0700)
Reconfiguring requires stopping and starting the stream, so only call
gsc_config_exclusive() when the configuration actually needs to be
changed.  Use the new gsc_wait_exclusive() operation to wait every frame
but only stop on cleanup.

Bug: 7202379
Change-Id: I28fc9f33a9345c91aef3f82098aeb668893f620e
Signed-off-by: Greg Hackmann <ghackmann@google.com>
libhwc/hwc.cpp

index c066583a2120c77b86c3d8319f1324aa3f0702af..aeb009aa41dd613ddb97dae0ccad8a65aa43d560 100644 (file)
@@ -1033,6 +1033,14 @@ static int exynos5_config_gsc_m2m(hwc_layer_1_t &layer,
     private_handle_t *dst_handle;
     int ret = 0;
 
+    if (layer.acquireFenceFd != -1) {
+        int err = sync_wait(layer.acquireFenceFd, 100);
+        if (err != 0)
+            ALOGW("fence didn't signal in 100 ms: %s", strerror(errno));
+        close(layer.acquireFenceFd);
+        layer.acquireFenceFd = -1;
+    }
+
     exynos_gsc_img src_cfg, dst_cfg;
     memset(&src_cfg, 0, sizeof(src_cfg));
     memset(&dst_cfg, 0, sizeof(dst_cfg));
@@ -1065,8 +1073,9 @@ static int exynos5_config_gsc_m2m(hwc_layer_1_t &layer,
     ALOGV("source configuration:");
     dump_gsc_img(src_cfg);
 
-    if (gsc_src_cfg_changed(src_cfg, gsc_data->src_cfg) ||
-            gsc_dst_cfg_changed(dst_cfg, gsc_data->dst_cfg)) {
+    bool reconfigure = gsc_src_cfg_changed(src_cfg, gsc_data->src_cfg) ||
+            gsc_dst_cfg_changed(dst_cfg, gsc_data->dst_cfg);
+    if (reconfigure) {
         int dst_stride;
         int usage = GRALLOC_USAGE_SW_READ_NEVER |
                 GRALLOC_USAGE_SW_WRITE_NEVER |
@@ -1120,10 +1129,12 @@ static int exynos5_config_gsc_m2m(hwc_layer_1_t &layer,
         }
     }
 
-    ret = exynos_gsc_config_exclusive(gsc_data->gsc, &src_cfg, &dst_cfg);
-    if (ret < 0) {
-        ALOGE("failed to configure gscaler %u", gsc_idx);
-        goto err_gsc_config;
+    if (reconfigure) {
+        ret = exynos_gsc_config_exclusive(gsc_data->gsc, &src_cfg, &dst_cfg);
+        if (ret < 0) {
+            ALOGE("failed to configure gscaler %u", gsc_idx);
+            goto err_gsc_config;
+        }
     }
 
     ret = exynos_gsc_run_exclusive(gsc_data->gsc, &src_cfg, &dst_cfg);
@@ -1132,6 +1143,12 @@ static int exynos5_config_gsc_m2m(hwc_layer_1_t &layer,
         goto err_gsc_config;
     }
 
+    ret = exynos_gsc_wait_frame_done_exclusive(gsc_data->gsc);
+    if (ret < 0) {
+        ALOGE("failed to wait for gscaler %u", gsc_idx);
+        goto err_gsc_config;
+    }
+
     gsc_data->src_cfg = src_cfg;
     gsc_data->dst_cfg = dst_cfg;
 
@@ -1162,6 +1179,7 @@ static void exynos5_cleanup_gsc_m2m(exynos5_hwc_composer_device_1_t *pdev,
 
     ALOGV("closing gscaler %u", AVAILABLE_GSC_UNITS[gsc_idx]);
 
+    exynos_gsc_stop_exclusive(gsc_data.gsc);
     exynos_gsc_destroy(gsc_data.gsc);
     for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++)
         if (gsc_data.dst_buf[i])
@@ -1271,14 +1289,6 @@ static int exynos5_post_fimd(exynos5_hwc_composer_device_1_t *pdev,
                 int gsc_idx = pdata->gsc_map[i].idx;
                 exynos5_gsc_data_t &gsc = pdev->gsc[gsc_idx];
 
-                if (layer.acquireFenceFd != -1) {
-                    int err = sync_wait(layer.acquireFenceFd, 100);
-                    if (err != 0)
-                        ALOGW("fence for layer %zu didn't signal in 100 ms: %s",
-                              i, strerror(errno));
-                    close(layer.acquireFenceFd);
-                }
-
                 // RGBX8888 surfaces are already in the right color order from the GPU,
                 // RGB565 and YUV surfaces need the Gscaler to swap R & B
                 int dst_format = HAL_PIXEL_FORMAT_BGRA_8888;
@@ -1289,17 +1299,11 @@ static int exynos5_post_fimd(exynos5_hwc_composer_device_1_t *pdev,
                 int err = exynos5_config_gsc_m2m(layer, pdev->alloc_device, &gsc,
                         gsc_idx, dst_format);
                 if (err < 0) {
-                    ALOGE("failed to queue gscaler %u input for layer %u",
+                    ALOGE("failed to configure gscaler %u for layer %u",
                             gsc_idx, i);
                     continue;
                 }
 
-                err = exynos_gsc_stop_exclusive(gsc.gsc);
-                if (err < 0) {
-                    ALOGE("failed to dequeue gscaler output for layer %u", i);
-                    continue;
-                }
-
                 buffer_handle_t dst_buf = gsc.dst_buf[gsc.current_buf];
                 gsc.current_buf = (gsc.current_buf + 1) % NUM_GSC_DST_BUFS;
                 private_handle_t *dst_handle =
@@ -1421,25 +1425,10 @@ static int exynos5_set_hdmi(exynos5_hwc_composer_device_1_t *pdev,
             ALOGV("HDMI video layer:");
             dump_layer(&layer);
 
-            if (layer.acquireFenceFd != -1) {
-                int err = sync_wait(layer.acquireFenceFd, 100);
-                if (err != 0)
-                    ALOGW("fence for layer %zu didn't signal in 100 ms: %s",
-                                                    i, strerror(errno));
-                close(layer.acquireFenceFd);
-                layer.acquireFenceFd = -1;
-            }
-
             exynos5_gsc_data_t &gsc = pdev->gsc[HDMI_GSC_IDX];
             exynos5_config_gsc_m2m(layer, pdev->alloc_device, &gsc, 1,
                                             HAL_PIXEL_FORMAT_RGBX_8888);
 
-            int err = exynos_gsc_stop_exclusive(gsc.gsc);
-            if (err < 0) {
-                ALOGE("failed to dequeue gscaler output for layer");
-                continue;
-            }
-
             buffer_handle_t dst_buf = gsc.dst_buf[gsc.current_buf];
             gsc.current_buf = (gsc.current_buf + 1) % NUM_GSC_DST_BUFS;
             private_handle_t *h = private_handle_t::dynamicCast(dst_buf);