Commit 7e6d5c65 authored by dscho's avatar dscho

NewFB encoding added

parent 131ede28
support for NewFB from Const Kaplinsky
memory leaks squashed (localtime pseudo leak is still there :-) memory leaks squashed (localtime pseudo leak is still there :-)
small improvements for OSXvnc (still not working correctly) small improvements for OSXvnc (still not working correctly)
synced with TightVNC 1.2.3 synced with TightVNC 1.2.3
......
No preview for this file type
...@@ -8,9 +8,10 @@ ...@@ -8,9 +8,10 @@
<TITLE> <TITLE>
$USER's $DESKTOP desktop ($DISPLAY) $USER's $DESKTOP desktop ($DISPLAY)
</TITLE> </TITLE>
<APPLET CODE=vncviewer.class ARCHIVE=VncViewer.jar <APPLET CODE=VncViewer.class ARCHIVE=VncViewer.jar
WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT> WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT>
<param name=PORT value=$PORT> <param name=PORT value=$PORT>
<param name="Open New Window" value=yes>
</APPLET> </APPLET>
<BR> <BR>
<A href="http://www.tightvnc.com/">www.TightVNC.com</A> <A href="http://www.tightvnc.com/">www.TightVNC.com</A>
......
...@@ -34,7 +34,8 @@ ...@@ -34,7 +34,8 @@
#include "rfb.h" #include "rfb.h"
#include "keysym.h" #include "keysym.h"
const int maxx=640, maxy=480, bpp=4; const int bpp=4;
int maxx=800, maxy=600;
/* TODO: odd maxx doesn't work (vncviewer bug) */ /* TODO: odd maxx doesn't work (vncviewer bug) */
/* This initializes a nice (?) background */ /* This initializes a nice (?) background */
...@@ -74,6 +75,23 @@ enum rfbNewClientAction newclient(rfbClientPtr cl) ...@@ -74,6 +75,23 @@ enum rfbNewClientAction newclient(rfbClientPtr cl)
return RFB_CLIENT_ACCEPT; return RFB_CLIENT_ACCEPT;
} }
/* switch to new framebuffer contents */
void newframebuffer(rfbScreenInfoPtr screen, int width, int height)
{
char *oldfb, *newfb;
maxx = width;
maxy = height;
oldfb = screen->frameBuffer;
newfb = (char*)malloc(maxx * maxy * bpp);
initBuffer(newfb);
rfbNewFramebuffer(screen, newfb, maxx, maxy, 8, 3, bpp);
free(oldfb);
/*** FIXME: Re-install cursor. ***/
}
/* aux function to draw a line */ /* aux function to draw a line */
void drawline(unsigned char* buffer,int rowstride,int bpp,int x1,int y1,int x2,int y2) void drawline(unsigned char* buffer,int rowstride,int bpp,int x1,int y1,int x2,int y2)
...@@ -158,6 +176,22 @@ void dokey(Bool down,KeySym key,rfbClientPtr cl) ...@@ -158,6 +176,22 @@ void dokey(Bool down,KeySym key,rfbClientPtr cl)
rfbUndrawCursor(cl->screen); rfbUndrawCursor(cl->screen);
initBuffer(cl->screen->frameBuffer); initBuffer(cl->screen->frameBuffer);
rfbMarkRectAsModified(cl->screen,0,0,maxx,maxy); 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) { } else if(key>=' ' && key<0x100) {
ClientData* cd=cl->clientData; ClientData* cd=cl->clientData;
int x1=cd->oldx,y1=cd->oldy,x2,y2; int x1=cd->oldx,y1=cd->oldy,x2,y2;
...@@ -266,7 +300,7 @@ int main(int argc,char** argv) ...@@ -266,7 +300,7 @@ int main(int argc,char** argv)
#ifdef USE_OWN_LOOP #ifdef USE_OWN_LOOP
{ {
int i; int i;
for(i=0;i<200;i++) { for(i=0;;i++) {
fprintf(stderr,"%d\r",i); fprintf(stderr,"%d\r",i);
rfbProcessEvents(rfbScreen,100000); rfbProcessEvents(rfbScreen,100000);
} }
...@@ -275,7 +309,7 @@ int main(int argc,char** argv) ...@@ -275,7 +309,7 @@ int main(int argc,char** argv)
#ifndef BACKGROUND_LOOP_TEST #ifndef BACKGROUND_LOOP_TEST
/* this is the blocking event loop, i.e. it never returns */ /* this is the blocking event loop, i.e. it never returns */
/* 40000 are the microseconds, i.e. 0.04 seconds */ /* 40000 are the microseconds to wait on select(), i.e. 0.04 seconds */
rfbRunEventLoop(rfbScreen,40000,FALSE); rfbRunEventLoop(rfbScreen,40000,FALSE);
#elif !defined(HAVE_PTHREADS) #elif !defined(HAVE_PTHREADS)
#error "I need pthreads for that." #error "I need pthreads for that."
...@@ -283,7 +317,7 @@ int main(int argc,char** argv) ...@@ -283,7 +317,7 @@ int main(int argc,char** argv)
/* this is the non-blocking event loop; a background thread is started */ /* this is the non-blocking event loop; a background thread is started */
rfbRunEventLoop(rfbScreen,-1,TRUE); rfbRunEventLoop(rfbScreen,-1,TRUE);
/* now we could do some cool things like rendering */ /* now we could do some cool things like rendering in idle time */
while(1) sleep(5); /* render(); */ while(1) sleep(5); /* render(); */
#endif #endif
......
...@@ -218,6 +218,8 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen) ...@@ -218,6 +218,8 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen)
fname = &fullFname[strlen(fullFname)]; fname = &fullFname[strlen(fullFname)];
maxFnameLen = 255 - strlen(fullFname); maxFnameLen = 255 - strlen(fullFname);
buf_filled=0;
/* Read data from the HTTP client until we get a complete request. */ /* Read data from the HTTP client until we get a complete request. */
while (1) { while (1) {
ssize_t got = read (rfbScreen->httpSock, buf + buf_filled, ssize_t got = read (rfbScreen->httpSock, buf + buf_filled,
......
...@@ -468,12 +468,57 @@ enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl) ...@@ -468,12 +468,57 @@ enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl)
return RFB_CLIENT_ACCEPT; 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, rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
int width,int height,int bitsPerSample,int samplesPerPixel, int width,int height,int bitsPerSample,int samplesPerPixel,
int bytesPerPixel) int bytesPerPixel)
{ {
rfbScreenInfoPtr rfbScreen=malloc(sizeof(rfbScreenInfo)); rfbScreenInfoPtr rfbScreen=malloc(sizeof(rfbScreenInfo));
rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
INIT_MUTEX(logMutex); INIT_MUTEX(logMutex);
...@@ -530,41 +575,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, ...@@ -530,41 +575,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
/* format */ /* format */
format->bitsPerPixel = rfbScreen->bitsPerPixel; rfbInitServerFormat(rfbScreen, bitsPerSample);
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;
}
}
}
/* cursor */ /* cursor */
...@@ -597,6 +608,84 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, ...@@ -597,6 +608,84 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
return(rfbScreen); 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) void rfbScreenCleanup(rfbScreenInfoPtr rfbScreen)
{ {
rfbClientIteratorPtr i=rfbGetClientIterator(rfbScreen); rfbClientIteratorPtr i=rfbGetClientIterator(rfbScreen);
......
...@@ -503,8 +503,12 @@ typedef struct _rfbClientRec { ...@@ -503,8 +503,12 @@ typedef struct _rfbClientRec {
Bool enableCursorShapeUpdates; /* client supports cursor shape updates */ Bool enableCursorShapeUpdates; /* client supports cursor shape updates */
Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */ Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */
Bool cursorWasChanged; /* cursor shape update should be sent */ Bool cursorWasChanged; /* cursor shape update should be sent */
Bool useNewFBSize; /* client supports NewFBSize encoding */
Bool newFBSizePending; /* framebuffer size was changed */
#ifdef BACKCHANNEL #ifdef BACKCHANNEL
Bool enableBackChannel; Bool enableBackChannel; /* custom channel for special clients */
#endif #endif
struct _rfbClientRec *prev; struct _rfbClientRec *prev;
...@@ -532,9 +536,10 @@ typedef struct _rfbClientRec { ...@@ -532,9 +536,10 @@ typedef struct _rfbClientRec {
* be sent to the client. * be sent to the client.
*/ */
#define FB_UPDATE_PENDING(cl) \ #define FB_UPDATE_PENDING(cl) \
((!(cl)->enableCursorShapeUpdates && !(cl)->screen->cursorIsDrawn) || \ ((!(cl)->enableCursorShapeUpdates && !(cl)->screen->cursorIsDrawn) || \
((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \ ((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \
((cl)->useNewFBSize && (cl)->newFBSizePending) || \
!sraRgnEmpty((cl)->copyRegion) || !sraRgnEmpty((cl)->modifiedRegion)) !sraRgnEmpty((cl)->copyRegion) || !sraRgnEmpty((cl)->modifiedRegion))
/* /*
...@@ -603,6 +608,7 @@ extern Bool rfbSendUpdateBuf(rfbClientPtr cl); ...@@ -603,6 +608,7 @@ extern Bool rfbSendUpdateBuf(rfbClientPtr cl);
extern void rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len); extern void rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len);
extern Bool rfbSendCopyRegion(rfbClientPtr cl,sraRegionPtr reg,int dx,int dy); extern Bool rfbSendCopyRegion(rfbClientPtr cl,sraRegionPtr reg,int dx,int dy);
extern Bool rfbSendLastRectMarker(rfbClientPtr cl); extern Bool rfbSendLastRectMarker(rfbClientPtr cl);
extern Bool rfbSendNewFBSize(rfbClientPtr cl, int w, int h);
extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, int nColours); extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, int nColours);
extern void rfbSendBell(rfbScreenInfoPtr rfbScreen); extern void rfbSendBell(rfbScreenInfoPtr rfbScreen);
...@@ -796,6 +802,10 @@ extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, ...@@ -796,6 +802,10 @@ extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
int width,int height,int bitsPerSample,int samplesPerPixel, int width,int height,int bitsPerSample,int samplesPerPixel,
int bytesPerPixel); int bytesPerPixel);
extern void rfbInitServer(rfbScreenInfoPtr rfbScreen); extern void rfbInitServer(rfbScreenInfoPtr rfbScreen);
extern void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen,char *framebuffer,
int width,int height, int bitsPerSample,int samplesPerPixel,
int bytesPerPixel);
extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo); extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo);
/* functions to accept/refuse a client that has been put on hold /* functions to accept/refuse a client that has been put on hold
......
...@@ -328,6 +328,7 @@ typedef struct { ...@@ -328,6 +328,7 @@ typedef struct {
#define rfbEncodingRichCursor 0xFFFFFF11 #define rfbEncodingRichCursor 0xFFFFFF11
#define rfbEncodingLastRect 0xFFFFFF20 #define rfbEncodingLastRect 0xFFFFFF20
#define rfbEncodingNewFBSize 0xFFFFFF21
#define rfbEncodingQualityLevel0 0xFFFFFFE0 #define rfbEncodingQualityLevel0 0xFFFFFFE0
#define rfbEncodingQualityLevel1 0xFFFFFFE1 #define rfbEncodingQualityLevel1 0xFFFFFFE1
......
...@@ -266,6 +266,7 @@ rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP) ...@@ -266,6 +266,7 @@ rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
cl->enableCursorShapeUpdates = FALSE; cl->enableCursorShapeUpdates = FALSE;
cl->useRichCursorEncoding = FALSE; cl->useRichCursorEncoding = FALSE;
cl->enableLastRectEncoding = FALSE; cl->enableLastRectEncoding = FALSE;
cl->useNewFBSize = FALSE;
cl->compStreamInited = FALSE; cl->compStreamInited = FALSE;
cl->compStream.total_in = 0; cl->compStream.total_in = 0;
...@@ -663,6 +664,7 @@ rfbProcessClientNormalMessage(cl) ...@@ -663,6 +664,7 @@ rfbProcessClientNormalMessage(cl)
cl->useCopyRect = FALSE; cl->useCopyRect = FALSE;
cl->enableCursorShapeUpdates = FALSE; cl->enableCursorShapeUpdates = FALSE;
cl->enableLastRectEncoding = FALSE; cl->enableLastRectEncoding = FALSE;
cl->useNewFBSize = FALSE;
for (i = 0; i < msg.se.nEncodings; i++) { for (i = 0; i < msg.se.nEncodings; i++) {
if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) { if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) {
...@@ -742,6 +744,13 @@ rfbProcessClientNormalMessage(cl) ...@@ -742,6 +744,13 @@ rfbProcessClientNormalMessage(cl)
cl->enableLastRectEncoding = TRUE; cl->enableLastRectEncoding = TRUE;
} }
break; break;
case rfbEncodingNewFBSize:
if (!cl->useNewFBSize) {
rfbLog("Enabling NewFBSize protocol extension for client "
"%s\n", cl->host);
cl->useNewFBSize = TRUE;
}
break;
#ifdef BACKCHANNEL #ifdef BACKCHANNEL
case rfbEncodingBackChannel: case rfbEncodingBackChannel:
if (!cl->enableBackChannel) { if (!cl->enableBackChannel) {
...@@ -924,6 +933,25 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion) ...@@ -924,6 +933,25 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion)
if(cl->screen->displayHook) if(cl->screen->displayHook)
cl->screen->displayHook(cl); cl->screen->displayHook(cl);
/*
* If framebuffer size was changed and the client supports NewFBSize
* encoding, just send NewFBSize marker and return.
*/
if (cl->useNewFBSize && cl->newFBSizePending) {
LOCK(cl->updateMutex);
cl->newFBSizePending = FALSE;
UNLOCK(cl->updateMutex);
cl->rfbFramebufferUpdateMessagesSent++;
fu->type = rfbFramebufferUpdate;
fu->nRects = Swap16IfLE(1);
cl->ublen = sz_rfbFramebufferUpdateMsg;
if (!rfbSendNewFBSize(cl, cl->screen->width, cl->screen->height)) {
return FALSE;
}
return rfbSendUpdateBuf(cl);
}
/* /*
* If this client understands cursor shape updates, cursor should be * If this client understands cursor shape updates, cursor should be
...@@ -1309,6 +1337,40 @@ rfbSendLastRectMarker(cl) ...@@ -1309,6 +1337,40 @@ rfbSendLastRectMarker(cl)
} }
/*
* Send NewFBSize pseudo-rectangle. This tells the client to change
* its framebuffer size.
*/
Bool
rfbSendNewFBSize(cl, w, h)
rfbClientPtr cl;
int w, h;
{
rfbFramebufferUpdateRectHeader rect;
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
if (!rfbSendUpdateBuf(cl))
return FALSE;
}
rect.encoding = Swap32IfLE(rfbEncodingNewFBSize);
rect.r.x = 0;
rect.r.y = 0;
rect.r.w = Swap16IfLE(w);
rect.r.h = Swap16IfLE(h);
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
sz_rfbFramebufferUpdateRectHeader);
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
cl->rfbLastRectMarkersSent++;
cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
return TRUE;
}
/* /*
* Send the contents of cl->updateBuf. Returns 1 if successful, -1 if * Send the contents of cl->updateBuf. Returns 1 if successful, -1 if
* not (errno should be set). * not (errno should be set).
......
...@@ -78,7 +78,7 @@ rfbPrintStats(rfbClientPtr cl) ...@@ -78,7 +78,7 @@ rfbPrintStats(rfbClientPtr cl)
totalBytesSent); totalBytesSent);
if (cl->rfbLastRectMarkersSent != 0) if (cl->rfbLastRectMarkersSent != 0)
rfbLog(" LastRect markers %d, bytes %d\n", rfbLog(" LastRect and NewFBSize markers %d, bytes %d\n",
cl->rfbLastRectMarkersSent, cl->rfbLastRectBytesSent); cl->rfbLastRectMarkersSent, cl->rfbLastRectBytesSent);
if (cl->rfbCursorUpdatesSent != 0) if (cl->rfbCursorUpdatesSent != 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment