diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-07-22 11:19:13 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-07-22 16:28:07 +0100 |
commit | 7d4a3e371beea65bf66e54ae13789d6d5ca91f8b (patch) | |
tree | 5b96c7c14660292bf87676c0cd7516288f393524 | |
parent | 40e0cf32a25e43e16184b2af87a1e1abeb8e4052 (diff) |
sna: Use an upload buffer for large stipples
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_accel.c | 335 |
1 files changed, 310 insertions, 25 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 0b0a3044..f39052fd 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -3519,9 +3519,7 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region, } while (--bh); b = sna->kgem.batch + sna->kgem.nbatch; - b[0] = XY_MONO_SRC_COPY; - if (drawable->bitsPerPixel == 32) - b[0] |= 3 << 20; + b[0] = XY_MONO_SRC_COPY | 3 << 20; b[0] |= ((box->x1 - x) & 7) << 17; b[1] = bo->pitch; if (sna->kgem.gen >= 40 && bo->tiling) { @@ -3649,9 +3647,7 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region, } while (--bh); b = sna->kgem.batch + sna->kgem.nbatch; - b[0] = XY_FULL_MONO_PATTERN_MONO_SRC_BLT; - if (drawable->bitsPerPixel == 32) - b[0] |= 3 << 20; + b[0] = XY_FULL_MONO_PATTERN_MONO_SRC_BLT | 3 << 20; b[0] |= ((box->x1 - x) & 7) << 17; b[1] = bo->pitch; if (sna->kgem.gen >= 40 && bo->tiling) { @@ -5852,9 +5848,7 @@ sna_copy_plane_blt(DrawablePtr source, DrawablePtr drawable, GCPtr gc, get_drawable_deltas(drawable, dst_pixmap, &dx, &dy); assert_pixmap_contains_boxes(dst_pixmap, box, n, dx, dy); - br00 = XY_MONO_SRC_COPY; - if (drawable->bitsPerPixel == 32) - br00 |= 3 << 20; + br00 = XY_MONO_SRC_COPY | 3 << 20; br13 = arg->bo->pitch; if (sna->kgem.gen >= 40 && arg->bo->tiling) { br00 |= BLT_DST_TILED; @@ -9667,9 +9661,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable, unsigned px = (0 - gc->patOrg.x - dx) & 7; unsigned py = (0 - gc->patOrg.y - dy) & 7; DBG(("%s: pat offset (%d, %d)\n", __FUNCTION__ ,px, py)); - br00 = XY_MONO_PAT | px << 12 | py << 8; - if (drawable->bitsPerPixel == 32) - br00 |= 3 << 20; + br00 = XY_MONO_PAT | px << 12 | py << 8 | 3 << 20; br13 = bo->pitch; if (sna->kgem.gen >= 40 && bo->tiling) { @@ -10327,12 +10319,12 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable, } static void -sna_poly_fill_rect_stippled_n_box(struct sna *sna, - struct kgem_bo *bo, - uint32_t br00, uint32_t br13, - GCPtr gc, - const BoxRec *box, - const DDXPointRec *origin) +sna_poly_fill_rect_stippled_n_box__imm(struct sna *sna, + struct kgem_bo *bo, + uint32_t br00, uint32_t br13, + const GC *gc, + const BoxRec *box, + const DDXPointRec *origin) { int x1, x2, y1, y2; uint32_t *b; @@ -10415,6 +10407,299 @@ sna_poly_fill_rect_stippled_n_box(struct sna *sna, } } +static void +sna_poly_fill_rect_stippled_n_box(struct sna *sna, + struct kgem_bo *bo, + uint32_t br00, uint32_t br13, + const GC *gc, + const BoxRec *box, + const DDXPointRec *origin) +{ + int x1, x2, y1, y2; + int w = gc->stipple->drawable.width; + int h = gc->stipple->drawable.height; + int stride = gc->stipple->devKind; + uint32_t *b; + + if ((((box->y2-box->y1) | (box->x2-box->x1)) & ~31) == 0) { + br00 = XY_MONO_SRC_COPY_IMM |(br00 & (BLT_DST_TILED | 3 << 20)); + sna_poly_fill_rect_stippled_n_box__imm(sna, bo, + br00, br13, gc, + box, origin); + return; + } + + for (y1 = box->y1; y1 < box->y2; y1 = y2) { + int row, oy = (y1 - origin->y) % gc->stipple->drawable.height; + if (oy < 0) + oy += h; + + y2 = box->y2; + if (y2 - y1 > h - oy) + y2 = y1 + h - oy; + + row = oy * stride; + for (x1 = box->x1; x1 < box->x2; x1 = x2) { + int bx1, bx2, bw, bh, len, ox; + + x2 = box->x2; + ox = (x1 - origin->x) % w; + if (ox < 0) + ox += w; + bx1 = ox & ~7; + bx2 = ox + (x2 - x1); + if (bx2 > w) { + bx2 = w; + x2 = x1 + bx2-ox; + } + + DBG(("%s: box((%d, %d)x(%d, %d)) origin=(%d, %d), pat=(%d, %d), up=(%d, %d), stipple=%dx%d\n", + __FUNCTION__, + x1, y1, x2-x1, y2-y1, + origin->x, origin->y, + ox, oy, bx1, bx2, w, h)); + + bw = (bx2 - bx1 + 7)/8; + bw = ALIGN(bw, 2); + bh = y2 - y1; + + len = bw*bh; + len = ALIGN(len, 8) / 4; + if (!kgem_check_batch(&sna->kgem, 7+len) || + !kgem_check_bo_fenced(&sna->kgem, bo) || + !kgem_check_reloc(&sna->kgem, 2)) { + _kgem_submit(&sna->kgem); + _kgem_set_mode(&sna->kgem, KGEM_BLT); + } + + b = sna->kgem.batch + sna->kgem.nbatch; + + if (len <= 128) { + uint8_t *dst, *src; + + b[0] = XY_MONO_SRC_COPY_IMM; + b[0] |= (br00 & (BLT_DST_TILED | 3 << 20)); + b[0] |= (ox & 7) << 17; + b[0] |= (5 + len); + b[1] = br13; + b[2] = y1 << 16 | x1; + b[3] = y2 << 16 | x2; + b[4] = kgem_add_reloc(&sna->kgem, sna->kgem.nbatch + 4, + bo, + I915_GEM_DOMAIN_RENDER << 16 | + I915_GEM_DOMAIN_RENDER | + KGEM_RELOC_FENCED, + 0); + b[5] = gc->bgPixel; + b[6] = gc->fgPixel; + + sna->kgem.nbatch += 7 + len; + + dst = (uint8_t *)&b[7]; + len = gc->stipple->devKind; + src = gc->stipple->devPrivate.ptr; + src += oy*len + ox/8; + len -= bw; + do { + int i = bw; + do { + *dst++ = byte_reverse(*src++); + *dst++ = byte_reverse(*src++); + i -= 2; + } while (i); + src += len; + } while (--bh); + } else { + struct kgem_bo *upload; + uint8_t *dst, *src; + void *ptr; + + upload = kgem_create_buffer(&sna->kgem, bw*bh, + KGEM_BUFFER_WRITE_INPLACE, + &ptr); + if (!upload) + return; + + b = sna->kgem.batch + sna->kgem.nbatch; + b[0] = br00 | (ox & 7) << 17; + b[1] = br13; + b[2] = y1 << 16 | x1; + b[3] = y2 << 16 | x2; + b[4] = kgem_add_reloc(&sna->kgem, sna->kgem.nbatch + 4, + bo, + I915_GEM_DOMAIN_RENDER << 16 | + I915_GEM_DOMAIN_RENDER | + KGEM_RELOC_FENCED, + 0); + b[5] = kgem_add_reloc(&sna->kgem, sna->kgem.nbatch + 5, + upload, + I915_GEM_DOMAIN_RENDER << 16 | + KGEM_RELOC_FENCED, + 0); + b[6] = gc->bgPixel; + b[7] = gc->fgPixel; + + sna->kgem.nbatch += 8; + + dst = ptr; + len = stride; + src = gc->stipple->devPrivate.ptr; + src += row + (ox >> 3); + len -= bw; + do { + int i = bw; + do { + *dst++ = byte_reverse(*src++); + *dst++ = byte_reverse(*src++); + i -= 2; + } while (i); + src += len; + } while (--bh); + + kgem_bo_destroy(&sna->kgem, upload); + } + } + } +} + +static bool +sna_poly_fill_rect_stippled_n_blt__imm(DrawablePtr drawable, + struct kgem_bo *bo, + struct sna_damage **damage, + GCPtr gc, int n, xRectangle *r, + const BoxRec *extents, unsigned clipped) +{ + PixmapPtr pixmap = get_drawable_pixmap(drawable); + struct sna *sna = to_sna_from_pixmap(pixmap); + DDXPointRec origin = gc->patOrg; + int16_t dx, dy; + uint32_t br00, br13; + + DBG(("%s: upload (%d, %d), (%d, %d), origin (%d, %d), clipped=%d, alu=%d, opaque=%d\n", __FUNCTION__, + extents->x1, extents->y1, + extents->x2, extents->y2, + origin.x, origin.y, + clipped, gc->alu, gc->fillStyle == FillOpaqueStippled)); + + get_drawable_deltas(drawable, pixmap, &dx, &dy); + kgem_set_mode(&sna->kgem, KGEM_BLT); + + br00 = XY_MONO_SRC_COPY_IMM | 3 << 20; + br13 = bo->pitch; + if (sna->kgem.gen >= 40 && bo->tiling) { + br00 |= BLT_DST_TILED; + br13 >>= 2; + } + br13 |= (gc->fillStyle == FillStippled) << 29; + br13 |= blt_depth(drawable->depth) << 24; + br13 |= copy_ROP[gc->alu] << 16; + + origin.x += dx + drawable->x; + origin.y += dy + drawable->y; + + if (!clipped) { + dx += drawable->x; + dy += drawable->y; + + sna_damage_add_rectangles(damage, r, n, dx, dy); + do { + BoxRec box; + + box.x1 = r->x + dx; + box.y1 = r->y + dy; + box.x2 = box.x1 + r->width; + box.y2 = box.y1 + r->height; + + sna_poly_fill_rect_stippled_n_box__imm(sna, bo, + br00, br13, gc, + &box, &origin); + r++; + } while (--n); + } else { + RegionRec clip; + + region_set(&clip, extents); + region_maybe_clip(&clip, gc->pCompositeClip); + if (!RegionNotEmpty(&clip)) { + DBG(("%s: all clipped\n", __FUNCTION__)); + return true; + } + + if (clip.data == NULL) { + DBG(("%s: clipped to extents ((%d, %d), (%d, %d))\n", + __FUNCTION__, + clip.extents.x1, clip.extents.y1, + clip.extents.x2, clip.extents.y2)); + do { + BoxRec box; + + box.x1 = r->x + drawable->x; + box.x2 = bound(box.x1, r->width); + box.y1 = r->y + drawable->y; + box.y2 = bound(box.y1, r->height); + r++; + + DBG(("%s: box (%d, %d), (%d, %d)\n", + __FUNCTION__, + box.x1, box.y1, box.x2, box.y2)); + if (!box_intersect(&box, &clip.extents)) + continue; + + box.x1 += dx; box.x2 += dx; + box.y1 += dy; box.y2 += dy; + + sna_poly_fill_rect_stippled_n_box__imm(sna, bo, + br00, br13, gc, + &box, &origin); + } while (--n); + } else { + const BoxRec * const clip_start = RegionBoxptr(&clip); + const BoxRec * const clip_end = clip_start + clip.data->numRects; + const BoxRec *c; + + DBG(("%s: clipped to boxes: start((%d, %d), (%d, %d)); end=((%d, %d), (%d, %d))\n", __FUNCTION__, + clip_start->x1, clip_start->y1, + clip_start->x2, clip_start->y2, + clip_end->x1, clip_end->y1, + clip_end->x2, clip_end->y2)); + do { + BoxRec unclipped; + + unclipped.x1 = r->x + drawable->x; + unclipped.x2 = bound(unclipped.x1, r->width); + unclipped.y1 = r->y + drawable->y; + unclipped.y2 = bound(unclipped.y1, r->height); + r++; + + c = find_clip_box_for_y(clip_start, + clip_end, + unclipped.y1); + while (c != clip_end) { + BoxRec box; + + if (unclipped.y2 <= c->y1) + break; + + box = unclipped; + if (!box_intersect(&box, c++)) + continue; + + box.x1 += dx; box.x2 += dx; + box.y1 += dy; box.y2 += dy; + + sna_poly_fill_rect_stippled_n_box__imm(sna, bo, + br00, br13, gc, + &box, &origin); + } + } while (--n); + } + } + + assert_pixmap_damage(pixmap); + sna->blt_state.fill_bo = 0; + return true; +} + static bool sna_poly_fill_rect_stippled_n_blt(DrawablePtr drawable, struct kgem_bo *bo, @@ -10434,14 +10719,16 @@ sna_poly_fill_rect_stippled_n_blt(DrawablePtr drawable, origin.x, origin.y, clipped, gc->alu, gc->fillStyle == FillOpaqueStippled)); - if (gc->stipple->drawable.width > 32 || - gc->stipple->drawable.height > 32) - return false; + if (((gc->stipple->drawable.width | gc->stipple->drawable.height) & ~31) == 0) + return sna_poly_fill_rect_stippled_n_blt__imm(drawable, + bo, damage, + gc, n, r, + extents, clipped); get_drawable_deltas(drawable, pixmap, &dx, &dy); kgem_set_mode(&sna->kgem, KGEM_BLT); - br00 = XY_MONO_SRC_COPY_IMM | 3 << 20; + br00 = XY_MONO_SRC_COPY | 3 << 20; br13 = bo->pitch; if (sna->kgem.gen >= 40 && bo->tiling) { br00 |= BLT_DST_TILED; @@ -12165,9 +12452,7 @@ sna_push_pixels_solid_blt(GCPtr gc, } while (--bh); b = sna->kgem.batch + sna->kgem.nbatch; - b[0] = XY_MONO_SRC_COPY; - if (drawable->bitsPerPixel == 32) - b[0] |= 3 << 20; + b[0] = XY_MONO_SRC_COPY | 3 << 20; b[0] |= ((box->x1 - region->extents.x1) & 7) << 17; b[1] = bo->pitch; if (sna->kgem.gen >= 40 && bo->tiling) { |