diff options
Diffstat (limited to 'src/sna/gen4_render.c')
-rw-r--r-- | src/sna/gen4_render.c | 82 |
1 files changed, 52 insertions, 30 deletions
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c index c3a82a33..02454b21 100644 --- a/src/sna/gen4_render.c +++ b/src/sna/gen4_render.c @@ -2122,11 +2122,8 @@ try_blt(struct sna *sna, } static bool -is_gradient(PicturePtr picture) +check_gradient(PicturePtr picture) { - if (picture->pDrawable) - return FALSE; - switch (picture->pSourcePict->type) { case SourcePictTypeSolidFill: case SourcePictTypeLinear: @@ -2155,17 +2152,38 @@ need_upload(PicturePtr p) } static bool -source_fallback(PicturePtr p) +source_is_busy(PixmapPtr pixmap) +{ + struct sna_pixmap *priv = sna_pixmap(pixmap); + if (priv == NULL) + return false; + + if (priv->clear) + return false; + + if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) + return true; + + return priv->gpu_damage && !priv->cpu_damage; +} + +static bool +source_fallback(PicturePtr p, PixmapPtr pixmap) { if (sna_picture_is_solid(p, NULL)) return false; - return (has_alphamap(p) || - is_gradient(p) || - !gen4_check_filter(p) || - !gen4_check_repeat(p) || - !gen4_check_format(p->format) || - need_upload(p)); + if (p->pSourcePict) + return check_gradient(p); + + if (!gen4_check_repeat(p) || !gen4_check_format(p->format)) + return true; + + /* soft errors: perfer to upload/compute rather than readback */ + if (pixmap && source_is_busy(pixmap)) + return false; + + return has_alphamap(p) || !gen4_check_filter(p) || need_upload(p); } static bool @@ -2178,6 +2196,7 @@ gen4_composite_fallback(struct sna *sna, PixmapPtr src_pixmap; PixmapPtr mask_pixmap; PixmapPtr dst_pixmap; + bool src_fallback, mask_fallback; if (!gen4_check_dst_format(dst->format)) { DBG(("%s: unknown destination format: %d\n", @@ -2186,18 +2205,27 @@ gen4_composite_fallback(struct sna *sna, } dst_pixmap = get_drawable_pixmap(dst->pDrawable); + src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL; - mask_pixmap = (mask && mask->pDrawable) ? get_drawable_pixmap(mask->pDrawable) : NULL; + src_fallback = source_fallback(src, src_pixmap); + + if (mask) { + mask_pixmap = mask->pDrawable ? get_drawable_pixmap(mask->pDrawable) : NULL; + mask_fallback = source_fallback(mask, mask_pixmap); + } else { + mask_pixmap = NULL; + mask_fallback = false; + } /* If we are using the destination as a source and need to * readback in order to upload the source, do it all * on the cpu. */ - if (src_pixmap == dst_pixmap && source_fallback(src)) { + if (src_pixmap == dst_pixmap && src_fallback) { DBG(("%s: src is dst and will fallback\n",__FUNCTION__)); return TRUE; } - if (mask_pixmap == dst_pixmap && source_fallback(mask)) { + if (mask_pixmap == dst_pixmap && mask_fallback) { DBG(("%s: mask is dst and will fallback\n",__FUNCTION__)); return TRUE; } @@ -2210,34 +2238,28 @@ gen4_composite_fallback(struct sna *sna, return FALSE; } - if (src_pixmap && !source_fallback(src)) { - priv = sna_pixmap(src_pixmap); - if (priv && priv->gpu_damage && !priv->cpu_damage) { - DBG(("%s: src is already on the GPU, try to use GPU\n", - __FUNCTION__)); - return FALSE; - } + if (!src_fallback) { + DBG(("%s: src is already on the GPU, try to use GPU\n", + __FUNCTION__)); + return FALSE; } - if (mask_pixmap && !source_fallback(mask)) { - priv = sna_pixmap(mask_pixmap); - if (priv && priv->gpu_damage && !priv->cpu_damage) { - DBG(("%s: mask is already on the GPU, try to use GPU\n", - __FUNCTION__)); - return FALSE; - } + if (mask && !mask_fallback) { + DBG(("%s: mask is already on the GPU, try to use GPU\n", + __FUNCTION__)); + return FALSE; } /* However if the dst is not on the GPU and we need to * render one of the sources using the CPU, we may * as well do the entire operation in place onthe CPU. */ - if (source_fallback(src)) { + if (src_fallback) { DBG(("%s: dst is on the CPU and src will fallback\n", __FUNCTION__)); return TRUE; } - if (mask && source_fallback(mask)) { + if (mask && mask_fallback) { DBG(("%s: dst is on the CPU and mask will fallback\n", __FUNCTION__)); return TRUE; |