summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-06-20 14:13:46 +0200
committerThomas Hellstrom <thellstrom@vmware.com>2011-06-22 22:34:50 +0200
commit4d5aec4a7e4512145c76014591488cb5a98ff0ea (patch)
tree2b7d987ef2dc381f62006142f97f0da5c4c18356
parentf6a4690832143b01d419b52a4cb74350cdfa38bf (diff)
vmwgfx: Make present readbacks not cross scanout bounding box boundaries
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
-rw-r--r--vmwgfx/vmwgfx_saa.c47
1 files changed, 40 insertions, 7 deletions
diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c
index 55b5fea..f095b9f 100644
--- a/vmwgfx/vmwgfx_saa.c
+++ b/vmwgfx/vmwgfx_saa.c
@@ -245,11 +245,24 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa,
struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
RegionRec intersection;
+ RegionRec screen_intersection;
+ struct _WsbmListHead *list;
if (!spix->damage || !REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw) ||
!vpix->dirty_present)
return TRUE;
+ /*
+ * Flush dirty stuff to screen.
+ */
+
+
+ vsaa->present_flush(vsaa->pScreen);
+
+ /*
+ * Intersect dirty region with region to be read back, if any.
+ */
+
REGION_NULL(vsaa->pScreen, &intersection);
REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_hw);
REGION_INTERSECT(vsaa->pScreen, &intersection, &intersection,
@@ -261,24 +274,44 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa,
if (!REGION_NOTEMPTY(vsaa->pScreen, &intersection))
goto out;
- vsaa->present_flush(vsaa->pScreen);
+ /*
+ * Make really sure there is a GMR to read back to.
+ */
+
if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap))
goto out_err;
-
/*
- * FIXME: Cliprects may not overlap screen boundaries.
+ * Readback regions are not allowed to cross screen boundaries, so
+ * loop over all scanouts and make sure all readback calls are completely
+ * contained within a scanout bounding box.
*/
- if (vmwgfx_present_readback(vsaa->drm_fd, &intersection) != 0)
- goto out_err;
+ REGION_NULL(vsaa->pScreen, &screen_intersection);
+ WSBMLISTFOREACH(list, &vpix->scanout_list) {
+ struct vmwgfx_screen_box *box =
+ WSBMLISTENTRY(list, struct vmwgfx_screen_box, scanout_head);
+
+ REGION_RESET(vsaa->pScreen, &screen_intersection, &box->box);
+ REGION_INTERSECT(vsaa->pScreen, &screen_intersection,
+ &screen_intersection, &intersection);
+
+ if (vmwgfx_present_readback(vsaa->drm_fd, &intersection) != 0)
+ goto out_readback_err;
+
+ REGION_SUBTRACT(vsaa->pScreen, &intersection, &intersection,
+ &screen_intersection);
+ REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw,
+ &spix->dirty_hw, &screen_intersection);
+ }
- REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw,
- &spix->dirty_hw, &intersection);
+ REGION_UNINIT(vsaa->pScreen, &screen_intersection);
out:
REGION_UNINIT(vsaa->pScreen, &intersection);
return TRUE;
+ out_readback_err:
+ REGION_UNINIT(vsaa->pScreen, &screen_intersection);
out_err:
REGION_UNINIT(vsaa->pScreen, &intersection);
return FALSE;