Exemple #1
0
Bool rfbSendCursorPos(rfbClientPtr cl) {
    rfbFramebufferUpdateRectHeader rect;

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    cl->clientCursorLocation = currentCursorLoc();

    rect.encoding = Swap32IfLE(rfbEncodingPointerPos);
    rect.r.x = Swap16IfLE((CARD16)cl->clientCursorLocation.x);
    rect.r.y = Swap16IfLE((CARD16)cl->clientCursorLocation.y);
    rect.r.w = 0;
    rect.r.h = 0;

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    cl->rfbRectanglesSent[rfbStatsCursorPosition]++;
    cl->rfbBytesSent[rfbStatsCursorPosition] += sz_rfbFramebufferUpdateRectHeader;

    if (!rfbSendUpdateBuf(cl))
        return FALSE;

    return TRUE;
}
Exemple #2
0
Bool
rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w, int h)
{
    rfbFramebufferUpdateRectHeader rect;

    if (ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    rect.r.x = Swap16IfLE(x);
    rect.r.y = Swap16IfLE(y);
    rect.r.w = Swap16IfLE(w);
    rect.r.h = Swap16IfLE(h);
    rect.encoding = Swap32IfLE(rfbEncodingHextile);

    memcpy(&updateBuf[ublen], (char *)&rect,
           sz_rfbFramebufferUpdateRectHeader);
    ublen += sz_rfbFramebufferUpdateRectHeader;

    cl->rfbRectanglesSent[rfbEncodingHextile]++;
    cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader;

    switch (cl->format.bitsPerPixel) {
    case 8:
        return sendHextiles8(cl, x, y, w, h);
    case 16:
        return sendHextiles16(cl, x, y, w, h);
    case 32:
        return sendHextiles32(cl, x, y, w, h);
    }

    rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
    return FALSE;
}
Exemple #3
0
rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
{
  zrleOutStream* zos;
  rfbFramebufferUpdateRectHeader rect;
  rfbZRLEHeader hdr;
  int i;

  if (cl->preferredEncoding == rfbEncodingZYWRLE) {
	  if (cl->tightQualityLevel < 0) {
		  cl->zywrleLevel = 1;
	  } else if (cl->tightQualityLevel < 3) {
		  cl->zywrleLevel = 3;
	  } else if (cl->tightQualityLevel < 6) {
		  cl->zywrleLevel = 2;
	  } else {
		  cl->zywrleLevel = 1;
	  }
  } else
	  cl->zywrleLevel = 0;

  if (!cl->zrleData)
    cl->zrleData = zrleOutStreamNew();
  zos = cl->zrleData;
  zos->in.ptr = zos->in.start;
  zos->out.ptr = zos->out.start;

  switch (cl->format.bitsPerPixel) {

  case 8:
    zrleEncode8NE(x, y, w, h, zos, zrleBeforeBuf, cl);
    break;

  case 16:
	if (cl->format.greenMax > 0x1F) {
		if (cl->format.bigEndian)
		  zrleEncode16BE(x, y, w, h, zos, zrleBeforeBuf, cl);
		else
		  zrleEncode16LE(x, y, w, h, zos, zrleBeforeBuf, cl);
	} else {
		if (cl->format.bigEndian)
		  zrleEncode15BE(x, y, w, h, zos, zrleBeforeBuf, cl);
		else
		  zrleEncode15LE(x, y, w, h, zos, zrleBeforeBuf, cl);
	}
    break;

  case 32: {
    rfbBool fitsInLS3Bytes
      = ((cl->format.redMax   << cl->format.redShift)   < (1<<24) &&
         (cl->format.greenMax << cl->format.greenShift) < (1<<24) &&
         (cl->format.blueMax  << cl->format.blueShift)  < (1<<24));

    rfbBool fitsInMS3Bytes = (cl->format.redShift   > 7  &&
                           cl->format.greenShift > 7  &&
                           cl->format.blueShift  > 7);

    if ((fitsInLS3Bytes && !cl->format.bigEndian) ||
        (fitsInMS3Bytes && cl->format.bigEndian)) {
	if (cl->format.bigEndian)
		zrleEncode24ABE(x, y, w, h, zos, zrleBeforeBuf, cl);
	else
		zrleEncode24ALE(x, y, w, h, zos, zrleBeforeBuf, cl);
    }
    else if ((fitsInLS3Bytes && cl->format.bigEndian) ||
             (fitsInMS3Bytes && !cl->format.bigEndian)) {
	if (cl->format.bigEndian)
		zrleEncode24BBE(x, y, w, h, zos, zrleBeforeBuf, cl);
	else
		zrleEncode24BLE(x, y, w, h, zos, zrleBeforeBuf, cl);
    }
    else {
	if (cl->format.bigEndian)
		zrleEncode32BE(x, y, w, h, zos, zrleBeforeBuf, cl);
	else
		zrleEncode32LE(x, y, w, h, zos, zrleBeforeBuf, cl);
    }
  }
    break;
  }

  rfbStatRecordEncodingSent(cl, rfbEncodingZRLE, sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + ZRLE_BUFFER_LENGTH(&zos->out),
      + w * (cl->format.bitsPerPixel / 8) * h);

  if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader
      > UPDATE_BUF_SIZE)
    {
      if (!rfbSendUpdateBuf(cl))
        return FALSE;
    }

  rect.r.x = Swap16IfLE(x);
  rect.r.y = Swap16IfLE(y);
  rect.r.w = Swap16IfLE(w);
  rect.r.h = Swap16IfLE(h);
  rect.encoding = Swap32IfLE(cl->preferredEncoding);

  memcpy(cl->updateBuf+cl->ublen, (char *)&rect,
         sz_rfbFramebufferUpdateRectHeader);
  cl->ublen += sz_rfbFramebufferUpdateRectHeader;

  hdr.length = Swap32IfLE(ZRLE_BUFFER_LENGTH(&zos->out));

  memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader);
  cl->ublen += sz_rfbZRLEHeader;

  /* copy into updateBuf and send from there.  Maybe should send directly? */

  for (i = 0; i < ZRLE_BUFFER_LENGTH(&zos->out);) {

    int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;

    if (i + bytesToCopy > ZRLE_BUFFER_LENGTH(&zos->out)) {
      bytesToCopy = ZRLE_BUFFER_LENGTH(&zos->out) - i;
    }

    memcpy(cl->updateBuf+cl->ublen, (uint8_t*)zos->out.start + i, bytesToCopy);

    cl->ublen += bytesToCopy;
    i += bytesToCopy;

    if (cl->ublen == UPDATE_BUF_SIZE) {
      if (!rfbSendUpdateBuf(cl))
        return FALSE;
    }
  }

  return TRUE;
}
Exemple #4
0
rfbBool
rfbSendCursorShape(rfbClientPtr cl)
{
    rfbCursorPtr pCursor;
    rfbFramebufferUpdateRectHeader rect;
    rfbXCursorColors colors;
    int saved_ublen;
    int bitmapRowBytes, maskBytes, dataBytes;
    int i, j;
    uint8_t *bitmapData;
    uint8_t bitmapByte;

    /* TODO: scale the cursor data to the correct size */

    pCursor = cl->screen->getCursorPtr(cl);
    /*if(!pCursor) return TRUE;*/

    if (cl->useRichCursorEncoding)
    {
        if(pCursor && !pCursor->richSource)
            rfbMakeRichCursorFromXCursor(cl->screen,pCursor);
        rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
    }
    else
    {
        if(pCursor && !pCursor->source)
            rfbMakeXCursorFromRichCursor(cl->screen,pCursor);
        rect.encoding = Swap32IfLE(rfbEncodingXCursor);
    }

    /* If there is no cursor, send update with empty cursor data. */

    if ( pCursor && pCursor->width == 1 &&
            pCursor->height == 1 &&
            pCursor->mask[0] == 0 )
    {
        pCursor = NULL;
    }

    if (pCursor == NULL)
    {
        if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE )
        {
            if (!rfbSendUpdateBuf(cl))
                return FALSE;
        }
        rect.r.x = rect.r.y = 0;
        rect.r.w = rect.r.h = 0;
        memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
               sz_rfbFramebufferUpdateRectHeader);
        cl->ublen += sz_rfbFramebufferUpdateRectHeader;

        if (!rfbSendUpdateBuf(cl))
            return FALSE;

        return TRUE;
    }

    /* Calculate data sizes. */

    bitmapRowBytes = (pCursor->width + 7) / 8;
    maskBytes = bitmapRowBytes * pCursor->height;
    dataBytes = (cl->useRichCursorEncoding) ?
                (pCursor->width * pCursor->height *
                 (cl->format.bitsPerPixel / 8)) : maskBytes;

    /* Send buffer contents if needed. */

    if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
            sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE )
    {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
            sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE )
    {
        return FALSE;		/* FIXME. */
    }

    saved_ublen = cl->ublen;

    /* Prepare rectangle header. */

    rect.r.x = Swap16IfLE(pCursor->xhot);
    rect.r.y = Swap16IfLE(pCursor->yhot);
    rect.r.w = Swap16IfLE(pCursor->width);
    rect.r.h = Swap16IfLE(pCursor->height);

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    /* Prepare actual cursor data (depends on encoding used). */

    if (!cl->useRichCursorEncoding)
    {
        /* XCursor encoding. */
        colors.foreRed   = (char)(pCursor->foreRed   >> 8);
        colors.foreGreen = (char)(pCursor->foreGreen >> 8);
        colors.foreBlue  = (char)(pCursor->foreBlue  >> 8);
        colors.backRed   = (char)(pCursor->backRed   >> 8);
        colors.backGreen = (char)(pCursor->backGreen >> 8);
        colors.backBlue  = (char)(pCursor->backBlue  >> 8);

        memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors);
        cl->ublen += sz_rfbXCursorColors;

        bitmapData = (uint8_t *)pCursor->source;

        for (i = 0; i < pCursor->height; i++)
        {
            for (j = 0; j < bitmapRowBytes; j++)
            {
                bitmapByte = bitmapData[i * bitmapRowBytes + j];
                cl->updateBuf[cl->ublen++] = (char)bitmapByte;
            }
        }
    }
Exemple #5
0
rfbBool
rfbSendRectEncodingRRE(rfbClientPtr cl,
                       int x,
                       int y,
                       int w,
                       int h)
{
    rfbFramebufferUpdateRectHeader rect;
    rfbRREHeader hdr;
    int nSubrects;
    int i;
    char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
                   + (x * (cl->scaledScreen->bitsPerPixel / 8)));

    int maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height
                      * (cl->format.bitsPerPixel / 8));

    if (cl->beforeEncBufSize < maxRawSize) {
        cl->beforeEncBufSize = maxRawSize;
        if (cl->beforeEncBuf == NULL)
            cl->beforeEncBuf = (char *)malloc(cl->beforeEncBufSize);
        else
            cl->beforeEncBuf = (char *)realloc(cl->beforeEncBuf, cl->beforeEncBufSize);
    }

    if (cl->afterEncBufSize < maxRawSize) {
        cl->afterEncBufSize = maxRawSize;
        if (cl->afterEncBuf == NULL)
            cl->afterEncBuf = (char *)malloc(cl->afterEncBufSize);
        else
            cl->afterEncBuf = (char *)realloc(cl->afterEncBuf, cl->afterEncBufSize);
    }

    (*cl->translateFn)(cl->translateLookupTable,
		       &(cl->screen->serverFormat),
                       &cl->format, fbptr, cl->beforeEncBuf,
                       cl->scaledScreen->paddedWidthInBytes, w, h);

    switch (cl->format.bitsPerPixel) {
    case 8:
        nSubrects = subrectEncode8(cl, (uint8_t *)cl->beforeEncBuf, w, h);
        break;
    case 16:
        nSubrects = subrectEncode16(cl, (uint16_t *)cl->beforeEncBuf, w, h);
        break;
    case 32:
        nSubrects = subrectEncode32(cl, (uint32_t *)cl->beforeEncBuf, w, h);
        break;
    default:
        rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
        return FALSE;
    }
        
    if (nSubrects < 0) {

        /* RRE encoding was too large, use raw */

        return rfbSendRectEncodingRaw(cl, x, y, w, h);
    }

    rfbStatRecordEncodingSent(cl, rfbEncodingRRE,
                              sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + cl->afterEncBufLen,
                              sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8));

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
        > UPDATE_BUF_SIZE)
    {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    rect.r.x = Swap16IfLE(x);
    rect.r.y = Swap16IfLE(y);
    rect.r.w = Swap16IfLE(w);
    rect.r.h = Swap16IfLE(h);
    rect.encoding = Swap32IfLE(rfbEncodingRRE);

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
           sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    hdr.nSubrects = Swap32IfLE(nSubrects);

    memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
    cl->ublen += sz_rfbRREHeader;

    for (i = 0; i < cl->afterEncBufLen;) {

        int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;

        if (i + bytesToCopy > cl->afterEncBufLen) {
            bytesToCopy = cl->afterEncBufLen - i;
        }

        memcpy(&cl->updateBuf[cl->ublen], &cl->afterEncBuf[i], bytesToCopy);

        cl->ublen += bytesToCopy;
        i += bytesToCopy;

        if (cl->ublen == UPDATE_BUF_SIZE) {
            if (!rfbSendUpdateBuf(cl))
                return FALSE;
        }
    }

    return TRUE;
}
Exemple #6
0
Bool rfbSendRichCursorUpdate(rfbClientPtr cl) {
    rfbFramebufferUpdateRectHeader rect;
    rfbPixelFormat cursorFormat;
    unsigned char *cursorData;
    int bufferMaskOffset;
    int cursorSize; // Size of cursor data from size
    int cursorRowBytes;
    int cursorDataSize; // Size to be sent to client
    int cursorMaskSize; // Mask Size to be sent to client
    int cursorDepth;
    int cursorBitsPerComponent;
    BOOL cursorIsDifferentFormat = FALSE;

    CGError err;
    CGSConnectionRef connection = getConnection();
    int components; // Cursor Components

    CGPoint hotspot;
    CGRect cursorRect;

    //rfbLog("Sending Cursor To Client");
    //GetCursorInfo();
    
	if (!connection) {
		if (!maxFailsRemaining)
			cl->useRichCursorEncoding = FALSE;		
		return FALSE;
	}
	
    if (CGSGetGlobalCursorDataSize(connection, &cursorDataSize) != kCGErrorSuccess) {
        rfbLog("Error obtaining cursor data - cursor not sent\n");
        return FALSE;
    }

    cursorData = (unsigned char*)malloc(sizeof(unsigned char) * cursorDataSize);
    err = CGSGetGlobalCursorData(connection,
                                 cursorData,
                                 &cursorDataSize,
                                 &cursorRowBytes,
                                 &cursorRect,
                                 &hotspot,
                                 &cursorDepth,
                                 &components,
                                 &cursorBitsPerComponent);

    //CGSReleaseConnection(connection);
    if (err != kCGErrorSuccess) {
        rfbLog("Error obtaining cursor data - cursor not sent\n");
        return FALSE;
    }

	
	if (cursorRect.size.height > 128 || cursorRect.size.width > 128) {
		// Wow That's one big cursor! We don't handle cursors this big 
		// (they are probably cursors with lots of states and that doesn't work so good for VNC.
		// For now just ignore them
		cl->currentCursorSeed = CGSCurrentCursorSeed();
		return FALSE;
	}
	
    // For This We Don't send location just the cursor shape (and Hot Spot)
    cursorFormat.depth = (cursorDepth == 32 ? 24 : cursorDepth);
    cursorFormat.bitsPerPixel = cursorDepth;
    cursorFormat.bigEndian = TRUE;
    cursorFormat.trueColour = TRUE;
    cursorFormat.redMax = cursorFormat.greenMax = cursorFormat.blueMax = (unsigned short) ((1<<cursorBitsPerComponent) - 1);
	cursorFormat.bigEndian = !littleEndian;
	cursorFormat.redShift   = (unsigned char) (cursorBitsPerComponent * 2);
	cursorFormat.greenShift = (unsigned char) (cursorBitsPerComponent * 1);
	cursorFormat.blueShift  = (unsigned char) (cursorBitsPerComponent * 0);
		
	//GetCursorInfo();
    //PrintPixelFormat(&cursorFormat);
    cursorIsDifferentFormat = !(PF_EQ(cursorFormat,rfbServerFormat));
    
    cursorSize = (cursorRect.size.width * cursorRect.size.height * (cl->format.bitsPerPixel / 8));
    cursorMaskSize = floor((cursorRect.size.width+7)/8) * cursorRect.size.height;

    // Make Sure we have space on the buffer (otherwise push the data out now)

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + cursorSize + cursorMaskSize > UPDATE_BUF_SIZE) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    // Send The Header
    rect.r.x = Swap16IfLE((short) hotspot.x);
    rect.r.y = Swap16IfLE((short) hotspot.y);
    rect.r.w = Swap16IfLE((short) cursorRect.size.width);
    rect.r.h = Swap16IfLE((short) cursorRect.size.height);
    rect.encoding = Swap32IfLE(rfbEncodingRichCursor);

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    // Apple Cursors can use a full Alpha channel.
    // Since we can only send a bit mask - to get closer we will compose the full color with a white
    // This requires us to jump ahead to write in the update buffer
    bufferMaskOffset = cl->ublen + cursorSize;

    // For starters we'll set mask to OFF (transparent) everywhere)
    memset(&cl->updateBuf[bufferMaskOffset], 0, cursorMaskSize);
    // This algorithm assumes the Alpha channel is the first component
    {
        unsigned char *cursorRowData = cursorData;
        unsigned char *cursorColumnData = cursorData;
        unsigned int cursorBytesPerPixel = (cursorDepth/8);
        unsigned char mask = 0;
		unsigned int alphaShift = (8 - cursorBitsPerComponent);
        unsigned char fullOn = (0xFF) >> alphaShift;
        unsigned char alphaThreshold = (0x60) >> alphaShift; // Only include the pixel if it's coverage is greater than this
        int dataX, dataY, componentIndex;

        for (dataY = 0; dataY < cursorRect.size.height; dataY++) {
            cursorColumnData = cursorRowData;
            for (dataX = 0; dataX < cursorRect.size.width; dataX++) {
				if (littleEndian)
					mask = (unsigned char)(*(cursorColumnData+(cursorBytesPerPixel-1))) >> alphaShift;
				else
					mask = (unsigned char)(*cursorColumnData) >> alphaShift;
                if (mask > alphaThreshold) {
                    // Write the Bit For The Mask to be ON (opaque)
                    cl->updateBuf[bufferMaskOffset+(dataX/8)] |= (0x0080 >> (dataX % 8));
                    // Composite Alpha into the cursors other channels - only for 32 bit
                    if (cursorDepth == 32 && mask != fullOn) {
                        for (componentIndex = 0; componentIndex < components; componentIndex++) {
                            *cursorColumnData = (unsigned char) (fullOn - mask + ((*cursorColumnData * mask)/fullOn)) & 0xFF;
                            cursorColumnData++;
                        }
                    }
                    else
                        cursorColumnData += cursorBytesPerPixel;
                }
                else
                    cursorColumnData += cursorBytesPerPixel;
            }
Exemple #7
0
rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
{
  zrleOutStream* zos;
  rfbFramebufferUpdateRectHeader rect;
  rfbZRLEHeader hdr;
  int i;

  if (!cl->zrleData)
    cl->zrleData = zrleOutStreamNew();
  zos = cl->zrleData;
  zos->in.ptr = zos->in.start;
  zos->out.ptr = zos->out.start;

  switch (cl->format.bitsPerPixel) {

  case 8:
    zrleEncode8( x, y, w, h, zos, zrleBeforeBuf, cl);
    break;

  case 16:
    zrleEncode16(x, y, w, h, zos, zrleBeforeBuf, cl);
    break;

  case 32: {
    rfbBool fitsInLS3Bytes
      = ((cl->format.redMax   << cl->format.redShift)   < (1<<24) &&
         (cl->format.greenMax << cl->format.greenShift) < (1<<24) &&
         (cl->format.blueMax  << cl->format.blueShift)  < (1<<24));

    rfbBool fitsInMS3Bytes = (cl->format.redShift   > 7  &&
                           cl->format.greenShift > 7  &&
                           cl->format.blueShift  > 7);

    if ((fitsInLS3Bytes && !cl->format.bigEndian) ||
        (fitsInMS3Bytes && cl->format.bigEndian))
    {
      zrleEncode24A(x, y, w, h, zos, zrleBeforeBuf, cl);
    }
    else if ((fitsInLS3Bytes && cl->format.bigEndian) ||
             (fitsInMS3Bytes && !cl->format.bigEndian))
    {
      zrleEncode24B(x, y, w, h, zos, zrleBeforeBuf, cl);
    }
    else
    {
      zrleEncode32(x, y, w, h, zos, zrleBeforeBuf, cl);
    }
  }
    break;
  }

  cl->rfbRectanglesSent[rfbEncodingZRLE]++;
  cl->rfbBytesSent[rfbEncodingZRLE] += (sz_rfbFramebufferUpdateRectHeader
                                        + sz_rfbZRLEHeader + ZRLE_BUFFER_LENGTH(&zos->out));

  if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader
      > UPDATE_BUF_SIZE)
    {
      if (!rfbSendUpdateBuf(cl))
        return FALSE;
    }

  rect.r.x = Swap16IfLE(x);
  rect.r.y = Swap16IfLE(y);
  rect.r.w = Swap16IfLE(w);
  rect.r.h = Swap16IfLE(h);
  rect.encoding = Swap32IfLE(rfbEncodingZRLE);

  memcpy(cl->updateBuf+cl->ublen, (char *)&rect,
         sz_rfbFramebufferUpdateRectHeader);
  cl->ublen += sz_rfbFramebufferUpdateRectHeader;

  hdr.length = Swap32IfLE(ZRLE_BUFFER_LENGTH(&zos->out));

  memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader);
  cl->ublen += sz_rfbZRLEHeader;

  /* copy into updateBuf and send from there.  Maybe should send directly? */

  for (i = 0; i < ZRLE_BUFFER_LENGTH(&zos->out);) {

    int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;

    if (i + bytesToCopy > ZRLE_BUFFER_LENGTH(&zos->out)) {
      bytesToCopy = ZRLE_BUFFER_LENGTH(&zos->out) - i;
    }

    memcpy(cl->updateBuf+cl->ublen, (uint8_t*)zos->out.start + i, bytesToCopy);

    cl->ublen += bytesToCopy;
    i += bytesToCopy;

    if (cl->ublen == UPDATE_BUF_SIZE) {
      if (!rfbSendUpdateBuf(cl))
        return FALSE;
    }
  }

  return TRUE;
}
Exemple #8
0
static rfbBool
rfbSendOneRectEncodingUltra(rfbClientPtr cl,
                            int x,
                            int y,
                            int w,
                            int h)
{
    rfbFramebufferUpdateRectHeader rect;
    rfbZlibHeader hdr;
    int deflateResult;
    int i;
    char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
                   + (x * (cl->scaledScreen->bitsPerPixel / 8)));

    int maxRawSize;
    lzo_uint maxCompSize;

    maxRawSize = (w * h * (cl->format.bitsPerPixel / 8));

    if (cl->beforeEncBufSize < maxRawSize)
    {
        cl->beforeEncBufSize = maxRawSize;
        if (cl->beforeEncBuf == NULL)
            cl->beforeEncBuf = (char *)MemAlloc(cl->beforeEncBufSize);
        else
            cl->beforeEncBuf = (char *)MemRealloc(cl->beforeEncBuf, cl->beforeEncBufSize);
    }

    /*
     * lzo requires output buffer to be slightly larger than the input
     * buffer, in the worst case.
     */
    maxCompSize = (maxRawSize + maxRawSize / 16 + 64 + 3);

    if (cl->afterEncBufSize < (int)maxCompSize)
    {
        cl->afterEncBufSize = maxCompSize;
        if (cl->afterEncBuf == NULL)
            cl->afterEncBuf = (char *)MemAlloc(cl->afterEncBufSize);
        else
            cl->afterEncBuf = (char *)MemRealloc(cl->afterEncBuf, cl->afterEncBufSize);
    }

    /*
     * Convert pixel data to client format.
     */
    (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,
                       &cl->format, fbptr, cl->beforeEncBuf,
                       cl->scaledScreen->paddedWidthInBytes, w, h);

    if ( cl->compStreamInitedLZO == FALSE )
    {
        cl->compStreamInitedLZO = TRUE;
        /* Work-memory needed for compression. Allocate memory in units
         * of `lzo_align_t' (instead of `char') to make sure it is properly aligned.
         */
        cl->lzoWrkMem = MemAlloc(sizeof(lzo_align_t) * (((LZO1X_1_MEM_COMPRESS) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)));
    }

    /* Perform the compression here. */
    deflateResult = lzo1x_1_compress((unsigned char *)cl->beforeEncBuf, (lzo_uint)(w * h * (cl->format.bitsPerPixel / 8)), (unsigned char *)cl->afterEncBuf, &maxCompSize, cl->lzoWrkMem);
    /* maxCompSize now contains the compressed size */

    /* Find the total size of the resulting compressed data. */
    cl->afterEncBufLen = maxCompSize;

    if ( deflateResult != LZO_E_OK )
    {
        ///rfbErr("lzo deflation error: %d\n", deflateResult);
        return FALSE;
    }

    /* Update statics */
    ///rfbStatRecordEncodingSent(cl, rfbEncodingUltra, sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + cl->afterEncBufLen, maxRawSize);

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader
            > UPDATE_BUF_SIZE)
    {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    rect.r.x = Swap16IfLE(x);
    rect.r.y = Swap16IfLE(y);
    rect.r.w = Swap16IfLE(w);
    rect.r.h = Swap16IfLE(h);
    rect.encoding = Swap32IfLE(rfbEncodingUltra);

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
           sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    hdr.nBytes = Swap32IfLE(cl->afterEncBufLen);

    memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader);
    cl->ublen += sz_rfbZlibHeader;

    /* We might want to try sending the data directly... */
    for (i = 0; i < cl->afterEncBufLen;)
    {

        int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;

        if (i + bytesToCopy > cl->afterEncBufLen)
        {
            bytesToCopy = cl->afterEncBufLen - i;
        }

        memcpy(&cl->updateBuf[cl->ublen], &cl->afterEncBuf[i], bytesToCopy);

        cl->ublen += bytesToCopy;
        i += bytesToCopy;

        if (cl->ublen == UPDATE_BUF_SIZE)
        {
            if (!rfbSendUpdateBuf(cl))
                return FALSE;
        }
    }

    return TRUE;

}
Exemple #9
0
rfbBool
rfbSendRectEncodingUltra(rfbClientPtr cl,
                         int x,
                         int y,
                         int w,
                         int h)
{
    int  maxLines;
    int  linesRemaining;
    rfbRectangle partialRect;

    partialRect.x = x;
    partialRect.y = y;
    partialRect.w = w;
    partialRect.h = h;

    /* Determine maximum pixel/scan lines allowed per rectangle. */
    maxLines = ( ULTRA_MAX_SIZE(w) / w );

    /* Initialize number of scan lines left to do. */
    linesRemaining = h;

    /* Loop until all work is done. */
    while ( linesRemaining > 0 )
    {

        int linesToComp;

        if ( maxLines < linesRemaining )
            linesToComp = maxLines;
        else
            linesToComp = linesRemaining;

        partialRect.h = linesToComp;

        /* Encode (compress) and send the next rectangle. */
        if ( ! rfbSendOneRectEncodingUltra( cl,
                                            partialRect.x,
                                            partialRect.y,
                                            partialRect.w,
                                            partialRect.h ))
        {

            return FALSE;
        }

        /* Technically, flushing the buffer here is not extrememly
         * efficient.  However, this improves the overall throughput
         * of the system over very slow networks.  By flushing
         * the buffer with every maximum size lzo rectangle, we
         * improve the pipelining usage of the server CPU, network,
         * and viewer CPU components.  Insuring that these components
         * are working in parallel actually improves the performance
         * seen by the user.
         * Since, lzo is most useful for slow networks, this flush
         * is appropriate for the desired behavior of the lzo encoding.
         */
        if (( cl->ublen > 0 ) &&
                ( linesToComp == maxLines ))
        {
            if (!rfbSendUpdateBuf(cl))
            {

                return FALSE;
            }
        }

        /* Update remaining and incremental rectangle location. */
        linesRemaining -= linesToComp;
        partialRect.y += linesToComp;

    }

    return TRUE;

}