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:
parent
e2ad0f6272
commit
d7d07d1df3
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue