150 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
#include <xcb/xcb.h>
 | 
						|
#include <xcb/xcb_aux.h>
 | 
						|
#include <xcb/xcb_image.h>
 | 
						|
#include <stdint.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <getopt.h>
 | 
						|
#include <ctype.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
/*
 | 
						|
 * This is a test which try to test correct glamor colors when rendered.
 | 
						|
 * It should be run with fullscreen Xephyr (with glamor) with present and with 
 | 
						|
 * etalon high-level Xserver (can be any, on CI - Xvfb). For testing this test
 | 
						|
 * creates an image in Xephyr X server, which filled by one of colors defined in
 | 
						|
 * test_pixels. Then it captures central pixel from both Xephyr and Xserver above.
 | 
						|
 * If pixels differ - test failed. Sleep is used to ensure than presentation on both 
 | 
						|
 * Xephyr and Xvfb kicks (xcb_aux_sync was not enough) and test results will be actual
 | 
						|
 */
 | 
						|
 | 
						|
#define WIDTH 300
 | 
						|
#define HEIGHT 300
 | 
						|
 | 
						|
int get_display_pixel(xcb_connection_t* c, xcb_drawable_t win);
 | 
						|
void draw_display_pixel(xcb_connection_t* c, xcb_drawable_t win, uint32_t pixel_color);
 | 
						|
 | 
						|
int get_display_pixel(xcb_connection_t* c, xcb_drawable_t win)
 | 
						|
{
 | 
						|
	xcb_image_t *image;
 | 
						|
	uint32_t    pixel;
 | 
						|
	int format = XCB_IMAGE_FORMAT_XY_PIXMAP;
 | 
						|
 | 
						|
	image = xcb_image_get (c, win,
 | 
						|
		 0, 0, WIDTH, HEIGHT,
 | 
						|
		 UINT32_MAX,
 | 
						|
		 format);
 | 
						|
	if (!image) {
 | 
						|
	  printf("xcb_image_get failed: exiting\n");
 | 
						|
	  exit(1);
 | 
						|
	}
 | 
						|
 | 
						|
	pixel = xcb_image_get_pixel(image, WIDTH/2, HEIGHT/2);
 | 
						|
 | 
						|
	return pixel;
 | 
						|
}
 | 
						|
 | 
						|
void draw_display_pixel(xcb_connection_t* c, xcb_drawable_t win, uint32_t pixel_color)
 | 
						|
{
 | 
						|
	xcb_gcontext_t       foreground;
 | 
						|
	uint32_t             mask = 0;
 | 
						|
 | 
						|
	xcb_rectangle_t rectangles[] = {
 | 
						|
	  {0, 0, WIDTH, HEIGHT},
 | 
						|
	};
 | 
						|
 | 
						|
	foreground = xcb_generate_id (c);
 | 
						|
	mask = XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH | XCB_GC_SUBWINDOW_MODE;
 | 
						|
 | 
						|
	uint32_t values[] = {
 | 
						|
		pixel_color,
 | 
						|
		20,
 | 
						|
		XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS
 | 
						|
	};
 | 
						|
 | 
						|
	xcb_create_gc (c, foreground, win, mask, values);
 | 
						|
 | 
						|
	xcb_poly_fill_rectangle (c, win, foreground, 1, rectangles);
 | 
						|
	xcb_aux_sync ( c );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int main(int argc, char* argv[])
 | 
						|
{
 | 
						|
	xcb_connection_t    *c, *r;
 | 
						|
	xcb_screen_t        *screen1, *screen2;
 | 
						|
	xcb_drawable_t       win1, win2;
 | 
						|
    char *name_test = NULL, *name_relevant = NULL;
 | 
						|
	uint32_t pixel_server1, pixel_server2;
 | 
						|
	int result = 0;
 | 
						|
	uint32_t test_pixels[3] = {0xff0000, 0x00ff00, 0x0000ff};
 | 
						|
	int gv;
 | 
						|
 | 
						|
	while ((gv = getopt (argc, argv, "t:r:")) != -1)
 | 
						|
	switch (gv)
 | 
						|
	  {
 | 
						|
	  case 't':
 | 
						|
		name_test = optarg;
 | 
						|
		break;
 | 
						|
	  case 'r':
 | 
						|
		name_relevant = optarg;
 | 
						|
		break;
 | 
						|
	  case '?':
 | 
						|
		if (optopt == 't' || optopt == 'r')
 | 
						|
		  fprintf (stderr, "Option -%c requires an argument - test screen name.\n", optopt);
 | 
						|
		else if (isprint (optopt))
 | 
						|
		  fprintf (stderr, "Unknown option `-%c'.\n", optopt);
 | 
						|
		else
 | 
						|
		  fprintf (stderr,
 | 
						|
		           "Unknown option character `\\x%x'.\n",
 | 
						|
		           optopt);
 | 
						|
		return 1;
 | 
						|
	  default:
 | 
						|
		abort ();
 | 
						|
	  }
 | 
						|
 | 
						|
	printf("test=%s, rel=%s\n", name_test, name_relevant);
 | 
						|
 | 
						|
	c = xcb_connect (name_test, NULL);
 | 
						|
	r = xcb_connect (name_relevant, NULL);
 | 
						|
 | 
						|
	/* get the first screen */
 | 
						|
	screen1 = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
 | 
						|
 | 
						|
    win1 = xcb_generate_id (c);
 | 
						|
    xcb_create_window (c,                    /* Connection          */
 | 
						|
                       XCB_COPY_FROM_PARENT,          /* depth (same as root)*/
 | 
						|
                       win1,                        /* window Id           */
 | 
						|
                       screen1->root,                  /* parent window       */
 | 
						|
                       0, 0,                          /* x, y                */
 | 
						|
                       WIDTH, HEIGHT,                /* width, height       */
 | 
						|
                       20,                            /* border_width        */
 | 
						|
                       XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
 | 
						|
                       screen1->root_visual,           /* visual              */
 | 
						|
                       0, NULL );                     /* masks, not used yet */
 | 
						|
 | 
						|
 | 
						|
    /* Map the window on the screen */
 | 
						|
    xcb_map_window (c, win1);
 | 
						|
    xcb_aux_sync(c);
 | 
						|
 | 
						|
	/* get the first screen */
 | 
						|
	screen2 = xcb_setup_roots_iterator (xcb_get_setup (r)).data;
 | 
						|
 | 
						|
	/* root window */
 | 
						|
	win2 = screen2->root;
 | 
						|
 | 
						|
	for(int i = 0; i < 3; i++)
 | 
						|
	{
 | 
						|
		draw_display_pixel(c, win1, test_pixels[i]);
 | 
						|
		xcb_aux_sync(r);
 | 
						|
		pixel_server1 = get_display_pixel(c, win1);
 | 
						|
		sleep(1);
 | 
						|
		pixel_server2 = get_display_pixel(r, win2);
 | 
						|
		xcb_aux_sync(r);
 | 
						|
		printf("p=0x%x, p2=0x%x\n", pixel_server1, pixel_server2);
 | 
						|
		result+= pixel_server1 == pixel_server2;
 | 
						|
	}
 | 
						|
	return result == 3 ? 0 : 1;
 | 
						|
}
 |