double rect_overlap(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2) { double a, A, o; sraRegionPtr r, R; sraRectangleIterator *iter; sraRect rt; a = nabs((x2 - x1) * (y2 - y1)); A = nabs((X2 - X1) * (Y2 - Y1)); r = sraRgnCreateRect(x1, y1, x2, y2); R = sraRgnCreateRect(X1, Y1, X2, Y2); sraRgnAnd(r, R); o = 0.0; iter = sraRgnGetIterator(r); while (sraRgnIteratorNext(iter, &rt)) { o += nabs( (rt.x2 - rt.x1) * (rt.y2 - rt.y1) ); } sraRgnReleaseIterator(iter); sraRgnDestroy(r); sraRgnDestroy(R); if (a < A) { o = o/a; } else { o = o/A; } return o; }
/* 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); }
sraRegion *sraRgnBBox(const sraRegion *src) { int xmin=((unsigned int)(int)-1)>>1,ymin=xmin,xmax=1-xmin,ymax=xmax; sraSpan *vcurr, *hcurr; if(!src) return sraRgnCreate(); vcurr = ((sraSpanList*)src)->front._next; while (vcurr != &(((sraSpanList*)src)->back)) { if(vcurr->start<ymin) ymin=vcurr->start; if(vcurr->end>ymax) ymax=vcurr->end; hcurr = vcurr->subspan->front._next; while (hcurr != &(vcurr->subspan->back)) { if(hcurr->start<xmin) xmin=hcurr->start; if(hcurr->end>xmax) xmax=hcurr->end; hcurr = hcurr->_next; } vcurr = vcurr->_next; } if(xmax<xmin || ymax<ymin) return sraRgnCreate(); return sraRgnCreateRect(xmin,ymin,xmax,ymax); }
rfbBool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, int nColours) { if (cl->screen->serverFormat.trueColour || !cl->readyForSetColourMapEntries) { return TRUE; } if (nColours == 0) { nColours = cl->screen->colourMap.count; } if (cl->format.trueColour) { LOCK(cl->updateMutex); (*rfbInitColourMapSingleTableFns [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable, &cl->screen->serverFormat, &cl->format,&cl->screen->colourMap); sraRgnDestroy(cl->modifiedRegion); cl->modifiedRegion = sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height); UNLOCK(cl->updateMutex); return TRUE; } return rfbSendSetColourMapEntries(cl, firstColour, nColours); }
void clear_xdamage_mark_region(sraRegionPtr markregion, int flush) { #if HAVE_LIBXDAMAGE XEvent ev; sraRegionPtr tmpregion; int count = 0; RAWFB_RET_VOID if (! xdamage_present || ! use_xdamage) { return; } if (! xdamage) { return; } if (! xdamage_base_event_type) { return; } if (unixpw_in_progress) return; X_LOCK; if (flush) { XFlush_wr(dpy); } while (XCheckTypedEvent(dpy, xdamage_base_event_type+XDamageNotify, &ev)) { count++; } /* clear the whole damage region */ XDamageSubtract(dpy, xdamage, None, None); X_UNLOCK; if (debug_tiles || debug_xdamage) { fprintf(stderr, "clear_xdamage_mark_region: %d\n", count); } if (! markregion) { /* NULL means mark the whole display */ tmpregion = sraRgnCreateRect(0, 0, dpy_x, dpy_y); add_region_xdamage(tmpregion); sraRgnDestroy(tmpregion); } else { add_region_xdamage(markregion); } #else if (0) flush++; /* compiler warnings */ if (0) markregion = NULL; #endif }
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); }
void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2) { sraRegionPtr region; int i; if(x1>x2) { i=x1; x1=x2; x2=i; } if(x1<0) x1=0; if(x2>=rfbScreen->width) x2=rfbScreen->width-1; if(x1==x2) return; if(y1>y2) { i=y1; y1=y2; y2=i; } if(y1<0) y1=0; if(y2>=rfbScreen->height) y2=rfbScreen->height-1; if(y1==y2) return; region = sraRgnCreateRect(x1,y1,x2,y2); rfbMarkRegionAsModified(rfbScreen,region); sraRgnDestroy(region); }
void rfbMarkRectAsModified(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2) { sraRegionPtr region; int i; if(x1>x2) { i=x1; x1=x2; x2=i; } if(x1<0) x1=0; if(x2>screen->width) x2=screen->width; if(x1==x2) return; if(y1>y2) { i=y1; y1=y2; y2=i; } if(y1<0) y1=0; if(y2>screen->height) y2=screen->height; if(y1==y2) return; /* update scaled copies for this rectangle */ rfbScaledScreenUpdate(screen,x1,y1,x2,y2); region = sraRgnCreateRect(x1,y1,x2,y2); rfbMarkRegionAsModified(screen,region); sraRgnDestroy(region); }
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); }
void rfbScheduleCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy) { sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2); rfbScheduleCopyRegion(screen,region,dx,dy); sraRgnDestroy(region); }
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); }
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; }
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; }
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; }
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; }
void rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy) { sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2); rfbDoCopyRegion(rfbScreen,region,dx,dy); }