sna/blt: Use SETUP_MONO to reduce the number of fill relocations

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2011-10-02 12:57:53 +01:00
parent 4d227d43f0
commit d8c96a6a1d
7 changed files with 301 additions and 38 deletions

View File

@ -2003,6 +2003,87 @@ gen2_render_fill(struct sna *sna, uint8_t alu,
return TRUE;
}
static Bool
gen2_render_fill_one_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
uint32_t color,
int16_t x1, int16_t y1, int16_t x2, int16_t y2,
uint8_t alu)
{
BoxRec box;
box.x1 = x1;
box.y1 = y1;
box.x2 = x2;
box.y2 = y2;
return sna_blt_fill_boxes(sna, alu,
bo, dst->drawable.bitsPerPixel,
color, &box, 1);
}
static Bool
gen2_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
uint32_t color,
int16_t x1, int16_t y1,
int16_t x2, int16_t y2,
uint8_t alu)
{
struct sna_composite_op tmp;
#if NO_FILL_BOXES
return gen2_render_fill_one_try_blt(sna, dst, bo, color,
x1, y1, x2, y2, alu);
#endif
/* Prefer to use the BLT if already engaged */
if (sna->kgem.mode != KGEM_RENDER &&
gen2_render_fill_one_try_blt(sna, dst, bo, color,
x1, y1, x2, y2, alu))
return TRUE;
/* Must use the BLT if we can't RENDER... */
if (!(alu == GXcopy || alu == GXclear) ||
dst->drawable.width > 2048 || dst->drawable.height > 2048 ||
bo->pitch > 8192)
return gen2_render_fill_one_try_blt(sna, dst, bo, color,
x1, y1, x2, y2, alu);
if (alu == GXclear)
color = 0;
memset(&tmp, 0, sizeof(tmp));
tmp.op = color == 0 ? PictOpClear : PictOpSrc;
tmp.dst.pixmap = dst;
tmp.dst.width = dst->drawable.width;
tmp.dst.height = dst->drawable.height;
tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
tmp.dst.bo = bo;
tmp.floats_per_vertex = 2;
tmp.src.u.gen2.pixel =
sna_rgba_for_color(color, dst->drawable.depth);
if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
kgem_submit(&sna->kgem);
if (gen2_render_fill_one_try_blt(sna, dst, bo, color,
x1, y1, x2, y2, alu))
return TRUE;
}
gen2_emit_fill_state(sna, &tmp);
gen2_get_rectangles(sna, &tmp, 1);
DBG((" (%d, %d), (%d, %d): %x\n", x1, y1, x2, y2, pixel));
OUT_VERTEX(x2);
OUT_VERTEX(y2);
OUT_VERTEX(x1);
OUT_VERTEX(y2);
OUT_VERTEX(x1);
OUT_VERTEX(y1);
gen2_vertex_flush(sna);
return TRUE;
}
static void
gen2_render_copy_setup_source(struct sna_composite_channel *channel,
PixmapPtr pixmap,
@ -2297,8 +2378,8 @@ Bool gen2_render_init(struct sna *sna)
render->composite = gen2_render_composite;
render->composite_spans = gen2_render_composite_spans;
render->fill_boxes = gen2_render_fill_boxes;
render->fill = gen2_render_fill;
render->fill_one = gen2_render_fill_one;
render->copy = gen2_render_copy;
render->copy_boxes = gen2_render_copy_boxes;

View File

@ -3659,6 +3659,90 @@ gen3_render_fill(struct sna *sna, uint8_t alu,
return TRUE;
}
static Bool
gen3_render_fill_one_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
uint32_t color,
int16_t x1, int16_t y1, int16_t x2, int16_t y2,
uint8_t alu)
{
BoxRec box;
box.x1 = x1;
box.y1 = y1;
box.x2 = x2;
box.y2 = y2;
return sna_blt_fill_boxes(sna, alu,
bo, dst->drawable.bitsPerPixel,
color, &box, 1);
}
static Bool
gen3_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
uint32_t color,
int16_t x1, int16_t y1,
int16_t x2, int16_t y2,
uint8_t alu)
{
struct sna_composite_op tmp;
#if NO_FILL_BOXES
return gen3_render_fill_one_try_blt(sna, dst, bo, color,
x1, y1, x2, y2, alu);
#endif
/* Prefer to use the BLT if already engaged */
if (sna->kgem.mode != KGEM_RENDER &&
gen3_render_fill_one_try_blt(sna, dst, bo, color,
x1, y1, x2, y2, alu))
return TRUE;
/* Must use the BLT if we can't RENDER... */
if (!(alu == GXcopy || alu == GXclear) ||
dst->drawable.width > 2048 || dst->drawable.height > 2048 ||
bo->pitch > 8192)
return gen3_render_fill_one_try_blt(sna, dst, bo, color,
x1, y1, x2, y2, alu);
if (alu == GXclear)
color = 0;
memset(&tmp, 0, sizeof(tmp));
tmp.op = color == 0 ? PictOpClear : PictOpSrc;
tmp.dst.pixmap = dst;
tmp.dst.width = dst->drawable.width;
tmp.dst.height = dst->drawable.height;
tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
tmp.dst.bo = bo;
tmp.floats_per_vertex = 2;
tmp.src.u.gen3.type = SHADER_CONSTANT;
tmp.src.u.gen3.mode =
sna_rgba_for_color(color, dst->drawable.depth);
if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
kgem_submit(&sna->kgem);
if (gen3_render_fill_one_try_blt(sna, dst, bo, color,
x1, y1, x2, y2, alu))
return TRUE;
}
gen3_emit_composite_state(sna, &tmp);
gen3_align_vertex(sna, &tmp);
gen3_get_rectangles(sna, &tmp, 1);
DBG((" (%d, %d), (%d, %d): %x\n", x1, y1, x2, y2, pixel));
OUT_VERTEX(x2);
OUT_VERTEX(y2);
OUT_VERTEX(x1);
OUT_VERTEX(y2);
OUT_VERTEX(x1);
OUT_VERTEX(y1);
gen3_vertex_flush(sna);
return TRUE;
}
static void gen3_render_flush(struct sna *sna)
{
gen3_vertex_finish(sna, TRUE);
@ -3683,6 +3767,7 @@ Bool gen3_render_init(struct sna *sna)
render->fill_boxes = gen3_render_fill_boxes;
render->fill = gen3_render_fill;
render->fill_one = gen3_render_fill_one;
render->reset = gen3_render_reset;
render->flush = gen3_render_flush;

View File

@ -1650,6 +1650,29 @@ sna_spans_extents(DrawablePtr drawable, GCPtr gc,
return box_empty(&box);
}
static struct sna_damage **
reduce_damage(DrawablePtr drawable,
struct sna_damage **damage,
const BoxRec *box)
{
PixmapPtr pixmap = get_drawable_pixmap(drawable);
int16_t dx, dy;
BoxRec r;
if (*damage == NULL)
return damage;
get_drawable_deltas(drawable, pixmap, &dx, &dy);
r = *box;
r.x1 += dx; r.x2 += dx;
r.y1 += dy; r.y2 += dy;
if (sna_damage_contains_box(*damage, &r) == PIXMAN_REGION_IN)
return NULL;
else
return damage;
}
static void
sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect);
@ -1702,13 +1725,14 @@ sna_fill_spans(DrawablePtr drawable, GCPtr gc, int n,
if (sna_drawable_use_gpu_bo(drawable, &extents) &&
sna_fill_spans_blt(drawable,
priv->gpu_bo,
priv->gpu_only ? NULL : &priv->gpu_damage,
priv->gpu_only ? NULL : reduce_damage(drawable, &priv->gpu_damage, &extents),
gc, n, pt, width, sorted))
return;
if (sna_drawable_use_cpu_bo(drawable, &extents) &&
sna_fill_spans_blt(drawable,
priv->cpu_bo, &priv->cpu_damage,
priv->cpu_bo,
reduce_damage(drawable, &priv->cpu_damage, &extents),
gc, n, pt, width, sorted))
return;
} else if (gc->fillStyle == FillTiled) {
@ -2556,6 +2580,33 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
DBG(("%s x %d [(%d, %d)+(%d, %d)...]\n",
__FUNCTION__, n, rect->x, rect->y, rect->width, rect->height));
if (n == 1 && REGION_NUM_RECTS(clip) == 1) {
BoxPtr box = REGION_RECTS(clip);
BoxRec r;
bool success = true;
r.x1 = rect->x + drawable->x;
r.y1 = rect->y + drawable->y;
r.x2 = bound(r.x1, rect->width);
r.y2 = bound(r.y1, rect->height);
if (box_intersect(&r, box)) {
get_drawable_deltas(drawable, pixmap, &dx, &dy);
r.x1 += dx; r.y1 += dy;
r.x2 += dx; r.y2 += dy;
if (sna->render.fill_one(sna, pixmap, bo, pixel,
r.x1, r.y1, r.x2, r.y2,
gc->alu)) {
if (damage) {
assert_pixmap_contains_box(pixmap, &r);
sna_damage_add_box(damage, &r);
}
} else
success = false;
}
return success;
}
if (!sna_fill_init_blt(&fill, sna, pixmap, bo, gc->alu, pixel)) {
DBG(("%s: unsupported blt\n", __FUNCTION__));
return FALSE;
@ -2935,14 +2986,14 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
if (sna_drawable_use_gpu_bo(draw, &extents) &&
sna_poly_fill_rect_blt(draw,
priv->gpu_bo,
priv->gpu_only ? NULL : &priv->gpu_damage,
priv->gpu_only ? NULL : reduce_damage(draw, &priv->gpu_damage, &extents),
gc, n, rect))
return;
if (sna_drawable_use_cpu_bo(draw, &extents) &&
sna_poly_fill_rect_blt(draw,
priv->cpu_bo,
&priv->cpu_damage,
reduce_damage(draw, &priv->cpu_damage, &extents),
gc, n, rect))
return;
} else if (gc->fillStyle == FillTiled) {
@ -2953,14 +3004,14 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
if (sna_drawable_use_gpu_bo(draw, &extents) &&
sna_poly_fill_rect_tiled(draw,
priv->gpu_bo,
priv->gpu_only ? NULL : &priv->gpu_damage,
priv->gpu_only ? NULL : reduce_damage(draw, &priv->gpu_damage, &extents),
gc, n, rect))
return;
if (sna_drawable_use_cpu_bo(draw, &extents) &&
sna_poly_fill_rect_tiled(draw,
priv->cpu_bo,
&priv->cpu_damage,
reduce_damage(draw, &priv->cpu_damage, &extents),
gc, n, rect))
return;
}

View File

@ -117,10 +117,9 @@ static bool sna_blt_fill_init(struct sna *sna,
struct kgem *kgem = &sna->kgem;
int pitch;
blt->bo[0] = bo;
blt->cmd = XY_COLOR_BLT_CMD;
blt->cmd = XY_SETUP_MONO_PATTERN_SL_BLT;
if (bpp == 32)
blt->cmd |= BLT_WRITE_ALPHA | BLT_WRITE_RGB;
@ -133,7 +132,7 @@ static bool sna_blt_fill_init(struct sna *sna,
return FALSE;
blt->overwrites = alu == GXcopy || alu == GXclear;
blt->br13 = (fill_ROP[alu] << 16) | pitch;
blt->br13 = 1<<31 | (fill_ROP[alu] << 16) | pitch;
switch (bpp) {
default: assert(0);
case 32: blt->br13 |= 1 << 25; /* RGB8888 */
@ -144,8 +143,29 @@ static bool sna_blt_fill_init(struct sna *sna,
blt->pixel = pixel;
kgem_set_mode(kgem, KGEM_BLT);
if (!kgem_check_bo_fenced(kgem, bo, NULL))
if (!kgem_check_bo_fenced(kgem, bo, NULL) ||
!kgem_check_batch(kgem, 3)) {
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
}
{
uint32_t *b = kgem->batch + kgem->nbatch;
b[0] = blt->cmd;
b[1] = blt->br13;
b[2] = 0;
b[3] = 0;
b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, bo,
I915_GEM_DOMAIN_RENDER << 16 |
I915_GEM_DOMAIN_RENDER |
KGEM_RELOC_FENCED,
0);
b[5] = pixel;
b[6] = pixel;
b[7] = 0;
b[8] = 0;
kgem->nbatch += 9;
}
return TRUE;
}
@ -165,36 +185,34 @@ static void sna_blt_fill_one(struct sna *sna,
assert(y >= 0);
assert((y+height) * blt->bo[0]->pitch <= blt->bo[0]->size);
/* All too frequently one blt completely overwrites the previous */
if (kgem->nbatch >= 6 &&
blt->overwrites &&
kgem->batch[kgem->nbatch-6] == blt->cmd &&
kgem->batch[kgem->nbatch-4] == ((uint32_t)y << 16 | (uint16_t)x) &&
kgem->batch[kgem->nbatch-3] == ((uint32_t)(y+height) << 16 | (uint16_t)(x+width)) &&
kgem->reloc[kgem->nreloc-1].target_handle == blt->bo[0]->handle) {
DBG(("%s: replacing last fill\n", __FUNCTION__));
kgem->batch[kgem->nbatch-5] = blt->br13;
kgem->batch[kgem->nbatch-1] = blt->pixel;
return;
if (!kgem_check_batch(kgem, 3)) {
_kgem_submit(kgem);
_kgem_set_mode(kgem, KGEM_BLT);
b = kgem->batch + kgem->nbatch;
b[0] = blt->cmd;
b[1] = blt->br13;
b[2] = 0;
b[3] = 0;
b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, blt->bo[0],
I915_GEM_DOMAIN_RENDER << 16 |
I915_GEM_DOMAIN_RENDER |
KGEM_RELOC_FENCED,
0);
b[5] = blt->pixel;
b[6] = blt->pixel;
b[7] = 0;
b[8] = 0;
kgem->nbatch += 9;
}
if (!kgem_check_batch(kgem, 6) ||
kgem->nreloc + 1 > KGEM_RELOC_SIZE(kgem))
_kgem_submit(kgem);
b = kgem->batch + kgem->nbatch;
b[0] = blt->cmd;
b[1] = blt->br13;
b[2] = (y << 16) | x;
b[3] = ((y + height) << 16) | (x + width);
b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4,
blt->bo[0],
I915_GEM_DOMAIN_RENDER << 16 |
I915_GEM_DOMAIN_RENDER |
KGEM_RELOC_FENCED,
0);
b[5] = blt->pixel;
kgem->nbatch += 6;
b[0] = XY_SCANLINE_BLT;
if (kgem->gen >= 40 && blt->bo[0]->tiling)
b[0] |= 1 << 11;
b[1] = (y << 16) | x;
b[2] = ((y + height) << 16) | (x + width);
kgem->nbatch += 3;
}
static Bool sna_blt_copy_init(struct sna *sna,

View File

@ -78,7 +78,10 @@
#define COLOR_BLT_CMD ((2<<29)|(0x40<<22)|(0x3))
#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|(0x4))
#define XY_SETUP_BLT_CMD ((2<<29)|(1<<22)|6)
#define XY_SETUP_MONO_PATTERN_SL_BLT ((2<<29)|(0x11<<22)|7)
#define XY_SETUP_CLIP_BLT_CMD ((2<<29)|(3<<22)|1)
#define XY_SCANLINE_BLT ((2<<29)|(0x25<<22)|1)
#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|0x4)
#define XY_PAT_BLT_IMMEDIATE ((2<<29)|(0x72<<22))

View File

@ -179,6 +179,26 @@ no_render_fill(struct sna *sna, uint8_t alu,
tmp);
}
static Bool
no_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
uint32_t color,
int16_t x1, int16_t y1, int16_t x2, int16_t y2,
uint8_t alu)
{
BoxRec box;
box.x1 = x1;
box.y1 = y1;
box.x2 = x2;
box.y2 = y2;
DBG(("%s (alu=%d, color=%08x) (%d,%d), (%d, %d)\n",
__FUNCTION__, alu, color, x1, y1, x2, y2));
return sna_blt_fill_boxes(sna, alu,
bo, dst->drawable.bitsPerPixel,
color, &box, 1);
}
static void no_render_reset(struct sna *sna)
{
(void)sna;
@ -216,6 +236,7 @@ void no_render_init(struct sna *sna)
render->fill_boxes = no_render_fill_boxes;
render->fill = no_render_fill;
render->fill_one = no_render_fill_one;
render->reset = no_render_reset;
render->flush = no_render_flush;

View File

@ -201,6 +201,10 @@ struct sna_render {
PixmapPtr dst, struct kgem_bo *dst_bo,
uint32_t color,
struct sna_fill_op *tmp);
Bool (*fill_one)(struct sna *sna, PixmapPtr dst, struct kgem_bo *dst_bo,
uint32_t color,
int16_t x1, int16_t y1, int16_t x2, int16_t y2,
uint8_t alu);
Bool (*copy_boxes)(struct sna *sna, uint8_t alu,
PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,