📄 winsurf2.cpp
字号:
void CWinSurface2::_CreateBuffer()
{
if (m_hRenThread)
{
WaitForSingleObject(m_hSurfaceMutex, INFINITE);
EnterCriticalSection(&m_csDisplay);
}
CWinSurface::_CreateBuffer();
BOOL bCreated = FALSE;
if (m_surface.fMode & WINDRAW_DIRECTDRAW)
{
bCreated = (m_surface.dd.lpDDSurface != NULL);
}
else
{
bCreated = (m_surface.gdi.lpGDIBackBuffer[0] != NULL);
}
if (bCreated)
{
if (m_hRenThread)
{
// We create our surface, start servicing GetVidMem calls
SetEvent(m_hReinit);
}
}
if (m_hRenThread)
{
ReleaseMutex(m_hSurfaceMutex);
LeaveCriticalSection(&m_csDisplay);
}
}
HX_RESULT CWinSurface2::_CreateOverlay(BOOL bOverlay, int cid, int x, int y)
{
if (m_hRenThread)
{
WaitForSingleObject(m_hSurfaceMutex, INFINITE);
EnterCriticalSection(&m_csDisplay);
}
HX_RESULT hr = CWinSurface::_CreateOverlay(bOverlay, cid, x, y);
if (HXR_OK == hr && m_hRenThread)
{
// We created our surface, start servicing GetVidMem calls
SetEvent(m_hReinit);
}
if (m_hRenThread)
{
LeaveCriticalSection(&m_csDisplay);
ReleaseMutex(m_hSurfaceMutex);
}
return hr;
}
HX_RESULT
CWinSurface2::ByPassCompositionSurface(UCHAR* pImageData,
HXBitmapInfoHeader* pBitmapInfo,
REF(HXxRect) rDestRect,
REF(HXxRect) rSrcRect,
UCHAR* pSurface,
INT32 nSurfPitch)
{
// Check for vidsurf2-only dest surfaces
if (CID_I420 == GETBITMAPCOLOR( pBitmapInfo) &&
m_pHwMemObj)
{
HXxSize srcSize = {pBitmapInfo->biWidth, pBitmapInfo->biHeight};
UCHAR* pYUV[3] = {pImageData,
pYUV[0] + pBitmapInfo->biHeight*nSurfPitch,
pYUV[1] + pBitmapInfo->biHeight*nSurfPitch/4};
INT32 nYUVPitch[3] = {nSurfPitch, nSurfPitch/2, nSurfPitch/2};
SourceInputStruct input = {pYUV, nYUVPitch, 3};
INT32 nPitch;
UCHAR* pVidMem =
(UCHAR*)m_pHwMemObj->DeviceToRenderer(pImageData,
nPitch,
WRITE_VIDEO_TO_STRUCT);
AlignRect(&rSrcRect, pBitmapInfo->biWidth, pBitmapInfo->biHeight);
AlignRect(&rDestRect, m_surfaceSize.cx, m_surfaceSize.cy);
HX_RESULT hr =
ColorConvert(MapCIDtoFourCC(GETBITMAPCOLOR(pBitmapInfo)),
&srcSize, &rSrcRect,
&input, MapCIDtoFourCC(m_nSurfaceCID), pVidMem,
&m_surfaceSize, &rDestRect, nSurfPitch);
m_pHwMemObj->RendererToDevice(pVidMem);
return hr;
}
return CWinSurface::ByPassCompositionSurface(pImageData,
pBitmapInfo,
rDestRect,
rSrcRect,
pSurface,
nSurfPitch);
}
void CWinSurface2::_ReleaseSurface(CBaseRootSurface* pSurface)
{
if (m_hRenThread)
{
Flush();
// Make the next GetVidMem wait on new surface creation
WaitForSingleObject(m_hSurfaceMutex, INFINITE);
ResetEvent(m_hReinit);
Flush();
EnterCriticalSection(&m_csDisplay);
}
WINDRAW* pWindraw = ((CWinBaseRootSurface*)pSurface)->GetWinDraw();
DestroyFallbackSurface();
DestroyGdiSurface();
CWinSurface::_ReleaseSurface(pSurface);
memset(&m_lastSrcRect, 0, sizeof(m_lastSrcRect));
if (m_hRenThread)
{
LeaveCriticalSection(&m_csDisplay);
ReleaseMutex(m_hSurfaceMutex);
}
m_dLastXScale = 0.0;
m_dLastYScale = 0.0;
}
void CWinSurface2::_ReleaseSurface(CWinBaseRootSurface* pSurface)
{
if (m_hRenThread)
{
Flush();
// Make the next GetVidMem wait on new surface creation
WaitForSingleObject(m_hSurfaceMutex, INFINITE);
ResetEvent(m_hReinit);
Flush();
EnterCriticalSection(&m_csDisplay);
}
WINDRAW* pWindraw = pSurface->GetWinDraw();
DestroyFallbackSurface();
DestroyGdiSurface();
CWinSurface::_ReleaseSurface(pSurface);
memset(&m_lastSrcRect, 0, sizeof(m_lastSrcRect));
if (m_hRenThread)
{
LeaveCriticalSection(&m_csDisplay);
ReleaseMutex(m_hSurfaceMutex);
}
m_dLastXScale = 0.0;
m_dLastYScale = 0.0;
}
void CWinSurface2::_ReleaseSurface()
{
if (m_hRenThread)
{
Flush();
// Make the next GetVidMem wait on new surface creation
WaitForSingleObject(m_hSurfaceMutex, INFINITE);
ResetEvent(m_hReinit);
Flush();
EnterCriticalSection(&m_csDisplay);
}
CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
if (pSurface)
{
WINDRAW* pWindraw = pSurface->GetWinDraw();
if (pWindraw)
{
DestroyFallbackSurface();
DestroyGdiSurface();
memset(&m_lastSrcRect, 0, sizeof(m_lastSrcRect));
CWinSurface::_ReleaseSurface();
}
}
if (m_hRenThread)
{
LeaveCriticalSection(&m_csDisplay);
ReleaseMutex(m_hSurfaceMutex);
}
m_dLastXScale = 0.0;
m_dLastYScale = 0.0;
}
void CWinSurface2::ReInitSurfaces()
{
if ( (m_surface.fMode & WINDRAW_DIRECTDRAW) && m_surface.dd.lpDDSurface && m_bVideoSurface2)
{
return;
}
// Set yuv priority for vidsurf2 mode
if (m_hRenThread)
{
// Lock the surface mutex
WaitForSingleObject(m_hSurfaceMutex, INFINITE);
m_pSite->_TLSLock();
int cid = GetBitmapColor((LPBITMAPINFO)m_pOptimizedFormat);
BOOL bRestore = SetYUVPriorityList(cid);
m_nBackBufferCount = m_nOverlayBackBuffersCreated;
CWinSurface::ReInitSurfaces();
if (bRestore)
RestoreColorspacePriorities(cid);
// We switched to a mode that does not support overlay...yikes!
if (m_bVideoSurface2 &&
(m_nBltMode != HX_OVERLAY_BLT || !m_nBackBufferCount))
{
m_bMultipleOverlay = TRUE;
ForceGDIMode(TRUE);
}
else
{
m_bMultipleOverlay = FALSE;
}
HXxSize rcSize = m_surfaceSize;
CreateFallbackSurface(m_nSurfaceCID, &rcSize);
m_pSite->_TLSUnlock();
ResetBufferTimes(0);
ReleaseMutex(m_hSurfaceMutex);
}
else
CWinSurface::ReInitSurfaces();
}
BOOL CWinSurface2::_IsDisplaySurfaceYuv()
{
if (!m_bVideoSurface2)
return CWinSurface::_IsDisplaySurfaceYuv();
return IsYUV(MapFourCCtoCID(m_bmi.biCompression));
}
BOOL CWinSurface2::_AllowsOverlayShrinking()
{
if (m_bSurfaceRequiresOverlay)
return TRUE;
else
return CWinSurface::_AllowsOverlayShrinking();
}
void CWinSurface2::_WaitForQueuedFrames()
{
WaitForQueuedFrames();
}
void CWinSurface2::_LockBlitter()
{
if (m_hSurfaceMutex)
{
// In the unlikely event that all of our hw buffers are
// full AND GetVideoMem is blocking with m_hSurfaceMutex
// while waiting for the time line to start, break
// out of the time line wait loop.
BOOL bOldValue = m_bWaitingForFlush;
m_bWaitingForFlush = TRUE;
WaitForSingleObject(m_hSurfaceMutex, INFINITE);
m_bWaitingForFlush = bOldValue;
}
}
void CWinSurface2::_UnlockBlitter()
{
if (m_hSurfaceMutex)
ReleaseMutex(m_hSurfaceMutex);
}
void CWinSurface2::_FlushSurfaces()
{
Flush();
}
STDMETHODIMP CWinSurface2::SetProperties(HXBitmapInfoHeader* bmi,
REF(UINT32) ulNumBuffers,
IHXRenderTimeLine* pTimeLine)
{
// Block GetVideoMem calls
WaitForSingleObject(m_hSurfaceMutex, INFINITE);
ulNumBuffers = min(m_nMaxBackBuffers+1, (INT32)ulNumBuffers);
CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
if (!pSurface)
{
ReleaseMutex(m_hSurfaceMutex);
return HXR_FAIL;
}
WINDRAW* pWindraw = pSurface->GetWinDraw();
// If we already have surfaces, destroy and recreate if necessary
if (m_hRenThread)
{
if (bmi->biWidth != m_bmi.biWidth ||
bmi->biHeight != m_bmi.biHeight ||
m_surface.dwBackBufferCount == 0 ||
ulNumBuffers != (UINT32)m_nBackBufferCount+1 ||
WAIT_OBJECT_0 != WaitForSingleObject(m_hReinit, 0))
{
// Wait for display buffers to render
if (HXR_OK != WaitForQueuedFrames())
Flush();
DestroySurfaces();
m_nBackBufferCount = 0;
memset(&m_bmi, 0, sizeof(m_bmi));
memset(&m_lastSrcRect, 0, sizeof(m_lastSrcRect));
}
else
{
HX_RELEASE(m_pTimeLine);
m_pTimeLine = pTimeLine;
if (m_pTimeLine)
m_pTimeLine->AddRef();
m_bVideoSurface2 = TRUE;
// If we are keeping our existing video buffers, reset
// the flipping chain indexes if we have DirectDraw.
if (!m_bLostHWAcceleration)
WinDraw_ResetSurfaceIndexes(pWindraw, &m_surface);
ReleaseMutex(m_hSurfaceMutex);
return HXR_OK;
}
}
// If we do not have a render thread and we have an optimized
// format, we are in VS1 mode so fail the VS2 init.
else if (m_pOptimizedFormat)
{
ReleaseMutex(m_hSurfaceMutex);
return HXR_FAIL;
}
// Try and create an overlay flpping chain of pRequest->nNumBuffers buffers
m_nBackBufferCount = ulNumBuffers - 1;
if (m_nBackBufferCount)
m_bFlipOverlay = TRUE;
m_bSpamUpdateOverlay = FALSE;
int cid = GetBitmapColor((LPBITMAPINFO)bmi);
BOOL bRestore = SetYUVPriorityList(cid);
BeginOptimizedBlt(bmi);
int nBltMode = m_nBltMode;
if (bRestore)
RestoreColorspacePriorities(cid);
if (nBltMode != HX_OVERLAY_BLT ||
!m_nBackBufferCount)
{
DestroySurfaces();
ulNumBuffers = 0;
m_bVideoSurface2 = FALSE;
ReleaseMutex(m_hSurfaceMutex);
return HXR_FAIL;
}
m_nOverlayBackBuffersCreated = m_nBackBufferCount;
bmi->biCompression = MapCIDtoFourCC(m_nSurfaceCID);
// How odd, a dd driver that returns the wrong caps.
// I have not seen anything like since the last time I tried
// to use the caps.
//
// We will always try interval flips and swith to flip
// waits if flip returns an error.
#if DIRECTDRAW_VERSION > 0x0500
// Can we use the flip interval flag
if ((pWindraw->dd.m_caps.dwCaps2 & DDCAPS2_FLIPINTERVAL) != DDCAPS2_FLIPINTERVAL)
{
m_bUseVBlankFlip = FALSE;
}
#else
m_bUseVBlankFlip = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -