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 + -
显示快捷键?