diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 161 |
1 files changed, 125 insertions, 36 deletions
@@ -468,12 +468,57 @@ enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl) return RFB_CLIENT_ACCEPT; } +/* + * Update server's pixel format in rfbScreenInfo structure. This + * function is called from rfbGetScreen() and rfbNewFramebuffer(). + */ + +static void rfbInitServerFormat(rfbScreenInfoPtr rfbScreen, int bitsPerSample) +{ + rfbPixelFormat* format=&rfbScreen->rfbServerFormat; + + format->bitsPerPixel = rfbScreen->bitsPerPixel; + format->depth = rfbScreen->depth; + format->bigEndian = rfbEndianTest?FALSE:TRUE; + format->trueColour = TRUE; + rfbScreen->colourMap.count = 0; + rfbScreen->colourMap.is16 = 0; + rfbScreen->colourMap.data.bytes = NULL; + + if (format->bitsPerPixel == 8) { + format->redMax = 7; + format->greenMax = 7; + format->blueMax = 3; + format->redShift = 0; + format->greenShift = 3; + format->blueShift = 6; + } else { + format->redMax = (1 << bitsPerSample) - 1; + format->greenMax = (1 << bitsPerSample) - 1; + format->blueMax = (1 << bitsPerSample) - 1; + if(rfbEndianTest) { + format->redShift = 0; + format->greenShift = bitsPerSample; + format->blueShift = bitsPerSample * 2; + } else { + if(format->bitsPerPixel==8*3) { + format->redShift = bitsPerSample*2; + format->greenShift = bitsPerSample*1; + format->blueShift = 0; + } else { + format->redShift = bitsPerSample*3; + format->greenShift = bitsPerSample*2; + format->blueShift = bitsPerSample; + } + } + } +} + rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, int width,int height,int bitsPerSample,int samplesPerPixel, int bytesPerPixel) { rfbScreenInfoPtr rfbScreen=malloc(sizeof(rfbScreenInfo)); - rfbPixelFormat* format=&rfbScreen->rfbServerFormat; INIT_MUTEX(logMutex); @@ -530,41 +575,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, /* format */ - format->bitsPerPixel = rfbScreen->bitsPerPixel; - format->depth = rfbScreen->depth; - format->bigEndian = rfbEndianTest?FALSE:TRUE; - format->trueColour = TRUE; - rfbScreen->colourMap.count = 0; - rfbScreen->colourMap.is16 = 0; - rfbScreen->colourMap.data.bytes = NULL; - - if(bytesPerPixel == 1) { - format->redMax = 7; - format->greenMax = 7; - format->blueMax = 3; - format->redShift = 0; - format->greenShift = 3; - format->blueShift = 6; - } else { - format->redMax = (1 << bitsPerSample) - 1; - format->greenMax = (1 << bitsPerSample) - 1; - format->blueMax = (1 << bitsPerSample) - 1; - if(rfbEndianTest) { - format->redShift = 0; - format->greenShift = bitsPerSample; - format->blueShift = bitsPerSample * 2; - } else { - if(bytesPerPixel==3) { - format->redShift = bitsPerSample*2; - format->greenShift = bitsPerSample*1; - format->blueShift = 0; - } else { - format->redShift = bitsPerSample*3; - format->greenShift = bitsPerSample*2; - format->blueShift = bitsPerSample; - } - } - } + rfbInitServerFormat(rfbScreen, bitsPerSample); /* cursor */ @@ -597,6 +608,84 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, return(rfbScreen); } +/* + * Switch to another framebuffer (maybe of different size and color + * format). Clients supporting NewFBSize pseudo-encoding will change + * their local framebuffer dimensions if necessary. + * NOTE: Rich cursor data should be converted to new pixel format by + * the caller. + */ + +void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen, char *framebuffer, + int width, int height, + int bitsPerSample, int samplesPerPixel, + int bytesPerPixel) +{ + rfbPixelFormat old_format; + Bool format_changed = FALSE; + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + + /* Remove the pointer */ + + rfbUndrawCursor(rfbScreen); + + /* Update information in the rfbScreenInfo structure */ + + old_format = rfbScreen->rfbServerFormat; + + if (width & 3) + rfbLog("WARNING: New width (%d) is not a multiple of 4.\n", width); + + rfbScreen->width = width; + rfbScreen->height = height; + rfbScreen->bitsPerPixel = rfbScreen->depth = 8*bytesPerPixel; + rfbScreen->paddedWidthInBytes = width*bytesPerPixel; + + rfbInitServerFormat(rfbScreen, bitsPerSample); + + if (memcmp(&rfbScreen->rfbServerFormat, &old_format, + sizeof(rfbPixelFormat)) != 0) { + format_changed = TRUE; + } + + 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) { + + /* Re-install color translation tables if necessary */ + + if (format_changed) + rfbScreen->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 rfbScreenCleanup(rfbScreenInfoPtr rfbScreen) { rfbClientIteratorPtr i=rfbGetClientIterator(rfbScreen); |