Integrating a VNC display

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 :slight_smile:

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);
}  

This is an OpenGL forum not a GDI one.

I think the questions is how to bridge the gap between GDI and OpenGL.
Although I have very limited knowledge of GDI the procedure should be similar to using avi files in OpenGL as textures. Take a look at “CreateDIBSection” and “DrawDibDraw” in the MSDN, this will help copying, scaling, and possibly converting color space to OpenGL. After that use glTexSubImage2D() to copy the image into your texture.
At least that"s what I would try… :slight_smile:

My bad…
Then yeah, what he said. That seems a long stride in the right direction.

Yes, I’m not looking for GDI help here. :slight_smile:

Obviously I can just upload the texture data by reading from the given bitmap. I would like to know if there are any shortcuts or caveats.

I’ll look into the device-independent bitmap functions tomorrow; thanks def.