diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-10 23:32:29 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-10 23:39:33 +0000 |
commit | 3cf5da1090ac777044912ec24619d349d1f6b521 (patch) | |
tree | 9e6de1b0c9ea21a113212debcbf4a3f5aa0f4bde | |
parent | f0e3f6b5bebf7471d3e3e84bd9b2d8469eb64093 (diff) |
sna: Amalgamate small replacements into upload buffers
Similar for the standard io paths, try to reuse an upload buffer for a
small replacement pixmap.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_io.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c index 50fae258..3c17d3aa 100644 --- a/src/sna/sna_io.c +++ b/src/sna/sna_io.c @@ -777,6 +777,107 @@ fallback: sna->blt_state.fill_bo = 0; } +static bool +indirect_replace(struct sna *sna, + PixmapPtr pixmap, + struct kgem_bo *bo, + const void *src, int stride) +{ + struct kgem *kgem = &sna->kgem; + struct kgem_bo *src_bo; + void *ptr; + bool ret; + + if (pixmap->devKind * pixmap->drawable.height >> 12 > kgem->half_cpu_cache_pages) + return false; + + if (bo->tiling == I915_TILING_Y || kgem->ring == KGEM_RENDER) { + BoxRec box; + + src_bo = kgem_create_buffer_2d(kgem, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.bitsPerPixel, + KGEM_BUFFER_WRITE, + &ptr); + if (!src_bo) + return false; + + memcpy_blt(src, ptr, pixmap->drawable.bitsPerPixel, + stride, src_bo->pitch, + 0, 0, + 0, 0, + pixmap->drawable.width, + pixmap->drawable.height); + + box.x1 = box.y1 = 0; + box.x2 = pixmap->drawable.width; + box.y2 = pixmap->drawable.height; + + ret = sna->render.copy_boxes(sna, GXcopy, + pixmap, src_bo, 0, 0, + pixmap, bo, 0, 0, + &box, 1); + } else { + uint32_t cmd, br13, *b; + + src_bo = kgem_create_buffer(kgem, + stride * pixmap->drawable.height, + KGEM_BUFFER_WRITE, + &ptr); + if (!src_bo) + return false; + + cmd = XY_SRC_COPY_BLT_CMD; + br13 = bo->pitch; + if (kgem->gen >= 40 && bo->tiling) { + cmd |= BLT_DST_TILED; + br13 >>= 2; + } + br13 |= 0xcc << 16; + switch (pixmap->drawable.bitsPerPixel) { + default: + case 32: cmd |= BLT_WRITE_ALPHA | BLT_WRITE_RGB; + br13 |= 1 << 25; /* RGB8888 */ + case 16: br13 |= 1 << 24; /* RGB565 */ + case 8: break; + } + + kgem_set_mode(kgem, KGEM_BLT); + if (kgem->nexec + 2 > KGEM_EXEC_SIZE(kgem) || + kgem->nreloc + 2 > KGEM_RELOC_SIZE(kgem) || + !kgem_check_batch(kgem, 8) || + !kgem_check_bo_fenced(kgem, bo, NULL)) { + _kgem_submit(kgem); + _kgem_set_mode(kgem, KGEM_BLT); + } + + memcpy(ptr, src, stride * pixmap->drawable.height); + + b = kgem->batch + kgem->nbatch; + b[0] = cmd; + b[1] = br13; + b[2] = 0; + b[3] = pixmap->drawable.height << 16 | pixmap->drawable.width; + 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] = 0; + b[6] = stride; + b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, src_bo, + I915_GEM_DOMAIN_RENDER << 16 | + KGEM_RELOC_FENCED, + 0); + kgem->nbatch += 8; + ret = true; + } + + kgem_bo_destroy(kgem, src_bo); + return ret; +} + struct kgem_bo *sna_replace(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo, @@ -792,6 +893,9 @@ struct kgem_bo *sna_replace(struct sna *sna, pixmap->drawable.bitsPerPixel, bo->tiling)); + if (indirect_replace(sna, pixmap, bo, src, stride)) + return bo; + if (kgem_bo_is_busy(bo)) { struct kgem_bo *new_bo; |