sna/gen8: Check offset alignment before using a userptr for RENDER

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=79053
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2014-06-06 08:30:59 +01:00
parent 1217dbc88e
commit 4fccfe3a51
1 changed files with 64 additions and 11 deletions

View File

@ -214,6 +214,35 @@ static inline bool too_large(int width, int height)
return width > GEN8_MAX_SIZE || height > GEN8_MAX_SIZE;
}
static bool unaligned(struct kgem_bo *bo, int bpp)
{
int x, y;
if (bo->proxy == NULL)
return false;
/* Assume that all tiled proxies are constructed correctly. */
if (bo->tiling)
return true;
DBG(("%s: checking alignment of a linear proxy, offset=%d, pitch=%d, bpp=%d: => (%d, %d)\n",
__FUNCTION__, bo->delta, bo->pitch, bpp,
8 * (bo->delta % bo->pitch) / bpp, bo->delta / bo->pitch));
/* This may be a random userptr map, check that it meets the
* render alignment of SURFACE_VALIGN_4 | SURFACE_HALIGN_4.
*/
y = bo->delta / bo->pitch;
if (y & 3)
return false;
x = 8 * (bo->delta - y * bo->pitch);
if (x & (4*bpp - 1))
return false;
return true;
}
static uint32_t gen8_get_blend(int op,
bool has_component_alpha,
uint32_t dst_format)
@ -1855,13 +1884,18 @@ gen8_composite_picture(struct sna *sna,
x, y, w, h, dst_x, dst_y);
}
static void gen8_composite_channel_convert(struct sna_composite_channel *channel)
static bool gen8_composite_channel_convert(struct sna_composite_channel *channel)
{
if (unaligned(channel->bo, PICT_FORMAT_BPP(channel->pict_format)))
return false;
channel->repeat = gen8_repeat(channel->repeat);
channel->filter = gen8_filter(channel->filter);
if (channel->card_format == (unsigned)-1)
channel->card_format = gen8_get_card_format(channel->pict_format);
assert(channel->card_format != (unsigned)-1);
return true;
}
static void gen8_render_composite_done(struct sna *sna,
@ -1917,6 +1951,9 @@ gen8_composite_set_target(struct sna *sna,
if (op->dst.bo == NULL)
return false;
if (unaligned(op->dst.bo, dst->pDrawable->bitsPerPixel))
return false;
get_drawable_deltas(dst->pDrawable, op->dst.pixmap,
&op->dst.x, &op->dst.y);
@ -2247,13 +2284,16 @@ gen8_render_composite(struct sna *sna,
case 1:
/* Did we just switch rings to prepare the source? */
if (mask == NULL &&
prefer_blt_composite(sna, tmp) &&
(prefer_blt_composite(sna, tmp) ||
unaligned(tmp->src.bo, PICT_FORMAT_BPP(tmp->src.pict_format))) &&
sna_blt_composite__convert(sna,
dst_x, dst_y, width, height,
tmp))
return true;
gen8_composite_channel_convert(&tmp->src);
if (!gen8_composite_channel_convert(&tmp->src))
goto cleanup_dst;
break;
}
@ -2298,7 +2338,8 @@ gen8_render_composite(struct sna *sna,
goto cleanup_src;
/* fall through to fixup */
case 1:
gen8_composite_channel_convert(&tmp->mask);
if (!gen8_composite_channel_convert(&tmp->mask))
goto cleanup_src;
break;
}
}
@ -2532,7 +2573,8 @@ gen8_render_composite_spans(struct sna *sna,
goto cleanup_dst;
/* fall through to fixup */
case 1:
gen8_composite_channel_convert(&tmp->base.src);
if (!gen8_composite_channel_convert(&tmp->base.src))
goto cleanup_dst;
break;
}
tmp->base.mask.bo = NULL;
@ -2712,7 +2754,9 @@ gen8_render_copy_boxes(struct sna *sna, uint8_t alu,
box, n))
return true;
if (!(alu == GXcopy || alu == GXclear)) {
if (!(alu == GXcopy || alu == GXclear) ||
unaligned(src_bo, src->drawable.bitsPerPixel) ||
unaligned(dst_bo, dst->drawable.bitsPerPixel)) {
fallback_blt:
DBG(("%s: fallback blt\n", __FUNCTION__));
if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
@ -2955,7 +2999,9 @@ gen8_render_copy(struct sna *sna, uint8_t alu,
if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo ||
too_large(src->drawable.width, src->drawable.height) ||
too_large(dst->drawable.width, dst->drawable.height)) {
too_large(dst->drawable.width, dst->drawable.height) ||
unaligned(src_bo, src->drawable.bitsPerPixel) ||
unaligned(dst_bo, dst->drawable.bitsPerPixel)) {
fallback:
if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
return false;
@ -3072,7 +3118,8 @@ gen8_render_fill_boxes(struct sna *sna,
}
if (prefer_blt_fill(sna, dst_bo, FILL_BOXES) ||
!gen8_check_dst_format(format)) {
!gen8_check_dst_format(format) ||
unaligned(dst_bo, PICT_FORMAT_BPP(format))) {
uint8_t alu = GXinvalid;
if (op <= PictOpSrc) {
@ -3301,7 +3348,8 @@ gen8_render_fill(struct sna *sna, uint8_t alu,
return true;
if (!(alu == GXcopy || alu == GXclear) ||
too_large(dst->drawable.width, dst->drawable.height))
too_large(dst->drawable.width, dst->drawable.height) ||
unaligned(dst_bo, dst->drawable.bitsPerPixel))
return sna_blt_fill(sna, alu,
dst_bo, dst->drawable.bitsPerPixel,
color,
@ -3387,7 +3435,8 @@ gen8_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
/* Must use the BLT if we can't RENDER... */
if (!(alu == GXcopy || alu == GXclear) ||
too_large(dst->drawable.width, dst->drawable.height))
too_large(dst->drawable.width, dst->drawable.height) ||
unaligned(bo, dst->drawable.bitsPerPixel))
return gen8_render_fill_one_try_blt(sna, dst, bo, color,
x1, y1, x2, y2, alu);
@ -3479,7 +3528,8 @@ gen8_render_clear(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo)
return true;
/* Must use the BLT if we can't RENDER... */
if (too_large(dst->drawable.width, dst->drawable.height))
if (too_large(dst->drawable.width, dst->drawable.height) ||
unaligned(bo, dst->drawable.bitsPerPixel))
return gen8_render_clear_try_blt(sna, dst, bo);
tmp.dst.pixmap = dst;
@ -3673,6 +3723,9 @@ gen8_render_video(struct sna *sna,
REGION_EXTENTS(NULL, dstRegion)->y2));
assert(priv->gpu_bo);
assert(!too_large(pixmap->drawable.width, pixmap->drawable.height));
assert(!unaligned(priv->gpu_bo, pixmap->drawable.bitsPerPixel));
memset(&tmp, 0, sizeof(tmp));
tmp.dst.pixmap = pixmap;