Clipping: clip.c

The module clip.c uses clipping to reduce the amount of work to do while copying the double buffer to the window.

If you look closely at the code of double.c you may note that at each time only a small portion of the pixmap is modified, while the whole pixmap is copyed to the window. This is inefficent, as the large part of the window is not modified by this operation. Clipping is the tecniques used to avoid this waste of resources.

The clipping tecnique is to copy only the part of the double buffer that has been modified. In X Window, the function for copying is XCopyArea, that decides what part of the origin has to be copied by looking at a component of the graphic context, named clipping mask. In other words, to make XCopyArea copy only a part of the origin, we have to set an appropriate clipping mask in the graphic context we are using.

A possible way to set the clipping mask is by defining it as a set of non-intersecting rectangles. This can be done by using an array whose elements are of type XRectangle. Each element is one of the rectangles we want to be copied. For the ball example, only one ball is in the screen, so we need only one rectangle. As a result, the array can have a single element (so it contains only one rectangle).

  XRectangle clip_rect[1];
Before copying the double buffer to the window, we have to specify which part of the pixmap have been changed. In the case of the ball, this is very simple: if the new position of the ball is x, y, then the coordinates of the previous position are either x-1 or x+1, and either y-1 or y+1. Since the ball is 40 points large, a rectangle positioned in x-1, y-1 and 42 points large surely contains both the old and the new position of the ball, so it can be used as a clipping mask. Before copying the double buffer to the screen we set the clipping mask:
      /* create the clipping rectangle */
      clip_rect[0].x=x-1;
      clip_rect[0].y=y-1;
      clip_rect[0].width=42;
      clip_rect[0].height=42;
      XSetClipRectangles(dpy, g, 0, 0, clip_rect, 1, Unsorted);
See the complete code clip.c to see how these code fragments are inserted in the rest of the program. To see the performance gain of clipping, remove the function call usleep(10); from both clip.c and double.c, and execute both.
Next: clipping using a bitmap