[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#941863: Patch to collect image body before transmitting it



Patch I'm using as workaround to postpone all sending data to
client until all GetImage() invocations are complete.  This
way XDamage events arrive before GetImage reply header, rather
than between GetImage reply header and image data.
diff -u xorg-server-1.20.4-pristine/dix/dispatch.c xorg-server-1.20.4/dix/dispatch.c
--- xorg-server-1.20.4-pristine/dix/dispatch.c	2019-02-26 11:28:50.000000000 -0800
+++ xorg-server-1.20.4/dix/dispatch.c	2019-10-06 23:31:32.067804155 -0700
@@ -2077,9 +2077,10 @@
 
     /* coordinates relative to the bounding drawable */
     int relx, rely;
-    long widthBytesLine, length;
+    long widthBytesLine, length, responseLength;
     Mask plane = 0;
     char *pBuf;
+    char *iPtr;
     xGetImageReply xgi;
     RegionPtr pVisibleRegion = NULL;
 
@@ -2155,21 +2156,19 @@
     xgi.depth = pDraw->depth;
     if (format == ZPixmap) {
         widthBytesLine = PixmapBytePad(width, pDraw->depth);
-        length = widthBytesLine * height;
+        responseLength = widthBytesLine * height;
 
     }
     else {
         widthBytesLine = BitmapBytePad(width);
         plane = ((Mask) 1) << (pDraw->depth - 1);
         /* only planes asked for */
-        length = widthBytesLine * height *
+        responseLength = widthBytesLine * height *
             Ones(planemask & (plane | (plane - 1)));
 
     }
 
-    xgi.length = length;
-
-    xgi.length = bytes_to_int32(xgi.length);
+    xgi.length = bytes_to_int32(responseLength);
     if (widthBytesLine == 0 || height == 0)
         linesPerBuf = 0;
     else if (widthBytesLine >= IMAGE_BUFSIZE)
@@ -2192,9 +2191,10 @@
             length += widthBytesLine;
         }
     }
-    if (!(pBuf = calloc(1, length)))
+    if (!(pBuf = calloc(1, responseLength)))
         return BadAlloc;
-    WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
+
+    iPtr = pBuf;
 
     if (pDraw->type == DRAWABLE_WINDOW)
         pVisibleRegion = &((WindowPtr) pDraw)->borderClip;
@@ -2206,23 +2206,24 @@
         linesDone = 0;
         while (height - linesDone > 0) {
             nlines = min(linesPerBuf, height - linesDone);
+            assert(responseLength >= iPtr - pBuf + nlines * widthBytesLine);
             (*pDraw->pScreen->GetImage) (pDraw,
                                          x,
                                          y + linesDone,
                                          width,
                                          nlines,
-                                         format, planemask, (void *) pBuf);
+                                         format, planemask, (void *) iPtr);
             if (pVisibleRegion)
                 XaceCensorImage(client, pVisibleRegion, widthBytesLine,
                                 pDraw, x, y + linesDone, width,
-                                nlines, format, pBuf);
+                                nlines, format, iPtr);
 
             /* Note that this is NOT a call to WriteSwappedDataToClient,
                as we do NOT byte swap */
-            ReformatImage(pBuf, (int) (nlines * widthBytesLine),
+            ReformatImage(iPtr, (int) (nlines * widthBytesLine),
                           BitsPerPixel(pDraw->depth), ClientOrder(client));
 
-            WriteToClient(client, (int) (nlines * widthBytesLine), pBuf);
+            iPtr += nlines * widthBytesLine;
             linesDone += nlines;
         }
     }
@@ -2233,29 +2234,33 @@
                 linesDone = 0;
                 while (height - linesDone > 0) {
                     nlines = min(linesPerBuf, height - linesDone);
+                    assert(responseLength >= iPtr - pBuf + nlines * widthBytesLine);
                     (*pDraw->pScreen->GetImage) (pDraw,
                                                  x,
                                                  y + linesDone,
                                                  width,
                                                  nlines,
-                                                 format, plane, (void *) pBuf);
+                                                 format, plane, (void *) iPtr);
                     if (pVisibleRegion)
                         XaceCensorImage(client, pVisibleRegion,
                                         widthBytesLine,
                                         pDraw, x, y + linesDone, width,
-                                        nlines, format, pBuf);
+                                        nlines, format, iPtr);
 
                     /* Note: NOT a call to WriteSwappedDataToClient,
                        as we do NOT byte swap */
-                    ReformatImage(pBuf, (int) (nlines * widthBytesLine),
+                    ReformatImage(iPtr, (int) (nlines * widthBytesLine),
                                   1, ClientOrder(client));
 
-                    WriteToClient(client, (int)(nlines * widthBytesLine), pBuf);
+                    iPtr += nlines * widthBytesLine;
                     linesDone += nlines;
                 }
             }
         }
     }
+    assert(iPtr - pBuf == responseLength);
+    WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
+    WriteToClient(client, iPtr - pBuf, pBuf);
     free(pBuf);
     return Success;
 }

Reply to: