void draw_new_circle(rfbScreenInfoPtr screen, int x, int y, float pressure) { float r = radius * oldpressure; circle(mouseX, mouseY, r, width, 0, 0, 0); rfbMarkRectAsModified(screen, mouseX - r - width, mouseY - r - width, mouseX + r + width + 1, mouseY + r + width + 1); mouseX = x; mouseY = y; oldpressure = pressure; r = radius * pressure; circle(mouseX, mouseY, r, width, 255, 255, 255); rfbMarkRectAsModified(screen, mouseX - r - width, mouseY - r - width, mouseX + r + width + 1, mouseY + r + width + 1); }
static void FUNCTION(rfbScreenInfoPtr screen) { OUT_T* buffer = (OUT_T*)screen->frameBuffer; int i, j, w = screen->width, h = screen->height; OUT_T* newBuffer = (OUT_T*)malloc(w * h * sizeof(OUT_T)); for (j = 0; j < h; j++) for (i = 0; i < w; i++) newBuffer[FUNC(i, j)] = buffer[i + j * w]; memcpy(buffer, newBuffer, w * h * sizeof(OUT_T)); free(newBuffer); #ifdef SWAPDIMENSIONS screen->width = h; screen->paddedWidthInBytes = h * OUT / 8; screen->height = w; { rfbClientIteratorPtr iterator; rfbClientPtr cl; iterator = rfbGetClientIterator(screen); while ((cl = rfbClientIteratorNext(iterator)) != NULL) cl->newFBSizePending = 1; } #endif rfbMarkRectAsModified(screen, 0, 0, screen->width, screen->height); }
void rotate(int value) { L("rotate()\n"); if (value == -1 || ((value == 90 || value == 270) && (rotation == 0 || rotation == 180)) || ((value == 0 || value == 180) && (rotation == 90 || rotation == 270))) { int h = vncscr->height; int w = vncscr->width; vncscr->width = h; vncscr->paddedWidthInBytes = h * screenformat.bitsPerPixel / CHAR_BIT; vncscr->height = w; rfbClientIteratorPtr iterator; rfbClientPtr cl; iterator = rfbGetClientIterator(vncscr); while ((cl = rfbClientIteratorNext(iterator)) != NULL) cl->newFBSizePending = 1; } if (value == -1) { rotation += 90; rotation %= 360; } else { rotation = value; } rfbMarkRectAsModified(vncscr, 0, 0, vncscr->width, vncscr->height); }
/* * Single-threaded application that interleaves client servicing with taking * pictures from the camera. This way, we do not update the framebuffer * while an encoding is working on it too (banding, and image artifacts). */ int main(int argc,char** argv) { long usec; rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,WIDTH,HEIGHT,8,3,BPP); if(!server) return 0; server->desktopName = "Live Video Feed Example"; server->frameBuffer=(char*)malloc(WIDTH*HEIGHT*BPP); server->alwaysShared=(1==1); /* Initialize the server */ rfbInitServer(server); /* Loop, processing clients and taking pictures */ while (rfbIsActive(server)) { if (TimeToTakePicture()) if (TakePicture((unsigned char *)server->frameBuffer)) rfbMarkRectAsModified(server,0,0,WIDTH,HEIGHT); usec = server->deferUpdateTime*1000; rfbProcessEvents(server,usec); } return(0); }
int main(int argc,char** argv) { td = new MyDrawable(0,0,100,100); server = rfbGetScreen(&argc,argv,400,300,8,3,4); server->frameBuffer = (char*)malloc(400*300*4); server->kbdAddEvent = keyevent; server->serverFormat.redShift = 16; server->serverFormat.greenShift = 8; server->serverFormat.blueShift = 0; rfbInitServer(server); rfbRunEventLoop(server,-1,TRUE); td->setBG(0xFFFF00); UGui::instance()->addRoot(*td); while( 1 ) { bool updated = UGui::instance()->eventLoop(); if (updated) { printf("."); fflush(0); rfbMarkRectAsModified(server, 0, 0, 400, 300); } usleep(10000); } return(0); }
int main(int argc,char** argv) { int width=400,height=300,w=20,x,y; double r,phi=0; rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,width,height,8,3,4); server->frameBuffer=(char*)malloc(width*height*4); initBackground(server); server->deferUpdateTime=0; rfbInitServer(server); r=0; while(1) { if(r<=0) { initBackground(server); rfbMarkRectAsModified(server,0,0,width,height); r=0.43; phi=0; } else { r-=0.0001; phi+=0.02; if(phi>2*M_PI) phi-=2*M_PI; } x=width*(0.5+cos(phi)*r); y=height*(0.5+sin(phi)*r); if(x>=0 && y>=0 && x+w<=width && y+w<=height) { unsigned int dx=width*0.5*(1-cos(phi)*r)-x, dy=height*0.5*(1-sin(phi)*r)-y; rfbDoCopyRect(server,x,y,x+w,y+w,-dx,-dy); } rfbProcessEvents(server,50000); } return(0); }
int updateFrameBuffer(rfbScreenInfoPtr screen) { // Tell VNC that everything has changed, and let it do the optimisation. rfbMarkRectAsModified(screen,0,0,maxx-1,maxy-1); return 0; }
void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,Pixel col) { int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3; char* colour=(char*)&col; if(!rfbEndianTest) colour += 4-bpp; SETPIXEL(x,y); rfbMarkRectAsModified(s,x,y,x+1,y+1); }
void VncServer::invalidate(int viewNum, int x, int y, int w, int h, const VncServer::ViewParameters ¶m, bool lastView) { if (m_numClients - m_numRhrClients > 0) { std::cerr << "Non-RHR clients: " << m_numClients - m_numRhrClients << std::endl; rfbMarkRectAsModified(m_screen, x, y, w, h); } if (m_numRhrClients > 0) { encodeAndSend(viewNum, x, y, w, h, param, lastView); } }
void vcDrawOrHideCursor(vncConsolePtr c) { int i,j,w=c->screen->paddedWidthInBytes; char *b=c->screen->frameBuffer+c->y*c->cHeight*w+c->x*c->cWidth; for(j=c->cy1;j<c->cy2;j++) for(i=c->cx1;i<c->cx2;i++) b[j*w+i]^=0x0f; rfbMarkRectAsModified(c->screen, c->x*c->cWidth+c->cx1,c->y*c->cHeight+c->cy1, c->x*c->cWidth+c->cx2,c->y*c->cHeight+c->cy2); c->cursorIsDrawn=c->cursorIsDrawn?FALSE:TRUE; }
/* before using this function, hide the cursor */ void vcScroll(vncConsolePtr c,int lineCount) { int y1,y2; rfbScreenInfoPtr s=c->screen; if(lineCount==0) return; /* rfbLog("begin scroll\n"); */ vcHideCursor(c); c->dontDrawCursor=TRUE; if(lineCount>=c->height || lineCount<=-c->height) { y1=0; y2=s->height; } else if(lineCount>0) { y1=s->height-lineCount*c->cHeight; y2=s->height; rfbDoCopyRect(s,0,0,s->width,y1,0,-lineCount*c->cHeight); memmove(c->screenBuffer, c->screenBuffer+(c->height-lineCount)*c->width, (c->height-lineCount)*c->width); #ifdef USE_ATTRIBUTE_BUFFER if(c->attributeBuffer) memmove(c->attributeBuffer, c->attributeBuffer+(c->height-lineCount)*c->width, (c->height-lineCount)*c->width); #endif } else { y1=0; y2=-lineCount*c->cHeight; rfbDoCopyRect(s,0,y2,s->width,s->height,0,-lineCount*c->cHeight); memmove(c->screenBuffer-lineCount*c->width, c->screenBuffer, (c->height+lineCount)*c->width); #ifdef USE_ATTRIBUTE_BUFFER if(c->attributeBuffer) memmove(c->attributeBuffer-lineCount*c->width, c->attributeBuffer, (c->height+lineCount)*c->width); #endif } c->dontDrawCursor=FALSE; memset(s->frameBuffer+y1*s->width,c->backColour,(y2-y1)*s->width); rfbMarkRectAsModified(s,0,y1-c->cHeight,s->width,y2); memset(c->screenBuffer+y1/c->cHeight*c->width,' ', (y2-y1)/c->cHeight*c->width); #ifdef USE_ATTRIBUTE_BUFFER if(c->attributeBuffer) memset(c->attributeBuffer+y1/c->cHeight*c->width,0x07, (y2-y1)/c->cHeight*c->width); #endif /* rfbLog("end scroll\n"); */ }
void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,Pixel col) { int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3; int i,j; char* colour=(char*)&col; if(!rfbEndianTest) colour += 4-bpp; for(j=y1;j<y2;j++) for(i=x1;i<x2;i++) memcpy(s->frameBuffer+j*rowstride+i*bpp,colour,bpp); rfbMarkRectAsModified(s,x1,y1,x2,y2); }
static void dokey(rfbBool down,rfbKeySym key,rfbClientPtr cl) { if(down) { if(key==XK_Escape) rfbCloseClient(cl); else if(key==XK_F12) /* close down server, disconnecting clients */ rfbShutdownServer(cl->screen,TRUE); else if(key==XK_F11) /* close down server, but wait for all clients to disconnect */ rfbShutdownServer(cl->screen,FALSE); else if(key==XK_Page_Up) { initBuffer((unsigned char*)cl->screen->frameBuffer); rfbMarkRectAsModified(cl->screen,0,0,maxx,maxy); } else if (key == XK_Up) { if (maxx < 1024) { if (maxx < 800) { newframebuffer(cl->screen, 800, 600); } else { newframebuffer(cl->screen, 1024, 768); } } } else if(key==XK_Down) { if (maxx > 640) { if (maxx > 800) { newframebuffer(cl->screen, 800, 600); } else { newframebuffer(cl->screen, 640, 480); } } } else if(key>=' ' && key<0x100) { ClientData* cd=cl->clientData; int x1=cd->oldx,y1=cd->oldy,x2,y2; cd->oldx+=rfbDrawCharWithClip(cl->screen,&radonFont,cd->oldx,cd->oldy,(char)key,0,0,cl->screen->width,cl->screen->height,0x00ffffff,0x00ffffff); rfbFontBBox(&radonFont,(char)key,&x1,&y1,&x2,&y2); rfbMarkRectAsModified(cl->screen,x1,y1,x2-1,y2-1); } } }
static void handlePointer(int buttonMask,int x,int y,rfbClientPtr cl) { // ClientData* cd = cl->clientData; #if 0 if(x>=0 && y>=0 && x<maxx && y<maxy) { if(buttonMask) { int i,j,x1,x2,y1,y2; if(cd->oldButton==buttonMask) { /* draw a line */ drawline((unsigned char*)cl->screen->frameBuffer,cl->screen->paddedWidthInBytes,bpp, x,y,cd->oldx,cd->oldy); x1=x; y1=y; if(x1>cd->oldx) x1++; else cd->oldx++; if(y1>cd->oldy) y1++; else cd->oldy++; rfbMarkRectAsModified(cl->screen,x,y,cd->oldx,cd->oldy); } else { /* draw a point (diameter depends on button) */ int w=cl->screen->paddedWidthInBytes; x1=x-buttonMask; if(x1<0) x1=0; x2=x+buttonMask; if(x2>maxx) x2=maxx; y1=y-buttonMask; if(y1<0) y1=0; y2=y+buttonMask; if(y2>maxy) y2=maxy; for(i=x1*bpp;i<x2*bpp;i++) for(j=y1;j<y2;j++) cl->screen->frameBuffer[j*w+i]=(char)0xff; rfbMarkRectAsModified(cl->screen,x1,y1,x2,y2); } /* we could get a selection like that: rfbGotXCutText(cl->screen,"Hallo",5); */ } else cd->oldButton=0; cd->oldx=x; cd->oldy=y; cd->oldButton=buttonMask; } #endif // draw_new_circle(cl->screen, x, y, 1.0); rfbDefaultPtrAddEvent(buttonMask,x,y,cl); }
static Ret on_display_change(void* ctx, FtkDisplay* display, int before, FtkBitmap* bitmap, FtkRect* rect, int xoffset, int yoffset) { if(!before && g_vnc_context.active) { ftk_bitmap_copy_to_data_rgba32(bitmap, rect, g_vnc_context.vnc_buffer, xoffset, yoffset, g_vnc_context.width, g_vnc_context.height); if(g_vnc_context.client_nr > 0) { rfbMarkRectAsModified(g_vnc_context.rfbScreen, xoffset, xoffset, rect->width, rect->height); } } return RET_OK; }
static void MarkRect( int x1, int y1, int x2, int y2 ) { if ( clients_connected ) { /* Enlarge the updated rectangle by a pixel, needed for 1 pixel wide rects */ if ( x2 < (rfbScreen->width - 1)) x2++; else if ( x1 > 0 ) x1--; if ( y2 < (rfbScreen->height - 1)) y2++; else if ( y1 > 0 ) y1--; rfbMarkRectAsModified(rfbScreen, x1, y1, x2, y2); } }
void FUNCTION(void) { int i, j; int offset = 0, pixelToVirtual; OUT_T* a; OUT_T* b = 0; struct fb_var_screeninfo scrinfo; //we'll need this to detect double FB on framebuffer scrinfo = FB_getscrinfo(); b = (OUT_T*) readBufferFB(); a = (OUT_T*)cmpbuf; int max_x = -1, max_y = -1, min_x = 99999, min_y = 99999; idle = 1; for (j = 0; j < vncscr->height; j++) { offset = j * vncscr->width; for (i = 0; i < vncscr->width; i++) { // multiply by 2 for scaling pixelToVirtual = PIXEL_TO_VIRTUALPIXEL_FB(i * 2, j * 2); if (a[i + offset]!=b[pixelToVirtual]) { a[i + offset]=b[pixelToVirtual]; if (i>max_x) max_x=i; if (i<min_x) min_x=i; if (j>max_y) max_y=j; if (j<min_y) min_y=j; idle = 0; } } } if (!idle) { _bgra2rgb565_neon(vncbuf, a, (screenformat.size/2) ); min_x--; min_x--; max_x++; max_y++; rfbMarkRectAsModified(vncscr, min_x, min_y, max_x, max_y); } }
static void* vnc_thread(void* args) { int i = 0; int argc = 1; int width = g_vnc_context.width; int height = g_vnc_context.height; char* argv[5] = {"FTKVNC", NULL}; rfbScreenInfoPtr rfbScreen = NULL; ftk_logd("%s: vnc thread start.\n", __func__); rfbScreen = rfbGetScreen(&argc, argv, width, height, 8, 4, 4); rfbScreen->desktopName = "FTK VNC"; rfbScreen->alwaysShared = 0; rfbScreen->frameBuffer = g_vnc_context.vnc_buffer; rfbScreen->ptrAddEvent = on_pointer_event; rfbScreen->kbdAddEvent = on_key_event; rfbScreen->newClientHook = on_new_client; rfbScreen->deferUpdateTime = 100; rfbInitServer(rfbScreen); g_vnc_context.rfbScreen = rfbScreen; for(i=0; !g_vnc_context.quit && rfbIsActive(rfbScreen); i++) { if(g_vnc_context.client_nr > 0 && g_vnc_context.active) { if((i % 10) == 0) { rfbMarkRectAsModified(g_vnc_context.rfbScreen, 0, 0, width, height); } } else { sleep(1); } rfbProcessEvents(rfbScreen, 200000); } ftk_logd("%s: vnc thread quit.\n", __func__); rfbScreenCleanup(rfbScreen); return NULL; }
int main(int argc,char **argv) { rfbScreenInfoPtr s; double t1, t2; double timeout; int nread; if (argc == 2) v4l2str = argv[1]; printf("Using dev %s\n", v4l2str); if (argc == 3) v4l2fps = atoi(argv[2]); printf("Using fps %d\n", v4l2fps); if (open_v4l2() != 0) exit(EXIT_FAILURE); if (init_v4l2() != 0) exit(EXIT_FAILURE); if (alloc_mem() != 0) exit(EXIT_FAILURE); s = rfbGetScreen(&argc, argv, v4l2width, v4l2height, 8, 3, v4l2Bpp); s->desktopName = "v4l2tovnc"; s->frameBuffer = (char *) v4l2buf; s->serverFormat.blueShift = 0; s->serverFormat.greenShift = 8; s->serverFormat.redShift = 16; timeout = 1.0 / v4l2fps; rfbInitServer(s); t1 = timestamp(); while (rfbIsActive(s)) { t2 = timestamp(); if ((t2 - t1) >= timeout) { nread = read_frame(); if (nread < 0) break; rfbMarkRectAsModified(s, 0, 0, v4l2width, v4l2height); t1 = timestamp(); } rfbProcessEvents(s, -1); } close_v4l2(); return 0; }
static void idle(rfbScreenInfo* server) { int c; rfbBool goForward; LOCK(statisticsMutex); #ifdef ALL_AT_ONCE goForward=(countGotUpdate==NUMBER_OF_ENCODINGS_TO_TEST); #else goForward=(countGotUpdate==1); #endif /* if(lastUpdateRect.x2==354) rfbLog("server checked: countGotUpdate=%d\n",countGotUpdate); */ UNLOCK(statisticsMutex); if(!goForward) return; countGotUpdate=0; LOCK(frameBufferMutex); { int i,j; int x1=(rand()%(server->width-1)),x2=(rand()%(server->width-1)), y1=(rand()%(server->height-1)),y2=(rand()%(server->height-1)); if(x1>x2) { i=x1; x1=x2; x2=i; } if(y1>y2) { i=y1; y1=y2; y2=i; } x2++; y2++; for(c=0;c<3;c++) { for(i=x1;i<x2;i++) for(j=y1;j<y2;j++) server->frameBuffer[i*4+c+j*server->paddedWidthInBytes]=255*(i-x1+j-y1)/(x2-x1+y2-y1); } rfbMarkRectAsModified(server,x1,y1,x2,y2); lastUpdateRect.x1=x1; lastUpdateRect.y1=y1; lastUpdateRect.x2=x2; lastUpdateRect.y2=y2; #ifdef VERY_VERBOSE rfbLog("Sent update (%d,%d)-(%d,%d)\n",x1,y1,x2,y2); #endif } UNLOCK(frameBufferMutex); }
void RemoteControl::timeoutSlot() { char *oldBuffer = rfbScreen->frameBuffer; QPixmap pm; pm = QPixmap::grabWindow(QApplication::desktop()->winId()); pm = pm.scaled(maxx, maxy,Qt::IgnoreAspectRatio, Qt::SmoothTransformation); QImage image = pm.toImage(); int i, j; memset(oldBuffer, 0x00, maxx*maxy*bpp); for(i=0; i<maxy; i++) { const uchar* data = image.scanLine(i); memcpy(&oldBuffer[i*maxx*bpp], data, maxx*bpp); } rfbMarkRectAsModified(this->rfbScreen,0, 0, maxx-1, maxy-1); }
void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,Pixel col) { int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3; int i; char* colour=(char*)&col; if(!rfbEndianTest) colour += 4-bpp; #define SWAPPOINTS { i=x1; x1=x2; x2=i; i=y1; y1=y2; y2=i; } if(abs(x1-x2)<abs(y1-y2)) { if(y1>y2) SWAPPOINTS for(i=y1;i<=y2;i++) SETPIXEL(x1+(i-y1)*(x2-x1)/(y2-y1),i); /* TODO: Maybe make this more intelligently? */ if(x2<x1) { i=x1; x1=x2; x2=i; } rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1); } else { if(x1>x2)
int VNCServer::CopyRect(BYTE *data,int x, int y, int width, int height, int dest_x, int dest_y) { Debug("-CopyRect from [%d,%d] to [%d,%d] size [%d,%d]\n",x,y,dest_x,dest_y,width,height); //LOck use.WaitUnusedAndLock(); //Update frame for (int j=0;j<height;++j) //Copy memcpy(screen->frameBuffer+(dest_x+(dest_y+j)*screen->width)*4,data+(x+(y+j)*screen->width)*4,width*4); //memset(screen->frameBuffer+dest_x+(dest_y+j)*screen->width*4,0xCA,width*4); //Set modified region //rfbScheduleCopyRect(screen,x, y,x+w, y+h, dest_x, dest_y); //Set modified region rfbMarkRectAsModified(screen,dest_x,dest_y,dest_x+width,dest_y+height); //Unlock use.Unlock(); }
static void init_fb_server(int argc, char **argv) { printf("Initializing server...\n"); /* Allocate the VNC server buffer to be managed (not manipulated) by * libvncserver. */ vncbuf = calloc(scrinfo.xres * scrinfo.yres, scrinfo.bits_per_pixel / 2); assert(vncbuf != NULL); /* Allocate the comparison buffer for detecting drawing updates from frame * to frame. */ fbbuf = calloc(scrinfo.xres * scrinfo.yres, scrinfo.bits_per_pixel / 2); assert(fbbuf != NULL); /* TODO: This assumes scrinfo.bits_per_pixel is 16. */ vncscr = rfbGetScreen(&argc, argv, scrinfo.xres, scrinfo.yres, 5, 2, 2); assert(vncscr != NULL); vncscr->desktopName = "Android"; vncscr->frameBuffer = (char *)vncbuf; vncscr->alwaysShared = TRUE; vncscr->httpDir = NULL; vncscr->port = VNC_PORT; vncscr->kbdAddEvent = keyevent; vncscr->ptrAddEvent = ptrevent; vncscr->setXCutText = textevent; rfbInitServer(vncscr); /* Mark as dirty since we haven't sent any updates at all yet. */ rfbMarkRectAsModified(vncscr, 0, 0, scrinfo.xres, scrinfo.yres); /* No idea. */ varblock.r_offset = scrinfo.red.offset + scrinfo.red.length - 5; varblock.g_offset = scrinfo.green.offset + scrinfo.green.length - 5; varblock.b_offset = scrinfo.blue.offset + scrinfo.blue.length - 5; varblock.rfb_xres = scrinfo.yres; varblock.rfb_maxy = scrinfo.xres - 1; }
int VNCServer::FrameBufferUpdate(const BYTE *data,int x,int y,int width,int height) { Debug("-FrameBufferUpdate [x:%d,y:%d,w:%d,h:%d]\n",x,y,width,height); //LOck use.WaitUnusedAndLock(); //Update frame for (int j=y;j<y+height;++j) //Copy memcpy(screen->frameBuffer+(x+j*screen->width)*4,data+(x+j*screen->width)*4,width*4); /* { screen->frameBuffer[(x+j*screen->width)*4] = 0xFF; screen->frameBuffer[(x+j*screen->width)*4+1] = 00; screen->frameBuffer[(x+j*screen->width)*4+2] = 00; screen->frameBuffer[(x+j*screen->width+width-1)*4] = 0x00; screen->frameBuffer[(x+j*screen->width+width-1)*4+1] = 0xFF; screen->frameBuffer[(x+j*screen->width+width-1)*4+2] = 00; } for (int i=x;i<x+width;i++) { screen->frameBuffer[(i+y*screen->width)*4] = 0xFF; screen->frameBuffer[(i+y*screen->width)*4+1] = 00; screen->frameBuffer[(i+y*screen->width)*4+2] = 00; screen->frameBuffer[(i+(y+height-1)*screen->width)*4] = 0x00; screen->frameBuffer[(i+(y+height-1)*screen->width)*4+1] = 00; screen->frameBuffer[(i+(y+height-1)*screen->width)*4+2] = 0xFF; } */ //Set modified region rfbMarkRectAsModified(screen,x,y,x+width,y+height); //Unlock use.Unlock(); }
void FUNCTION(void) { static int i,j,offset; update_fb_info(); // // detect active buffer // offset= (scrinfo.xoffset) * (scrinfo.bits_per_pixel/8) + // (scrinfo.yoffset) * scrinfo.xres; // if (scrinfo.yoffset) // offset=scrinfo.xres*scrinfo.yoffset; // else // offset=0; offset = scrinfo.xres * scrinfo.yoffset + scrinfo.xoffset * scrinfo.bits_per_pixel / CHAR_BIT; OUT_T* a = (OUT_T*)cmpbuf; OUT_T* b = (OUT_T*)fbmmap; int max_x=-1,max_y=-1, min_x=9999, min_y=9999; idle=1; if (rotation==0) { //memcpy(vncbuf,fbmmap,vncscr->width*vncscr->height*scrinfo.bits_per_pixel/CHAR_BIT); for (j = 0; j < scrinfo.yres; j++) { for (i = 0; i < scrinfo.xres; i++) { if (a[i + j * scrinfo.xres]!=b[i + j * scrinfo.xres + offset ]) { a[i + j * scrinfo.xres]=b[i + j * scrinfo.xres + offset]; if (i>max_x) max_x=i; if (i<min_x) min_x=i; if (j>max_y) max_y=j; if (j<min_y) min_y=j; if (idle) idle=0; } } } } else if (rotation==90) { for (j = 0; j < scrinfo.yres; j++) { for (i = 0; i < scrinfo.xres; i++) { if (a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] != b[i + j * scrinfo.xres + offset]) { a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] = b[i + j * scrinfo.xres + offset ]; if (i>max_y) max_y=i; if (i<min_y) min_y=i; int h=scrinfo.yres-j; if (h < min_x) min_x=scrinfo.yres-j; if (h > max_x) max_x=scrinfo.yres-j; if (idle) idle=0; } } } } else if (rotation==180) { for (j = 0; j < scrinfo.yres; j++) { for (i = 0; i < scrinfo.xres; i++) { if (a[i + j * scrinfo.xres]!=b[scrinfo.yres*scrinfo.xres - (i + j * scrinfo.xres ) + offset ]) { a[i + j * scrinfo.xres]=b[scrinfo.yres*scrinfo.xres - (i + j * scrinfo.xres) + offset ]; if (i>max_x) max_x=i; if (i<min_x) min_x=i; if (j>max_y) max_y=j; if (j<min_y) min_y=j; if (idle) idle=0; } } } } else if (rotation==270) { for (j = 0; j < scrinfo.yres; j++) { for (i = 0; i < scrinfo.xres; i++) { if(a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] != b[ scrinfo.yres * scrinfo.xres - (i + j * scrinfo.xres) + offset ]) { a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] = b[ scrinfo.yres * scrinfo.xres - (i + j * scrinfo.xres) + offset ]; if (i>max_y) max_y=i; if (i<min_y) min_y=i; int h=scrinfo.yres-j; if (h < min_x) min_x=scrinfo.yres-j; if (h > max_x) max_x=scrinfo.yres-j; if (idle) idle=0; } } } } memcpy(vncbuf,a,vncscr->width*vncscr->height*scrinfo.bits_per_pixel/CHAR_BIT); if (min_x!=9999 && min_y!=9999 && max_x!=-1 && max_y!=-1) { // min_x--; max_x++; // min_y--; max_y++; rfbMarkRectAsModified(vncscr, min_x, min_y, max_x, max_y); rfbProcessEvents(vncscr, 10000); } // rfbMarkRectAsModified(vncscr, 0, 0, scrinfo.yres,scrinfo.xres); // rfbProcessEvents(vncscr, 10000); if (idle) { standby=standby+1; if (standby>30) rfbProcessEvents(vncscr, 1000000); else rfbProcessEvents(vncscr, 100000); // __android_log_print(ANDROID_LOG_INFO,"VNC","standby %d xoff=%d yoff=%d\n",standby,scrinfo.xoffset,scrinfo.yoffset); change=0; } else { change=change+1; standby=0; rfbProcessEvents(vncscr, 100000); // __android_log_print(ANDROID_LOG_INFO,"VNC","change %d\tmin_x=%d max_x=%d min_y=%d max_y=%d xoff=%d yoff=%d\n",change,min_x,max_x,min_y,max_y,scrinfo.xoffset,scrinfo.yoffset); } }
void initVncServer(int argc, char **argv) { vncbuf = calloc(screenformat.width * screenformat.height, screenformat.bitsPerPixel/CHAR_BIT); cmpbuf = calloc(screenformat.width * screenformat.height, screenformat.bitsPerPixel/CHAR_BIT); assert(vncbuf != NULL); assert(cmpbuf != NULL); if (rotation==0 || rotation==180) vncscr = rfbGetScreen(&argc, argv, screenformat.width , screenformat.height, 0 /* not used */ , 3, screenformat.bitsPerPixel/CHAR_BIT); else vncscr = rfbGetScreen(&argc, argv, screenformat.height, screenformat.width, 0 /* not used */ , 3, screenformat.bitsPerPixel/CHAR_BIT); assert(vncscr != NULL); vncscr->desktopName = "Android"; vncscr->frameBuffer =(char *)vncbuf; vncscr->port = VNC_PORT; vncscr->kbdAddEvent = keyEvent; vncscr->ptrAddEvent = ptrEvent; vncscr->newClientHook = (rfbNewClientHookPtr)clientHook; vncscr->setXCutText = CutText; if (strcmp(VNC_PASSWORD,"")!=0) { char **passwords = (char **)malloc(2 * sizeof(char **)); passwords[0] = VNC_PASSWORD; passwords[1] = NULL; vncscr->authPasswdData = passwords; vncscr->passwordCheck = rfbCheckPasswordByList; } vncscr->httpDir = "webclients/"; // vncscr->httpEnableProxyConnect = TRUE; vncscr->sslcertfile = "self.pem"; vncscr->serverFormat.redShift = screenformat.redShift; vncscr->serverFormat.greenShift = screenformat.greenShift; vncscr->serverFormat.blueShift = screenformat.blueShift; vncscr->serverFormat.redMax = (( 1 << screenformat.redMax) -1); vncscr->serverFormat.greenMax = (( 1 << screenformat.greenMax) -1); vncscr->serverFormat.blueMax = (( 1 << screenformat.blueMax) -1); vncscr->serverFormat.trueColour = TRUE; vncscr->serverFormat.bitsPerPixel = screenformat.bitsPerPixel; vncscr->alwaysShared = TRUE; vncscr->handleEventsEagerly = TRUE; vncscr->deferUpdateTime = 5; rfbInitServer(vncscr); //assign update_screen depending on bpp if (vncscr->serverFormat.bitsPerPixel == 32) update_screen=&CONCAT2E(update_screen_,32); else if (vncscr->serverFormat.bitsPerPixel == 16) update_screen=&CONCAT2E(update_screen_,16); else if (vncscr->serverFormat.bitsPerPixel == 8) update_screen=&CONCAT2E(update_screen_,8); else { L("Unsupported pixel depth: %d\n", vncscr->serverFormat.bitsPerPixel); sendMsgToGui("~SHOW|Unsupported pixel depth, please send bug report.\n"); close_app(); exit(-1); } /* Mark as dirty since we haven't sent any updates at all yet. */ rfbMarkRectAsModified(vncscr, 0, 0, vncscr->width, vncscr->height); }
int rfbSelectBox(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, char** list, int x1,int y1,int x2,int y2, Pixel colour,Pixel backColour, int border,SelectionChangedHookPtr selChangedHook) { int bpp = rfbScreen->bitsPerPixel/8; char* frameBufferBackup; void* screenDataBackup = rfbScreen->screenData; KbdAddEventProcPtr kbdAddEventBackup = rfbScreen->kbdAddEvent; PtrAddEventProcPtr ptrAddEventBackup = rfbScreen->ptrAddEvent; GetCursorProcPtr getCursorPtrBackup = rfbScreen->getCursorPtr; DisplayHookPtr displayHookBackup = rfbScreen->displayHook; rfbSelectData selData; int i,j,k; int fx1,fy1,fx2,fy2; /* for font bbox */ if(list==0 || *list==0) return(-1); rfbWholeFontBBox(font, &fx1, &fy1, &fx2, &fy2); selData.textH = fy2-fy1; /* I need at least one line for the choice and one for the buttons */ if(y2-y1<selData.textH*2+3*border) return(-1); selData.xhot = -fx1; selData.yhot = -fy2; selData.x1 = x1+border; selData.y1 = y1+border; selData.y2 = y2-selData.textH-3*border; selData.x2 = x2-2*border; selData.pageH = (selData.y2-selData.y1)/selData.textH; i = rfbWidthOfString(font,okStr); j = rfbWidthOfString(font,cancelStr); selData.buttonWidth= k = 4*border+(i<j)?j:i; selData.okBX = x1+(x2-x1-2*k)/3; if(selData.okBX<x1+border) /* too narrow! */ return(-1); selData.cancelBX = x1+k+(x2-x1-2*k)*2/3; selData.okX = selData.okBX+(k-i)/2; selData.cancelX = selData.cancelBX+(k-j)/2; selData.okY = y2-border; rfbUndrawCursor(rfbScreen); frameBufferBackup = (char*)malloc(bpp*(x2-x1)*(y2-y1)); selData.state = SELECTING; selData.screen = rfbScreen; selData.font = font; selData.list = list; selData.colour = colour; selData.backColour = backColour; for(i=0;list[i];i++); selData.selected = i; selData.listSize = i; selData.displayStart = i; selData.lastButtons = 0; selData.selChangedHook = selChangedHook; rfbScreen->screenData = &selData; rfbScreen->kbdAddEvent = selKbdAddEvent; rfbScreen->ptrAddEvent = selPtrAddEvent; rfbScreen->getCursorPtr = selGetCursorPtr; rfbScreen->displayHook = 0; /* backup screen */ for(j=0;j<y2-y1;j++) memcpy(frameBufferBackup+j*(x2-x1)*bpp, rfbScreen->frameBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp, (x2-x1)*bpp); /* paint list and buttons */ rfbFillRect(rfbScreen,x1,y1,x2,y2,colour); selPaintButtons(&selData,FALSE,FALSE); selSelect(&selData,0); /* modal loop */ while(selData.state == SELECTING) rfbProcessEvents(rfbScreen,20000); /* copy back screen data */ for(j=0;j<y2-y1;j++) memcpy(rfbScreen->frameBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp, frameBufferBackup+j*(x2-x1)*bpp, (x2-x1)*bpp); free(frameBufferBackup); rfbMarkRectAsModified(rfbScreen,x1,y1,x2,y2); rfbScreen->screenData = screenDataBackup; rfbScreen->kbdAddEvent = kbdAddEventBackup; rfbScreen->ptrAddEvent = ptrAddEventBackup; rfbScreen->getCursorPtr = getCursorPtrBackup; rfbScreen->displayHook = displayHookBackup; if(selData.state==CANCEL) selData.selected=-1; return(selData.selected); }
int updateFrameBuffer(rfbScreenInfoPtr screen) { // draw all pixels onto VNC frame buffer int x,y; for(y=0;y<1200;y++) { unsigned char linebuffer[1920*4]; unsigned int crc=raster_crc[y]; if (last_raster_crc[y]!=crc) { if (raster_cache[crc&0xffff].crc==crc) { for(x=0;x<1920;x++) { // unpack RRRGGGBB pixels into RGB bytes for VNC ((unsigned char *)screen->frameBuffer)[(y*1920*4)+x*4+0]=raster_cache[crc&0xffff].data[x]&0xe0; ((unsigned char *)screen->frameBuffer)[(y*1920*4)+x*4+1]=raster_cache[crc&0xffff].data[x]<<3; ((unsigned char *)screen->frameBuffer)[(y*1920*4)+x*4+2]=raster_cache[crc&0xffff].data[x]<<6; // if (y>410&&y<420) // ((unsigned char *)screen->frameBuffer)[(y*1920*4)+x*4+0]=0xff; } raster_zero[y]=0; } else { // clear rasters for which we have no valid data if (!raster_zero[y]) { raster_zero[y]=1; // Zeroing rasters looks good with horizontal scrolling, but bad in text mode. // so for now don't zero it. // bzero(&((unsigned char *)screen->frameBuffer)[(y*1920*4)],1920*4); } } } // if (y>410&&y<420) printf("[%08x]",crc); } // printf("\n"); int last_changed=1; int last_y=0; int updated_y=0; for(y=0;y<1200;y++) { int this_changed=0; if (raster_crc[y]!=last_raster_crc[y]) this_changed=1; if (this_changed!=last_changed) { if (last_changed) { // Tell VNC that everything has changed, and let it do the optimisation. rfbMarkRectAsModified(screen,0,last_y,1919,y); updated_y+=y-last_y+1; last_changed=this_changed; } last_y=y; last_changed=this_changed; } if (raster_cache[raster_crc[y]&0xffff].crc==raster_crc[y]) last_raster_crc[y]=raster_crc[y]; } if (last_changed) { rfbMarkRectAsModified(screen,0,last_y,1919,y); last_y=y; updated_y+=y-last_y+1; } // printf("Updated %d rasters\n",updated_y); return 0; }
static void update_screen(void) { unsigned int *f, *c, *r; int x, y; varblock.min_i = varblock.min_j = 9999; varblock.max_i = varblock.max_j = -1; f = (unsigned int *)fbmmap; /* -> framebuffer */ c = (unsigned int *)fbbuf; /* -> compare framebuffer */ r = (unsigned int *)vncbuf; /* -> remote framebuffer */ for (y = 0; y < scrinfo.yres; y++) { /* Compare every 2 pixels at a time, assuming that changes are likely * in pairs. */ for (x = 0; x < scrinfo.xres; x += 2) { unsigned int pixel = *f; if (pixel != *c) { *c = pixel; /* XXX: Undo the checkered pattern to test the efficiency * gain using hextile encoding. */ if (pixel == 0x18e320e4 || pixel == 0x20e418e3) pixel = 0x18e318e3; *r = PIXEL_FB_TO_RFB(pixel, varblock.r_offset, varblock.g_offset, varblock.b_offset); if (x < varblock.min_i) varblock.min_i = x; else { if (x > varblock.max_i) varblock.max_i = x; if (y > varblock.max_j) varblock.max_j = y; else if (y < varblock.min_j) varblock.min_j = y; } } f++, c++; r++; } } if (varblock.min_i < 9999) { if (varblock.max_i < 0) varblock.max_i = varblock.min_i; if (varblock.max_j < 0) varblock.max_j = varblock.min_j; fprintf(stderr, "Dirty page: %dx%d+%d+%d...\n", (varblock.max_i+2) - varblock.min_i, (varblock.max_j+1) - varblock.min_j, varblock.min_i, varblock.min_j); rfbMarkRectAsModified(vncscr, varblock.min_i, varblock.min_j, varblock.max_i + 2, varblock.max_j + 1); rfbProcessEvents(vncscr, 10000); } }