Home | History | Annotate | Line # | Download | only in bugs
      1 #include <xcb/xcb.h>
      2 #include <xcb/xcb_aux.h>
      3 #include <xcb/xcb_image.h>
      4 #include <stdint.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <getopt.h>
      8 #include <ctype.h>
      9 #include <unistd.h>
     10 
     11 /*
     12  * This is a test which try to test correct glamor colors when rendered.
     13  * It should be run with fullscreen Xephyr (with glamor) with present and with
     14  * etalon high-level Xserver (can be any, on CI - Xvfb). For testing this test
     15  * creates an image in Xephyr X server, which filled by one of colors defined in
     16  * test_pixels. Then it captures central pixel from both Xephyr and Xserver above.
     17  * If pixels differ - test failed. Sleep is used to ensure than presentation on both
     18  * Xephyr and Xvfb kicks (xcb_aux_sync was not enough) and test results will be actual
     19  */
     20 
     21 #define WIDTH 300
     22 #define HEIGHT 300
     23 
     24 int get_display_pixel(xcb_connection_t* c, xcb_drawable_t win);
     25 void draw_display_pixel(xcb_connection_t* c, xcb_drawable_t win, uint32_t pixel_color);
     26 
     27 int get_display_pixel(xcb_connection_t* c, xcb_drawable_t win)
     28 {
     29 	xcb_image_t *image;
     30 	uint32_t    pixel;
     31 	int format = XCB_IMAGE_FORMAT_XY_PIXMAP;
     32 
     33 	image = xcb_image_get (c, win,
     34 		 0, 0, WIDTH, HEIGHT,
     35 		 UINT32_MAX,
     36 		 format);
     37 	if (!image) {
     38 	  printf("xcb_image_get failed: exiting\n");
     39 	  exit(1);
     40 	}
     41 
     42 	pixel = xcb_image_get_pixel(image, WIDTH/2, HEIGHT/2);
     43 
     44 	return pixel;
     45 }
     46 
     47 void draw_display_pixel(xcb_connection_t* c, xcb_drawable_t win, uint32_t pixel_color)
     48 {
     49 	xcb_gcontext_t       foreground;
     50 	uint32_t             mask = 0;
     51 
     52 	xcb_rectangle_t rectangles[] = {
     53 	  {0, 0, WIDTH, HEIGHT},
     54 	};
     55 
     56 	foreground = xcb_generate_id (c);
     57 	mask = XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH | XCB_GC_SUBWINDOW_MODE;
     58 
     59 	uint32_t values[] = {
     60 		pixel_color,
     61 		20,
     62 		XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS
     63 	};
     64 
     65 	xcb_create_gc (c, foreground, win, mask, values);
     66 
     67 	xcb_poly_fill_rectangle (c, win, foreground, 1, rectangles);
     68 	xcb_aux_sync ( c );
     69 }
     70 
     71 
     72 int main(int argc, char* argv[])
     73 {
     74 	xcb_connection_t    *c, *r;
     75 	xcb_screen_t        *screen1, *screen2;
     76 	xcb_drawable_t       win1, win2;
     77     char *name_test = NULL, *name_relevant = NULL;
     78 	uint32_t pixel_server1, pixel_server2;
     79 	int result = 0;
     80 	uint32_t test_pixels[3] = {0xff0000, 0x00ff00, 0x0000ff};
     81 	int gv;
     82 
     83 	while ((gv = getopt (argc, argv, "t:r:")) != -1)
     84 	switch (gv)
     85 	  {
     86 	  case 't':
     87 		name_test = optarg;
     88 		break;
     89 	  case 'r':
     90 		name_relevant = optarg;
     91 		break;
     92 	  case '?':
     93 		if (optopt == 't' || optopt == 'r')
     94 		  fprintf (stderr, "Option -%c requires an argument - test screen name.\n", optopt);
     95 		else if (isprint (optopt))
     96 		  fprintf (stderr, "Unknown option `-%c'.\n", optopt);
     97 		else
     98 		  fprintf (stderr,
     99 		           "Unknown option character `\\x%x'.\n",
    100 		           optopt);
    101 		return 1;
    102 	  default:
    103 		abort ();
    104 	  }
    105 
    106 	printf("test=%s, rel=%s\n", name_test, name_relevant);
    107 
    108 	c = xcb_connect (name_test, NULL);
    109 	r = xcb_connect (name_relevant, NULL);
    110 
    111 	/* get the first screen */
    112 	screen1 = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
    113 
    114     win1 = xcb_generate_id (c);
    115     xcb_create_window (c,                    /* Connection          */
    116                        XCB_COPY_FROM_PARENT,          /* depth (same as root)*/
    117                        win1,                        /* window Id           */
    118                        screen1->root,                  /* parent window       */
    119                        0, 0,                          /* x, y                */
    120                        WIDTH, HEIGHT,                /* width, height       */
    121                        20,                            /* border_width        */
    122                        XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
    123                        screen1->root_visual,           /* visual              */
    124                        0, NULL );                     /* masks, not used yet */
    125 
    126 
    127     /* Map the window on the screen */
    128     xcb_map_window (c, win1);
    129     xcb_aux_sync(c);
    130 
    131 	/* get the first screen */
    132 	screen2 = xcb_setup_roots_iterator (xcb_get_setup (r)).data;
    133 
    134 	/* root window */
    135 	win2 = screen2->root;
    136 
    137 	for(int i = 0; i < 3; i++)
    138 	{
    139 		draw_display_pixel(c, win1, test_pixels[i]);
    140 		xcb_aux_sync(r);
    141 		pixel_server1 = get_display_pixel(c, win1);
    142 		sleep(1);
    143 		pixel_server2 = get_display_pixel(r, win2);
    144 		xcb_aux_sync(r);
    145 		printf("p=0x%x, p2=0x%x\n", pixel_server1, pixel_server2);
    146 		result+= pixel_server1 == pixel_server2;
    147 	}
    148 	return result == 3 ? 0 : 1;
    149 }
    150