Exemple #1
0
/* pipe the output to sort|uniq -u and you'll get the errors. */
int main(int argc, char** argv)
{
    sraRegionPtr region, region1, region2;
    sraRectangleIterator* i;
    sraRect rect;
    rfbBool b;

    region = sraRgnCreateRect(10, 10, 600, 300);
    region1 = sraRgnCreateRect(40, 50, 350, 200);
    region2 = sraRgnCreateRect(0, 0, 20, 40);

    sraRgnPrint(region);
    printf("\n[(10-300)[(10-600)]]\n\n");

    b = sraRgnSubtract(region, region1);
    printf("%s ",b?"true":"false");
    sraRgnPrint(region);
    printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n");

    sraRgnOr(region, region2);
    printf("%ld\n6\n\n", sraRgnCountRects(region));

    i = sraRgnGetIterator(region);
    while(sraRgnIteratorNext(i, &rect))
        printf("%dx%d+%d+%d ",
               rect.x2-rect.x1,rect.y2-rect.y1,
               rect.x1,rect.y1);
    sraRgnReleaseIterator(i);
    printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200 \n\n");

    i = sraRgnGetReverseIterator(region,1,0);
    while(sraRgnIteratorNext(i, &rect))
        printf("%dx%d+%d+%d ",
               rect.x2-rect.x1,rect.y2-rect.y1,
               rect.x1,rect.y1);
    sraRgnReleaseIterator(i);
    printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200 \n\n");

    i = sraRgnGetReverseIterator(region,1,1);
    while(sraRgnIteratorNext(i, &rect))
        printf("%dx%d+%d+%d ",
               rect.x2-rect.x1,rect.y2-rect.y1,
               rect.x1,rect.y1);
    sraRgnReleaseIterator(i);
    printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0 \n\n");

    sraRgnDestroy(region);
    sraRgnDestroy(region1);
    sraRgnDestroy(region2);

    return(0);
}
Exemple #2
0
void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion)
{
   rfbClientIteratorPtr iterator;
   rfbClientPtr cl;

   iterator=rfbGetClientIterator(rfbScreen);
   while((cl=rfbClientIteratorNext(iterator))) {
     LOCK(cl->updateMutex);
     sraRgnOr(cl->modifiedRegion,modRegion);
     UNLOCK(cl->updateMutex);
   }

   rfbReleaseClientIterator(iterator);
}
Exemple #3
0
void add_region_xdamage(sraRegionPtr new_region) {
	sraRegionPtr reg;
	int prev_tick, nreg;

	if (! xdamage_regions) {
		return;
	}

	nreg = (xdamage_memory * NSCAN) + 1;
	prev_tick = xdamage_ticker - 1;
	if (prev_tick < 0) {
		prev_tick = nreg - 1;
	}

	reg = xdamage_regions[prev_tick];  
	if (reg != NULL && new_region != NULL) {
if (debug_xdamage > 1) fprintf(stderr, "add_region_xdamage: prev_tick: %d reg %p  new_region %p\n", prev_tick, (void *)reg, (void *)new_region);
		sraRgnOr(reg, new_region);
	}
}
Exemple #4
0
void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
{  
   rfbClientIteratorPtr iterator;
   rfbClientPtr cl;

   iterator=rfbGetClientIterator(rfbScreen);
   while((cl=rfbClientIteratorNext(iterator))) {
     LOCK(cl->updateMutex);
     if(cl->useCopyRect) {
       sraRegionPtr modifiedRegionBackup;
       if(!sraRgnEmpty(cl->copyRegion)) {
	  if(cl->copyDX!=dx || cl->copyDY!=dy) {
	     /* if a copyRegion was not yet executed, treat it as a
	      * modifiedRegion. The idea: in this case it could be
	      * source of the new copyRect or modified anyway. */
	     sraRgnOr(cl->modifiedRegion,cl->copyRegion);
	     sraRgnMakeEmpty(cl->copyRegion);
	  } else {
	     /* we have to set the intersection of the source of the copy
	      * and the old copy to modified. */
	     modifiedRegionBackup=sraRgnCreateRgn(copyRegion);
	     sraRgnOffset(modifiedRegionBackup,-dx,-dy);
	     sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
	     sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
	     sraRgnDestroy(modifiedRegionBackup);
	  }
       }
	  
       sraRgnOr(cl->copyRegion,copyRegion);
       cl->copyDX = dx;
       cl->copyDY = dy;

       /* if there were modified regions, which are now copied,
	* mark them as modified, because the source of these can be overlapped
	* either by new modified or now copied regions. */
       modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion);
       sraRgnOffset(modifiedRegionBackup,dx,dy);
       sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
       sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
       sraRgnDestroy(modifiedRegionBackup);

       if(!cl->enableCursorShapeUpdates) {
          /*
           * n.b. (dx, dy) is the vector pointing in the direction the
           * copyrect displacement will take place.  copyRegion is the
           * destination rectangle (say), not the source rectangle.
           */
          sraRegionPtr cursorRegion;
          int x = cl->cursorX - cl->screen->cursor->xhot;
          int y = cl->cursorY - cl->screen->cursor->yhot;
          int w = cl->screen->cursor->width;
          int h = cl->screen->cursor->height;

          cursorRegion = sraRgnCreateRect(x, y, x + w, y + h);
          sraRgnAnd(cursorRegion, cl->copyRegion);
          if(!sraRgnEmpty(cursorRegion)) {
             /*
              * current cursor rect overlaps with the copy region *dest*,
              * mark it as modified since we won't copy-rect stuff to it.
              */
             sraRgnOr(cl->modifiedRegion, cursorRegion);
          }
          sraRgnDestroy(cursorRegion);

          cursorRegion = sraRgnCreateRect(x, y, x + w, y + h);
          /* displace it to check for overlap with copy region source: */
          sraRgnOffset(cursorRegion, dx, dy);
          sraRgnAnd(cursorRegion, cl->copyRegion);
          if(!sraRgnEmpty(cursorRegion)) {
             /*
              * current cursor rect overlaps with the copy region *source*,
              * mark the *displaced* cursorRegion as modified since we
              * won't copyrect stuff to it.
              */
             sraRgnOr(cl->modifiedRegion, cursorRegion);
          }
          sraRgnDestroy(cursorRegion);
       }

     } else {
       sraRgnOr(cl->modifiedRegion,copyRegion);
     }
     TSIGNAL(cl->updateCond);
     UNLOCK(cl->updateMutex);
   }

   rfbReleaseClientIterator(iterator);
}
Exemple #5
0
int xdamage_hint_skip(int y) {
	static sraRegionPtr scanline = NULL;
	static sraRegionPtr tmpl_y = NULL;
	int fast_tmpl = 1;
	sraRegionPtr reg, tmpl;
	int ret, i, n, nreg;
#ifndef NO_NCACHE
	static int ncache_no_skip = 0;
	static double last_ncache_no_skip = 0.0;
	static double last_ncache_no_skip_long = 0.0, ncache_fac = 0.25;
#endif

	if (! xdamage_present || ! use_xdamage) {
		return 0;	/* cannot skip */
	}
	if (! xdamage_regions) {
		return 0;	/* cannot skip */
	}

	if (! scanline) {
		/* keep it around to avoid malloc etc, recreate */
		scanline = sraRgnCreate();
	}
	if (! tmpl_y) {
		tmpl_y = sraRgnCreateRect(0, 0, dpy_x, 1);
	}

	nreg = (xdamage_memory * NSCAN) + 1;

#ifndef NO_NCACHE
	if (ncache > 0) {
		if (ncache_no_skip == 0) {
			double now = g_now;
			if (now > last_ncache_no_skip + 8.0) {
				ncache_no_skip = 1;
			} else if (now < last_bs_restore + 0.5) {
				ncache_no_skip = 1;
			} else if (now < last_su_restore + 0.5) {
				ncache_no_skip = 1;
			} else if (now < last_copyrect + 0.5) {
				ncache_no_skip = 1;
			}
			if (ncache_no_skip) {
				last_ncache_no_skip = dnow();
				if (now > last_ncache_no_skip_long + 60.0) {
					ncache_fac = 2.0;
					last_ncache_no_skip_long = now;
				} else {
					ncache_fac = 0.25;
				}
				return 0;
			}
		} else {
			if (ncache_no_skip++ >= ncache_fac*nreg + 4) {
				ncache_no_skip = 0;
			} else {
				return 0;
			}
		}
	}
#endif

	if (fast_tmpl) {
		sraRgnOffset(tmpl_y, 0, y);
		tmpl = tmpl_y;
	} else {
		tmpl = sraRgnCreateRect(0, y, dpy_x, y+1);
	}

	ret = 1;
	for (i=0; i<nreg; i++) {
		/* go back thru the history starting at most recent */
		n = (xdamage_ticker + nreg - i) % nreg;
		reg = xdamage_regions[n];  
		if (reg == NULL) {
			continue;
		}
		if (sraRgnEmpty(reg)) {
			/* checking for emptiness is very fast */
			continue;
		}
		sraRgnMakeEmpty(scanline);
		sraRgnOr(scanline, tmpl);
		if (sraRgnAnd(scanline, reg)) {
			ret = 0;
			break;
		}
	}
	if (fast_tmpl) {
		sraRgnOffset(tmpl_y, 0, -y);
	} else {
		sraRgnDestroy(tmpl);
	}
if (0) fprintf(stderr, "xdamage_hint_skip: %d -> %d\n", y, ret);

	return ret;
}
Exemple #6
0
int collect_xdamage(int scancnt, int call) {
#if HAVE_LIBXDAMAGE
	XDamageNotifyEvent *dev;
	XEvent ev;
	sraRegionPtr tmpregion;
	sraRegionPtr reg;
	static int rect_count = 0;
	int nreg, ccount = 0, dcount = 0, ecount = 0;
	static time_t last_rpt = 0;
	time_t now;
	int x, y, w, h, x2, y2;
	int i, dup, next = 0, dup_max = 0;
#define DUPSZ 32
	int dup_x[DUPSZ], dup_y[DUPSZ], dup_w[DUPSZ], dup_h[DUPSZ];
	double tm, dt;
	int mark_all = 0, retries = 0, too_many = 1000, tot_ev = 0;

	RAWFB_RET(0)

	if (scancnt) {} /* unused vars warning: */

	if (! xdamage_present || ! use_xdamage) {
		return 0;
	}
	if (! xdamage) {
		return 0;
	}
	if (! xdamage_base_event_type) {
		return 0;
	}
	if (! xdamage_regions) {
		return 0;
	}

	dtime0(&tm);

	nreg = (xdamage_memory * NSCAN) + 1;

	if (call == 0) {
		xdamage_ticker = (xdamage_ticker+1) % nreg;
		xdamage_direct_count = 0;
		reg = xdamage_regions[xdamage_ticker];  
		if (reg != NULL) {
			sraRgnMakeEmpty(reg);
		}
	} else {
		if (xdamage_ticker < 0) {
			xdamage_ticker = 0;
		}
		reg = xdamage_regions[xdamage_ticker];  
	}
	if (reg == NULL) {
		return 0;
	}


	X_LOCK;
if (0)	XFlush_wr(dpy);
if (0)	XEventsQueued(dpy, QueuedAfterFlush);

	come_back_for_more:

	while (XCheckTypedEvent(dpy, xdamage_base_event_type+XDamageNotify, &ev)) {
		/*
		 * TODO max cut off time in this loop?
		 * Could check QLength and if huge just mark the whole
		 * screen.
		 */
		ecount++;
		tot_ev++;

		if (mark_all) {
			continue;
		}
		if (ecount == too_many) {
			int nqa = XEventsQueued(dpy, QueuedAlready);
			if (nqa >= too_many) {
				static double last_msg = 0.0;
				tmpregion = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
				sraRgnOr(reg, tmpregion);
				sraRgnDestroy(tmpregion);
				if (dnow() > last_msg + xdamage_crazy_delay) {
					rfbLog("collect_xdamage: too many xdamage events %d+%d\n", ecount, nqa);
					last_msg = dnow();
				}
				mark_all = 1;
			}
		}

		if (ev.type != xdamage_base_event_type + XDamageNotify) {
			break;
		}
		dev = (XDamageNotifyEvent *) &ev;
		if (dev->damage != xdamage) {
			continue;	/* not ours! */
		}

		x = dev->area.x;
		y = dev->area.y;
		w = dev->area.width;
		h = dev->area.height;

		/*
		 * we try to manually remove some duplicates because
		 * certain activities can lead to many 10's of dups
		 * in a row.  The region work can be costly and reg is
		 * later used in xdamage_hint_skip loops, so it is good
		 * to skip them if possible.
		 */
		dup = 0;
		for (i=0; i < dup_max; i++) {
			if (dup_x[i] == x && dup_y[i] == y && dup_w[i] == w &&
			    dup_h[i] == h) {
				dup = 1;
				break;
			}
		}
		if (dup) {
			dcount++;
			continue;
		}
		if (dup_max < DUPSZ) {
			next = dup_max;
			dup_max++;
		} else {
			next = (next+1) % DUPSZ;
		}
		dup_x[next] = x;
		dup_y[next] = y;
		dup_w[next] = w;
		dup_h[next] = h;

		/* translate if needed */
		if (clipshift) {
			/* set coords relative to fb origin */
			if (0 && rootshift) {
				/*
				 * Note: not needed because damage is
				 * relative to subwin, not rootwin.
				 */
				x = x - off_x;
				y = y - off_y;
			}
			if (clipshift) {
				x = x - coff_x;
				y = y - coff_y;
			}

			x2 = x + w;		/* upper point */
			x  = nfix(x,  dpy_x);	/* place both in fb area */
			x2 = nfix(x2, dpy_x+1);
			w = x2 - x;		/* recompute w */
			
			y2 = y + h;
			y  = nfix(y,  dpy_y);
			y2 = nfix(y2, dpy_y+1);
			h = y2 - y;

			if (w <= 0 || h <= 0) {
				continue;
			}
		}
		if (debug_xdamage > 2) {
			fprintf(stderr, "xdamage: -> event %dx%d+%d+%d area:"
			    " %d  dups: %d  %s\n", w, h, x, y, w*h, dcount,
			    (w*h > xdamage_max_area) ? "TOO_BIG" : "");
		}

		record_desired_xdamage_rect(x, y, w, h);

		tmpregion = sraRgnCreateRect(x, y, x + w, y + h); 
		sraRgnOr(reg, tmpregion);
		sraRgnDestroy(tmpregion);
		rect_count++;
		ccount++;
	}

	if (mark_all) {
		if (ecount + XEventsQueued(dpy, QueuedAlready) >= 3 * too_many && retries < 3) {
			retries++;
			XFlush_wr(dpy);
			usleep(20 * 1000);
			XFlush_wr(dpy);
			ecount = 0;
			goto come_back_for_more;
		}
	}

	/* clear the whole damage region for next time. XXX check */
	if (call == 1) {
		XDamageSubtract(dpy, xdamage, None, None);
	}
	X_UNLOCK;

	if (tot_ev > 20 * too_many) {
		rfbLog("collect_xdamage: xdamage has gone crazy (screensaver or game?) ev: %d ret: %d\n", tot_ev, retries);
		rfbLog("collect_xdamage: disabling xdamage for %d seconds.\n", (int) xdamage_crazy_delay);
		destroy_xdamage_if_needed();
		X_LOCK;
		XSync(dpy, False);
		while (XCheckTypedEvent(dpy, xdamage_base_event_type+XDamageNotify, &ev)) {
			;
		}
		X_UNLOCK;
		xdamage_crazy_time = dnow();
	}

	if (0 && xdamage_direct_count) {
		fb_push();
	}

	dt = dtime(&tm);
	if ((debug_tiles > 1 && ecount) || (debug_tiles && ecount > 200)
	    || debug_xdamage > 1) {
		fprintf(stderr, "collect_xdamage(%d): %.4f t: %.4f ev/dup/accept"
		    "/direct %d/%d/%d/%d\n", call, dt, tm - x11vnc_start, ecount,
		    dcount, ccount, xdamage_direct_count); 
	}
	now = time(NULL);
	if (! last_rpt) {
		last_rpt = now;
	}
	if (now > last_rpt + 15) {
		double rat = -1.0;

		if (XD_tot) {
			rat = ((double) XD_skip)/XD_tot;
		}
		if (debug_tiles || debug_xdamage) {
			fprintf(stderr, "xdamage: == scanline skip/tot: "
			    "%04d/%04d =%.3f  rects: %d  desired: %d\n",
			    XD_skip, XD_tot, rat, rect_count, XD_des);
		}
			
		XD_skip = 0;
		XD_tot  = 0;
		XD_des  = 0;
		rect_count = 0;
		last_rpt = now;
	}
#else
	if (0) scancnt++;	/* compiler warnings */
	if (0) call++;
	if (0) record_desired_xdamage_rect(0, 0, 0, 0);
#endif
	return 0;
}
Exemple #7
0
int collect_non_X_xdamage(int x_in, int y_in, int w_in, int h_in, int call) {
	sraRegionPtr tmpregion;
	sraRegionPtr reg;
	static int rect_count = 0;
	int nreg, ccount = 0, dcount = 0, ecount = 0;
	static time_t last_rpt = 0;
	time_t now;
	double tm, dt;
	int x, y, w, h, x2, y2;

if (call && debug_xdamage > 1) fprintf(stderr, "collect_non_X_xdamage: %d %d %d %d - %d / %d\n", x_in, y_in, w_in, h_in, call, use_xdamage);

	if (! use_xdamage) {
		return 0;
	}
	if (! xdamage_regions) {
		return 0;
	}

	dtime0(&tm);

	nreg = (xdamage_memory * NSCAN) + 1;

	if (call == 0) {
		xdamage_ticker = (xdamage_ticker+1) % nreg;
		xdamage_direct_count = 0;
		reg = xdamage_regions[xdamage_ticker];  
		if (reg != NULL) {
			sraRgnMakeEmpty(reg);
		}
	} else {
		if (xdamage_ticker < 0) {
			xdamage_ticker = 0;
		}
		reg = xdamage_regions[xdamage_ticker];  
	}
	if (reg == NULL) {
		return 0;
	}

	if (x_in < 0) {
		return 0;
	}


	x = x_in;
	y = y_in;
	w = w_in;
	h = h_in;

	/* translate if needed */
	if (clipshift) {
		/* set coords relative to fb origin */
		if (0 && rootshift) {
			/*
			 * Note: not needed because damage is
			 * relative to subwin, not rootwin.
			 */
			x = x - off_x;
			y = y - off_y;
		}
		if (clipshift) {
			x = x - coff_x;
			y = y - coff_y;
		}

		x2 = x + w;		/* upper point */
		x  = nfix(x,  dpy_x);	/* place both in fb area */
		x2 = nfix(x2, dpy_x+1);
		w = x2 - x;		/* recompute w */
		
		y2 = y + h;
		y  = nfix(y,  dpy_y);
		y2 = nfix(y2, dpy_y+1);
		h = y2 - y;

		if (w <= 0 || h <= 0) {
			return 0;
		}
	}
	if (debug_xdamage > 2) {
		fprintf(stderr, "xdamage: -> event %dx%d+%d+%d area:"
		    " %d  dups: %d  %s reg: %p\n", w, h, x, y, w*h, dcount,
		    (w*h > xdamage_max_area) ? "TOO_BIG" : "", (void *)reg);
	}

	record_desired_xdamage_rect(x, y, w, h);

	tmpregion = sraRgnCreateRect(x, y, x + w, y + h); 
	sraRgnOr(reg, tmpregion);
	sraRgnDestroy(tmpregion);
	rect_count++;
	ccount++;

	if (0 && xdamage_direct_count) {
		fb_push();
	}

	dt = dtime(&tm);
	if ((debug_tiles > 1 && ecount) || (debug_tiles && ecount > 200)
	    || debug_xdamage > 1) {
		fprintf(stderr, "collect_non_X_xdamage(%d): %.4f t: %.4f ev/dup/accept"
		    "/direct %d/%d/%d/%d\n", call, dt, tm - x11vnc_start, ecount,
		    dcount, ccount, xdamage_direct_count); 
	}
	now = time(NULL);
	if (! last_rpt) {
		last_rpt = now;
	}
	if (now > last_rpt + 15) {
		double rat = -1.0;

		if (XD_tot) {
			rat = ((double) XD_skip)/XD_tot;
		}
		if (debug_tiles || debug_xdamage) {
			fprintf(stderr, "xdamage: == scanline skip/tot: "
			    "%04d/%04d =%.3f  rects: %d  desired: %d\n",
			    XD_skip, XD_tot, rat, rect_count, XD_des);
		}
			
		XD_skip = 0;
		XD_tot  = 0;
		XD_des  = 0;
		rect_count = 0;
		last_rpt = now;
	}
	return 0;
}
Exemple #8
0
void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
{  
   rfbClientIteratorPtr iterator;
   rfbClientPtr cl;

   iterator=rfbGetClientIterator(rfbScreen);
   while((cl=rfbClientIteratorNext(iterator))) {
     LOCK(cl->updateMutex);
     if(cl->useCopyRect) {
       sraRegionPtr modifiedRegionBackup;
       if(!sraRgnEmpty(cl->copyRegion)) {
	  if(cl->copyDX!=dx || cl->copyDY!=dy) {
	     /* if a copyRegion was not yet executed, treat it as a
	      * modifiedRegion. The idea: in this case it could be
	      * source of the new copyRect or modified anyway. */
	     sraRgnOr(cl->modifiedRegion,cl->copyRegion);
	     sraRgnMakeEmpty(cl->copyRegion);
	  } else {
	     /* we have to set the intersection of the source of the copy
	      * and the old copy to modified. */
	     modifiedRegionBackup=sraRgnCreateRgn(copyRegion);
	     sraRgnOffset(modifiedRegionBackup,-dx,-dy);
	     sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
	     sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
	     sraRgnDestroy(modifiedRegionBackup);
	  }
       }
	  
       sraRgnOr(cl->copyRegion,copyRegion);
       cl->copyDX = dx;
       cl->copyDY = dy;

       /* if there were modified regions, which are now copied,
	* mark them as modified, because the source of these can be overlapped
	* either by new modified or now copied regions. */
       modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion);
       sraRgnOffset(modifiedRegionBackup,dx,dy);
       sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
       sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
       sraRgnDestroy(modifiedRegionBackup);

#if 0
       /* TODO: is this needed? Or does it mess up deferring? */
       /* while(!sraRgnEmpty(cl->copyRegion)) */ {
	   {
	     sraRegionPtr updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
	     sraRgnOr(updateRegion,cl->copyRegion);
	     UNLOCK(cl->updateMutex);
	     rfbSendFramebufferUpdate(cl,updateRegion);
	     sraRgnDestroy(updateRegion);
	     continue;
	   }
       }
#endif
     } else {
       sraRgnOr(cl->modifiedRegion,copyRegion);
     }
     UNLOCK(cl->updateMutex);
   }

   rfbReleaseClientIterator(iterator);
}