diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-07 10:37:01 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-07 18:11:35 +0000 |
commit | d7d07d1df3ffc889ccc32c2ed44ce374e37f851d (patch) | |
tree | 4364ee66f899ec96296558dc46b3adedf9f5ed13 | |
parent | e2ad0f6272c776939499c6202fb60bdcc2e955fa (diff) |
sna: Pad upload buffers to ensure there are an even number of rows
One restriction common to all generations is that samplers access pairs
of rows and so we need to pad the buffer to accommodate access to that
second row. Do so unconditionally along paths that may be used by the
render pipeline.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/kgem.c | 58 | ||||
-rw-r--r-- | src/sna/kgem.h | 4 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 12 | ||||
-rw-r--r-- | src/sna/sna_io.c | 38 | ||||
-rw-r--r-- | src/sna/sna_render.c | 51 |
5 files changed, 89 insertions, 74 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c index 4bccccbf..537cad9d 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -2957,6 +2957,34 @@ done: return kgem_create_proxy(&bo->base, offset, size); } +struct kgem_bo *kgem_create_buffer_2d(struct kgem *kgem, + int width, int height, int bpp, + uint32_t flags, + void **ret) +{ + struct kgem_bo *bo; + int stride; + + stride = width * bpp >> 3; + stride = ALIGN(stride, 4); + + bo = kgem_create_buffer(kgem, stride * ALIGN(height, 2), flags, ret); + if (bo == NULL) + return NULL; + + if (height & 1) { + /* Having padded this surface to ensure that accesses to + * the last pair of rows is valid, remove the padding so + * that it can be allocated to other pixmaps. + */ + ((struct kgem_partial_bo *)bo->proxy)->used -= stride; + bo->size -= stride; + } + + bo->pitch = stride; + return bo; +} + struct kgem_bo *kgem_upload_source_image(struct kgem *kgem, const void *data, BoxPtr box, @@ -2964,25 +2992,22 @@ struct kgem_bo *kgem_upload_source_image(struct kgem *kgem, { int width = box->x2 - box->x1; int height = box->y2 - box->y1; - int dst_stride = ALIGN(width * bpp, 32) >> 3; - int size = dst_stride * height; struct kgem_bo *bo; void *dst; DBG(("%s : (%d, %d), (%d, %d), stride=%d, bpp=%d\n", __FUNCTION__, box->x1, box->y1, box->x2, box->y2, stride, bpp)); - bo = kgem_create_buffer(kgem, size, KGEM_BUFFER_WRITE, &dst); - if (bo == NULL) - return NULL; - - memcpy_blt(data, dst, bpp, - stride, dst_stride, - box->x1, box->y1, - 0, 0, - width, height); + bo = kgem_create_buffer_2d(kgem, + width, height, bpp, + KGEM_BUFFER_WRITE, &dst); + if (bo) + memcpy_blt(data, dst, bpp, + stride, bo->pitch, + box->x1, box->y1, + 0, 0, + width, height); - bo->pitch = dst_stride; return bo; } @@ -2993,8 +3018,6 @@ struct kgem_bo *kgem_upload_source_image_halved(struct kgem *kgem, int width, int height, int stride, int bpp) { - int dst_stride = ALIGN(width * bpp / 2, 32) >> 3; - int size = dst_stride * height / 2; struct kgem_bo *bo; pixman_image_t *src_image, *dst_image; pixman_transform_t t; @@ -3003,12 +3026,14 @@ struct kgem_bo *kgem_upload_source_image_halved(struct kgem *kgem, DBG(("%s : (%d, %d), (%d, %d), stride=%d, bpp=%d\n", __FUNCTION__, x, y, width, height, stride, bpp)); - bo = kgem_create_buffer(kgem, size, KGEM_BUFFER_WRITE, &dst); + bo = kgem_create_buffer_2d(kgem, + width, height, bpp, + KGEM_BUFFER_WRITE, &dst); if (bo == NULL) return NULL; dst_image = pixman_image_create_bits(format, width/2, height/2, - dst, dst_stride); + dst, bo->pitch); if (dst_image == NULL) goto cleanup_bo; @@ -3034,7 +3059,6 @@ struct kgem_bo *kgem_upload_source_image_halved(struct kgem *kgem, pixman_image_unref(src_image); pixman_image_unref(dst_image); - bo->pitch = dst_stride; return bo; cleanup_dst: diff --git a/src/sna/kgem.h b/src/sna/kgem.h index e5b7ccf2..57ac6478 100644 --- a/src/sna/kgem.h +++ b/src/sna/kgem.h @@ -403,6 +403,10 @@ void kgem_sync(struct kgem *kgem); struct kgem_bo *kgem_create_buffer(struct kgem *kgem, uint32_t size, uint32_t flags, void **ret); +struct kgem_bo *kgem_create_buffer_2d(struct kgem *kgem, + int width, int height, int bpp, + uint32_t flags, + void **ret); void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *bo); void kgem_throttle(struct kgem *kgem); diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index e3816b39..5bf13951 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -1410,7 +1410,6 @@ sna_pixmap_create_upload(ScreenPtr screen, PixmapPtr pixmap; struct sna_pixmap *priv; int bpp = BitsPerPixel(depth); - int pad = ALIGN(width * bpp / 8, 4); void *ptr; DBG(("%s(%d, %d, %d)\n", __FUNCTION__, width, height, depth)); @@ -1453,23 +1452,22 @@ sna_pixmap_create_upload(ScreenPtr screen, priv = _sna_pixmap_reset(pixmap); priv->header = true; - priv->gpu_bo = kgem_create_buffer(&sna->kgem, - pad*height, KGEM_BUFFER_WRITE, - &ptr); + priv->gpu_bo = kgem_create_buffer_2d(&sna->kgem, + width, height, bpp, + KGEM_BUFFER_WRITE, + &ptr); if (!priv->gpu_bo) { free(priv); fbDestroyPixmap(pixmap); return NullPixmap; } - priv->gpu_bo->pitch = pad; - pixmap->drawable.width = width; pixmap->drawable.height = height; pixmap->drawable.depth = depth; pixmap->drawable.bitsPerPixel = bpp; pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - pixmap->devKind = pad; + pixmap->devKind = priv->gpu_bo->pitch; pixmap->devPrivate.ptr = ptr; return pixmap; diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c index aef3f509..761d3241 100644 --- a/src/sna/sna_io.c +++ b/src/sna/sna_io.c @@ -346,30 +346,27 @@ fallback: extents.y2 = box[n].y2; } - tmp.drawable.width = extents.x2 - extents.x1; + tmp.drawable.width = extents.x2 - extents.x1; tmp.drawable.height = extents.y2 - extents.y1; - tmp.drawable.depth = dst->drawable.depth; + tmp.drawable.depth = dst->drawable.depth; tmp.drawable.bitsPerPixel = dst->drawable.bitsPerPixel; tmp.devPrivate.ptr = NULL; assert(tmp.drawable.width); assert(tmp.drawable.height); - tmp.devKind = tmp.drawable.width * tmp.drawable.bitsPerPixel / 8; - tmp.devKind = ALIGN(tmp.devKind, 4); - - src_bo = kgem_create_buffer(kgem, - tmp.drawable.height * tmp.devKind, - KGEM_BUFFER_WRITE, - &ptr); + src_bo = kgem_create_buffer_2d(kgem, + tmp.drawable.width, + tmp.drawable.height, + tmp.drawable.bitsPerPixel, + KGEM_BUFFER_WRITE, + &ptr); if (!src_bo) goto fallback; - src_bo->pitch = tmp.devKind; - for (n = 0; n < nbox; n++) { memcpy_blt(src, ptr, tmp.drawable.bitsPerPixel, - stride, tmp.devKind, + stride, src_bo->pitch, box[n].x1 + src_dx, box[n].y1 + src_dy, box[n].x1 - extents.x1, @@ -594,21 +591,18 @@ fallback: assert(tmp.drawable.width); assert(tmp.drawable.height); - tmp.devKind = tmp.drawable.width * tmp.drawable.bitsPerPixel / 8; - tmp.devKind = ALIGN(tmp.devKind, 4); - - src_bo = kgem_create_buffer(kgem, - tmp.drawable.height * tmp.devKind, - KGEM_BUFFER_WRITE, - &ptr); + src_bo = kgem_create_buffer_2d(kgem, + tmp.drawable.width, + tmp.drawable.height, + tmp.drawable.bitsPerPixel, + KGEM_BUFFER_WRITE, + &ptr); if (!src_bo) goto fallback; - src_bo->pitch = tmp.devKind; - for (n = 0; n < nbox; n++) { memcpy_xor(src, ptr, tmp.drawable.bitsPerPixel, - stride, tmp.devKind, + stride, src_bo->pitch, box[n].x1 + src_dx, box[n].y1 + src_dy, box[n].x1 - extents.x1, diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c index 2501e535..712e2454 100644 --- a/src/sna/sna_render.c +++ b/src/sna/sna_render.c @@ -1129,7 +1129,6 @@ sna_render_picture_fixup(struct sna *sna, int16_t dst_x, int16_t dst_y) { pixman_image_t *dst, *src; - uint32_t pitch; int dx, dy; void *ptr; @@ -1169,25 +1168,23 @@ sna_render_picture_fixup(struct sna *sna, } do_fixup: - if (PICT_FORMAT_RGB(picture->format) == 0) { - pitch = ALIGN(w, 4); + if (PICT_FORMAT_RGB(picture->format) == 0) channel->pict_format = PIXMAN_a8; - } else { - pitch = sizeof(uint32_t)*w; + else channel->pict_format = PIXMAN_a8r8g8b8; - } if (channel->pict_format != picture->format) { - DBG(("%s: converting to %08x (pitch=%d) from %08x\n", - __FUNCTION__, channel->pict_format, pitch, picture->format)); + DBG(("%s: converting to %08x from %08x\n", + __FUNCTION__, channel->pict_format, picture->format)); } if (picture->pDrawable && !sna_drawable_move_to_cpu(picture->pDrawable, MOVE_READ)) return 0; - channel->bo = kgem_create_buffer(&sna->kgem, - pitch*h, KGEM_BUFFER_WRITE, - &ptr); + channel->bo = kgem_create_buffer_2d(&sna->kgem, + w, h, PIXMAN_FORMAT_BPP(channel->pict_format), + KGEM_BUFFER_WRITE, + &ptr); if (!channel->bo) { DBG(("%s: failed to create upload buffer, using clear\n", __FUNCTION__)); @@ -1195,12 +1192,12 @@ do_fixup: } /* XXX Convolution filter? */ - memset(ptr, 0, pitch*h); - channel->bo->pitch = pitch; + memset(ptr, 0, channel->bo->size); /* Composite in the original format to preserve idiosyncracies */ if (picture->format == channel->pict_format) - dst = pixman_image_create_bits(picture->format, w, h, ptr, pitch); + dst = pixman_image_create_bits(picture->format, + w, h, ptr, channel->bo->pitch); else dst = pixman_image_create_bits(picture->format, w, h, NULL, 0); if (!dst) { @@ -1233,7 +1230,7 @@ do_fixup: src = dst; dst = pixman_image_create_bits(channel->pict_format, - w, h, ptr, pitch); + w, h, ptr, channel->bo->pitch); if (dst) { pixman_image_composite(PictOpSrc, src, NULL, dst, 0, 0, @@ -1242,7 +1239,7 @@ do_fixup: w, h); pixman_image_unref(src); } else { - memset(ptr, 0, h*pitch); + memset(ptr, 0, channel->bo->size); dst = src; } } @@ -1273,7 +1270,6 @@ sna_render_picture_convert(struct sna *sna, int16_t w, int16_t h, int16_t dst_x, int16_t dst_y) { - uint32_t pitch; pixman_image_t *src, *dst; BoxRec box; void *ptr; @@ -1338,27 +1334,26 @@ sna_render_picture_convert(struct sna *sna, return 0; if (PICT_FORMAT_RGB(picture->format) == 0) { - pitch = ALIGN(w, 4); channel->pict_format = PIXMAN_a8; - DBG(("%s: converting to a8 (pitch=%d) from %08x\n", - __FUNCTION__, pitch, picture->format)); + DBG(("%s: converting to a8 from %08x\n", + __FUNCTION__, picture->format)); } else { - pitch = sizeof(uint32_t)*w; channel->pict_format = PIXMAN_a8r8g8b8; - DBG(("%s: converting to a8r8g8b8 (pitch=%d) from %08x\n", - __FUNCTION__, pitch, picture->format)); + DBG(("%s: converting to a8r8g8b8 from %08x\n", + __FUNCTION__, picture->format)); } - channel->bo = kgem_create_buffer(&sna->kgem, - pitch*h, KGEM_BUFFER_WRITE, - &ptr); + channel->bo = kgem_create_buffer_2d(&sna->kgem, + w, h, PIXMAN_FORMAT_BPP(channel->pict_format), + KGEM_BUFFER_WRITE, + &ptr); if (!channel->bo) { pixman_image_unref(src); return 0; } - channel->bo->pitch = pitch; - dst = pixman_image_create_bits(channel->pict_format, w, h, ptr, pitch); + dst = pixman_image_create_bits(channel->pict_format, + w, h, ptr, channel->bo->pitch); if (!dst) { kgem_bo_destroy(&sna->kgem, channel->bo); pixman_image_unref(src); |