[PATCH qxl] Dynamically adjust chunk size to avoid command buffer overflow.
David Mansfield
spice at dm.cobite.com
Wed Jun 4 06:13:21 PDT 2014
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 <spice at dm.cobite.com>
---
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
More information about the xorg-devel
mailing list