5

XGetImage takes 3-4 seconds to execute and completely freezes X11

Display *display;
    display = XOpenDisplay(NULL);
if (!display) {fprintf(stderr, "unable to connect to display");return 7;}
    Window w;
    int x,y,i;
    unsigned m;
    Window root = XDefaultRootWindow(display);
if (!root) {fprintf(stderr, "unable to open rootwindow");return 8;}
    //sleep(1);
    if(!XQueryPointer(display,root,&root,&w,&x,&y,&i,&i,&m))
{  printf("unable to query pointer\n"); return 9;}
    XImage *image;
    XWindowAttributes attr;
    XGetWindowAttributes(display, root, &attr);
    image = XGetImage(display,root,0,0,attr.width,attr.height,AllPlanes,XYPixmap);
    XCloseDisplay(display);
if (!image) {printf("unable to get image\n"); return 10;}

In the Xorg log:

[ 13234.693] AUDIT: Thu Jan  7 20:12:13 2016: 3856: client 45 connected from local host ( uid=500 gid=500 pid=12993 )
  Auth name: MIT-MAGIC-COOKIE-1 ID: 153
[ 13238.774] AUDIT: Thu Jan  7 20:12:18 2016: 3856: client 45 disconnected

time:
real    0m4.080s
user    0m0.002s
sys 0m0.007s

Ideally I want this function to run in less than 0.1 seconds

Tiago Mussi
  • 801
  • 3
  • 13
  • 20
Adel Ahmed
  • 638
  • 7
  • 24
  • 2
    You still have not tested any function return values, as recommended when you posted your [previous similar question](http://stackoverflow.com/questions/34661001/i-want-to-determine-the-cause-of-a-sigsegv) – Weather Vane Jan 07 '16 at 18:17
  • I've added some error handling to opening the display, what other functions need error handling? – Adel Ahmed Jan 07 '16 at 19:06
  • Until you know the source of the problem: ***every*** function that returns a value, ***and*** the values returned by pointer arguments. – Weather Vane Jan 07 '16 at 19:08
  • I've modified the code to add some error correction, let me know if additional eror correction is needed – Adel Ahmed Jan 07 '16 at 19:49
  • it's a bunch oif i5 laptops that cannot be change, I don't think it's slow and if it is I cannot replace it :( – Adel Ahmed Jan 07 '16 at 20:20
  • for understandability and readability by us humans 1) consistently indent the code. suggest using 4 space per indent level. indent after every opening brace ''{' un-indent before every closing brace '}'. 2) separate code blocks (for, if, else, while, do...while, switch, case, default) by a blank line. 3) follow the axiom: only one statement per line and (at most) one variable declaration per statement. – user3629249 Jan 08 '16 at 02:36
  • regarding this line: `if(!XQueryPointer(display,root,&root,&w,&x,&y,&i,&i,&m))`. it is unlikely that the address of variable `i` would be passed twice to the XQueryPointer() function. – user3629249 Jan 08 '16 at 02:40
  • You probably want ZPixmap rather than XYPixmap. – n. m. could be an AI Jan 08 '16 at 15:19
  • you are right, zpixmap is alot faster than xypixmap, please post that answer so I cna mark it as the correct one – Adel Ahmed Jan 08 '16 at 15:22

1 Answers1

8

XYPixmap is a very specialized format that doesn't have many uses. You should use ZPixmap nearly always.

XYPixmap works plane by plane. What does it mean? Take bit 0 of every pixel, and tightly pack all these bits in an array of unsigned int. That's youir plane 0. Then take bit 1 of every pixel, and pack all these bits in an array. That's your plane 1. Then take bit 2 of every pixel...

   Framebuffer
   __________________________________________________________________
  / 
   Pixel 0                     Pixel 1                      Pixel 2
   [0][1][2][3][4][5][6][7]    [0][1][2][3][4][5][6][7]     [0][1][2]....
    |                           |                            |
    |  +------------------------+                            |
    |  |                                                     |
    |  |  +--------------------------------------------------+
    |  |  |
    v  v  v
   [0][0][0]..... \
   (Plane 0)      |
                  |
   [1][1][1]....  | Result
   (Plane 1)      |
   ....           |
   [7][7][7]....  |
   (Plane 7)      |
                  /

If your framebuffer is stored like this, which is the case for most modern hardware, that's a lot of bit manipulation!

The picture shows 8 bit pixels, but it's the same for any other depth.

ZPixmap on the other hand takes entire pixels and stuffs them into an array:

   Framebuffer
   __________________________________________________________________
  / 
   Pixel 0                     Pixel 1                      Pixel 2
   [0][1][2][3][4][5][6][7]    [0][1][2][3][4][5][6][7]     [0][1][2]....
    |  |  |  |  |  |  |  |      |  |  |  |  |  |  |  |       |  |  |
    v  v  v  v  v  v  v  v      v  v  v  v  v  v  v  v       v  v  v
   [0][1][2][3][4][5][6][7]    [0][1][2][3][4][5][6][7]     [0][1][2]....
  \_____________________________________________________________________
    Result

This is simple direct copying, which should be very fast.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • 2
    Wonderful, I've tried looking around for that sort of explanation but found none, this was very informative, thank you very much – Adel Ahmed Jan 23 '16 at 23:42
  • 2
    There's such few information available on XGetImage, struct XImage, and, specially, XYPixmap, plane masks, and the like. Goodness, I had to google for an hour to find such useful information! (The man pages tell you next to nothing...) – étale-cohomology Jul 11 '16 at 11:07