diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2011-11-08 14:49:36 +0100 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2011-11-09 14:02:17 +0100 |
commit | d0b493d67afd1b5e8c8397c7938752ecd56c91ba (patch) | |
tree | 67ed19ad43d496011c167ccb8c8998fee092770e | |
parent | aff799d007c8383321213ad177e5a9deec2b3978 (diff) |
vmwgfx: A number of damage fixes
A damage tracker was sometimes attached to a pixmap in the middle of an
operation. That meant that damage was never registered for that operation
which caused dirty-tracking to fail. Instead, add a damage tracker as
soon as we have storage attached to the pixmap.
Also, when a pixmap was resized, the dirty region trackers could become
stale, and cause DMA operation extending outside of the pixmap with
server crashes as a result. This commit fixes that.
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Jakob Bornecrantz <jakob@vmware.com>
-rw-r--r-- | vmwgfx/vmwgfx_saa.c | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index bd90b3d..3c80ef2 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -34,8 +34,11 @@ #include "vmwgfx_drmi.h" #include "vmwgfx_saa_priv.h" +/* + * Damage to be added as soon as we attach storage to the pixmap. + */ static Bool -vmwgfx_pixmap_add_damage(PixmapPtr pixmap, Bool dirty_as_hw) +vmwgfx_pixmap_add_damage(PixmapPtr pixmap) { struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); @@ -53,10 +56,12 @@ vmwgfx_pixmap_add_damage(PixmapPtr pixmap, Bool dirty_as_hw) box.y1 = 0; box.y2 = draw->height; - if (dirty_as_hw && vpix->hw) { - REGION_INIT(draw->pScreen, &spix->dirty_hw, &box, 1); + if (vpix->hw) { + REGION_RESET(draw->pScreen, &spix->dirty_hw, &box); + REGION_EMPTY(draw->pScreen, &spix->dirty_shadow); } else { - REGION_INIT(draw->pScreen, &spix->dirty_shadow, &box, 1); + REGION_RESET(draw->pScreen, &spix->dirty_shadow, &box); + REGION_EMPTY(draw->pScreen, &spix->dirty_hw); } return TRUE; @@ -68,7 +73,7 @@ vmwgfx_pixmap_remove_damage(PixmapPtr pixmap) struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); - if (!spix->damage || (vpix->hw && vpix->gmr)) + if (!spix->damage || vpix->hw || vpix->gmr || vpix->malloc) return; DamageUnregister(&pixmap->drawable, spix->damage); @@ -115,18 +120,7 @@ vmwgfx_pixmap_add_present(PixmapPtr pixmap, Bool present_opt) if (!vpix->pending_present) goto out_no_pending_present; - /* - * We're not creating new storage here, so if there isn't already - * a damage tracker attached, there is either only sw storage or - * only hw storage, and we use that fact to determine where to put - * the initial dirty region. - */ - if (!vmwgfx_pixmap_add_damage(pixmap, vpix->hw != NULL)) - goto out_no_damage; - return TRUE; - out_no_damage: - REGION_DESTROY(pScreen, vpix->pending_present); out_no_pending_present: REGION_DESTROY(pScreen, vpix->pending_update); out_no_pending_update: @@ -179,7 +173,7 @@ vmwgfx_pixmap_create_gmr(struct vmwgfx_saa *vsaa, PixmapPtr pixmap) memcpy(addr, vpix->malloc, size); vmwgfx_dmabuf_unmap(gmr); - } else if (vpix->hw && !vmwgfx_pixmap_add_damage(pixmap, TRUE)) + } else if (!vmwgfx_pixmap_add_damage(pixmap)) goto out_no_transfer; vpix->backing |= VMWGFX_PIX_GMR; @@ -207,7 +201,7 @@ vmwgfx_pixmap_create_sw(struct vmwgfx_saa *vsaa, PixmapPtr pixmap) vpix->malloc = malloc(pixmap->devKind * pixmap->drawable.height); if (!vpix->malloc) goto out_no_malloc; - if (!vmwgfx_pixmap_add_damage(pixmap, TRUE)) + if (!vmwgfx_pixmap_add_damage(pixmap)) goto out_no_damage; } else if (vpix->backing & VMWGFX_PIX_GMR) return vmwgfx_pixmap_create_gmr(vsaa, pixmap); @@ -534,9 +528,12 @@ vmwgfx_pix_resize(PixmapPtr pixmap, unsigned int old_pitch, { ScreenPtr pScreen = pixmap->drawable.pScreen; struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen)); - struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); DrawablePtr draw = &pixmap->drawable; unsigned int size = pixmap->devKind * draw->height; + BoxRec b_box; + RegionRec b_reg; /* * Ignore copying errors. At worst they will show up as rendering @@ -589,6 +586,31 @@ vmwgfx_pix_resize(PixmapPtr pixmap, unsigned int old_pitch, xa_format_unknown, vpix->xa_flags, 1) != 0) return FALSE; } + + b_box.x1 = 0; + b_box.x2 = draw->width; + b_box.y1 = 0; + b_box.y2 = draw->height; + + REGION_INIT(pScreen, &b_reg, &b_box, 1); + REGION_INTERSECT(pScreen, &spix->dirty_shadow, &spix->dirty_shadow, + &b_reg); + REGION_INTERSECT(pScreen, &spix->dirty_hw, &spix->dirty_hw, &b_reg); + if (vpix->dirty_present) + REGION_INTERSECT(pScreen, vpix->dirty_present, vpix->dirty_present, + &b_reg); + if (vpix->pending_update) + REGION_INTERSECT(pScreen, vpix->pending_update, vpix->pending_update, + &b_reg); + if (vpix->pending_present) + REGION_INTERSECT(pScreen, vpix->pending_present, + vpix->pending_present, &b_reg); + if (vpix->present_damage) + REGION_INTERSECT(pScreen, vpix->present_damage, vpix->present_damage, + &b_reg); + + REGION_UNINIT(pScreen, &b_reg); + return TRUE; } @@ -743,7 +765,7 @@ vmwgfx_create_hw(struct vmwgfx_saa *vsaa, vpix->xa_flags = new_flags; - if ((vpix->gmr || vpix->malloc) && !vmwgfx_pixmap_add_damage(pixmap, FALSE)) + if (!vmwgfx_pixmap_add_damage(pixmap)) goto out_no_damage; /* |