Example #1
0
void initialize_xdamage(void) {
	sraRegionPtr *ptr;
	int i, nreg;

	if (! xdamage_present) {
		use_xdamage = 0;
	}
	if (xdamage_regions)  {
		ptr = xdamage_regions;
		while (*ptr != NULL) {
			sraRgnDestroy(*ptr);
			ptr++;
		}
		free(xdamage_regions);
		xdamage_regions = NULL;
	}
	if (use_xdamage) {
		nreg = (xdamage_memory * NSCAN) + 2;
		xdamage_regions = (sraRegionPtr *)
		    malloc(nreg * sizeof(sraRegionPtr));
		for (i = 0; i < nreg; i++) {
			ptr = xdamage_regions+i;
			if (i == nreg - 1) {
				*ptr = NULL;
			} else {
				*ptr = sraRgnCreate();
				sraRgnMakeEmpty(*ptr);
			}
		}
		/* set so will be 0 in first collect_xdamage call */
		xdamage_ticker = -1;
	}
}
Example #2
0
File: main.c Project: DjCBS3/vino
void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen, char *framebuffer,
                       int width, int height)
{
  rfbClientIteratorPtr iterator;
  rfbClientPtr cl;

  if (width & 3)
    rfbErr("WARNING: New width (%d) is not a multiple of 4.\n", width);

  /* Update information in the rfbScreenInfo structure */

  rfbScreen->width = width;
  rfbScreen->height = height;
  rfbScreen->frameBuffer = framebuffer;

  /* Adjust pointer position if necessary */

  if (rfbScreen->cursorX >= width)
    rfbScreen->cursorX = width - 1;
  if (rfbScreen->cursorY >= height)
    rfbScreen->cursorY = height - 1;

  /* For each client: */
  iterator = rfbGetClientIterator(rfbScreen);
  while ((cl = rfbClientIteratorNext(iterator)) != NULL) {

    /* Mark the screen contents as changed, and schedule sending
       NewFBSize message if supported by this client. */

    LOCK(cl->updateMutex);
    sraRgnDestroy(cl->modifiedRegion);
    cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height);
    sraRgnMakeEmpty(cl->copyRegion);
    cl->copyDX = 0;
    cl->copyDY = 0;

    if (cl->useNewFBSize)
      cl->newFBSizePending = TRUE;

    UNLOCK(cl->updateMutex);
  }
  rfbReleaseClientIterator(iterator);
}
Example #3
0
void rfbNewFramebuffer(rfbScreenInfoPtr screen, char *framebuffer,
                       int width, int height,
                       int bitsPerSample, int samplesPerPixel,
                       int bytesPerPixel)
{
  rfbPixelFormat old_format;
  rfbBool format_changed = FALSE;
  rfbClientIteratorPtr iterator;
  rfbClientPtr cl;

  /* Update information in the screenInfo structure */

  old_format = screen->serverFormat;

  if (width & 3)
    rfbErr("WARNING: New width (%d) is not a multiple of 4.\n", width);

  screen->width = width;
  screen->height = height;
  screen->bitsPerPixel = screen->depth = 8*bytesPerPixel;
  screen->paddedWidthInBytes = width*bytesPerPixel;

  rfbInitServerFormat(screen, bitsPerSample);

  if (memcmp(&screen->serverFormat, &old_format,
             sizeof(rfbPixelFormat)) != 0) {
    format_changed = TRUE;
  }

  screen->frameBuffer = framebuffer;

  /* Adjust pointer position if necessary */

  if (screen->cursorX >= width)
    screen->cursorX = width - 1;
  if (screen->cursorY >= height)
    screen->cursorY = height - 1;

  /* For each client: */
  iterator = rfbGetClientIterator(screen);
  while ((cl = rfbClientIteratorNext(iterator)) != NULL) {

    /* Re-install color translation tables if necessary */

    if (format_changed)
      screen->setTranslateFunction(cl);

    /* Mark the screen contents as changed, and schedule sending
       NewFBSize message if supported by this client. */

    LOCK(cl->updateMutex);
    sraRgnDestroy(cl->modifiedRegion);
    cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height);
    sraRgnMakeEmpty(cl->copyRegion);
    cl->copyDX = 0;
    cl->copyDY = 0;

    if (cl->useNewFBSize)
      cl->newFBSizePending = TRUE;

    TSIGNAL(cl->updateCond);
    UNLOCK(cl->updateMutex);
  }
  rfbReleaseClientIterator(iterator);
}
Example #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);
}
Example #5
0
int VNCServer::Client::Run()
{
	Log(">VNCServer::Client::Run [this:%p]\n",this);

	//Lock
	LOCK(cl->updateMutex);

	//Set new modified region
	cl->modifiedRegion = sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height);

	//Until ended
	while (!wait.IsCanceled())
	{
		Debug("-VNCServer::Client lopp [this:%p,state:%d,empty:%d]\n",this,cl->state,sraRgnEmpty(cl->requestedRegion));

		//If connected, always require a FB Update Request (otherwise can crash.)
		if (cl->state == rfbClientRec::RFB_NORMAL && !sraRgnEmpty(cl->requestedRegion))
		{
			//If reseted
			if (reset)
			{
				Log("-Reseting client\n");
				//Reset message
				char msg[] = {16};
				//Write it
				if (!Write(msg,sizeof(msg)))
					//WS closed
					break;
				//Clear reset flag
				reset = false;
			}
/*

			//If the scren has been resized
			if (cl->newFBSizePending)
			{
				//Free region
				sraRgnDestroy(cl->modifiedRegion);
				//Set new modified region
				cl->modifiedRegion = sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height);
			}
*/
		

			//We need to update by default
			bool haveUpdate = true;

			/* Now, get the region we're going to update, and remove
			it from cl->modifiedRegion _before_ we send the update.
			That way, if anything that overlaps the region we're sending
			is updated, we'll be sure to do another update later. */
			sraRegion* updateRegion = sraRgnCreateRgn(cl->modifiedRegion);

			//Check if we didn't already have a pending update
			if  (!FB_UPDATE_PENDING(cl))
				//Check it is inside requested region
				haveUpdate = !sraRgnEmpty(cl->modifiedRegion);//sraRgnAnd(updateRegion,cl->requestedRegion);

			//IF we are freezed
			if (freeze)
				//Don't send any change
				sraRgnMakeEmpty(updateRegion);

			//Clean modified region
			sraRgnMakeEmpty(cl->modifiedRegion);

			//Unlock region
			UNLOCK(cl->updateMutex);

			Debug("-VNCServer::Client update [this:%p,update:%d,mod:%d,req:%d]\n",this,haveUpdate,sraRgnEmpty(cl->modifiedRegion),sraRgnEmpty(cl->requestedRegion));

			//If we have to update and not freezed
			if (haveUpdate)
			{
				Debug(">VNCServer::Client SendFramebufferUpdate [%p]\n",this);
				/* Now actually send the update. */
				rfbIncrClientRef(cl);
				//LOCK(cl->sendMutex);
				rfbSendFramebufferUpdate(cl, updateRegion);
				//UNLOCK(cl->sendMutex);
				rfbDecrClientRef(cl);
				Debug("<VNCServer::Client SendFramebufferUpdate [%p]\n",this);
			}

			//Destroy region
			sraRgnDestroy(updateRegion);

			//Lock again
			LOCK(cl->updateMutex);
		}

		//Check if we have been cancelled
		if (wait.IsCanceled())
			//Exit
			break;

		//Wait cond
		Debug("<VNCServer::Client going to sleep [this:%p]\n",this);
		WAIT(cl->updateCond,cl->updateMutex);
		Debug(">VNCServer::Client waked up from wait mutex[this:%p,isCanceled:%d]\n",this,wait.IsCanceled());
	}
	//Unlock
	UNLOCK(cl->updateMutex);

	Log("<VNCServer::Client::Run [this:%p]\n",this);

	//OK
	return 0;
}
Example #6
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;
}
Example #7
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;
}
Example #8
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;
}
Example #9
0
File: main.c Project: DjCBS3/vino
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);
}