?? drawyuv.cpp
字號:
vfDest.vfBitCount = 32;
break;
default:
vfDest.vfBitCount = 0; // No support
break;
}
if (vfDest.vfBitCount == 0) break;
m_dwBitCount = vfDest.vfBitCount;
// Create a converter
vfSource.vfWidth = vfDest.vfWidth = nWidth;
vfSource.vfHeight = vfDest.vfHeight = nHeight;
vfSource.vfBitCount = SOURCE_BIT_COUNT;
vfSource.vfFourCC = SOURCE_COLOR_SPACE;
vfDest.vfFourCC = BI_RGB;
m_pConverter = new Converter;
if (!m_pConverter) break;
if (!m_pConverter->Create(&vfSource, &vfDest)) break;
}
/***********************************/
/* Create a clipper for our window */
/***********************************/
ddrval = IDirectDraw_CreateClipper(m_lpDD, 0, &m_lpDDClipper, NULL);
if( ddrval != DD_OK ) break;
m_pDisplayWindow = new DisplayWindow;
if (!m_pDisplayWindow) break;
bRtn = m_pDisplayWindow->Create(lpszWindowName, dwStyle, x, y, nWidth, nHeight, hwndParent, fOverlay, m_lpDDSPrimary, m_lpDDClipper);
if (!bRtn) break;
ddrval = IDirectDrawClipper_SetHWnd(m_lpDDClipper, 0, m_pDisplayWindow->GetHwnd());
if( ddrval != DD_OK ) break;
if (!fOverlay)
{
ddrval = IDirectDrawSurface_SetClipper(m_lpDDSPrimary, m_lpDDClipper);
if (ddrval != DD_OK) break;
}
bSuccess = TRUE;
m_dwWidth = nWidth;
m_dwHeight = nHeight;
} while(0);
if (!bSuccess)
{
this->Close();
}
return bSuccess;
}
BOOL DrawYUV::Close()
{
if (m_pDisplayWindow)
{
m_bClosed = m_pDisplayWindow->Close();
delete m_pDisplayWindow;
m_pDisplayWindow = NULL;
}
if (m_pConverter)
{
delete m_pConverter;
m_pConverter = NULL;
}
SAFE_RELEASE(m_lpDDSOverlay);
SAFE_RELEASE(m_lpDDSBack);
SAFE_RELEASE(m_lpDDClipper);
SAFE_RELEASE(m_lpDDSPrimary);
SAFE_RELEASE(m_lpDD);
return TRUE;
}
BOOL DrawYUV::IsClose()
{
return m_bClosed;
}
BOOL DrawYUV::SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags)
{
if (m_pDisplayWindow)
{
return ::SetWindowPos(m_pDisplayWindow->GetHwnd(), hWndInsertAfter, x, y, cx, cy, uFlags);
}
return FALSE;
}
BOOL DrawYUV::Draw(LPBYTE lpBuffer, DWORD dwSize)
{
if (!lpBuffer || dwSize == 0) return FALSE;
LPBYTE lpOutput = NULL;
HRESULT ddrval;
RECT rectClient;// Window size and position
RECT rectDest;
DDOVERLAYFX ddofx;// Effects used in displaying the overlay
DWORD dwFlags;
int nTemp = 0;
POINT point;
point.x = 0;
point.y = 0;
if (m_pConverter)
{
if (!m_pConverter->Convert(lpBuffer, &lpOutput)) return FALSE;
}
SetRect(&rectDest, 0, 0, m_dwWidth, m_dwHeight);
DDSURFACEDESC ddsd;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
if (m_bIsOverlay)
{
ddrval = m_lpDDSOverlay->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
if (ddrval != DD_OK) return FALSE;
memcpy_MMX(ddsd.lpSurface, lpOutput == NULL ? lpBuffer : lpOutput, \
lpOutput == NULL ? dwSize : ((m_dwWidth * m_dwHeight * m_dwBitCount) >> 3));
m_lpDDSOverlay->Unlock(NULL);
/*************************/
/* Where is the window ? */
/*************************/
GetWindowRect(m_pDisplayWindow->GetHwnd(), &rectClient);
ddofx.dwSize = sizeof(DDOVERLAYFX);
ddofx.dckSrcColorkey.dwColorSpaceLowValue = DD_OVERLAY_COLORKEY_16BPP;
ddofx.dckSrcColorkey.dwColorSpaceHighValue = DD_OVERLAY_COLORKEY_16BPP;
ddofx.dckDestColorkey.dwColorSpaceLowValue = DD_OVERLAY_COLORKEY_16BPP;
ddofx.dckDestColorkey.dwColorSpaceHighValue = DD_OVERLAY_COLORKEY_16BPP;
dwFlags = DDOVER_SHOW | DDOVER_DDFX | DDOVER_KEYDESTOVERRIDE;
ddrval = IDirectDrawSurface_UpdateOverlay (m_lpDDSOverlay,
&rectDest,
m_lpDDSPrimary,
&rectClient,
dwFlags,
&ddofx);
}
else
{
ddrval = m_lpDDSBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
if (ddrval != DD_OK) return FALSE;
memcpy_MMX(ddsd.lpSurface, lpOutput, ((m_dwWidth * m_dwHeight * m_dwBitCount) >> 3));
m_lpDDSBack->Unlock(NULL);
::GetClientRect(m_pDisplayWindow->GetHwnd(), &rectClient);
::ClientToScreen(m_pDisplayWindow->GetHwnd(), &point);
nTemp = rectClient.right - rectClient.left;
rectClient.left = point.x;
rectClient.right = point.x + nTemp;
nTemp = rectClient.bottom - rectClient.top;
rectClient.top = point.y;
rectClient.bottom = point.y + nTemp;
ddrval = m_lpDDSPrimary->Blt(&rectClient, m_lpDDSBack, &rectDest, DDBLT_WAIT, NULL);
}
return ddrval == DD_OK;
}
BOOL DrawYUV::ShowWindow(int nCmdShow)
{
if (m_pDisplayWindow)
{
return ::ShowWindow(m_pDisplayWindow->GetHwnd(), nCmdShow);
}
return FALSE;
}
BOOL DrawYUV::AreOverlaysSupported()
{
DDCAPS capsDrv;
HRESULT ddrval;
memset (&capsDrv, 0, sizeof(capsDrv));
capsDrv.dwSize = sizeof(capsDrv);
ddrval = this->m_lpDD->GetCaps(&capsDrv, NULL);
if (ddrval != DD_OK)
{
return FALSE;
}
if (!(capsDrv.dwCaps & DDCAPS_OVERLAY))
{
return FALSE;
}
return TRUE;
}
void DrawYUV::memcpy_MMX( void *dest, const void *src, unsigned int nbytes )
{
__asm
{
MOV ESI, src ;; pointer to src, DWORD aligned
MOV EDI, dest ;; pointer to dst, DWORD aligned
MOV ECX, nbytes ;; number of bytes to copy
MOV EDX, ECX ;; backup number of bytes
CMP ECX, 4 ;; less than one DWORD to copy ?
JB $copybyte2_cc ;; yes, must be no DWORDs to copy, maybe bytes
SHR ECX, 2 ;; number of DWORDs to copy
TEST EDI,7 ;; dst QWORD aligned?
JZ $dstqaligned2_cc ;; yes
MOVD MM0,[ ESI ] ;; read one DWORD from src
MOVD [EDI ] ,MM0 ;; store one DWORD to dst
ADD ESI,4 ;; src++
ADD EDI,4 ;; dst++
DEC ECX ;; number of DWORDs to copy
$dstqaligned2_cc:
MOV EBX,ECX ;; number of DWORDs to copy
SHR ECX,4 ;; number of cache lines to copy
JZ $copyqwords2_cc ;; no whole cache lines to copy, maybe QWORDs
ALIGN 16 ;; align loop for optimal performance
$cloop2_cc:
MOVQ MM0,[ ESI ] ;; load first QWORD in cache line from src
ADD EDI,64 ;; src++
MOVQ MM1,[ ESI+8 ] ;; load second QWORD in cache line from src
ADD ESI,64 ;; dst++
MOVQ MM2,[ ESI-48 ] ;; load third QWORD in cache line from src
MOVQ [EDI-64 ] ,MM0 ;; store first DWORD in cache line to dst
MOVQ MM0,[ ESI-40 ] ;; load fourth QWORD in cache line from src
MOVQ [EDI-56 ] ,MM1 ;; store second DWORD in cache line to dst
MOVQ MM1,[ ESI-32 ] ;; load fifth QWORD in cache line from src
MOVQ [EDI-48 ] ,MM2 ;; store third DWORD in cache line to dst
MOVQ MM2,[ ESI-24 ] ;; load sixth QWORD in cache line from src
MOVQ [EDI-40 ] ,MM0 ;; store fourth DWORD in cache line to dst
MOVQ MM0,[ ESI-16 ] ;; load seventh QWORD in cache line from src
MOVQ [EDI-32 ] ,MM1 ;; store fifth DWORD in cache line to dst
MOVQ MM1,[ ESI-8 ] ;; load eight QWORD in cache line from src
MOVQ [EDI-24 ] ,MM2 ;; store sixth DWORD in cache line to dst
MOVQ [EDI-16 ] ,MM0 ;; store seventh DWORD in cache line to dst
DEC ECX ;; count--
MOVQ [EDI-8 ] ,MM1 ;; store eighth DWORD in cache line to dst
JNZ $cloop2_cc ;; until no more cache lines to copy
$copyqwords2_cc:
MOV ECX,EBX ;; number of DWORDs to copy
AND EBX,0xE ;; number of QWORDS left to copy *2
SHR EBX, 1 ;; number of QWORDS left to copy
JZ $copydword2_cc ;; no QWORDs left, maybe DWORD left
ALIGN 16 ;; align loop for optimal performance
$qloop2_cc:
MOVQ MM0, [ESI] ;; read QWORD from src
MOVQ [EDI], MM0 ;; store QWORD to dst
ADD ESI,8 ;; src++
ADD EDI,8 ;; dst++
SUB EBX,1 ;; count--
JNZ $qloop2_cc ;; until no more QWORDs left to copy
$copydword2_cc:
TEST ECX, 1 ;; DWORD left to copy ?
JZ $copybyte2_cc ;; nope, but maybe bytes left
MOVD MM0, [ESI] ;; read last DWORD from src
MOVD [EDI], MM0 ;; store last DWORD to dst
ADD ESI, 4 ;; 4 bytes read
ADD EDI, 4 ;; 4 bytes written
$copybyte2_cc:
AND EDX, 0x3 ;; number of bytes left to copy
JZ $copydone2_cc ;; no bytes left, we're done
$bloop2_cc:
MOV AH,BYTE PTR [ESI]
MOV BYTE PTR [EDI],AH
ADD ESI,1 ;; src++
ADD EDI,1 ;; dst++
SUB EDX,1 ;; count--
JNZ $bloop2_cc ;; until no more bytes left to copy
$copydone2_cc:
EMMS ;; clear MMX state
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -