diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-02-07 13:32:20 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-02-07 13:32:20 +0000 |
commit | 58f634b792c6d109c5f2374a3e24d759e744abb4 (patch) | |
tree | f4d3c0f289cfd986bb663f72bb971adb60606fd4 | |
parent | bf3518ea910a2a3c5b4500dcba7c829576fbfd47 (diff) |
sna: Handle tile alignment for untiled large bo more carefully
We ended up trying to align the upper bound to zero as the integer
divsion of the tile width by pixel was zero.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/gen6_render.c | 12 | ||||
-rw-r--r-- | src/sna/sna_render.c | 150 |
2 files changed, 97 insertions, 65 deletions
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c index c4d23010..d337b300 100644 --- a/src/sna/gen6_render.c +++ b/src/sna/gen6_render.c @@ -3285,8 +3285,7 @@ fallback_blt: tmp.src.filter = SAMPLER_FILTER_NEAREST; tmp.src.repeat = SAMPLER_EXTEND_NONE; - tmp.src.card_format = - gen6_get_card_format(tmp.src.pict_format); + tmp.src.card_format = gen6_get_card_format(tmp.src.pict_format); if (too_large(src->drawable.width, src->drawable.height)) { BoxRec extents = box[0]; int i; @@ -3307,8 +3306,10 @@ fallback_blt: extents.x1 + src_dx, extents.y1 + src_dy, extents.x2 - extents.x1, - extents.y2 - extents.y1)) + extents.y2 - extents.y1)) { + DBG(("%s: unable to extract partial pixmap\n", __FUNCTION__)); goto fallback_tiled_dst; + } } else { tmp.src.bo = kgem_bo_reference(src_bo); tmp.src.width = src->drawable.width; @@ -3336,8 +3337,11 @@ fallback_blt: kgem_set_mode(&sna->kgem, KGEM_RENDER); if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) { kgem_submit(&sna->kgem); - if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) + if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) { + DBG(("%s: too large for a single operation\n", + __FUNCTION__)); goto fallback_tiled_src; + } _kgem_set_mode(&sna->kgem, KGEM_RENDER); } diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c index 3309157d..1625b91b 100644 --- a/src/sna/sna_render.c +++ b/src/sna/sna_render.c @@ -819,10 +819,10 @@ sna_render_pixmap_partial(struct sna *sna, int16_t w, int16_t h) { BoxRec box; - int tile_width, tile_height, tile_size; int offset; - DBG(("%s (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h)); + DBG(("%s (%d, %d)x(%d, %d), pitch %d, max %d\n", + __FUNCTION__, x, y, w, h, bo->pitch, sna->render.max_3d_pitch)); if (bo->pitch > sna->render.max_3d_pitch) return false; @@ -840,20 +840,32 @@ sna_render_pixmap_partial(struct sna *sna, box.x2 = pixmap->drawable.width; if (box.y2 > pixmap->drawable.height) box.y2 = pixmap->drawable.height; + DBG(("%s: unaligned box (%d, %d), (%d, %d)\n", + __FUNCTION__, box.x1, box.y1, box.x2, box.y2)); - kgem_get_tile_size(&sna->kgem, bo->tiling, - &tile_width, &tile_height, &tile_size); + if (bo->tiling) { + int tile_width, tile_height, tile_size; - /* Ensure we align to an even tile row */ - box.y1 = box.y1 & ~(2*tile_height - 1); - box.y2 = ALIGN(box.y2, 2*tile_height); - if (box.y2 > pixmap->drawable.height) - box.y2 = pixmap->drawable.height; + kgem_get_tile_size(&sna->kgem, bo->tiling, + &tile_width, &tile_height, &tile_size); + DBG(("%s: tile size for tiling %d: %dx%d, size=%d\n", + __FUNCTION__, bo->tiling, tile_width, tile_height, tile_size)); - box.x1 = box.x1 & ~(tile_width * 8 / pixmap->drawable.bitsPerPixel - 1); - box.x2 = ALIGN(box.x2, tile_width * 8 / pixmap->drawable.bitsPerPixel); - if (box.x2 > pixmap->drawable.width) - box.x2 = pixmap->drawable.width; + /* Ensure we align to an even tile row */ + box.y1 = box.y1 & ~(2*tile_height - 1); + box.y2 = ALIGN(box.y2, 2*tile_height); + if (box.y2 > pixmap->drawable.height) + box.y2 = pixmap->drawable.height; + + assert(tile_width * 8 >= pixmap->drawable.bitsPerPixel); + box.x1 = box.x1 & ~(tile_width * 8 / pixmap->drawable.bitsPerPixel - 1); + box.x2 = ALIGN(box.x2, tile_width * 8 / pixmap->drawable.bitsPerPixel); + if (box.x2 > pixmap->drawable.width) + box.x2 = pixmap->drawable.width; + + offset = box.x1 * pixmap->drawable.bitsPerPixel / 8 / tile_width * tile_size; + } else + offset = box.x1 * pixmap->drawable.bitsPerPixel / 8; w = box.x2 - box.x1; h = box.y2 - box.y1; @@ -862,11 +874,13 @@ sna_render_pixmap_partial(struct sna *sna, pixmap->drawable.width, pixmap->drawable.height)); if (w <= 0 || h <= 0 || w > sna->render.max_3d_size || - h > sna->render.max_3d_size) + h > sna->render.max_3d_size) { + DBG(("%s: box too large (%dx%d) for 3D pipeline (max %d)\n", + __FUNCTION__, w, h, sna->render.max_3d_size)); return false; + } /* How many tiles across are we? */ - offset = box.x1 * pixmap->drawable.bitsPerPixel / 8 / tile_width * tile_size; channel->bo = kgem_create_proxy(bo, box.y1 * bo->pitch + offset, h * bo->pitch); @@ -895,27 +909,11 @@ sna_render_picture_partial(struct sna *sna, struct kgem_bo *bo = NULL; PixmapPtr pixmap = get_drawable_pixmap(picture->pDrawable); BoxRec box; - int tile_width, tile_height, tile_size; int offset; DBG(("%s (%d, %d)x(%d, %d) [dst=(%d, %d)]\n", __FUNCTION__, x, y, w, h, dst_x, dst_y)); - if (use_cpu_bo(sna, pixmap, &box)) { - if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ)) - return 0; - - bo = sna_pixmap(pixmap)->cpu_bo; - } else { - if (!sna_pixmap_force_to_gpu(pixmap, MOVE_READ)) - return 0; - - bo = sna_pixmap(pixmap)->gpu_bo; - } - - if (bo->pitch > sna->render.max_3d_pitch) - return 0; - box.x1 = x; box.y1 = y; box.x2 = x + w; @@ -951,19 +949,41 @@ sna_render_picture_partial(struct sna *sna, } } - kgem_get_tile_size(&sna->kgem, bo->tiling, - &tile_width, &tile_height, &tile_size); + if (use_cpu_bo(sna, pixmap, &box)) { + if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ)) + return 0; - /* Ensure we align to an even tile row */ - box.y1 = box.y1 & ~(2*tile_height - 1); - box.y2 = ALIGN(box.y2, 2*tile_height); - if (box.y2 > pixmap->drawable.height) - box.y2 = pixmap->drawable.height; + bo = sna_pixmap(pixmap)->cpu_bo; + } else { + if (!sna_pixmap_force_to_gpu(pixmap, MOVE_READ)) + return 0; - box.x1 = box.x1 & ~(tile_width * 8 / pixmap->drawable.bitsPerPixel - 1); - box.x2 = ALIGN(box.x2, tile_width * 8 / pixmap->drawable.bitsPerPixel); - if (box.x2 > pixmap->drawable.width) - box.x2 = pixmap->drawable.width; + bo = sna_pixmap(pixmap)->gpu_bo; + } + + if (bo->pitch > sna->render.max_3d_pitch) + return 0; + + if (bo->tiling) { + int tile_width, tile_height, tile_size; + + kgem_get_tile_size(&sna->kgem, bo->tiling, + &tile_width, &tile_height, &tile_size); + + /* Ensure we align to an even tile row */ + box.y1 = box.y1 & ~(2*tile_height - 1); + box.y2 = ALIGN(box.y2, 2*tile_height); + if (box.y2 > pixmap->drawable.height) + box.y2 = pixmap->drawable.height; + + box.x1 = box.x1 & ~(tile_width * 8 / pixmap->drawable.bitsPerPixel - 1); + box.x2 = ALIGN(box.x2, tile_width * 8 / pixmap->drawable.bitsPerPixel); + if (box.x2 > pixmap->drawable.width) + box.x2 = pixmap->drawable.width; + + offset = box.x1 * pixmap->drawable.bitsPerPixel / 8 / tile_width * tile_size; + } else + offset = box.x1 * pixmap->drawable.bitsPerPixel / 8; w = box.x2 - box.x1; h = box.y2 - box.y1; @@ -976,7 +996,6 @@ sna_render_picture_partial(struct sna *sna, return 0; /* How many tiles across are we? */ - offset = box.x1 * pixmap->drawable.bitsPerPixel / 8 / tile_width * tile_size; channel->bo = kgem_create_proxy(bo, box.y1 * bo->pitch + offset, h * bo->pitch); @@ -1638,53 +1657,63 @@ sna_render_composite_redirect(struct sna *sna, return FALSE; #endif - DBG(("%s: target too large (%dx%d), copying to temporary %dx%d\n", - __FUNCTION__, op->dst.width, op->dst.height, width,height)); + DBG(("%s: target too large (%dx%d), copying to temporary %dx%d, max %d\n", + __FUNCTION__, + op->dst.width, op->dst.height, + width, height, + sna->render.max_3d_size)); if (!width || !height) return FALSE; - if (width > sna->render.max_3d_pitch || - height > sna->render.max_3d_pitch) + if (width > sna->render.max_3d_size || + height > sna->render.max_3d_size) return FALSE; if (op->dst.bo->pitch <= sna->render.max_3d_pitch) { - int tile_width, tile_height, tile_size; BoxRec box; - int w, h; + int w, h, offset; DBG(("%s: dst pitch (%d) fits within render pipeline (%d)\n", __FUNCTION__, op->dst.bo->pitch, sna->render.max_3d_pitch)); - kgem_get_tile_size(&sna->kgem, op->dst.bo->tiling, - &tile_width, &tile_height, &tile_size); - box.x1 = x; box.x2 = x + width; box.y1 = y; box.y2 = y + height; /* Ensure we align to an even tile row */ - box.y1 = box.y1 & ~(2*tile_height - 1); - box.y2 = ALIGN(box.y2, 2*tile_height); + if (op->dst.bo->tiling) { + int tile_width, tile_height, tile_size; + + kgem_get_tile_size(&sna->kgem, op->dst.bo->tiling, + &tile_width, &tile_height, &tile_size); + + box.y1 = box.y1 & ~(2*tile_height - 1); + box.y2 = ALIGN(box.y2, 2*tile_height); + + box.x1 = box.x1 & ~(tile_width * 8 / op->dst.pixmap->drawable.bitsPerPixel - 1); + box.x2 = ALIGN(box.x2, tile_width * 8 / op->dst.pixmap->drawable.bitsPerPixel); + + offset = box.x1 * op->dst.pixmap->drawable.bitsPerPixel / 8 / tile_width * tile_size; + } else + offset = box.x1 * op->dst.pixmap->drawable.bitsPerPixel / 8; + if (box.y2 > op->dst.pixmap->drawable.height) box.y2 = op->dst.pixmap->drawable.height; - box.x1 = box.x1 & ~(tile_width * 8 / op->dst.pixmap->drawable.bitsPerPixel - 1); - box.x2 = ALIGN(box.x2, tile_width * 8 / op->dst.pixmap->drawable.bitsPerPixel); if (box.x2 > op->dst.pixmap->drawable.width) box.x2 = op->dst.pixmap->drawable.width; w = box.x2 - box.x1; h = box.y2 - box.y1; - DBG(("%s box=(%d, %d), (%d, %d): (%d, %d)/(%d, %d)\n", __FUNCTION__, + DBG(("%s box=(%d, %d), (%d, %d): (%d, %d)/(%d, %d), max %d\n", __FUNCTION__, box.x1, box.y1, box.x2, box.y2, w, h, op->dst.pixmap->drawable.width, - op->dst.pixmap->drawable.height)); + op->dst.pixmap->drawable.height, + sna->render.max_3d_size)); if (w <= sna->render.max_3d_size && h <= sna->render.max_3d_size) { - int offset; - t->box.x2 = t->box.x1 = op->dst.x; t->box.y2 = t->box.y1 = op->dst.y; t->real_bo = op->dst.bo; @@ -1695,7 +1724,6 @@ sna_render_composite_redirect(struct sna *sna, } /* How many tiles across are we? */ - offset = box.x1 * op->dst.pixmap->drawable.bitsPerPixel / 8 / tile_width * tile_size; op->dst.bo = kgem_create_proxy(op->dst.bo, box.y1 * op->dst.bo->pitch + offset, h * op->dst.bo->pitch); |