dri2,dumb: add dirty flag to omap bo and propagate it to mali-driver

Add a dirty flag to omap dumb buffers, set when host writes to a buffer.
The flag is conveyed to mali-driver via bit 0 in flags field of DRI2 buffer
structure and reset when rendered buffer arrives from mali-driver via
SwapBuffers. The flag is used by mali-driver to invalidate CRC surface
attached to the buffer, otherwise GPU would not write over what host has
written for the tiles that it thinks are identical to previous frame
(because they have the same CRC). Additionally the flag is also set on
newly created buffers to make sure CRC is not used for them as well.

While we are here, also move update of acquire_cnt and acquire_exclusive
to after ioctl succeeds.

CQ-DEPEND=*I24701eadf776234e88dd991cb39ad6cd4959b60e
BUG=chromium:374983
TEST=connect 1080 monitor to PeachPi, switch to mirror mode, disconnect\
monitor, powerd_dbus_suspend, connect monitor, resume

Change-Id: Ief69351a43c5d0a353801d4eea09905c248e9ed4
Signed-off-by: Dominik Behr <dbehr@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/203533
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
diff --git a/src/omap_dri2.c b/src/omap_dri2.c
index 1e4b02f..45a303e 100644
--- a/src/omap_dri2.c
+++ b/src/omap_dri2.c
@@ -240,7 +240,7 @@
 	DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap);
 	DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8;
 	DRIBUF(buf)->format = format;
-	DRIBUF(buf)->flags = 0;
+	DRIBUF(buf)->flags = omap_bo_get_dirty(bo) ? DRI2_ARMSOC_PRIVATE_CRC_DIRTY : 0;
 	buf->pPixmap = pPixmap;
 	buf->previous_canflip = -1;
 
@@ -518,6 +518,8 @@
 	src_priv = exaGetPixmapDriverPrivate(src->pPixmap);
 	dst_priv = exaGetPixmapDriverPrivate(dst->pPixmap);
 
+	/* src bo was just rendered to by GPU so it is not dirty */
+	omap_bo_clear_dirty(src_priv->bo);
 	new_canflip = canflip(pDraw, src_priv->bo);
 
 	/* If we can flip using a crtc scanout, switch the front buffer bo */
@@ -677,6 +679,7 @@
 	OMAPPixmapPrivPtr omap_priv = exaGetPixmapDriverPrivate(pPixmap);
 
 	buffer->name = omap_bo_get_name(omap_priv->bo);
+	buffer->flags = omap_bo_get_dirty(omap_priv->bo) ? DRI2_ARMSOC_PRIVATE_CRC_DIRTY : 0;
 }
 
 /**
diff --git a/src/omap_driver.h b/src/omap_driver.h
index a62255f..9862651 100644
--- a/src/omap_driver.h
+++ b/src/omap_driver.h
@@ -76,6 +76,7 @@
 /*#define OMAP_SUPPORT_GAMMA		1 -- Not supported on exynos*/
 
 #define MAX_SCANOUTS		3
+#define DRI2_ARMSOC_PRIVATE_CRC_DIRTY 1 /* DRI2 private buffer flag */
 
 typedef struct _OMAPScanout
 {
diff --git a/src/omap_dumb.c b/src/omap_dumb.c
index 712943a..742d959 100644
--- a/src/omap_dumb.c
+++ b/src/omap_dumb.c
@@ -53,6 +53,7 @@
 	int refcnt;
 	int acquired_exclusive;
 	int acquire_cnt;
+	int dirty;
 };
 
 enum {
@@ -178,6 +179,7 @@
 	new_buf->refcnt = 1;
 	new_buf->acquired_exclusive = 0;
 	new_buf->acquire_cnt = 0;
+	new_buf->dirty = TRUE;
 
 	return new_buf;
 
@@ -338,17 +340,22 @@
 		bo->acquire_cnt++;
 		return 0;
 	}
-	bo->acquired_exclusive = op & OMAP_GEM_WRITE;
-	bo->acquire_cnt++;
 	acquire.handle = bo->exynos_bo->handle;
 	acquire.flags = (op & OMAP_GEM_WRITE)
 		? DRM_EXYNOS_GEM_CPU_ACQUIRE_EXCLUSIVE
 		: DRM_EXYNOS_GEM_CPU_ACQUIRE_SHARED;
 	ret = drmIoctl(bo->dev->exynos_dev.fd, DRM_IOCTL_EXYNOS_GEM_CPU_ACQUIRE,
 			&acquire);
-	if (ret)
+	if (ret) {
 		ERROR_MSG("DRM_IOCTL_EXYNOS_GEM_CPU_ACQUIRE failed: %s",
 				strerror(errno));
+	} else {
+		bo->acquired_exclusive = op & OMAP_GEM_WRITE;
+		bo->acquire_cnt++;
+		if (bo->acquired_exclusive) {
+			bo->dirty = TRUE;
+		}
+	}
 	return ret;
 }
 
@@ -371,3 +378,14 @@
 				strerror(errno));
 	return ret;
 }
+
+int omap_bo_get_dirty(struct omap_bo *bo)
+{
+	return bo->dirty;
+}
+
+void omap_bo_clear_dirty(struct omap_bo *bo)
+{
+	bo->dirty = FALSE;
+}
+
diff --git a/src/omap_dumb.h b/src/omap_dumb.h
index f911edc..c1f29e7 100644
--- a/src/omap_dumb.h
+++ b/src/omap_dumb.h
@@ -44,6 +44,8 @@
 
 int omap_bo_cpu_prep(struct omap_bo *bo, enum omap_gem_op op);
 int omap_bo_cpu_fini(struct omap_bo *bo, enum omap_gem_op op);
+int omap_bo_get_dirty(struct omap_bo *bo);
+void omap_bo_clear_dirty(struct omap_bo *bo);
 
 struct omap_bo *omap_bo_new_with_depth(struct omap_device *dev, uint32_t width,
 		uint32_t height, uint8_t depth, uint8_t bpp);