summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-01-10 01:42:37 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-01-10 17:08:15 +0000
commit87f73b043426c47efa7670fb65bdcc7dfcf71fc3 (patch)
tree77cc6003904baed1a5d94d84078b465968be4433
parent2ccb31c5a4120efb940168c5e52154add01b0586 (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.c21
-rw-r--r--src/sna/gen3_render.c46
-rw-r--r--src/sna/gen4_render.c8
-rw-r--r--src/sna/gen5_render.c9
-rw-r--r--src/sna/gen6_render.c9
-rw-r--r--src/sna/gen7_render.c9
-rw-r--r--src/sna/sna_render.h6
-rw-r--r--src/sna/sna_tiling.c101
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(&region, 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, &region, &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(&region);
+ return ret;
+}