Ah, no attachments, here is the code:

void CVNCClient::SetupBitmapInfo()
{
 m_bmi = new BYTE[sizeof(BITMAPINFOHEADER) + (4 * sizeof(DWORD))];

 BITMAPINFO* m_bi = (BITMAPINFO *) m_bmi;
 m_bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 m_bi->bmiHeader.biWidth = 0;   // set later
 m_bi->bmiHeader.biHeight = 0;   // set later
 m_bi->bmiHeader.biPlanes = 1;
 m_bi->bmiHeader.biBitCount = m_pixelFormat.bitsPerPixel;
 m_bi->bmiHeader.biCompression = BI_BITFIELDS;
 m_bi->bmiHeader.biSizeImage = 0;  // set later
 m_bi->bmiHeader.biXPelsPerMeter = 0;  // ??
 m_bi->bmiHeader.biYPelsPerMeter = 0;  // ??
 m_bi->bmiHeader.biClrUsed = 0;
 m_bi->bmiHeader.biClrImportant = 0;
 DWORD* m = (DWORD *)(m_bmi + sizeof(BITMAPINFOHEADER));
 *m = ((DWORD)m_pixelFormat.redMax) << m_pixelFormat.redShift;
 TRACE(_T(" -- red mask: %X\n"), *m);
 m++;
 *m = ((DWORD)m_pixelFormat.greenMax) << m_pixelFormat.greenShift;
 TRACE(_T(" -- green mask: %X\n"), *m);
 m++;
 *m = ((DWORD)m_pixelFormat.blueMax) << m_pixelFormat.blueShift;
 TRACE(_T(" -- blue mask: %X\n"), *m);
 m++;
 *m = 0;

 // BUF_LINES about 100 or so
 if (8 == m_pixelFormat.bitsPerPixel || 16 == m_pixelFormat.bitsPerPixel)
 {
  // we are going to have to DWORD align some rects, this
  // is a scratch buffer for this
  m_pixbuf = new BYTE[
   GetFrameBufferWidth() * GetMinPixelBytes() * BUF_LINES];
  TRACE(_T(" pixbuf len: %d\n"),
   GetFrameBufferWidth() * GetMinPixelBytes() * BUF_LINES);
 }
}

void CVNCClient::FastSetPixels(
 CDC& dc,
 BYTE* buffer, int x, int y, int w, int h)
{
 /* setup the bitmap header */
 BITMAPINFO* bi = GetBitmapInfo();
 bi->bmiHeader.biWidth = w;
 bi->bmiHeader.biHeight = -h; /* top down */
 bi->bmiHeader.biSizeImage = GetMinPixelBytes() * w * h;

 int lineSize = GetMinPixelBytes() * w;

 if (lineSize % sizeof(DWORD) == 0)
 {
  // already aligned
  ::SetDIBitsToDevice(dc.m_hDC,
   x, y,  /* destination */
   w, h, /* source width/height */
   0, 0, /* source x,y */
   0,  /* fist scanline */
   h,  /* number of scanlines */
   buffer, /* bits */
   bi,
   DIB_RGB_COLORS);
 }
 else
 {
  int nLeft = h;
  int extraBytesNeeded = sizeof(DWORD) - GetMinPixelBytes();
  ASSERT((lineSize + extraBytesNeeded) % sizeof(DWORD) == 0);
  int nDrawn = 0;
  while (nLeft > 0)
  {
   int nlines = min(nLeft, BUF_LINES);
   BYTE* buf = m_pixbuf;

   // DWORD align in scratch buffer
   for (int l = 0; l < nlines; l++)
   {
    memcpy(buf, buffer, lineSize);
    buffer += lineSize;
    buf += lineSize + extraBytesNeeded;
   }

   bi->bmiHeader.biHeight = -nlines; /* top down */
   bi->bmiHeader.biSizeImage = (lineSize + extraBytesNeeded) * nlines;

   int s = ::SetDIBitsToDevice(dc.m_hDC,
    x, y,  /* destination */
    w, nlines, /* source width/height */
    0, 0, /* source x,y */
    0,  /* fist scanline */
    nlines,  /* number of scanlines */
    m_pixbuf, /* bits */
    bi,
    DIB_RGB_COLORS);

   nLeft -= nlines;
   y += nlines;
   nDrawn += nlines;
  }

  ASSERT(nDrawn == h);
 }
}

----- Original Message -----
From: "Tony Rozga" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Thursday, March 06, 2003 8:45 PM
Subject: A windows optimization


> Hi,
> I wish I had time to submit this as a patch but I'm in the middle of a
> monster project...
> you know how that goes.  Anyway, we noticed that processing updates in the
> windows
> viewer was taking, well, a long time.  A little profiling led us to the
> SETPIXELs
> macros.  SetPixel is slow.  For example, just profiling SetPixel, it took
> 5-6 seconds
> to process a 1280x1024 full update (zlib) on a fast machine with ok video.
>
> The optimization is simple.  Treat the buffer as the bits of a DIB and use
> SetDIBitsToDevice
> to write to the DC.
>
> I've attached two methods, one to setup a BITMAPINFO once the clients
pixel
> format is set and
> one called FastSetPixels.  The only trickiness is that scanlines must be
> DWORD aligned, no
> prob for 32 bits, can be a problem in 8 and 16 bits.  Our solution was to
> pre-create a
> temp buffer to hold 100 scan lines and use that to draw those updates that
> did not come in
> aligned in chunks.
>
> The result is a significant improvement, 5-6 seconds dropped to <1 second.
>
> This code has only been tested in 16/32 bit modes so be warned.  Also,
this
> code will not drop
> straight into the standard viewer code but it is pretty obvious.
>
> Anyway, that is all.  Hope you like it.  Gotta get back to it.
>
> Tony Rozga
> NeoValent
>
> [demime 0.99d.1 removed an attachment of type application/octet-stream
which had a name of vncopt.cpp]
> _______________________________________________
> VNC-List mailing list
> [EMAIL PROTECTED]
> http://www.realvnc.com/mailman/listinfo/vnc-list
_______________________________________________
VNC-List mailing list
[EMAIL PROTECTED]
http://www.realvnc.com/mailman/listinfo/vnc-list

Reply via email to