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>
This commit is contained in:
Chris Wilson 2012-01-10 01:42:37 +00:00
parent 2ccb31c5a4
commit 87f73b0434
8 changed files with 178 additions and 31 deletions

View File

@ -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,

View File

@ -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));

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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;
}