[Mesa-dev] [PATCH] RFC: drisw/glx: use XShm if possible

Adam Jackson ajax at redhat.com
Mon Jun 8 08:12:57 PDT 2015


On Fri, 2015-06-05 at 19:14 +0200, Marc-André Lureau wrote:
> XPutImage requires to copy the images around, and the request may be
> split over several chunks. Using XShm may improve performance.

Almost certainly will, the XPutImage implementation is fairly comic.

> +static volatile int XErrorFlag = 0;
> +
> +/**
> + * Catches potential Xlib errors.
> + */
> +static int
> +handle_xerror(Display *dpy, XErrorEvent *event)
> +{
> +   (void) dpy;
> +   (void) event;
> +   XErrorFlag = 1;
> +   return 0;
> +}
> 

This should only set the error flag if the error really did come from
XShmAttach, and (ideally) should call through to the old handler
otherwise.  X is async, there might be requests before the ShmAttach in
the queue that fail.

> +static Bool
> +XCreateDrawable(struct drisw_drawable * pdp, int shmid, Display * dpy)
> +{
> +   if (pdp->ximage)
> +      XDestroyImage(pdp->ximage);
> +
> +   if (shmid >= 0) {
> +      int (*old_handler)(Display *, XErrorEvent *);
> +
> +      pdp->shminfo.shmid = shmid;
> +      pdp->ximage = XShmCreateImage(dpy,
> +                                    pdp->visinfo->visual,
> +                                    pdp->visinfo->depth,
> +                                    ZPixmap,
> +                                    NULL,
> +                                    &pdp->shminfo,
> +                                    0, 0);
> +      if (pdp->ximage == NULL)
> +         goto ximage;
> +
> +      XErrorFlag = 0;
> +      old_handler = XSetErrorHandler(handle_xerror);
> +      /* This may trigger the X protocol error we're ready to catch: */
> +      XShmAttach(dpy, &pdp->shminfo);
> +      XSync(dpy, False);
> +
> +      if (!XErrorFlag)
> +         goto end;
> +
> +      /* we are on a remote display, this error is normal, don't print it */
> +      XFlush(dpy);

XFlush after XSync is a no-op.  (Well, unless other threads have
touched the display, but even if they have there's no reason to flush
here.)

> +      XErrorFlag = 0;
> +      XDestroyImage(pdp->ximage);
> +      pdp->ximage = NULL;
> +      (void) XSetErrorHandler(old_handler);
> +   }

This is the non-shm fallback path; it's also the only place where
you're restoring old_handler.  Should do it right after XSync.

> @@ -144,6 +203,11 @@ swrastPutImage2(__DRIdrawable * draw, int op,
>     XImage *ximage;
>     GC gc;
>  
> +   if (!pdp->ximage || shmid != pdp->shminfo.shmid) {
> +      if (!XCreateDrawable(pdp, shmid, dpy))
> +         return;
> +   }
> +

Can you explain why you're doing image realization lazily instead of at
createDrawable time?

Also, you're punishing remote clients pretty harshly here.  You've got
dri_sw_displaytarget_display calling put_image_shm if the storage was
allocated as a shm segment (shmid != -1), but pdp->shminfo.shmid is
only set to shmid if ShmAttach succeeds.  On remote connections it
won't, but you take an XSync on every SwapBuffers to find that out.

> @@ -156,24 +220,51 @@ swrastPutImage2(__DRIdrawable * draw, int op,
>     }
>  
>     drawable = pdraw->xDrawable;
> -
>     ximage = pdp->ximage;
> -   ximage->data = data;
> -   ximage->width = w;
> -   ximage->height = h;
>     ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
> +   ximage->data = data;
>  
> -   XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h);
> -
> +   if (pdp->shminfo.shmid >= 0) {
> +      ximage->width = ximage->bytes_per_line / 4;
> +      ximage->height = h;
> +      XShmPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h, False);

Pretty sure this is broken for non-32bpp.

- ajax


More information about the mesa-dev mailing list