Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

windump for simple cloning to nvidia optimus card

  • Loading branch information...
commit f8dca869fba106b7ae093a8ebf617ce389551540 1 parent 37b23e3
Tim Felgentreff authored

Showing 2 changed files with 516 additions and 0 deletions. Show diff stats Hide diff stats

  1. BIN  bin/windump
  2. +516 0 bin/windump.c
BIN  bin/windump
Binary file not shown
516 bin/windump.c
... ... @@ -0,0 +1,516 @@
  1 +// gcc -O3 -o windump windump.c -lX11 -lXfixes -lXext -lXtst
  2 +// gcc -O3 -o windump windump.c -lX11 -lXfixes -lXext
  3 +
  4 +#include <sys/ipc.h>
  5 +#include <sys/shm.h>
  6 +#include <X11/Xos.h>
  7 +#include <X11/Xlib.h>
  8 +#include <X11/Xutil.h>
  9 +#include <X11/Xatom.h>
  10 +#include <X11/cursorfont.h>
  11 +#include <X11/extensions/XShm.h>
  12 +#ifdef USE_XTEST
  13 +#include <X11/extensions/XTest.h>
  14 +#endif
  15 +#include <X11/extensions/Xfixes.h>
  16 +#include <stdio.h>
  17 +#include <stdlib.h>
  18 +#include <stdarg.h>
  19 +#include <unistd.h>
  20 +
  21 +int format = ZPixmap;
  22 +typedef struct
  23 +{
  24 + unsigned flags;
  25 + unsigned functions;
  26 + unsigned decorations;
  27 + int inputMode;
  28 + unsigned status;
  29 +} Hints;
  30 +
  31 +
  32 +
  33 +double time_s()
  34 +// gives back time in microseconds
  35 +{
  36 +#ifndef _WIN32
  37 + struct timeval tv;
  38 + struct timezone tz;
  39 + tz.tz_minuteswest = 0;
  40 + tz.tz_dsttime = 0;
  41 + gettimeofday(&tv,&tz);
  42 + return ( (double)tv.tv_sec+(double)tv.tv_usec*1E-6 );
  43 +#else
  44 + union{
  45 + long int ns100;
  46 + FILETIME ft;
  47 + } now;
  48 + GetSystemTimeAsFileTime(&now.ft);
  49 + return( ((double)now.ns100)*1.0E-7 );
  50 +#endif
  51 +}
  52 +
  53 +
  54 +XImage *
  55 +CaptRoot(Display * dpy, int screen)
  56 +{
  57 + unsigned long swaptest = 1;
  58 + XColor *colors;
  59 + unsigned buffer_size;
  60 + int win_name_size;
  61 + int header_size;
  62 + int ncolors, i;
  63 + char *win_name;
  64 + Bool got_win_name;
  65 + XWindowAttributes win_info;
  66 + XImage *image;
  67 + int absx, absy, x, y;
  68 + unsigned width, height;
  69 + int dwidth, dheight;
  70 + int bw;
  71 + Window dummywin;
  72 +
  73 +#if 0
  74 + int transparentOverlays , multiVis;
  75 + int numVisuals;
  76 + XVisualInfo *pVisuals;
  77 + int numOverlayVisuals;
  78 + OverlayInfo *pOverlayVisuals;
  79 + int numImageVisuals;
  80 + XVisualInfo **pImageVisuals;
  81 + list_ptr vis_regions; /* list of regions to read from */
  82 + list_ptr vis_image_regions ;
  83 + Visual vis_h,*vis ;
  84 +#endif
  85 + int allImage = 0 ;
  86 +
  87 + Window window=RootWindow (dpy, screen);
  88 +
  89 + if (!XGetWindowAttributes(dpy, window, &win_info))
  90 + { fprintf(stderr,"Can't get target window attributes."); exit(1); }
  91 +
  92 + absx=0; absy=0;
  93 + win_info.x = 0;
  94 + win_info.y = 0;
  95 + width = win_info.width;
  96 + height = win_info.height;
  97 + bw = 0;
  98 +
  99 + dwidth = DisplayWidth (dpy, screen);
  100 + dheight = DisplayHeight (dpy, screen);
  101 +
  102 + XFetchName(dpy, window, &win_name);
  103 + if (!win_name || !win_name[0]) {
  104 + win_name = "xwdump";
  105 + got_win_name = False;
  106 + } else {
  107 + got_win_name = True;
  108 + }
  109 +
  110 + /* sizeof(char) is included for the null string terminator. */
  111 + win_name_size = strlen(win_name) + sizeof(char);
  112 +
  113 + /*
  114 + * Snarf the pixmap with XGetImage.
  115 + */
  116 +
  117 + x = absx - win_info.x;
  118 + y = absy - win_info.y;
  119 +#if 0
  120 + multiVis = GetMultiVisualRegions(dpy,RootWindow(dpy, screen),absx,absy,
  121 + width,height,&transparentOverlays,&numVisuals,&pVisuals,
  122 + &numOverlayVisuals,&pOverlayVisuals,&numImageVisuals,
  123 + &pImageVisuals,&vis_regions,&vis_image_regions,&allImage) ;
  124 + if (on_root || multiVis)
  125 + {
  126 + if (!multiVis)
  127 + image = XGetImage (dpy, RootWindow(dpy, screen), absx, absy,
  128 + width, height, AllPlanes, format);
  129 + else
  130 + image = ReadAreaToImage(dpy, RootWindow(dpy, screen), absx, absy,
  131 + width, height,
  132 + numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,
  133 + numImageVisuals, pImageVisuals,vis_regions,
  134 + vis_image_regions,format,allImage);
  135 + }
  136 + else
  137 +#endif
  138 + image = XGetImage (dpy, window, x, y, width, height,
  139 + AllPlanes, format);
  140 + if (!image) {
  141 + fprintf (stderr, "unable to get image at %dx%d+%d+%d\n",
  142 + width, height, x, y);
  143 + exit (1);
  144 + }
  145 +
  146 + //if (add_pixel_value != 0) XAddPixel (image, add_pixel_value);
  147 +
  148 + return image;
  149 +}
  150 +
  151 +Window CreateWindow(Display * dpy, int screen, int width, int height, int windowdec)
  152 +{
  153 + XSetWindowAttributes winAttr;
  154 + winAttr.override_redirect=((windowdec==0)?True:False);
  155 +
  156 + //printf("w=%d h=%d dpy=%p scr=%d\n",width,height,dpy,screen);
  157 + Window win = 0;
  158 + win = XCreateWindow(dpy, RootWindow(dpy, screen),
  159 + 0, 0, width, height,
  160 + 0,
  161 + 24,
  162 + InputOutput,
  163 + DefaultVisual(dpy, screen),
  164 + //CWBorderPixel|CWBackPixel|CWColormap|CWEventMask|CWBitGravity,
  165 + CWOverrideRedirect, &winAttr);
  166 +
  167 + XSizeHints sizeHints;
  168 + sizeHints.flags = PPosition | PSize;
  169 + sizeHints.x = 0;
  170 + sizeHints.y = 0;
  171 + sizeHints.width = width;
  172 + sizeHints.height = height;
  173 +
  174 + XSetNormalHints(dpy,win,&sizeHints);
  175 +
  176 + XSelectInput(dpy, win, StructureNotifyMask|ButtonPressMask|ButtonReleaseMask);
  177 +
  178 + XMapWindow(dpy, win);
  179 + return win;
  180 +}
  181 +
  182 +void DrawImage(Display * dpy, Window win, XImage * image)
  183 +{
  184 + static GC gc;
  185 + if(win!=0)
  186 + {
  187 + if(gc==0)
  188 + {
  189 + XGCValues gc_val;
  190 + gc = XCreateGC (dpy, win, GCForeground|GCBackground, &gc_val);
  191 + }
  192 + XPutImage (dpy, win, gc, image, 0, 0, 0, 0, image->width, image->height);
  193 + }
  194 +}
  195 +
  196 +void createShmImage(int w, int h, XShmSegmentInfo * sinfo, XShmSegmentInfo * tinfo, Display * sdpy, Display * tdpy, int sscr, int tscr, XImage ** simage, XImage ** timage)
  197 +{
  198 + sinfo->shmid=tinfo->shmid=shmget(IPC_PRIVATE,w*h*sizeof(unsigned),IPC_CREAT|0666 );
  199 + sinfo->shmaddr=tinfo->shmaddr=(char*)shmat(sinfo->shmid,0,0);
  200 + sinfo->readOnly=False;
  201 + tinfo->readOnly=False;
  202 + //printf("%d %d\n",DefaultDepth(sdpy,sscr),DefaultDepth(tdpy,tscr));
  203 + *simage = XShmCreateImage(
  204 + sdpy, DefaultVisual(sdpy,sscr), DefaultDepth(sdpy,sscr),
  205 + ZPixmap/*format*/,
  206 + (char *)sinfo->shmaddr, sinfo,
  207 + w,h /*width,height*/
  208 + );
  209 + *timage = XShmCreateImage(
  210 + tdpy, DefaultVisual(tdpy,tscr), DefaultDepth(tdpy,tscr),
  211 + ZPixmap/*format*/,
  212 + (char *)tinfo->shmaddr, tinfo,
  213 + w,h /*width,height*/
  214 + );
  215 + XShmAttach(sdpy, sinfo);
  216 + XShmAttach(tdpy, tinfo);
  217 +}
  218 +
  219 +void drawMouse(XImage * img, int xm, int ym, int color)
  220 +{
  221 + int x,y,x1,y1,x2,y2,w,h;
  222 +
  223 + unsigned * data = (unsigned *)(img->data);
  224 +
  225 + w=img->width;
  226 + h=img->height;
  227 +
  228 + x=xm; if(x<0) x=0; if(x>=w) x=w-1;
  229 + y=ym; if(y<0) y=0; if(y>=h) y=h-1;
  230 + x1=xm-5; if(x1<0) x1=0; if(x1>w) x1=w;
  231 + x2=xm+6; if(x2<0) x2=0; if(x2>w) x2=w;
  232 + for(x=x1;x<x2;x++) data[y*w+x] = color;
  233 + //data[y*w+x] = 0xFFFFFF;
  234 +
  235 + x=xm; if(x<0) x=0; if(x>=w) x=w-1;
  236 + y=ym; if(y<0) y=0; if(y>=h) y=h-1;
  237 + y1=ym-5; if(y1<0) y1=0; if(y1>h) y1=h;
  238 + y2=ym+6; if(y2<0) y2=0; if(y2>h) y2=h;
  239 + for(y=y1;y<y2;y++) data[y*w+x] = color;
  240 +}
  241 +
  242 +// Clamp a value between a lower and upper bound, inclusive.
  243 +#define CLAMP(x, l, u) ((x) < (l) ? (l) : ((x) > (u) ? (u) : (x)))
  244 +#define MIN(a, b) ((a) < (b) ? (a) : (b))
  245 +#define MAX(a, b) ((a) > (b) ? (a) : (b))
  246 +
  247 +void drawMouseImage(XImage* img, XFixesCursorImage* cur, int xm, int ym)
  248 +{
  249 + int x, y, x1, y1, x2, y2, w, h, cw, ch;
  250 +
  251 + unsigned int* data = (unsigned int*)(img->data);
  252 +
  253 + w = img->width;
  254 + h = img->height;
  255 + cw = cur->width;
  256 + ch = cur->height;
  257 + xm -= cur->xhot;
  258 + ym -= cur->yhot;
  259 +
  260 + y = CLAMP(ym, 0, h - 1);
  261 + x1 = MAX(-xm, 0);
  262 + x2 = MIN(w - xm, cw);
  263 + y1 = MAX(-ym, 0);
  264 + y2 = MIN(h - ym, ch);
  265 + for(y = y1; y < y2; ++y)
  266 + {
  267 + for(x = x1; x < x2; ++x)
  268 + {
  269 + // Alpha blending, ugly
  270 + // FIXME: use the XImage RGB masks instead of hard coded colour byte order.
  271 + unsigned long cursor_pixel = cur->pixels[y * cw + x];
  272 + unsigned int image_pixel = data[(ym + y) * w + xm + x];
  273 +
  274 + unsigned char alpha = ((cursor_pixel & 0xFF000000) >> 24);
  275 + unsigned char alpha_inv = 0xFF - alpha;
  276 + unsigned char r = (((cursor_pixel & 0x00FF0000) >> 16) * alpha + ((image_pixel & 0x00FF0000) >> 16) * alpha_inv) >> 8;
  277 + unsigned char g = (((cursor_pixel & 0x0000FF00) >> 8) * alpha + ((image_pixel & 0x0000FF00) >> 8) * alpha_inv) >> 8;
  278 + unsigned char b = (((cursor_pixel & 0x000000FF) >> 0) * alpha + ((image_pixel & 0x000000FF) >> 0) * alpha_inv) >> 8;
  279 + //~ unsigned char g = ((cursor_pixel & 0x0000FF00) >> 8);
  280 + //~ unsigned char b = ((cursor_pixel & 0x000000FF) >> 0);
  281 + //~ unsigned int color = cur->pixels[y * cw + x] * alpha + data[(ym + y) * w + xm + x] * (0xFF - alpha);
  282 + data[(ym + y) * w + xm + x] = (r << 16) | (g << 8) | (b << 0);
  283 + }
  284 + }
  285 +}
  286 +
  287 +modifyMouseCursor(XFixesCursorImage* cur)
  288 +{
  289 + int x,y;
  290 + for( y=0 ; y<cur->height ; y++ )
  291 + {
  292 + for( x=0 ; x<cur->width ; x++ )
  293 + {
  294 + cur->pixels[y * cur->width + x]&=0xAFFF0000;
  295 + }
  296 + }
  297 +}
  298 +
  299 +
  300 +void emulateEvents(Display * sdpy, Window swin, Display * tdpy, Window twin)
  301 +{
  302 +#ifdef USE_XTEST
  303 + int xmouse, ymouse;
  304 + XEvent e;
  305 +
  306 + //long mask=ButtonPressMask|ButtonReleaseMask|MotionNotifyMask;
  307 + //while(XCheckWindowEvent(tdpy, twin, mask, &e)!=False)
  308 + //while( XCheckTypedWindowEvent(tdpy, twin, ButtonPress, &e)!=False ) XPutBackEvent( sdpy, &e );
  309 + //while( XCheckTypedWindowEvent(tdpy, twin, ButtonRelease, &e)!=False ) XPutBackEvent( sdpy, &e );
  310 +
  311 + while(XCheckTypedWindowEvent(tdpy, twin, ButtonPress, &e)!=False ||
  312 + XCheckTypedWindowEvent(tdpy, twin, ButtonRelease, &e)!=False )
  313 + {
  314 + printf("button event\n");
  315 + //if(emulate_events)
  316 + {
  317 + /*e.xbutton.display=sdpy;
  318 + e.xbutton.window=swin;
  319 + e.xbutton.root=swin;
  320 + e.xbutton.window=swin;
  321 + e.xbutton.x_root=e.xbutton.x;
  322 + e.xbutton.y_root=e.xbutton.y;*/
  323 + //XSendEvent( sdpy, swin, True, mask, &e );
  324 + XPutBackEvent( sdpy, &e );
  325 + //XTestFakeMotionEvent(sdpy,sscr,e.xbutton.x,e.xbutton.y,0);
  326 + XTestFakeButtonEvent(sdpy,e.xbutton.button,e.xbutton.type==ButtonPress,0);
  327 + }
  328 + }
  329 + while(XCheckTypedWindowEvent(sdpy, swin, MotionNotify, &e)!=False)
  330 + {
  331 + //XPutBackEvent( sdpy, &e );
  332 + //printf("motion event\n");
  333 + xmouse=e.xbutton.x_root;
  334 + ymouse=e.xbutton.y_root;
  335 + }
  336 +#endif
  337 +}
  338 +
  339 +void printUsage()
  340 +{
  341 + printf("\nusage: windump [srcdpy [destdpy]] [-s srcdpy] [-t destdpy] [-d delay_us] [-w windowdec] [-a autohide] [-i srcwinID] [srcdpy [destdpy]]\n");
  342 + printf("\n");
  343 + printf(" srcdpy ...... source display to capture\n");
  344 + printf(" [default: :0.0]\n");
  345 + printf(" destdpy ..... target display where to display the captured screen\n");
  346 + printf(" [default: :0.1]\n");
  347 + printf(" delay_us .... time delay between frame captures in mycroseconds\n");
  348 + printf(" [default: 15000]\n");
  349 + printf(" windowdec ... enable window decoration\n");
  350 + printf(" [default: 0]\n");
  351 + printf(" autohide .... auto hide captured screen\n");
  352 + printf(" [default: 1]\n");
  353 + printf(" srcwinID .... window ID (in hex) to be captured if not root window\n");
  354 + printf(" [default: root window]\n");
  355 + printf("\n");
  356 +}
  357 +
  358 +main(int argc, char * argv [])
  359 +{
  360 + int opt;
  361 + if (argc<=1)
  362 + {
  363 + //printHelp();
  364 + }
  365 + char * sdpyName = ":0.0";
  366 + char * tdpyName = ":0.1";
  367 +
  368 + Window swin=0;
  369 +
  370 + int delay_us=15000;
  371 + int windowdec=0;
  372 + int autohide=1;
  373 +#define MYBOOL(x) ((int)((x)[0]=='y'||(x)[0]=='1'||(x)[0]=='t'))
  374 + if ( argc>1 && argv[1][0]!='-' ) {
  375 + sdpyName=argv[1]; argv[1]=argv[0]; argv=&(argv[1]); argc--;
  376 + if ( argc>1 && argv[1][0]!='-' ) {
  377 + tdpyName=argv[1]; argv[1]=argv[0]; argv=&(argv[1]); argc--;
  378 + }
  379 + }
  380 + while ((opt = getopt(argc, argv, "s:t:d:w:a:i:")) != -1) {
  381 + switch (opt) {
  382 + case 's': sdpyName=strdup(optarg); break;
  383 + case 't': tdpyName=strdup(optarg); break;
  384 + case 'd': delay_us=atoi(optarg); break;
  385 + case 'w': windowdec=MYBOOL(optarg); break;
  386 + case 'a': autohide=MYBOOL(optarg); break;
  387 + case 'i': sscanf(optarg,"%x",(unsigned int *)&swin); break;
  388 + default: printUsage(); exit(1); break;
  389 + }
  390 + }
  391 +
  392 + if (optind <argc) sdpyName=argv[optind];
  393 + if (optind+1<argc) tdpyName=argv[optind+1];
  394 + //if (argc>2) tdpyName=argv[2];
  395 + Display * sdpy = XOpenDisplay(sdpyName);
  396 + Display * tdpy = XOpenDisplay(tdpyName);
  397 + int sscr = XDefaultScreen(sdpy);
  398 + int tscr = XDefaultScreen(tdpy);
  399 + GC tgc = DefaultGC(tdpy,tscr);
  400 + if(swin==0) swin=RootWindow (sdpy,sscr);
  401 + //if (argc>3) swin=atoi(argv[3]);
  402 + int width, height, dummy;
  403 + XGetGeometry(sdpy, swin, (Window *)&dummy, &dummy, &dummy, &width, &height, &dummy, &dummy);
  404 + Window twin=CreateWindow(tdpy,tscr,width,height,windowdec);
  405 + XSelectInput(sdpy, swin, PointerMotionMask);
  406 + XImage * image;
  407 + XImage * simage;
  408 + XImage * timage;
  409 + int use_shm=1;
  410 + int use_xv=0;
  411 + XShmSegmentInfo xshm_sinfo;
  412 + XShmSegmentInfo xshm_tinfo;
  413 + if(use_shm) createShmImage(width,height,&xshm_sinfo,&xshm_tinfo,sdpy,tdpy,sscr,tscr,&simage,&timage);
  414 +
  415 + int frame=0;
  416 + for(;;) {
  417 + XEvent e;
  418 + XNextEvent(tdpy, &e);
  419 + if (e.type == MapNotify)
  420 + break;
  421 + }
  422 +
  423 + int emulate_events=0;
  424 +
  425 +#ifdef USE_XATOM
  426 + Hints hints;
  427 + Atom property;
  428 + hints.flags = 2; // Specify that we're changing the window decorations.
  429 + hints.functions=0;
  430 + hints.decorations = 0; // 0 (false) means that window decorations should go bye-bye.
  431 + property = XInternAtom(tdpy, "_MOTIF_WM_HINTS", True);
  432 + XChangeProperty(tdpy, twin, property, property, 32, PropModeReplace, (unsigned char *) &hints, 5);
  433 +
  434 +
  435 + XSetWindowAttributes attributes;
  436 +
  437 + //attributes.override_redirect = True;
  438 + //XChangeWindowAttributes(tdpy, twin,
  439 + // CWOverrideRedirect, &attributes);
  440 +#endif
  441 +
  442 + double t;
  443 + while(1)
  444 + {
  445 +
  446 + if(emulate_events) emulateEvents(sdpy,swin,tdpy,twin);
  447 +
  448 + //{ static double t=0.0; if (t==0.0) t=time_s(); printf("fps %f\n", 1.0/(time_s()-t)); t=time_s(); }
  449 +
  450 + //t=time_s();
  451 + usleep(delay_us);
  452 + //printf("sleep: %f sec\n", time_s()-t);
  453 +
  454 + Window rwin,cwin;
  455 + int xmouse,ymouse,x,y,mask;
  456 + XQueryPointer(sdpy,swin,&rwin,&cwin,&xmouse,&ymouse,&x,&y,&mask);
  457 + if( (x==xmouse && y==ymouse) || !autohide )
  458 + {
  459 + if(autohide)
  460 + {
  461 + XResizeWindow(tdpy,twin,width,height);
  462 + XRaiseWindow(tdpy,twin);
  463 + }
  464 +
  465 + if(use_xv)
  466 + {
  467 + //XvShmGetImage (sdpy, swin, simage, 0, 0, AllPlanes);
  468 + }
  469 + else if(use_shm)
  470 + {
  471 + int use_damage=0;
  472 + if(use_damage)
  473 + {
  474 + }
  475 + else {
  476 + //t=time_s();
  477 + XShmGetImage (sdpy, swin, simage, 0, 0, AllPlanes);
  478 + //printf("get: %f sec\n", time_s()-t);
  479 +
  480 + //drawMouse(timage, xmouse+1, ymouse+1,0x000000);
  481 + //drawMouse(timage, xmouse, ymouse,0xFFFFFF);
  482 + XFixesCursorImage* cur = XFixesGetCursorImage(sdpy);
  483 + //modifyMouseCursor(cur);
  484 + drawMouseImage(timage, cur, xmouse, ymouse);
  485 + XFree(cur);
  486 +
  487 + //t=time_s();
  488 + XShmPutImage (tdpy, twin, tgc, timage, 0, 0, 0, 0, timage->width, timage->height, False);
  489 + //printf("put: %f sec\n", time_s()-t);
  490 + }
  491 + }
  492 + else
  493 + {
  494 + //t=time_s();
  495 + image=CaptRoot(sdpy,sscr);
  496 + //printf("get: %f sec\n", time_s()-t);
  497 +
  498 + //t=time_s();
  499 + DrawImage(tdpy,twin,image);
  500 + XDestroyImage(image);
  501 + //printf("put: %f sec\n", time_s()-t);
  502 + }
  503 + }
  504 + else
  505 + {
  506 + if(autohide)
  507 + {
  508 + XResizeWindow(tdpy,twin,1,1);
  509 + }
  510 + }
  511 + //t=time_s();
  512 + XFlush(tdpy);
  513 + //XSync(tdpy,False);
  514 + //printf("flush: %f sec\n", time_s()-t);
  515 + }
  516 +}

0 comments on commit f8dca86

Please sign in to comment.
Something went wrong with that request. Please try again.