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>
This commit is contained in:
Chris Wilson 2012-01-07 10:37:01 +00:00
parent e2ad0f6272
commit d7d07d1df3
5 changed files with 89 additions and 74 deletions

View File

@ -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;
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);
memcpy_blt(data, dst, bpp,
stride, dst_stride,
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:

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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);