hwc: set retire fence fds
authorGreg Hackmann <ghackmann@google.com>
Tue, 2 Oct 2012 18:39:13 +0000 (11:39 -0700)
committerGreg Hackmann <ghackmann@google.com>
Fri, 16 Nov 2012 23:03:50 +0000 (15:03 -0800)
Change-Id: Iece6483e6402a9a425086b8ee8e67e17909b7d8a

libhwc/hwc.cpp

index c23e6f0e351286d15844e1c67f8e4f4e514a08e4..e210fc2ccdf7cb519c3f85a7c95c099c8c997021 100644 (file)
@@ -198,6 +198,22 @@ inline int HEIGHT(const hwc_rect &rect) { return rect.bottom - rect.top; }
 template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
 template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
 
+static int dup_or_warn(int fence)
+{
+    int dup_fd = dup(fence);
+    if (dup_fd < 0)
+        ALOGW("fence dup failed: %s", strerror(errno));
+    return dup_fd;
+}
+
+static int merge_or_warn(const char *name, int f1, int f2)
+{
+    int merge_fd = sync_merge(name, f1, f2);
+    if (merge_fd < 0)
+        ALOGW("fence merge failed: %s", strerror(errno));
+    return merge_fd;
+}
+
 template<typename T> void align_crop_and_center(T &w, T &h,
         hwc_rect_t *crop, size_t alignment)
 {
@@ -1487,9 +1503,7 @@ static int exynos5_set_fimd(exynos5_hwc_composer_device_1_t *pdev,
         if (pdev->bufs.overlay_map[i] != -1) {
             hwc_layer_1_t &layer =
                     contents->hwLayers[pdev->bufs.overlay_map[i]];
-            int dup_fd = dup(fence);
-            if (dup_fd < 0)
-                ALOGW("release fence dup failed: %s", strerror(errno));
+            int dup_fd = dup_or_warn(fence);
             if (pdev->bufs.gsc_map[i].mode == exynos5_gsc_map_t::GSC_M2M) {
                 int gsc_idx = pdev->bufs.gsc_map[i].idx;
                 exynos5_gsc_data_t &gsc = pdev->gsc[gsc_idx];
@@ -1500,7 +1514,7 @@ static int exynos5_set_fimd(exynos5_hwc_composer_device_1_t *pdev,
             }
         }
     }
-    close(fence);
+    contents->retireFenceFd = fence;
 
     return err;
 }
@@ -1557,6 +1571,14 @@ static int exynos5_set_hdmi(exynos5_hwc_composer_device_1_t *pdev,
 
             gsc.dst_buf_fence[gsc.current_buf] = releaseFenceFd;
             gsc.current_buf = (gsc.current_buf + 1) % NUM_GSC_DST_BUFS;
+            if (contents->retireFenceFd < 0)
+                contents->retireFenceFd = dup_or_warn(releaseFenceFd);
+            else {
+                int merged = merge_or_warn("hdmi",
+                        contents->retireFenceFd, layer.releaseFenceFd);
+                close(contents->retireFenceFd);
+                contents->retireFenceFd = merged;
+            }
         }
 
         if (layer.compositionType == HWC_FRAMEBUFFER_TARGET) {
@@ -1570,6 +1592,14 @@ static int exynos5_set_hdmi(exynos5_hwc_composer_device_1_t *pdev,
             hdmi_output(pdev, pdev->hdmi_layers[1], layer, h, layer.acquireFenceFd,
                                                              &layer.releaseFenceFd);
             fb_layer = &layer;
+            if (contents->retireFenceFd < 0)
+                contents->retireFenceFd = dup_or_warn(layer.releaseFenceFd);
+            else {
+                int merged = merge_or_warn("hdmi",
+                        contents->retireFenceFd, layer.releaseFenceFd);
+                close(contents->retireFenceFd);
+                contents->retireFenceFd = merged;
+            }
         }
     }