As a quick proof of concept for a military client, I’d like to create a virtual room of workstations, each updating their display from a real computer running a VNC server.
I have limited time to do this, so I’m hoping you have some pointers. I’d like to avoid overly complex extensions at the moment. I don’t have any experience with PBO, for example. Render to texture through CopySubImage2D is something I’m more comfortable with. Performance is not my goal here; I’d just like to get it working over the next few days.
Any ‘beware!’ responses would be much appreciated as well
VNC is open source, so here’s the relevant code:
inline void ClientConnection::DoBlit()
{
if (m_hBitmap == NULL) return;
if (!m_running) return;
// No other threads can use bitmap DC
omni_mutex_lock l(m_bitmapdcMutex);
PAINTSTRUCT ps;
HDC hdc = BeginPaint(m_hwnd, &ps);
// Select and realize hPalette
PaletteSelector p(hdc, m_hPalette);
ObjectSelector b(m_hBitmapDC, m_hBitmap);
if (m_opts.m_delay) {
// Display the area to be updated for debugging purposes
COLORREF oldbgcol = SetBkColor(hdc, RGB(0,0,0));
::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &ps.rcPaint, NULL, 0, NULL);
SetBkColor(hdc,oldbgcol);
::Sleep(m_pApp->m_options.m_delay);
}
if (m_opts.m_scaling) {
int n = m_opts.m_scale_num;
int d = m_opts.m_scale_den;
// We're about to do some scaling on these values in the StretchBlt
// We want to make sure that they divide nicely by n so we round them
// down and up appropriately.
ps.rcPaint.left = ((ps.rcPaint.left + m_hScrollPos) / n * n) - m_hScrollPos;
ps.rcPaint.right = ((ps.rcPaint.right + m_hScrollPos + n - 1) / n * n) - m_hScrollPos;
ps.rcPaint.top = ((ps.rcPaint.top + m_vScrollPos) / n * n) - m_vScrollPos;
ps.rcPaint.bottom = ((ps.rcPaint.bottom + m_vScrollPos + n - 1) / n * n) - m_vScrollPos;
// This is supposed to give better results. I think my driver ignores it?
SetStretchBltMode(hdc, HALFTONE);
// The docs say that you should call SetBrushOrgEx after SetStretchBltMode,
// but not what the arguments should be.
SetBrushOrgEx(hdc, 0,0, NULL);
if (!StretchBlt(
hdc,
ps.rcPaint.left,
ps.rcPaint.top,
ps.rcPaint.right-ps.rcPaint.left,
ps.rcPaint.bottom-ps.rcPaint.top,
m_hBitmapDC,
(ps.rcPaint.left+m_hScrollPos) * d / n,
(ps.rcPaint.top+m_vScrollPos) * d / n,
(ps.rcPaint.right-ps.rcPaint.left) * d / n,
(ps.rcPaint.bottom-ps.rcPaint.top) * d / n,
SRCCOPY))
{
vnclog.Print(0, _T("Blit error %d
"), GetLastError());
// throw ErrorException("Error in blit!
");
};
} else {
if (!BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right-ps.rcPaint.left, ps.rcPaint.bottom-ps.rcPaint.top,
m_hBitmapDC, ps.rcPaint.left+m_hScrollPos, ps.rcPaint.top+m_vScrollPos, SRCCOPY))
{
vnclog.Print(0, _T("Blit error %d
"), GetLastError());
// throw ErrorException("Error in blit!
");
}
}
EndPaint(m_hwnd, &ps);
}