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:
parent
4d227d43f0
commit
d8c96a6a1d
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue