diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-10 01:42:37 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-10 17:08:15 +0000 |
commit | 87f73b043426c47efa7670fb65bdcc7dfcf71fc3 (patch) | |
tree | 77cc6003904baed1a5d94d84078b465968be4433 | |
parent | 2ccb31c5a4120efb940168c5e52154add01b0586 (diff) |
sna/gen[23]: Tile render fill to oversized bo
If we are forced to perform a render operation to a bo too large to fit
in the pipeline, copy to an intermediate and split the operation into
tiles rather than fallback.
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 | 46 | ||||
-rw-r--r-- | src/sna/gen4_render.c | 8 | ||||
-rw-r--r-- | src/sna/gen5_render.c | 9 | ||||
-rw-r--r-- | src/sna/gen6_render.c | 9 | ||||
-rw-r--r-- | src/sna/gen7_render.c | 9 | ||||
-rw-r--r-- | src/sna/sna_render.h | 6 | ||||
-rw-r--r-- | src/sna/sna_tiling.c | 101 |
8 files changed, 178 insertions, 31 deletions
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c index 8f6a1647..30dd6941 100644 --- a/src/sna/gen2_render.c +++ b/src/sna/gen2_render.c @@ -112,7 +112,7 @@ static const struct formatinfo { static inline bool too_large(int width, int height) { - return (width | height) > MAX_3D_SIZE; + return width > MAX_3D_SIZE || height > MAX_3D_SIZE; } static inline uint32_t @@ -2365,10 +2365,21 @@ gen2_render_fill_boxes(struct sna *sna, if (too_large(dst->drawable.width, dst->drawable.height) || dst_bo->pitch < 8 || dst_bo->pitch > 8192 || - !gen2_check_dst_format(format)) - return gen2_render_fill_boxes_try_blt(sna, op, format, color, - dst, dst_bo, - box, n); + !gen2_check_dst_format(format)) { + DBG(("%s: try blt, too large or incompatible destination\n", + __FUNCTION__)); + if (gen2_render_fill_boxes_try_blt(sna, op, format, color, + dst, dst_bo, + box, n)) + return TRUE; + + if (!gen2_check_dst_format(format)) + return FALSE; + + assert(dst_bo->pitch >= 8); + return sna_tiling_fill_boxes(sna, op, format, color, + dst, dst_bo, box, n); + } if (prefer_blt_fill(sna) && gen2_render_fill_boxes_try_blt(sna, op, format, color, diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c index fcbe9c7d..f0255153 100644 --- a/src/sna/gen3_render.c +++ b/src/sna/gen3_render.c @@ -126,7 +126,7 @@ static const struct formatinfo { static inline bool too_large(int width, int height) { - return (width | height) > MAX_3D_SIZE; + return width > MAX_3D_SIZE || height > MAX_3D_SIZE; } static inline uint32_t gen3_buf_tiling(uint32_t tiling) @@ -3885,8 +3885,11 @@ gen3_render_fill_boxes_try_blt(struct sna *sna, uint8_t alu = GXcopy; uint32_t pixel; - if (dst_bo->tiling == I915_TILING_Y) + if (dst_bo->tiling == I915_TILING_Y) { + DBG(("%s: y-tiling, can't blit\n", __FUNCTION__)); + assert(!too_large(dst->drawable.width, dst->drawable.height)); return FALSE; + } if (color->alpha >= 0xff00) { if (op == PictOpOver) @@ -3905,15 +3908,18 @@ gen3_render_fill_boxes_try_blt(struct sna *sna, if (color->alpha <= 0x00ff) alu = GXclear; else if (!sna_get_pixel_from_rgba(&pixel, - color->red, - color->green, - color->blue, - color->alpha, - format)) + color->red, + color->green, + color->blue, + color->alpha, + format)) { + DBG(("%s: unknown format %x\n", __FUNCTION__, format)); return FALSE; - } else + } + } else { + DBG(("%s: unhandle op %d\n", __FUNCTION__, alu)); return FALSE; - + } return sna_blt_fill_boxes(sna, alu, dst_bo, dst->drawable.bitsPerPixel, @@ -3958,10 +3964,20 @@ gen3_render_fill_boxes(struct sna *sna, if (too_large(dst->drawable.width, dst->drawable.height) || dst_bo->pitch > 8192 || - !gen3_check_dst_format(format)) - return gen3_render_fill_boxes_try_blt(sna, op, format, color, - dst, dst_bo, - box, n); + !gen3_check_dst_format(format)) { + DBG(("%s: try blt, too large or incompatible destination\n", + __FUNCTION__)); + if (gen3_render_fill_boxes_try_blt(sna, op, format, color, + dst, dst_bo, + box, n)) + return TRUE; + + if (!gen3_check_dst_format(format)) + return FALSE; + + return sna_tiling_fill_boxes(sna, op, format, color, + dst, dst_bo, box, n); + } if (prefer_fill_blt(sna) && gen3_render_fill_boxes_try_blt(sna, op, format, color, @@ -3977,8 +3993,10 @@ gen3_render_fill_boxes(struct sna *sna, color->green, color->blue, color->alpha, - PICT_a8r8g8b8)) + PICT_a8r8g8b8)) { + assert(0); return FALSE; + } } DBG(("%s: using shader for op=%d, format=%x, pixel=%x\n", __FUNCTION__, op, (int)format, pixel)); diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c index cf6d947b..1df5bde5 100644 --- a/src/sna/gen4_render.c +++ b/src/sna/gen4_render.c @@ -2580,10 +2580,12 @@ gen4_render_fill_boxes(struct sna *sna, pixel, box, n)) return TRUE; - if (dst->drawable.width > 8192 || - dst->drawable.height > 8192 || - !gen4_check_dst_format(format)) + if (!gen4_check_dst_format(format)) return FALSE; + + if (dst->drawable.width > 8192 || dst->drawable.height > 8192) + return sna_tiling_fill_boxes(sna, op, format, color, + dst, dst_bo, box, n); } #if NO_FILL_BOXES diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c index f0bb1875..862f03e9 100644 --- a/src/sna/gen5_render.c +++ b/src/sna/gen5_render.c @@ -282,7 +282,7 @@ gen5_emit_pipelined_pointers(struct sna *sna, static inline bool too_large(int width, int height) { - return (width | height) > MAX_3D_SIZE; + return width > MAX_3D_SIZE || height > MAX_3D_SIZE; } static int @@ -2920,9 +2920,12 @@ gen5_render_fill_boxes(struct sna *sna, pixel, box, n)) return TRUE; - if (too_large(dst->drawable.width, dst->drawable.height) || - !gen5_check_dst_format(format)) + if (!gen5_check_dst_format(format)) return FALSE; + + if (too_large(dst->drawable.width, dst->drawable.height)) + return sna_tiling_fill_boxes(sna, op, format, color, + dst, dst_bo, box, n); } if (op == PictOpClear) diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c index e95cdd66..521b6f20 100644 --- a/src/sna/gen6_render.c +++ b/src/sna/gen6_render.c @@ -1954,7 +1954,7 @@ gen6_composite_solid_init(struct sna *sna, static inline bool too_large(int width, int height) { - return (width | height) > GEN6_MAX_SIZE; + return width > GEN6_MAX_SIZE || height > GEN6_MAX_SIZE; } static int @@ -3191,9 +3191,12 @@ gen6_render_fill_boxes(struct sna *sna, pixel, box, n)) return TRUE; - if (too_large(dst->drawable.width, dst->drawable.height) || - !gen6_check_dst_format(format)) + if (!gen6_check_dst_format(format)) return FALSE; + + if (too_large(dst->drawable.width, dst->drawable.height)) + return sna_tiling_fill_boxes(sna, op, format, color, + dst, dst_bo, box, n); } #if NO_FILL_BOXES diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c index 9d17c879..302a1dcf 100644 --- a/src/sna/gen7_render.c +++ b/src/sna/gen7_render.c @@ -2048,7 +2048,7 @@ gen7_composite_solid_init(struct sna *sna, static inline bool too_large(int width, int height) { - return (width | height) > GEN7_MAX_SIZE; + return width > GEN7_MAX_SIZE || height > GEN7_MAX_SIZE; } static int @@ -3247,9 +3247,12 @@ gen7_render_fill_boxes(struct sna *sna, pixel, box, n)) return TRUE; - if (too_large(dst->drawable.width, dst->drawable.height) || - !gen7_check_dst_format(format)) + if (!gen7_check_dst_format(format)) return FALSE; + + if (too_large(dst->drawable.width, dst->drawable.height)) + return sna_tiling_fill_boxes(sna, op, format, color, + dst, dst_bo, box, n); } #if NO_FILL_BOXES diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h index f780428d..19dfdfba 100644 --- a/src/sna/sna_render.h +++ b/src/sna/sna_render.h @@ -495,6 +495,12 @@ Bool sna_tiling_composite(uint32_t op, int16_t dst_x, int16_t dst_y, int16_t width, int16_t height, struct sna_composite_op *tmp); +Bool sna_tiling_fill_boxes(struct sna *sna, + CARD8 op, + PictFormat format, + const xRenderColor *color, + PixmapPtr dst, struct kgem_bo *dst_bo, + const BoxRec *box, int n); Bool sna_blt_composite(struct sna *sna, uint32_t op, diff --git a/src/sna/sna_tiling.c b/src/sna/sna_tiling.c index 6e681305..52572bc6 100644 --- a/src/sna/sna_tiling.c +++ b/src/sna/sna_tiling.c @@ -307,3 +307,104 @@ sna_tiling_composite(uint32_t op, tmp->u.priv = tile; return TRUE; } + +Bool +sna_tiling_fill_boxes(struct sna *sna, + CARD8 op, + PictFormat format, + const xRenderColor *color, + PixmapPtr dst, struct kgem_bo *dst_bo, + const BoxRec *box, int n) +{ + RegionRec region, tile, this; + struct kgem_bo *bo; + Bool ret = FALSE; + + pixman_region_init_rects(®ion, box, n); + + DBG(("%s (op=%d, format=%x, color=(%04x,%04x,%04x, %04x), tile.size=%d, box=%dx[(%d, %d), (%d, %d)])\n", + __FUNCTION__, op, (int)format, + color->red, color->green, color->blue, color->alpha, + sna->render.max_3d_size, n, + region.extents.x1, region.extents.y1, + region.extents.x2, region.extents.y2)); + + for (tile.extents.y1 = tile.extents.y2 = region.extents.y1; + tile.extents.y2 < region.extents.y2; + tile.extents.y1 = tile.extents.y2) { + tile.extents.y2 = tile.extents.y1 + sna->render.max_3d_size; + if (tile.extents.y2 > region.extents.y2) + tile.extents.y2 = region.extents.y2; + + for (tile.extents.x1 = tile.extents.x2 = region.extents.x1; + tile.extents.x2 < region.extents.x2; + tile.extents.x1 = tile.extents.x2) { + PixmapRec tmp; + + tile.extents.x2 = tile.extents.x1 + sna->render.max_3d_size; + if (tile.extents.x2 > region.extents.x2) + tile.extents.x2 = region.extents.x2; + + tile.data = NULL; + + RegionNull(&this); + RegionIntersect(&this, ®ion, &tile); + if (!RegionNotEmpty(&this)) + continue; + + tmp.drawable.width = this.extents.x2 - this.extents.x1; + tmp.drawable.height = this.extents.y2 - this.extents.y1; + tmp.drawable.depth = dst->drawable.depth; + tmp.drawable.bitsPerPixel = dst->drawable.bitsPerPixel; + tmp.devPrivate.ptr = NULL; + + bo = kgem_create_2d(&sna->kgem, + tmp.drawable.width, + tmp.drawable.height, + dst->drawable.bitsPerPixel, + kgem_choose_tiling(&sna->kgem, + I915_TILING_X, + tmp.drawable.width, + tmp.drawable.height, + dst->drawable.bitsPerPixel), + CREATE_SCANOUT); + if (bo) { + int16_t dx = this.extents.x1; + int16_t dy = this.extents.y1; + + assert(bo->pitch <= 8192); + assert(bo->tiling != I915_TILING_Y); + + if (!sna->render.copy_boxes(sna, GXcopy, + dst, dst_bo, 0, 0, + &tmp, bo, -dx, -dy, + REGION_RECTS(&this), REGION_NUM_RECTS(&this))) + goto err; + + RegionTranslate(&this, -dx, -dy); + if (!sna->render.fill_boxes(sna, op, format, color, + &tmp, bo, + REGION_RECTS(&this), REGION_NUM_RECTS(&this))) + goto err; + + if (!sna->render.copy_boxes(sna, GXcopy, + &tmp, bo, 0, 0, + dst, dst_bo, dx, dy, + REGION_RECTS(&this), REGION_NUM_RECTS(&this))) + goto err; + + kgem_bo_destroy(&sna->kgem, bo); + } + RegionUninit(&this); + } + } + + ret = TRUE; + goto done; +err: + kgem_bo_destroy(&sna->kgem, bo); + RegionUninit(&this); +done: + pixman_region_fini(®ion); + return ret; +} |