The maximum number of "commands" that can be queued at once is fixed at compile time at MAX_RELOCS. However, during the creation of an image object in qxl_image_create(), the image is split into commands of maximum size 512*512. For a large dual-head system, it is easy to create an image for which the number of chunks will result in an overflow of MAX_RELOCS number of "commands".
Identify this scenario and dynamically increase the chunk size to avoid the overflow, and the resulting assert() which crashes Xorg. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=79317 Signed-off-by: David Mansfield <[email protected]> --- src/qxl_image.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/qxl_image.c b/src/qxl_image.c index 0a0ca30..396aa0f 100644 --- a/src/qxl_image.c +++ b/src/qxl_image.c @@ -140,6 +140,7 @@ qxl_image_create (qxl_screen_t *qxl, const uint8_t *data, struct qxl_bo *image_bo; int dest_stride = (width * Bpp + 3) & (~3); int h; + int chunk_size; data += y * stride + x * Bpp; @@ -155,9 +156,23 @@ qxl_image_create (qxl_screen_t *qxl, const uint8_t *data, hash = 0; h = height; + + chunk_size = MAX (512 * 512, dest_stride); + + /* ensure we will not create too many pieces and overflow + * the command buffer (MAX_RELOCS). if so, increase the chunk_size. + * each loop creates at least 2 cmd buffer entries, and + * we have to leave room when we're done. + */ + if (height / (chunk_size / dest_stride) > (MAX_RELOCS / 4)) { + chunk_size = height / (MAX_RELOCS/4) * dest_stride; +#if 0 + ErrorF ("adjusted chunk_size to %d\n", chunk_size); +#endif + } + while (h) { - int chunk_size = MAX (512 * 512, dest_stride); int n_lines = MIN ((chunk_size / dest_stride), h); struct qxl_bo *bo = qxl->bo_funcs->bo_alloc (qxl, sizeof (QXLDataChunk) + n_lines * dest_stride, "image data"); -- 1.9.0 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
