diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2011-06-20 14:13:46 +0200 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2011-06-22 22:34:50 +0200 |
commit | 4d5aec4a7e4512145c76014591488cb5a98ff0ea (patch) | |
tree | 2b7d987ef2dc381f62006142f97f0da5c4c18356 /vmwgfx/vmwgfx_saa.c | |
parent | f6a4690832143b01d419b52a4cb74350cdfa38bf (diff) |
vmwgfx: Make present readbacks not cross scanout bounding box boundaries
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Diffstat (limited to 'vmwgfx/vmwgfx_saa.c')
-rw-r--r-- | vmwgfx/vmwgfx_saa.c | 47 |
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; |