From d3f7d5d614748306cc376d1929da2bbc14494a6e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 19 Jan 2012 11:15:38 +0000 Subject: [PATCH] sna: Only use the blitter to emit spans if we cannot stream the updates If either the region is busy on the gpu or if we need to read the destination then we would incur penalties for trying to perform the operation through the GTT. However, if we are simply streaming pixels to an unbusy bo then we can do so inplace faster than computing the corresponding GPU commands and uploading them. Signed-off-by: Chris Wilson --- src/sna/sna_accel.c | 71 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 08889f89..dd13eba7 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -60,7 +60,7 @@ #define USE_SPANS 0 #define USE_INPLACE 1 -#define USE_ZERO_SPANS 1 +#define USE_ZERO_SPANS 1 /* -1 force CPU, 1 force GPU */ #define USE_BO_FOR_SCRATCH_PIXMAP 1 #define MIGRATE_ALL 0 @@ -1148,8 +1148,6 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, if (flags & MOVE_INPLACE_HINT && priv->stride && priv->gpu_bo && - (DAMAGE_IS_ALL(priv->gpu_damage) || - region_inplace(sna, pixmap, region, priv)) && sna_pixmap_move_area_to_gpu(pixmap, ®ion->extents)) { kgem_bo_submit(&sna->kgem, priv->gpu_bo); @@ -5250,6 +5248,69 @@ sna_poly_line_extents(DrawablePtr drawable, GCPtr gc, return 1 | blt << 2 | clip << 1; } +/* Only use our spans code if the destination is busy and we can't perform + * the operation in place. + * + * Currently it looks to be faster to use the GPU for zero spans on all + * platforms. + */ +inline static bool +_use_zero_spans(DrawablePtr drawable, GCPtr gc, const BoxRec *extents) +{ + PixmapPtr pixmap; + struct sna_pixmap *priv; + BoxRec area; + int16_t dx, dy; + + if (USE_ZERO_SPANS) + return USE_ZERO_SPANS > 0; + + if ((drawable_gc_flags(drawable, gc, false) & MOVE_INPLACE_HINT) == 0) + return TRUE; + + /* XXX check for GPU stalls on the gc (stipple, tile, etc) */ + + pixmap = get_drawable_pixmap(drawable); + priv = sna_pixmap(pixmap); + if (priv == NULL) + return FALSE; + + if (DAMAGE_IS_ALL(priv->cpu_damage)) + return FALSE; + + if (priv->stride == 0 || priv->gpu_bo == NULL) + return FALSE; + + if (!kgem_bo_is_busy(priv->gpu_bo)) + return FALSE; + + if (DAMAGE_IS_ALL(priv->gpu_damage)) + return TRUE; + + if (priv->gpu_damage == NULL) + return FALSE; + + get_drawable_deltas(drawable, pixmap, &dx, &dy); + area = *extents; + area.x1 += dx; + area.x2 += dx; + area.y1 += dy; + area.y2 += dy; + DBG(("%s extents (%d, %d), (%d, %d)\n", __FUNCTION__, + area.x1, area.y1, area.x2, area.y2)); + + return sna_damage_contains_box(priv->gpu_damage, + &area) != PIXMAN_REGION_OUT; +} + +static bool +use_zero_spans(DrawablePtr drawable, GCPtr gc, const BoxRec *extents) +{ + bool ret = _use_zero_spans(drawable, gc, extents); + DBG(("%s? %d\n", __FUNCTION__, ret)); + return ret; +} + static void sna_poly_line(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr pt) @@ -5339,7 +5400,7 @@ sna_poly_line(DrawablePtr drawable, GCPtr gc, ®ion.extents, flags & 2)) return; } else { /* !rectilinear */ - if (USE_ZERO_SPANS && + if (use_zero_spans(drawable, gc, ®ion.extents) && sna_drawable_use_gpu_bo(drawable, ®ion.extents, &damage) && @@ -6219,7 +6280,7 @@ sna_poly_segment(DrawablePtr drawable, GCPtr gc, int n, xSegment *seg) ®ion.extents, flags & 2)) return; } else { - if (USE_ZERO_SPANS && + if (use_zero_spans(drawable, gc, ®ion.extents) && sna_drawable_use_gpu_bo(drawable, ®ion.extents, &damage) &&