#include #include #include #include #include extern const char *__progname; static Display *disp; static Screen *scr; static int depth; static Window rootwin; static Colormap wincmap; static int defcmap; static GC gc; static XVisualInfo visinfo; static Window win; static unsigned long int *imgdata; static XImage *img; #include "readloop-X.h" static void find_visual(void) { XVisualInfo *xvi; int nvi; XVisualInfo template; int i; int best; int best_onscr; template.class = TrueColor; xvi = XGetVisualInfo(disp,VisualClassMask,&template,&nvi); best = -1; best_onscr = -1; for (i=0;i xvi[best_onscr].depth) || ( (xvi[i].depth == xvi[best_onscr].depth) && (xvi[i].visual == XDefaultVisual(disp,xvi[i].screen)) ) ) { best_onscr = i; } } if ( (best < 0) || (xvi[i].depth > xvi[best].depth) || ( (xvi[i].depth == xvi[best].depth) && (xvi[i].visual == XDefaultVisual(disp,xvi[i].screen)) ) ) { best = i; } } if (best < 0) { fprintf(stderr,"%s: no TrueColor visual available\n",__progname); exit(1); } if (best_onscr < 0) { fprintf(stderr,"%s: no TrueColor visual on screen %d, using screen %d\n",__progname,XDefaultScreen(disp),xvi[best].screen); } else { best = best_onscr; } visinfo = xvi[best]; } static void setup_gc(void) { if (depth == XDefaultDepthOfScreen(scr)) { gc = XDefaultGCOfScreen(scr); } else { Pixmap p; p = XCreatePixmap(disp,rootwin,1,1,depth); gc = XCreateGC(disp,p,0,0); XFreePixmap(disp,p); } } static void setup_cmap(void) { if (visinfo.visual == XDefaultVisualOfScreen(scr)) { wincmap = XDefaultColormapOfScreen(scr); defcmap = 1; } else { wincmap = XCreateColormap(disp,rootwin,visinfo.visual,AllocNone); defcmap = 0; } } static void setup_image(void) { imgdata = malloc(640*480*4); img = XCreateImage(disp,visinfo.visual,depth,ZPixmap,0,(void *)imgdata,640,480,32,640*4); img->byte_order = LSBFirst; img->bitmap_unit = 32; img->bitmap_bit_order = LSBFirst; img->bitmap_pad = 32; } static void setup_window(void) { unsigned long int attrmask; XSetWindowAttributes attr; attrmask = 0; attr.background_pixel = ~0U; attrmask |= CWBackPixel; attr.border_pixel = 0; attrmask |= CWBorderPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = 0; attrmask |= CWEventMask; attr.colormap = wincmap; attrmask |= CWColormap; win = XCreateWindow(disp,rootwin,0,0,640,480,0,depth,InputOutput,visinfo.visual,attrmask,&attr); XMapRaised(disp,win); } static void ping_myself(void) { XEvent e; e.type = ClientMessage; e.xclient.send_event = True; e.xclient.window = win; e.xclient.message_type = XA_X_HEIGHT; e.xclient.format = 8; XSendEvent(disp,win,False,0,&e); } static void await_ping(void) { XEvent e; do { XNextEvent(disp,&e); } while (e.type != ClientMessage); } void setup_X(void) { disp = XOpenDisplay(0); if (disp == 0) { fprintf(stderr,"%s: can't open display\n",__progname); exit(1); } find_visual(); scr = XScreenOfDisplay(disp,visinfo.screen); depth = visinfo.depth; rootwin = XRootWindowOfScreen(scr); setup_gc(); setup_cmap(); setup_image(); setup_window(); ping_myself(); XFlush(disp); } void display_frame(const unsigned char *dbuf) { int x; int y; unsigned long int *ip; ip = imgdata; for (y=0;y<640;y++) { for (x=0;x<480;x+=2) { *ip++ = 0x00010101 * *dbuf++; dbuf ++; *ip++ = 0x00010101 * *dbuf++; dbuf ++; } } await_ping(); XPutImage(disp,win,gc,img,0,0,0,0,640,480); ping_myself(); XFlush(disp); }