diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-29 11:02:38 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-29 14:47:12 +0000 |
commit | 5c6255ba2f12f04938fd586ca02562ee3cae05af (patch) | |
tree | 88f5f8899ff85566f60d76c142b069610c3b0255 | |
parent | 65466f86263b3788b438fe021a12ade371190b01 (diff) |
sna: Determine whether to use a partial proxy based on the pitch
On gen4+ devices the maximum render pitch is much larger than is simply
required for the maximum coordinates. This makes it possible to use
proxy textures as a subimage into the oversized texture without having
to blit into a temporary copy for virtually every single bo we use.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/gen2_render.c | 21 | ||||
-rw-r--r-- | src/sna/gen3_render.c | 16 | ||||
-rw-r--r-- | src/sna/gen4_render.c | 1 | ||||
-rw-r--r-- | src/sna/gen5_render.c | 1 | ||||
-rw-r--r-- | src/sna/gen6_render.c | 1 | ||||
-rw-r--r-- | src/sna/gen7_render.c | 1 | ||||
-rw-r--r-- | src/sna/kgem.c | 33 | ||||
-rw-r--r-- | src/sna/kgem.h | 2 | ||||
-rw-r--r-- | src/sna/sna_render.c | 157 | ||||
-rw-r--r-- | src/sna/sna_render.h | 1 |
10 files changed, 173 insertions, 61 deletions
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c index 2a97cea7..398988a3 100644 --- a/src/sna/gen2_render.c +++ b/src/sna/gen2_render.c @@ -55,6 +55,7 @@ #define PREFER_BLT_COPY 1 #define MAX_3D_SIZE 2048 +#define MAX_3D_PITCH 8192 #define BATCH(v) batch_emit(sna, v) #define BATCH_F(v) batch_emit_float(sna, v) @@ -547,7 +548,7 @@ gen2_get_batch(struct sna *sna) static void gen2_emit_target(struct sna *sna, const struct sna_composite_op *op) { - assert(op->dst.bo->pitch >= 8 && op->dst.bo->pitch <= 8192); + assert(op->dst.bo->pitch >= 8 && op->dst.bo->pitch <= MAX_3D_PITCH); assert(sna->render_state.gen2.vertex_offset == 0); if (sna->render_state.gen2.target == op->dst.bo->unique_id) { @@ -1736,7 +1737,7 @@ gen2_render_composite(struct sna *sna, tmp->op = op; if (too_large(tmp->dst.width, tmp->dst.height) || - tmp->dst.bo->pitch > 8192) { + tmp->dst.bo->pitch > MAX_3D_PITCH) { if (!sna_render_composite_redirect(sna, tmp, dst_x, dst_y, width, height)) return FALSE; @@ -2192,7 +2193,7 @@ gen2_render_composite_spans(struct sna *sna, tmp->base.op = op; if (too_large(tmp->base.dst.width, tmp->base.dst.height) || - tmp->base.dst.bo->pitch > 8192) { + tmp->base.dst.bo->pitch > MAX_3D_PITCH) { if (!sna_render_composite_redirect(sna, &tmp->base, dst_x, dst_y, width, height)) return FALSE; @@ -2388,7 +2389,7 @@ gen2_render_fill_boxes(struct sna *sna, color->red, color->green, color->blue, color->alpha)); if (too_large(dst->drawable.width, dst->drawable.height) || - dst_bo->pitch < 8 || dst_bo->pitch > 8192 || + dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH || !gen2_check_dst_format(format)) { DBG(("%s: try blt, too large or incompatible destination\n", __FUNCTION__)); @@ -2589,7 +2590,7 @@ gen2_render_fill(struct sna *sna, uint8_t alu, /* Must use the BLT if we can't RENDER... */ if (too_large(dst->drawable.width, dst->drawable.height) || - dst_bo->pitch < 8 || dst_bo->pitch > 8192) + dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH) return sna_blt_fill(sna, alu, dst_bo, dst->drawable.bitsPerPixel, color, @@ -2665,7 +2666,7 @@ gen2_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo, /* Must use the BLT if we can't RENDER... */ if (too_large(dst->drawable.width, dst->drawable.height) || - bo->pitch < 8 || bo->pitch > 8192) + bo->pitch < 8 || bo->pitch > MAX_3D_PITCH) return gen2_render_fill_one_try_blt(sna, dst, bo, color, x1, y1, x2, y2, alu); @@ -2832,9 +2833,9 @@ gen2_render_copy_boxes(struct sna *sna, uint8_t alu, if (src_bo == dst_bo || /* XXX handle overlap using 3D ? */ too_large(src->drawable.width, src->drawable.height) || - src_bo->pitch > 8192 || + src_bo->pitch > MAX_3D_PITCH || too_large(dst->drawable.width, dst->drawable.height) || - dst_bo->pitch < 8 || dst_bo->pitch > 8192) + dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH) return sna_blt_copy_boxes_fallback(sna, alu, src, src_bo, src_dx, src_dy, dst, dst_bo, dst_dx, dst_dy, @@ -2957,7 +2958,8 @@ gen2_render_copy(struct sna *sna, uint8_t alu, /* Must use the BLT if we can't RENDER... */ if (too_large(src->drawable.width, src->drawable.height) || too_large(dst->drawable.width, dst->drawable.height) || - src_bo->pitch > 8192 || dst_bo->pitch < 8 || dst_bo->pitch > 8192) { + src_bo->pitch > MAX_3D_PITCH || + dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH) { if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) return FALSE; @@ -3045,5 +3047,6 @@ Bool gen2_render_init(struct sna *sna) render->flush = gen2_render_flush; render->max_3d_size = MAX_3D_SIZE; + render->max_3d_pitch = MAX_3D_PITCH; return TRUE; } diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c index 931142d2..da90d823 100644 --- a/src/sna/gen3_render.c +++ b/src/sna/gen3_render.c @@ -65,6 +65,7 @@ enum { }; #define MAX_3D_SIZE 2048 +#define MAX_3D_PITCH 8192 #define OUT_BATCH(v) batch_emit(sna, v) #define OUT_BATCH_F(v) batch_emit_float(sna, v) @@ -143,7 +144,7 @@ static inline uint32_t gen3_buf_tiling(uint32_t tiling) static inline Bool gen3_check_pitch_3d(struct kgem_bo *bo) { - return bo->pitch <= 8192; + return bo->pitch <= MAX_3D_PITCH; } static uint32_t gen3_get_blend_cntl(int op, @@ -3826,9 +3827,9 @@ gen3_render_copy_boxes(struct sna *sna, uint8_t alu, if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo || /* XXX handle overlap using 3D ? */ - src_bo->pitch > 8192 || + src_bo->pitch > MAX_3D_PITCH || too_large(src->drawable.width, src->drawable.height) || - dst_bo->pitch > 8192 || + dst_bo->pitch > MAX_3D_PITCH || too_large(dst->drawable.width, dst->drawable.height)) return sna_blt_copy_boxes_fallback(sna, alu, src, src_bo, src_dx, src_dy, @@ -3959,7 +3960,7 @@ gen3_render_copy(struct sna *sna, uint8_t alu, if (!(alu == GXcopy || alu == GXclear) || too_large(src->drawable.width, src->drawable.height) || too_large(dst->drawable.width, dst->drawable.height) || - src_bo->pitch > 8192 || dst_bo->pitch > 8192) { + src_bo->pitch > MAX_3D_PITCH || dst_bo->pitch > MAX_3D_PITCH) { if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) return FALSE; @@ -4083,7 +4084,7 @@ gen3_render_fill_boxes(struct sna *sna, color->red, color->green, color->blue, color->alpha)); if (too_large(dst->drawable.width, dst->drawable.height) || - dst_bo->pitch > 8192 || + dst_bo->pitch > MAX_3D_PITCH || !gen3_check_dst_format(format)) { DBG(("%s: try blt, too large or incompatible destination\n", __FUNCTION__)); @@ -4265,7 +4266,7 @@ gen3_render_fill(struct sna *sna, uint8_t alu, /* Must use the BLT if we can't RENDER... */ if (!(alu == GXcopy || alu == GXclear) || too_large(dst->drawable.width, dst->drawable.height) || - dst_bo->pitch > 8192) + dst_bo->pitch > MAX_3D_PITCH) return sna_blt_fill(sna, alu, dst_bo, dst->drawable.bitsPerPixel, color, @@ -4346,7 +4347,7 @@ gen3_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) || - bo->pitch > 8192) + bo->pitch > MAX_3D_PITCH) return gen3_render_fill_one_try_blt(sna, dst, bo, color, x1, y1, x2, y2, alu); @@ -4424,5 +4425,6 @@ Bool gen3_render_init(struct sna *sna) render->fini = gen3_render_fini; render->max_3d_size = MAX_3D_SIZE; + render->max_3d_pitch = MAX_3D_PITCH; return TRUE; } diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c index 91d5f49e..d9542eae 100644 --- a/src/sna/gen4_render.c +++ b/src/sna/gen4_render.c @@ -3220,5 +3220,6 @@ Bool gen4_render_init(struct sna *sna) sna->render.fini = gen4_render_fini; sna->render.max_3d_size = 8192; + sna->render.max_3d_pitch = 1 << 18; return TRUE; } diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c index 2c6d020b..34651210 100644 --- a/src/sna/gen5_render.c +++ b/src/sna/gen5_render.c @@ -3702,5 +3702,6 @@ Bool gen5_render_init(struct sna *sna) sna->render.fini = gen5_render_fini; sna->render.max_3d_size = MAX_3D_SIZE; + sna->render.max_3d_pitch = 1 << 18; return TRUE; } diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c index 41e05d0e..0d244f18 100644 --- a/src/sna/gen6_render.c +++ b/src/sna/gen6_render.c @@ -4044,5 +4044,6 @@ Bool gen6_render_init(struct sna *sna) sna->render.fini = gen6_render_fini; sna->render.max_3d_size = GEN6_MAX_SIZE; + sna->render.max_3d_pitch = 1 << 18; return TRUE; } diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c index 282b7249..ff046315 100644 --- a/src/sna/gen7_render.c +++ b/src/sna/gen7_render.c @@ -4097,5 +4097,6 @@ Bool gen7_render_init(struct sna *sna) sna->render.fini = gen7_render_fini; sna->render.max_3d_size = GEN7_MAX_SIZE; + sna->render.max_3d_pitch = 1 << 18; return TRUE; } diff --git a/src/sna/kgem.c b/src/sna/kgem.c index 208c8f27..d062a1d6 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -704,6 +704,39 @@ static uint32_t kgem_untiled_pitch(struct kgem *kgem, return ALIGN(width, scanout ? 64 : kgem->min_alignment); } +void kgem_get_tile_size(struct kgem *kgem, int tiling, + int *tile_width, int *tile_height, int *tile_size) +{ + if (kgem->gen < 30) { + if (tiling) { + *tile_width = 512; + *tile_height = 16; + *tile_size = 2048; + } else { + *tile_width = 1; + *tile_height = 1; + *tile_size = 1; + } + } else switch (tiling) { + default: + case I915_TILING_NONE: + *tile_width = 1; + *tile_height = 1; + *tile_size = 1; + break; + case I915_TILING_X: + *tile_width = 512; + *tile_height = 8; + *tile_size = 4096; + break; + case I915_TILING_Y: + *tile_width = kgem->gen <= 30 ? 512 : 128; + *tile_height = 32; + *tile_size = 4096; + break; + } +} + static uint32_t kgem_surface_size(struct kgem *kgem, bool relaxed_fencing, bool scanout, diff --git a/src/sna/kgem.h b/src/sna/kgem.h index 2631e818..f3869673 100644 --- a/src/sna/kgem.h +++ b/src/sna/kgem.h @@ -361,6 +361,8 @@ Bool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo, const void *data, int length); int kgem_bo_fenced_size(struct kgem *kgem, struct kgem_bo *bo); +void kgem_get_tile_size(struct kgem *kgem, int tiling, + int *tile_width, int *tile_height, int *tile_size); static inline int kgem_bo_size(struct kgem_bo *bo) { diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c index 7077f363..abc6325b 100644 --- a/src/sna/sna_render.c +++ b/src/sna/sna_render.c @@ -816,10 +816,27 @@ 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; @@ -855,51 +872,65 @@ sna_render_picture_partial(struct sna *sna, } } - /* Presume worst case tile-row alignment for Y-tiling */ - box.y1 = box.y1 & (64 - 1); - box.y2 = ALIGN(box.y2, 64); + 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; + w = box.x2 - box.x1; h = box.y2 - box.y1; DBG(("%s box=(%d, %d), (%d, %d): (%d, %d)/(%d, %d)\n", __FUNCTION__, box.x1, box.y1, box.x2, box.y2, w, h, pixmap->drawable.width, pixmap->drawable.height)); - if (w <= 0 || h <= 0 || h > sna->render.max_3d_size) + if (w <= 0 || h <= 0 || + w > sna->render.max_3d_size || + h > sna->render.max_3d_size) return 0; - memset(&channel->embedded_transform, - 0, - sizeof(channel->embedded_transform)); - channel->embedded_transform.matrix[0][0] = 1 << 16; - channel->embedded_transform.matrix[0][2] = 0; - channel->embedded_transform.matrix[1][1] = 1 << 16; - channel->embedded_transform.matrix[1][2] = -box.y1 << 16; - channel->embedded_transform.matrix[2][2] = 1 << 16; - if (channel->transform) + /* 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); + if (channel->bo == NULL) + return 0; + + channel->bo->pitch = bo->pitch; + + if (channel->transform) { + memset(&channel->embedded_transform, + 0, + sizeof(channel->embedded_transform)); + channel->embedded_transform.matrix[0][0] = 1 << 16; + channel->embedded_transform.matrix[0][2] = -box.x1 << 16; + channel->embedded_transform.matrix[1][1] = 1 << 16; + channel->embedded_transform.matrix[1][2] = -box.y1 << 16; + channel->embedded_transform.matrix[2][2] = 1 << 16; pixman_transform_multiply(&channel->embedded_transform, &channel->embedded_transform, channel->transform); - channel->transform = &channel->embedded_transform; - - if (use_cpu_bo(sna, pixmap, &box)) { - if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ)) - return 0; - - bo = sna_pixmap(pixmap)->cpu_bo; + channel->transform = &channel->embedded_transform; } else { - if (!sna_pixmap_force_to_gpu(pixmap, MOVE_READ)) - return 0; - - bo = sna_pixmap(pixmap)->gpu_bo; + x -= box.x1; + y -= box.y1; } channel->offset[0] = x - dst_x; channel->offset[1] = y - dst_y; - channel->scale[0] = 1.f/pixmap->drawable.width; + channel->scale[0] = 1.f/w; channel->scale[1] = 1.f/h; - channel->width = pixmap->drawable.width; + channel->width = w; channel->height = h; - channel->bo = kgem_create_proxy(bo, box.y1 * bo->pitch, h * bo->pitch); - return channel->bo != NULL; + return 1; } int @@ -927,8 +958,7 @@ sna_render_picture_extract(struct sna *sna, return -1; } - if (pixmap->drawable.width < sna->render.max_3d_size && - sna_render_picture_partial(sna, picture, channel, + if (sna_render_picture_partial(sna, picture, channel, x, y, w, h, dst_x, dst_y)) return 1; @@ -1527,30 +1557,67 @@ sna_render_composite_redirect(struct sna *sna, return FALSE; } - if (op->dst.pixmap->drawable.width <= sna->render.max_3d_size) { - int y1, y2; + if (op->dst.bo->pitch <= sna->render.max_3d_pitch) { + int tile_width, tile_height, tile_size; + BoxRec box; + int w, h; - assert(op->dst.pixmap->drawable.height > sna->render.max_3d_size); - y1 = y + op->dst.y; - y2 = y1 + height; - y1 &= y1 & (64 - 1); - y2 = ALIGN(y2, 64); + 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 (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__, + box.x1, box.y1, box.x2, box.y2, w, h, + op->dst.pixmap->drawable.width, + op->dst.pixmap->drawable.height)); + if (w <= sna->render.max_3d_size && + h <= sna->render.max_3d_size) { + int offset; - if (y2 - y1 <= sna->render.max_3d_size) { t->box.x2 = t->box.x1 = op->dst.x; t->box.y2 = t->box.y1 = op->dst.y; - t->real_bo = priv->gpu_bo; + t->real_bo = op->dst.bo; t->real_damage = op->damage; if (op->damage) { t->damage = sna_damage_create(); op->damage = &t->damage; } - op->dst.bo = kgem_create_proxy(priv->gpu_bo, - y1 * priv->gpu_bo->pitch, - (y2 - y1) * priv->gpu_bo->pitch); - op->dst.y += -y1; - op->dst.height = y2 - y1; + /* 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); + if (!op->dst.bo) { + t->real_bo = NULL; + if (t->damage) + __sna_damage_destroy(t->damage); + return FALSE; + } + + op->dst.bo->pitch = t->real_bo->pitch; + + op->dst.x += -box.x1; + op->dst.y += -box.y1; + op->dst.width = w; + op->dst.height = h; return TRUE; } } @@ -1583,7 +1650,7 @@ sna_render_composite_redirect(struct sna *sna, return FALSE; } - t->real_bo = priv->gpu_bo; + t->real_bo = op->dst.bo; t->real_damage = op->damage; if (op->damage) { t->damage = sna_damage_create(); diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h index b23a8a72..5df53dc0 100644 --- a/src/sna/sna_render.h +++ b/src/sna/sna_render.h @@ -186,6 +186,7 @@ struct sna_copy_op { struct sna_render { int max_3d_size; + int max_3d_pitch; Bool (*composite)(struct sna *sna, uint8_t op, PicturePtr dst, PicturePtr src, PicturePtr mask, |