gpecer.cpp

来自「老外的一个开源项目」· C++ 代码 · 共 1,328 行 · 第 1/3 页

CPP
1,328
字号
		if (pThis->m_Sock == INVALID_SOCKET) {
			pThis->m_Sock = socket (AF_INET, SOCK_STREAM, 0);
		}

		// Close broadcast thread
		WaitForSingleObject (hBroadcastThread, INFINITE);
		CloseHandle (hBroadcastThread);

		DEBUGMSG (1, (TEXT("GPECERem::Refresh connected\r\n")));

		// Turn off the nagle option.
		BOOL fNoDelay = TRUE;
		setsockopt (pThis->m_Sock, IPPROTO_TCP, TCP_NODELAY, (char *)&fNoDelay, sizeof(fNoDelay));

		// Turn on keep alive option.
		BOOL fKeepAlive = TRUE;
		setsockopt (pThis->m_Sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&fKeepAlive, sizeof(fKeepAlive));

		// Send identifier
		pThis->InitCerDispInfo(&Info);
		if (TCPSend (pThis->m_Sock, (char *)&Info, sizeof(Info)) != sizeof(Info)) {
			DEBUGMSG (1, (TEXT("GPECERem::Refresh Error %d sending info\r\n"), WSAGetLastError()));
			CloseSocket (&pThis->m_Sock);
			continue;
		}
		
		// Send default config
		dwThreadID = CEROBJ_CONFIG;
		if (TCPSend (pThis->m_Sock, (char *)&dwThreadID, sizeof(dwThreadID))!=sizeof(dwThreadID) ||
			TCPSend (pThis->m_Sock, (char *)&pThis->m_Config, sizeof(pThis->m_Config))!=sizeof(pThis->m_Config)) {
			DEBUGMSG (1, (TEXT("GPECERem::Refresh Error %d sending config\r\n"), WSAGetLastError()));
			CloseSocket (&pThis->m_Sock);
			continue;
		}

		// Start the input thread.
		hInputThread = CreateThread (NULL, 0, DoInput, (LPVOID)pThis, 0, &dwThreadID);

		// Now map the frame buffer and start copying.
		RectObj.dwObjType = CEROBJ_RECT;
		RectObj.rect.left = 0;
		RectObj.rect.top = 0;
		RectObj.rect.right = pThis->m_nScreenWidth;
		RectObj.rect.bottom = pThis->m_nScreenHeight;

		// Worst case is that I need twice the original buffer for the compressed image
		pwDst = (WORD *)LocalAlloc (LMEM_FIXED, 2*pThis->m_nScreenWidth*pThis->m_nScreenHeight*pThis->m_colorDepth/8);
		pwSrc = (WORD *)pThis->m_VirtualFrameBuffer;
		dwOldCheck  = 0xFFFFFFFF;
		pdwRowCheck = (DWORD *)LocalAlloc (LMEM_FIXED, pThis->m_nScreenHeight*sizeof(DWORD));
		memset ((char *)pdwRowCheck, 0xFF, pThis->m_nScreenHeight*sizeof(DWORD));

		v_fPalChanged = TRUE; // force send init palette
		dwLastTick = GetTickCount();
		cWords = (int)pThis->m_nScreenWidth*pThis->m_nScreenHeight*pThis->m_colorDepth/16;

		while (INVALID_SOCKET != pThis->m_Sock) 
		{
			// Send palette, if need
			if (v_fPalChanged) {
				PalObj.dwObjType = CEROBJ_PALETTE;
				PalObj.dwSize = sizeof(rgq);
				if (TCPSend (pThis->m_Sock, (char *)&PalObj, sizeof(PalObj)) != sizeof(PalObj)) {
					DEBUGMSG (1, (TEXT("GPECERem::Refresh Unable to send PalObj, Error %d\r\n"), WSAGetLastError()));
					break;
				}

				for (i=0; i < 256; i++) {
					rgq[i].rgbRed = _rgbIdentity[i].peRed;
					rgq[i].rgbGreen = _rgbIdentity[i].peGreen;
					rgq[i].rgbBlue = _rgbIdentity[i].peBlue;
					rgq[i].rgbReserved = 0;
				}

				if (TCPSend (pThis->m_Sock, (char *)rgq, sizeof(rgq)) != sizeof(rgq)) {
					DEBUGMSG (1, (TEXT("GPECERem::Refresh Unable to send Palette data, Error %d\r\n"), WSAGetLastError()));
					break;
				}
				v_fPalChanged = FALSE;
			}

			if (pThis->m_Config.dwUpdatePolicy) {
				dwCheck = ComputeCheck (pThis->m_Config.dwCheckPolicy, pwSrc, cWords);
				if (dwCheck != dwOldCheck) {
					dwOldCheck = dwCheck;
					offset = CompressRect (pwSrc, pwDst, cWords);
					RectObj.dwSize = offset;
					
					if (TCPSend (pThis->m_Sock, (char *)&RectObj, sizeof(RectObj)) != sizeof(RectObj)) {
						DEBUGMSG (1, (TEXT("Error %d from send of RectInfo\r\n"), WSAGetLastError()));
						break;
					}

					if (TCPSend (pThis->m_Sock, (char *)pwDst, offset*sizeof(WORD)) != offset*sizeof(WORD)) {
						DEBUGMSG (1, (TEXT("Error %d from send of screen data\r\n"), WSAGetLastError()));
						break;
					}
				}
			}
			else {
				// Now use the new ROW format.
				int	RowWords = pThis->m_nScreenWidth*pThis->m_colorDepth/16;

				offset = 0;
				for (i=0; i < pThis->m_nScreenHeight; i++) {
					dwCheck = ComputeCheck (pThis->m_Config.dwCheckPolicy, pwSrc+i*RowWords, RowWords);
//					RETAILMSG (1, (TEXT("Row %d, dwCheck=%d, pdwRowCheck[%d]=%d\r\n"), i, dwCheck, i, pdwRowCheck[i]));

					if (dwCheck != pdwRowCheck[i]) {
						pdwRowCheck[i] = dwCheck;

						pwDst[offset] = i;	// Set row number
						offset += CompressRow (pwSrc+i*RowWords, pwDst+offset, RowWords);
//						RETAILMSG (1, (TEXT("Sending row update, row=%d, size=%d\r\n"), pwDst[0], pwDst[1]));
					}
				}
				if (offset) {
					dwThreadID = CEROBJ_ROWUPDATE;
					if (TCPSend (pThis->m_Sock, (char *)&dwThreadID, sizeof(dwThreadID)) != sizeof(dwThreadID)) {
						DEBUGMSG (1, (TEXT("GPECERem::Refresh Unable to send ObjType, Error %d\r\n"), WSAGetLastError()));
						break;
					}
					
					if (TCPSend (pThis->m_Sock, (char *)pwDst, sizeof(WORD)*offset) != (int)(sizeof(WORD)*offset)) {
						DEBUGMSG (1, (TEXT("GPECERem::Refresh Unable to send Row Update, Error %d\r\n"), WSAGetLastError()));
						break;
					}
					
					// Now send the end of Row indicator
					pwDst[0] = 0xFFFF;
					if (TCPSend (pThis->m_Sock, (char *)pwDst, sizeof(WORD)) != sizeof(WORD)) {
						DEBUGMSG (1, (TEXT("GPECERem::Refresh Unable to send Row Update, Error %d\r\n"), WSAGetLastError()));
						break;
					}
				}
			}
			Sleep (pThis->m_Config.dwRefreshInterval);

			// Send heart beat signal, if need
			if (GetTickCount() - dwLastTick >= 60*1000) {
				dwLastTick = GetTickCount();
				dwThreadID = CEROBJ_HEARTBEAT;
				if (TCPSend (pThis->m_Sock, (char *)&dwThreadID, sizeof(dwThreadID)) != sizeof(dwThreadID)) {
					DEBUGMSG (1, (TEXT("GPECERem::Refresh Unable to send Heart Beat, Error %d\r\n"), WSAGetLastError()));
					break;
				}
			}
		}
		// Free memory
		LocalFree((HGLOBAL)pwDst);
		LocalFree((HGLOBAL)pdwRowCheck);

		CloseSocket (&pThis->m_Sock);

		// Close input thread
		WaitForSingleObject (hInputThread, INFINITE);
		CloseHandle (hInputThread);
	}

	closesocket (ListenSock);
	return 0;
}


GPECERem::GPECERem (void)
{
	ULONG		fbSize;
	ULONG		fbOffset;
	ULONG		offsetX, offsetY;
	HKEY		hKey;
	DWORD		dwSize;

	DEBUGMSG(GPE_ZONE_INIT,(TEXT("GPECERem::GPECERem\r\n")));

	// [HKEY_LOCAL_MACHINE\Drivers\Display\DDI_CER]
	//		"CxScreen"=dword:280
	//		"CyScreen"=dword:1E0
	//		"Bpp"=dword:8
	//		"Refresh"=dword:32
	// Useful Hex Values
	//	1024=0x400, 800=0x320, 768=0x300, 640=0x280, 600=0x258, 480=0x1E0, 320=140, 240=0xF0
	//	8=0x8, 16=0x10
	//	50=0x32, 100=0x64, 250=0xFA, 500=0x1F4

	// Default Settings
	m_Config.dwRefreshInterval = 100;
	m_Config.dwUpdatePolicy = 0;
	m_Config.dwCheckPolicy = 0;
	
	m_nScreenWidth = 640;
	m_nScreenHeight = 480;
	m_colorDepth = 8;
	m_noServer = 0;
RETAILMSG (1, (TEXT("GPECERem::Start thread priority=%d\r\n"), CeGetThreadPriority(GetCurrentThread())));

	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Drivers\\Display\\DDI_CER"), 0, 0, &hKey)) {
		// This ignores return values, defaults set above.
		dwSize = sizeof(dwSize);
		RegQueryValueEx (hKey, TEXT("Refresh"), 0, NULL, (LPBYTE)&m_Config.dwRefreshInterval, &dwSize); 
		dwSize = sizeof(dwSize);
		RegQueryValueEx (hKey, TEXT("Update"), 0, NULL, (LPBYTE)&m_Config.dwUpdatePolicy, &dwSize); 
		dwSize = sizeof(dwSize);
		RegQueryValueEx (hKey, TEXT("Difference"), 0, NULL, (LPBYTE)&m_Config.dwCheckPolicy, &dwSize); 
		dwSize = sizeof(dwSize);
		RegQueryValueEx (hKey, TEXT("CxScreen"), 0, NULL, (LPBYTE)&m_nScreenWidth, &dwSize); 
		dwSize = sizeof(dwSize);
		RegQueryValueEx (hKey, TEXT("CyScreen"), 0, NULL, (LPBYTE)&m_nScreenHeight, &dwSize); 
		dwSize = sizeof(dwSize);
		RegQueryValueEx (hKey, TEXT("Bpp"), 0, NULL, (LPBYTE)&m_colorDepth, &dwSize); 
		dwSize = sizeof(dwSize);
		RegQueryValueEx (hKey, TEXT("NoServer"), 0, NULL, (LPBYTE)&m_noServer, &dwSize); 
		
		RegCloseKey (hKey);
	}

	// We only support 8 bits/Pixel now
	m_colorDepth = 8;
	
	// Generate some debug clutter.
	RETAILMSG (1, (TEXT("GPECER:: Initializing to %dx%dx%d Refresh=%d\r\n"),
				   m_nScreenWidth, m_nScreenHeight, m_colorDepth, m_Config.dwRefreshInterval));
	
	m_cxPhysicalScreen = m_nScreenWidth;
	m_cyPhysicalScreen = m_nScreenHeight;
	m_pvFlatFrameBuffer = 0;	// Dirty Rect driver....
	m_cbScanLineLength = m_nScreenWidth;

	// set rest of ModeInfo values
	m_ModeInfo.modeId = 0;
	m_ModeInfo.width = m_nScreenWidth;
	m_ModeInfo.height = m_nScreenHeight;
	m_ModeInfo.Bpp = m_colorDepth;
	m_ModeInfo.frequency = 60;	// ?
	switch (m_colorDepth)
	{
		case	8:
			m_ModeInfo.format = gpe8Bpp;
			break;

		case	16:
			m_ModeInfo.format = gpe16Bpp;
			break;

		case	24:
			m_ModeInfo.format = gpe24Bpp;
			break;

		case	32:
			m_ModeInfo.format = gpe32Bpp;
			break;

		default:
			DEBUGMSG(GPE_ZONE_ERROR,(TEXT("Invalid BPP value passed to driver - %d\r\n"), m_ModeInfo.Bpp));
			m_ModeInfo.format = gpeUndefined;
			break;
	}
	m_pMode = &m_ModeInfo;

	// compute frame buffer displayable area offset
	offsetX = (m_cxPhysicalScreen - m_nScreenWidth) / 2;
	offsetY = (m_cyPhysicalScreen - m_nScreenHeight) / 2;
	fbOffset = (offsetY * m_cbScanLineLength) + offsetX;

	// compute physical frame buffer size
	fbSize = m_cyPhysicalScreen * m_cbScanLineLength;


	// it is a "dirty-rect" driver - we create a system memory bitmap to represent
	// the screen and refresh rectangles of this to the screen as they are altered
#ifdef	DD_ENABLE
	m_pPrimarySurface = new DDGPESurf( m_nScreenWidth, m_nScreenHeight, m_ModeInfo.format );
#else
	m_pPrimarySurface = new GPESurf( m_nScreenWidth, m_nScreenHeight, m_ModeInfo.format );
#endif

	m_VirtualFrameBuffer = (DWORD)m_pPrimarySurface->Buffer();
	
	memset ((void*)m_VirtualFrameBuffer, 0x0, fbSize);

	m_CursorVisible = FALSE;
	m_CursorDisabled = TRUE;
	m_CursorForcedOff = FALSE;
	v_CursorDrawnByCE = FALSE;
	memset (&m_CursorRect, 0x0, sizeof(m_CursorRect));
	m_CursorBackingStore = NULL;
	m_CursorXorShape = NULL;
	m_CursorAndShape = NULL;
	m_Sock = INVALID_SOCKET;

	if (m_noServer == 0) {
		HANDLE hThread;
		DWORD ThreadID;
		hThread = CreateThread (NULL, 0, Refresh, (LPVOID)this, 0, &ThreadID);
		CloseHandle (hThread);
	}
}

SCODE	GPECERem::SetMode (INT modeId, HPALETTE *palette)
{
	DEBUGMSG(GPE_ZONE_INIT,(TEXT("GPECERem::SetMode\r\n")));

	if (modeId != 0)
	{
		DEBUGMSG(GPE_ZONE_ERROR,(TEXT("GPECERem::SetMode Want mode %d, only have mode 0\r\n"),modeId));
		return	E_INVALIDARG;
	}

	if (palette)
	{
		switch (m_colorDepth)
		{
			case	8:
				*palette = EngCreatePalette (PAL_INDEXED,
											 PALETTE_SIZE,
											 (ULONG*)_rgbIdentity,
											 0,
											 0,
											 0);
				break;

			case	16:
			case	24:
			case	32:
				*palette = EngCreatePalette (PAL_BITFIELDS,
											 0,
											 NULL,
											 ((1 << m_RedMaskSize) - 1) << m_RedMaskPosition,
											 ((1 << m_GreenMaskSize) - 1) << m_GreenMaskPosition,
											 ((1 << m_BlueMaskSize) - 1) << m_BlueMaskPosition);
				break;
		}
	}

	return S_OK;
}

SCODE	GPECERem::GetModeInfo(GPEMode *mode,	INT modeNumber)
{
	DEBUGMSG (GPE_ZONE_INIT, (TEXT("GPECERem::GetModeInfo\r\n")));

	if (modeNumber != 0)
	{
		return E_INVALIDARG;
	}

	*mode = m_ModeInfo;

	return S_OK;
}

int		GPECERem::NumModes()
{
	DEBUGMSG (GPE_ZONE_INIT, (TEXT("GPECERem::NumModes\r\n")));
	return	1;
}

void	GPECERem::CursorOn (void)
{
	UCHAR	*ptrScreen = (UCHAR*)m_pPrimarySurface->Buffer();
	UCHAR	*ptrLine;
	UCHAR	*cbsLine;
	UCHAR	*xorLine;
	UCHAR	*andLine;
	int		x, y;

	if (v_CursorDrawnByCE && !m_CursorForcedOff && !m_CursorDisabled && !m_CursorVisible)
	{
		if (!m_CursorBackingStore)
		{
			DEBUGMSG (GPE_ZONE_ERROR, (TEXT("GPECERem::CursorOn - No backing store available\r\n")));
			return;
		}

		for (y = m_CursorRect.top; y < m_CursorRect.bottom; y++)
		{
			if (y < 0)
			{
				continue;
			}
			if (y >= m_nScreenHeight)
			{
				break;
			}

			ptrLine = &ptrScreen[y * m_pPrimarySurface->Stride()];
			cbsLine = &m_CursorBackingStore[(y - m_CursorRect.top) * (m_CursorSize.x * (m_colorDepth >> 3))];
			xorLine = &m_CursorXorShape[(y - m_CursorRect.top) * m_CursorSize.x];
			andLine = &m_CursorAndShape[(y - m_CursorRect.top) * m_CursorSize.x];

			for (x = m_CursorRect.left; x < m_CursorRect.right; x++)
			{
				if (x < 0)
				{
					continue;
				}
				if (x >= m_nScreenWidth)
				{
					break;
				}

				cbsLine[(x - m_CursorRect.left) * (m_colorDepth >> 3)] = ptrLine[x * (m_colorDepth >> 3)];
				ptrLine[x * (m_colorDepth >> 3)] &= andLine[x - m_CursorRect.left];
				ptrLine[x * (m_colorDepth >> 3)] ^= xorLine[x - m_CursorRect.left];
				if (m_colorDepth > 8)
				{
					cbsLine[(x - m_CursorRect.left) * (m_colorDepth >> 3) + 1] = ptrLine[x * (m_colorDepth >> 3) + 1];
					ptrLine[x * (m_colorDepth >> 3) + 1] &= andLine[x - m_CursorRect.left];
					ptrLine[x * (m_colorDepth >> 3) + 1] ^= xorLine[x - m_CursorRect.left];
					if (m_colorDepth > 16)
					{
						cbsLine[(x - m_CursorRect.left) * (m_colorDepth >> 3) + 2] = ptrLine[x * (m_colorDepth >> 3) + 2];
						ptrLine[x * (m_colorDepth >> 3) + 2] &= andLine[x - m_CursorRect.left];
						ptrLine[x * (m_colorDepth >> 3) + 2] ^= xorLine[x - m_CursorRect.left];
					}
				}
			}
		}
		m_CursorVisible = TRUE;
	}
}

void	GPECERem::CursorOff (void)
{
	UCHAR	*ptrScreen = (UCHAR*)m_pPrimarySurface->Buffer();
	UCHAR	*ptrLine;
	UCHAR	*cbsLine;
	int		x, y;

	if (v_CursorDrawnByCE && !m_CursorForcedOff && !m_CursorDisabled && m_CursorVisible)
	{
		if (!m_CursorBackingStore)
		{
			DEBUGMSG (GPE_ZONE_ERROR, (TEXT("GPECERem::CursorOff - No backing store available\r\n")));
			return;
		}

		for (y = m_CursorRect.top; y < m_CursorRect.bottom; y++)
		{
			// clip to displayable screen area (top/bottom)
			if (y < 0)
			{
				continue;
			}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?