drm_hwcomposer: Implement release and retire fences using sw_sync

Once drm supports passing sync through, we'll move onto that.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
Change-Id: I78bd5d380212b4aaec4b41dcba6cc882f1e5cc20
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index 0ae9381..ea60c36 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -32,6 +32,7 @@
 #include <hardware/hwcomposer.h>
 
 #include <sync/sync.h>
+#include <sw_sync.h>
 
 #include "drm_hwcomposer.h"
 
@@ -70,6 +71,9 @@
 
 	std::queue<struct hwc_drm_bo> buf_queue;
 	struct hwc_drm_bo front;
+
+	int timeline_fd;
+	unsigned timeline_next;
 };
 
 struct hwc_context_t {
@@ -348,6 +352,10 @@
 		ret = hwc_wait_and_set(hd, &buf);
 		if (ret)
 			ALOGE("Failed to wait and set %d", ret);
+
+		ret = sw_sync_timeline_inc(hd->timeline_fd, 1);
+		if (ret)
+			ALOGE("Failed to increment sync timeline %d", ret);
 	} while (true);
 
 out:
@@ -405,13 +413,23 @@
 		return ret;
 	}
 	buf.acquire_fence_fd = layer->acquireFenceFd;
-	layer->releaseFenceFd = -1;
 
 	ret = pthread_mutex_lock(&hd->set_worker.lock);
 	if (ret) {
 		ALOGE("Failed to lock set lock in set() %d", ret);
 		return ret;
 	}
+
+	/*
+	 * TODO: Retire and release can use the same sync point here b/c hwc is
+	 * restricted to one layer. Once that is no longer true, this will need
+	 * to change
+	 */
+	hd->timeline_next++;
+	display_contents->retireFenceFd = sw_sync_fence_create(hd->timeline_fd,
+					"drm_hwc_retire", hd->timeline_next);
+	layer->releaseFenceFd = sw_sync_fence_create(hd->timeline_fd,
+					"drm_hwc_release", hd->timeline_next);
 	hd->buf_queue.push(buf);
 
 	ret = pthread_cond_signal(&hd->set_worker.cond);
@@ -441,11 +459,7 @@
 	struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
 	int ret = 0, i;
 
-	/* TODO: Handle acquire & release fences */
-
 	for (i = 0; i < (int)num_displays && i < MAX_NUM_DISPLAYS; i++) {
-		display_contents[i]->retireFenceFd = -1; /* TODO: sync */
-
 		ret = hwc_set_display(ctx, i, display_contents[i]);
 	}
 
@@ -964,6 +978,13 @@
 	hd->active_config = -1;
 	hd->connector_id = connector_id;
 
+	ret = sw_sync_timeline_create();
+	if (ret < 0) {
+		ALOGE("Failed to create sw sync timeline %d", ret);
+		return ret;
+	}
+	hd->timeline_fd = ret;
+
 	ret = hwc_initialize_worker(hd, &hd->set_worker, hwc_set_worker);
 	if (ret) {
 		ALOGE("Failed to create set worker %d\n", ret);