This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch feature/udp-support in repository x2gokdrive. commit d83fc364d9cbacf9fb027adf8aaee86f2c7b2e4a Author: Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> Date: Tue Dec 6 12:52:01 2022 -0600 Improving detecting the regions of dirty pixels. --- x2gokdriveremote.c | 156 +++++++++++++++++++++++++++++++++++++++++------------ x2gokdriveremote.h | 2 +- 2 files changed, 122 insertions(+), 36 deletions(-) diff --git a/x2gokdriveremote.c b/x2gokdriveremote.c index e4d7002..0287a83 100644 --- a/x2gokdriveremote.c +++ b/x2gokdriveremote.c @@ -4750,12 +4750,16 @@ remote_paint_rect(KdScreenInfo *screen, struct PaintRectRegion *regions=NULL; struct PaintRectRegion *currentRegion=NULL; struct PaintRectRegion *lastRegion=NULL; + BOOL noRegions=FALSE; uint32_t reg_size; int reg_width, reg_height; int numOfRegs=0; int totalSizeOfRegions=0; int totalDirtySize=0; BOOL allUnited=FALSE; + int centerx, centery; + int xinc, yinc, firstquatx, lastquatx, firstqauty, lastquaty; + int quarter; if(remoteVars.rootless) @@ -4791,7 +4795,8 @@ remote_paint_rect(KdScreenInfo *screen, maxdiff=2; mindiff=-2; - /* check if updated rec really is as big */ + /* determine actual dimensions of the region which is updated */ +// int dirty_pix=0; for(int32_t y=dy; y< dy+height;++y) { uint32_t ind=(y*remoteVars.main_img_width+dx)*XSERVERBPP; @@ -4800,11 +4805,6 @@ remote_paint_rect(KdScreenInfo *screen, BOOL pixIsDirty=FALSE; //CHECK R-COMPONENT int16_t diff=remoteVars.main_img[ind]-remoteVars.second_buffer[ind]; - -// if(x > 250 && x<255 && y >5 && y< 7) -// { -// EPHYR_DBG("rdiff %d - %u %u ", diff, remoteVars.main_img[ind],remoteVars.second_buffer[ind]); -// } if(diff>maxdiff || diff< mindiff) { pixIsDirty=TRUE; @@ -4829,25 +4829,7 @@ remote_paint_rect(KdScreenInfo *screen, } if(pixIsDirty) { - if(!insideOfRegion(currentRegion,x,y)) - { - //point is not inside of current region, find the region, point belongs to - currentRegion=findRegionForPoint(regions, x, y); - if(!currentRegion) - { - //creating new region and add it to the end of the list - currentRegion=malloc(sizeof(struct PaintRectRegion)); - currentRegion->next=NULL; - currentRegion->united=FALSE; - currentRegion->x1=currentRegion->x2=x; - currentRegion->y1=currentRegion->y2=y; - if(lastRegion) - lastRegion->next=currentRegion; - if(!regions) - regions=currentRegion; - lastRegion=currentRegion; - } - } +// dirty_pix++; if(x>dirtyx_max) { dirtyx_max=x; @@ -4864,25 +4846,127 @@ remote_paint_rect(KdScreenInfo *screen, { dirtyy_min=y; } - //copy only RGB part (A always same) + //copy only RGB part, use A part to mark the pixel dirty or clean memcpy(remoteVars.second_buffer+ind, remoteVars.main_img+ind,3); + remoteVars.main_img[ind+3]=255;//will mark the pixel as dirty for further process } + else + remoteVars.main_img[ind+3]=0;//will mark the pixel as clean for further process ind+=XSERVERBPP; } } - - pthread_mutex_unlock(&remoteVars.mainimg_mutex); - width=dirtyx_max-dirtyx_min+1; height=dirtyy_max-dirtyy_min+1; -// EPHYR_DBG("DIRTY %d:%d, %dx%d---", dirtyx_min, dirtyy_min, width, height); -// int oldsize=size; totalDirtySize=size=width*height*XSERVERBPP; - if(width<=0 || height<=0||size<=0) + if(width<=0 || height<=0||size<=0)//no changes, not doing anything { // EPHYR_DBG("NO CHANGES DETECTED, NOT UPDATING"); + pthread_mutex_unlock(&remoteVars.mainimg_mutex); return; } +// EPHYR_DBG("DIRTY %dx%d - %dx%d total pix %d, dirty pix %d---", dirtyx_min, dirtyy_min, dirtyx_max, dirtyy_max, width*height, dirty_pix); + + if(width<=4 || height<=4) + { + //rectangle is to small, don't try to split it + noRegions=TRUE; + } + + /* check if we can transfer dirty pixels in the smaller region instead of sending all rectangle + * we are starting from the center of the region and going to it edges to better process + * the regions where dirty pixels are only on the edges, like windows, which are only changing + * the color of frame, but the content is remaing same + */ + + if(!noRegions) + { + centerx=dirtyx_min+width/2; + centery=dirtyy_min+height/2; + + for(quarter=0;quarter<4;++quarter) + { + switch(quarter) + { + case 0: + firstquatx=centerx; + firstqauty=centery; + lastquatx=dirtyx_min; + lastquaty=dirtyy_min; + xinc=-1; + yinc=-1; + break; + case 1: + firstquatx=centerx+1; + firstqauty=centery; + lastquatx=dirtyx_max; + lastquaty=dirtyy_min; + xinc=1; + yinc=-1; + break; + case 2: + firstquatx=centerx; + firstqauty=centery+1; + lastquatx=dirtyx_min; + lastquaty=dirtyy_max; + xinc=-1; + yinc=1; + break; + case 3: + firstquatx=centerx+1; + firstqauty=centery+1; + lastquatx=dirtyx_max; + lastquaty=dirtyy_max; + xinc=1; + yinc=1; + break; + } +// EPHYR_DBG("Process quarter %d - %dx%d -%dx%d", quarter, firstquatx, firstqauty, lastquatx, lastquaty); + for(int32_t y=firstqauty;; y+=yinc) + { + for(int32_t x=firstquatx;; x+=xinc) + { + int32_t ind=(y*remoteVars.main_img_width+x)*XSERVERBPP; + if(remoteVars.main_img[ind+3])//pixel is dirty + { + if(!insideOfRegion(currentRegion,x,y)) + { + //point is not inside of current region, find the region, point belongs to + currentRegion=findRegionForPoint(regions, x, y); + if(!currentRegion) + { + //creating new region and add it to the end of the list + currentRegion=malloc(sizeof(struct PaintRectRegion)); + currentRegion->next=NULL; + currentRegion->united=FALSE; + currentRegion->x1=currentRegion->x2=x; + currentRegion->y1=currentRegion->y2=y; + if(lastRegion) + lastRegion->next=currentRegion; + if(!regions) + regions=currentRegion; + lastRegion=currentRegion; + //EPHYR_DBG("Creating new region for pix %dx%d",x,y); + } +/* else + { + EPHYR_DBG("Dirty pix %dx%d from quarter belongs to existing region - %dx%d - %dx%d",x,y, currentRegion->x1, currentRegion->y1, currentRegion->x2, currentRegion->y2); + }*/ + } +/* else + { + //EPHYR_DBG("Dirty pix %dx%d belongs to current region - %dx%d - %dx%d",x,y, currentRegion->x1, currentRegion->y1, currentRegion->x2, currentRegion->y2); + }*/ + } + if(x==lastquatx) + break; + } + if(y==lastquaty) + break; + } + } + } + + pthread_mutex_unlock(&remoteVars.mainimg_mutex); dx=sx=dirtyx_min; dy=sy=dirtyy_min; // remoteVars.sizeOfRects+=totalDirtySize; @@ -4891,11 +4975,13 @@ remote_paint_rect(KdScreenInfo *screen, // { // EPHYR_DBG("new update rect dimensions: %dx%d", width, height); // } -/* + #warning debug block currentRegion=regions; +// int i=0; while(currentRegion) { +// EPHYR_DBG("Region %d %d:%d %dx%d",i++, currentRegion->x1,currentRegion->y1, (currentRegion->x2-currentRegion->x1),(currentRegion->y2-currentRegion->y1)); totalSizeOfRegions+=(currentRegion->x2-currentRegion->x1 +1)*(currentRegion->y2-currentRegion->y1+1)*XSERVERBPP; numOfRegs++; currentRegion=currentRegion->next; @@ -4905,7 +4991,7 @@ remote_paint_rect(KdScreenInfo *screen, numOfRegs=0; //end of debug block -*/ + while(!allUnited) { currentRegion=regions; @@ -4960,7 +5046,7 @@ remote_paint_rect(KdScreenInfo *screen, //EPHYR_DBG("regions: %d dirty size=%d, total reg size=%d, diff=%d ",numOfRegs, totalDirtySize, totalSizeOfRegions, totalDirtySize-totalSizeOfRegions); }*/ - if(totalDirtySize-totalSizeOfRegions <= 0) + if(totalDirtySize-totalSizeOfRegions <= 0 || noRegions) { /*if(totalDirtySize-totalSizeOfRegions < 0) { diff --git a/x2gokdriveremote.h b/x2gokdriveremote.h index aed4902..fca85b0 100644 --- a/x2gokdriveremote.h +++ b/x2gokdriveremote.h @@ -212,7 +212,7 @@ enum ClientDgramType{ #define SCREEN_REG_HEIGHT 40 //the distance to determinate if the point belongs to region -#define MAXDISTANCETOREGION 40 +#define MAXDISTANCETOREGION 20 //regions to split the paint rectangle struct PaintRectRegion { -- Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/x2gokdrive.git