diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-09-25 16:41:11 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-09-25 16:41:11 +0100 |
commit | e9087f50bf6dafff87c566d3bdbe6cef29d71fde (patch) | |
tree | ce09429a9a0a7dfaf34a245720db3f922482fa60 | |
parent | 9f7c1a4c4f2a6352263c36e75a984ed4095adbc0 (diff) |
sna: Check scanout Pixmaps are the correct pitch and convert if necessary
As a final precaution, fixup the pitch on the bo to be used for
scanout by switching the bo on the Pixmap for a new correctly aligned
scanout bo.
Reported-by: Egbert Eich <eich@suse.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_display.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index e7908cb7..ea355aa2 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -1832,6 +1832,61 @@ static void set_shadow(struct sna *sna, RegionPtr region) priv->move_to_gpu_data = sna; } +static struct kgem_bo * +get_scanout_bo(struct sna *sna, PixmapPtr pixmap) +{ + struct sna_pixmap *priv; + + priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ | __MOVE_SCANOUT); + if (!priv) + return NULL; + + if (priv->gpu_bo->pitch & 63) { + struct kgem_bo *tmp; + BoxRec b; + + DBG(("%s: converting to scanout bo due to bad pitch [%d]\n", + __FUNCTION__, priv->gpu_bo->pitch)); + + if (priv->pinned) { + DBG(("%s: failed as the Pixmap is already pinned [%x]\n", + __FUNCTION__, priv->pinned)); + return NULL; + } + + tmp = kgem_create_2d(&sna->kgem, + pixmap->drawable.width, + pixmap->drawable.height, + sna->scrn->bitsPerPixel, + priv->gpu_bo->tiling, + CREATE_EXACT | CREATE_SCANOUT); + if (tmp == NULL) { + DBG(("%s: allocation failed\n", __FUNCTION__)); + return NULL; + } + + b.x1 = 0; + b.y1 = 0; + b.x2 = pixmap->drawable.width; + b.y2 = pixmap->drawable.height; + + if (sna->render.copy_boxes(sna, GXcopy, + &pixmap->drawable, priv->gpu_bo, 0, 0, + &pixmap->drawable, tmp, 0, 0, + &b, 1, COPY_LAST)) { + DBG(("%s: copy failed\n", __FUNCTION__)); + kgem_bo_destroy(&sna->kgem, tmp); + return NULL; + } + + kgem_bo_destroy(&sna->kgem, priv->gpu_bo); + priv->gpu_bo = tmp; + } + + priv->pinned |= PIN_SCANOUT; + return priv->gpu_bo; +} + static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc) { struct sna_crtc *sna_crtc = to_sna_crtc(crtc); @@ -1937,7 +1992,7 @@ out_shadow: if (sna_crtc->slave_pixmap) { DBG(("%s: attaching to scanout pixmap\n", __FUNCTION__)); - bo = sna_pixmap_pin(sna_crtc->slave_pixmap, PIN_SCANOUT); + bo = get_scanout_bo(sna, sna_crtc->slave_pixmap); if (bo == NULL) { DBG(("%s: failed to pin crtc scanout\n", __FUNCTION__)); sna_crtc->fallback_shadow = true; @@ -1953,7 +2008,7 @@ out_shadow: } } else { DBG(("%s: attaching to framebuffer\n", __FUNCTION__)); - bo = sna_pixmap_pin(sna->front, PIN_SCANOUT); + bo = get_scanout_bo(sna, sna->front); if (bo == NULL) { DBG(("%s: failed to pin framebuffer\n", __FUNCTION__)); sna_crtc->fallback_shadow = true; |