winsurf2.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:134k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: winsurf2.cpp,v 1.23.2.2 2004/07/26 10:28:48 pankajgupta Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxtypes.h"
- #include <math.h>
- #include "ddraw.h"
- #include "hxcom.h"
- #include "hxwintyp.h"
- #include "hxvsurf.h"
- #include "hxslist.h"
- #include "ddhlpr.h"
- #include "winsurf.h"
- #include "vidsurf2.h"
- #include "winsurf2.h"
- #include "winsite.h"
- #include "colormap.h"
- #include "windraw2.h"
- #include "hxprefs.h"
- #include "hxtick.h"
- #include "hxheap.h"
- #include "hxevent.h"
- #include "hwmemobj.h"
- // these are defined in basesurf.cpp and should probably be moved to a .h file
- #define HX_OVER_KEYDEST 1
- #define HX_OVER_HIDE 2
- #define HX_OVER_SHOW 4
- #define OVERLAY_NOT_VISIBLE 0
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #include "winthrd.h"
- #endif
- #define OS_THREAD_QUANTUM 10
- #define MAX_PREEMPTION_CHECK_ATTEMPTS 3
- #define TIME_JITTER_FILTER_THRESHOLD 0.45
- #define MIN_ALLOWED_REGRESSION 0.95
- //#define HARDCODE_GRANULE
- #define SCHEDULE_GRANULE 5
- //#define LOG_JITTER_DATA
- #define JITTER_LOG_FILE "c:\temp\ts.txt"
- /****************************************************************************
- * Debug
- */
- //#define ENABLE_SYNC_TRACE
- #ifdef ENABLE_SYNC_TRACE
- #define MAX_SYNC_TRACE_ENTRIES 10000
- ULONG32 ulSyncTraceIdx = 0;
- double syncTraceArray[MAX_SYNC_TRACE_ENTRIES][3];
- void DumpSyncEntries(void)
- {
- FILE* pFile = NULL;
- ULONG32 ulIdx;
- if (ulSyncTraceIdx > 0)
- {
- pFile = fopen("/tmp/getscanline.txt", "wb"); /* Flawfinder: ignore */
- }
- if (pFile)
- {
- for (ulIdx = 0; ulIdx < (ulSyncTraceIdx < MAX_SYNC_TRACE_ENTRIES ?
- ulSyncTraceIdx : MAX_SYNC_TRACE_ENTRIES); ulIdx++)
- {
- fprintf(pFile, "%lft%lft%lfn", syncTraceArray[ulIdx][0],
- syncTraceArray[ulIdx][1],
- syncTraceArray[ulIdx][2]
- );
- }
- fclose(pFile);
- }
- ulSyncTraceIdx = 0;
- }
- #endif // ENABLE_SYNC_TRACE
- //#define ENABLE_ERROR_TRACE
- #ifdef ENABLE_ERROR_TRACE
- #define MAX_ERROR_TRACE_ENTRIES 10000
- double g_error[MAX_ERROR_TRACE_ENTRIES][3];
- double g_alternateError[MAX_ERROR_TRACE_ENTRIES];
- ULONG32 g_ulFrameCount;
- UINT32 g_sleepError[MAX_ERROR_TRACE_ENTRIES];
- ULONG32 g_ulSleepCount;
- void DumpErrorEntries(void)
- {
- FILE* pFile = NULL;
- ULONG32 ulIdx;
- if (g_ulFrameCount > 0)
- {
- pFile = fopen("/tmp/vblankerror.txt", "wb"); /* Flawfinder: ignore */
- }
- if (pFile)
- {
- for (ulIdx = 0; ulIdx < (g_ulFrameCount < MAX_SYNC_TRACE_ENTRIES ?
- g_ulFrameCount : MAX_SYNC_TRACE_ENTRIES); ulIdx++)
- {
- fprintf(pFile, "%lft%lft%lfn", g_error[ulIdx][0],
- g_error[ulIdx][1],
- g_error[ulIdx][2]);
- }
- fclose(pFile);
- }
- g_ulFrameCount = 0;
- }
- #endif // ENABLE_ERROR_TRACE
- // Using "this" in constructor initialzer
- #pragma warning(disable:4355)
- CWinSurface2::CWinSurface2(IUnknown* pContext, CHXBaseSite* pSite)
- : CWinSurface(pContext,pSite)
- , CVideoSurface2((IUnknown*)(IHXVideoSurface*)this)
- , m_hRenThread(0)
- , m_hFrameSem(0)
- , m_hReinit(0)
- , m_hAbort(0)
- , m_hForceRender(0)
- , m_hSurfaceMutex(0)
- , m_bCont(FALSE)
- , m_bBoostRenderThread(TRUE)
- , m_bDoAlphaCheck(TRUE)
- , m_bQueryMonitorFreq(FALSE)
- , m_bUseVBlankFlip(TRUE)
- , m_bIngnorePresentIfReady(FALSE)
- , m_bScratchSurface(FALSE)
- , m_bGDISurface(FALSE)
- , m_nScratchIndex(0)
- , m_nLastDisplayTime(0)
- , m_pListOfFrames(NULL)
- , m_pTimeLine(NULL)
- , m_hFallbackEmpty(0)
- , m_nFallbackSurfaceCID(0)
- , m_bFallbackSurfaceCreated(FALSE)
- , m_pSysMemSurf(NULL)
- , m_nSysMemSurfSize(0)
- , m_nSysMemSurfCount(0)
- , m_nSysMemSurfPitch(0)
- , m_nSysMemSurfID(0)
- , m_nNextSysMemBuffer(0)
- , m_bUseSysMemSurface(FALSE)
- , m_nGdiSurfaceCount(0)
- , m_nLastGdiSurface(-1)
- , m_nNextGdiSurface(0)
- , m_nGdiSurfaceCID(0)
- , m_bGdiSurfaceCreated(FALSE)
- , m_ulFillColoryKeyCount(0)
- , m_bFlushing(FALSE)
- , m_bFrameHasHWAlphaBlend(FALSE)
- , m_bSurfaceRequiresOverlay(FALSE)
- , m_bSwitchingingOverlay(FALSE)
- , m_bUseDDColorControls(FALSE)
- , m_bWaitingForFlush(FALSE)
- , m_bWasInVidSurf2(FALSE)
- , m_dLastXScale(0.0)
- , m_dLastYScale(0.0)
- , m_nOverlayBackBuffersCreated(0)
- , m_dLastBlitError(0)
- {
- // initialize data so we don't have invalid ptrs floating around.
- memset(&m_surface,0,sizeof(m_surface));
- memset(&m_GDIsurface,0,sizeof(m_GDIsurface));
- memset(&m_fallbackSurface,0,sizeof(m_fallbackSurface));
- memset(&m_allocatedFallbackSize, 0, sizeof(m_allocatedFallbackSize));
- memset(&m_allocatedSysMemSurfSize, 0, sizeof(m_allocatedSysMemSurfSize));
- memset(&m_allocatedFallbackSize, 0, sizeof(m_allocatedFallbackSize));
- memset(&m_rcLast, 0, sizeof(m_rcLast));
- InitializeCriticalSection(&m_csDisplay);
- InitializeCriticalSection(&m_csFallback);
- InitializeCriticalSection(&m_csList);
- InitializeCriticalSection(&m_csScale);
- m_hAbort = CreateEvent(NULL, TRUE, FALSE, NULL);
- m_hForceRender = CreateEvent(NULL, TRUE, FALSE, NULL);
- m_hReinit = CreateEvent(NULL, TRUE, TRUE, NULL);
- m_hFallbackEmpty = CreateEvent(NULL, TRUE, TRUE, NULL);
- m_hSurfaceMutex = CreateMutex(NULL, FALSE, NULL);
- m_pListOfFrames = new CHXSimpleList;
- // Read some preferences
- IHXPreferences* pPreferences = NULL;
- IHXBuffer* pBuffer = NULL;
- if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
- {
- // Use vblank flags for flipping
- if (pPreferences->ReadPref("VideoBoost\DisableVBlankFlip", pBuffer) == HXR_OK)
- {
- m_bUseVBlankFlip = !(::atoi((char*) pBuffer->GetBuffer()) == 1);
- }
- HX_RELEASE(pBuffer);
- // Turn-off render thread priority boosting
- if (pPreferences->ReadPref("VideoBoost\DisablePriorityBoost", pBuffer) == HXR_OK)
- {
- m_bBoostRenderThread = !(::atoi((char*) pBuffer->GetBuffer()) == 1);
- }
- HX_RELEASE(pBuffer);
- // Limit number of hw buffers
- if (pPreferences->ReadPref("VideoBoost\MaxBuffers", pBuffer) == HXR_OK)
- {
- m_nMaxBackBuffers = ::atoi((char*) pBuffer->GetBuffer()) - 1;
- m_nMaxBackBuffers = max(1, m_nMaxBackBuffers);
- }
- HX_RELEASE(pBuffer);
- }
- HX_RELEASE(pPreferences);
- }
- CWinSurface2::~CWinSurface2()
- {
- if (m_hRenThread)
- {
- m_bCont = FALSE;
- SetEvent(m_hAbort);
- WaitForSingleObject(m_hRenThread, INFINITE);
- CloseHandle(m_hFrameSem);
- m_hFrameSem = 0;
- CloseHandle(m_hRenThread);
- m_hRenThread = 0;
- DestroyFallbackSurface();
- DestroySysMemSurface();
- DestroyGdiSurface();
- }
- if (m_hAbort)
- {
- CloseHandle(m_hAbort);
- m_hAbort = 0;
- }
- if (m_hForceRender)
- {
- CloseHandle(m_hForceRender);
- m_hForceRender = 0;
- }
- if (m_hReinit)
- {
- CloseHandle(m_hReinit);
- m_hReinit = 0;
- }
- if (m_hFallbackEmpty)
- {
- CloseHandle(m_hFallbackEmpty);
- m_hFallbackEmpty = NULL;
- }
- if (m_hSurfaceMutex)
- {
- CloseHandle(m_hSurfaceMutex);
- m_hSurfaceMutex = 0;
- }
- HX_DELETE(m_pListOfFrames);
- DeleteCriticalSection(&m_csDisplay);
- DeleteCriticalSection(&m_csFallback);
- DeleteCriticalSection(&m_csList);
- DeleteCriticalSection(&m_csScale);
- HX_RELEASE(m_pTimeLine);
- }
- STDMETHODIMP CWinSurface2::QueryInterface(REFIID riid, void** ppvObj)
- {
- if (IsEqualIID(riid, IID_IHXVideoSurface2))
- {
- return CVideoSurface2::QueryInterface(riid, ppvObj);
- }
- return CWinSurface::QueryInterface(riid, ppvObj);
- }
- STDMETHODIMP_(ULONG32) CWinSurface2::AddRef()
- {
- return CWinSurface::AddRef();
- }
- STDMETHODIMP_(ULONG32) CWinSurface2::Release()
- {
- return CWinSurface::Release();
- }
- STDMETHODIMP CWinSurface2::BeginOptimizedBlt(HXBitmapInfoHeader* pBitmapInfo)
- {
- if (m_bWasInVidSurf2 &&
- pBitmapInfo &&
- m_pOptimizedFormat)
- {
- // Are the new parameters the same as the old paramaters? If not
- // then delete the old surfaces.
- if (pBitmapInfo->biWidth != m_pOptimizedFormat->biWidth ||
- pBitmapInfo->biHeight != m_pOptimizedFormat->biHeight ||
- pBitmapInfo->biPlanes != m_pOptimizedFormat->biPlanes ||
- pBitmapInfo->biBitCount != m_pOptimizedFormat->biBitCount ||
- pBitmapInfo->biCompression != m_pOptimizedFormat->biCompression ||
- m_bWasInVidSurf2)
- {
- if (m_bWasInVidSurf2)
- _WaitForFlush();
- DestroySurfaces();
- if (m_bWasInVidSurf2)
- {
- m_bVideoSurface2 = FALSE;
- m_bFlipOverlay = FALSE;
- m_nBackBufferCount = 0;
- }
- }
- }
- return CWinSurface::BeginOptimizedBlt(pBitmapInfo);
- }
- STDMETHODIMP CWinSurface2::Blt( UCHAR* pImageData,
- HXBitmapInfoHeader* pBitmapInfo,
- REF(HXxRect) rDestRect,
- REF(HXxRect) rSrcRect)
- {
- m_pSite->_TLSLock();
- // Handle VS2->VS1 transions
- if (m_bWasInVidSurf2)
- {
- if (!m_pSite->_BordersActive() &&
- !m_pSite->_FadeTransitionActive() &&
- (!m_pSite->AreVideoControlsActive() || m_bUseDDColorControls) &&
- !m_pSite->IsHigherZOrderTranstitionActive() &&
- m_pSite->m_pUser && !m_LinkedSites.GetCount() &&
- !m_pLinkedOverlay)
- {
- HXxEvent event = {HX_SURFACE_MODE_CHANGE, NULL, NULL,
- (void*)HX_VIDEOSURFACE1_NOT_RECOMMENDED, 0, 0};
- m_bWasInVidSurf2 = FALSE;
- // If we just turned off color controls inform the color converter
- m_pSite->CheckColorSettings();
- m_pSite->m_pUser->HandleEvent(&event);
- // The renderer switched to VideoSurface1 so don't give them a buffer
- if (event.handled)
- {
- m_pSite->_TLSUnlock();
- return HXR_FAIL;
- }
- else
- m_bWasInVidSurf2 = TRUE;
- }
- else if (m_bVideoSurface2)
- {
- m_pSite->_TLSUnlock();
- _WaitForFlush();
- m_bVideoSurface2 = FALSE;
- m_pSite->_TLSLock();
- }
- }
- HX_RESULT hr = CWinSurface::Blt(pImageData, pBitmapInfo, rDestRect, rSrcRect);
- m_pSite->_TLSUnlock();
- return hr;
- }
- 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;
- #endif
- if (pWindraw->dwMaxScanLine && pWindraw->dMsPerVBlank > 0.0)
- m_bOptimalVideoScheduler = TRUE;
- // If we are using a DirectDraw surface represented by a structure,
- // several of our post-processing functions will not work. Set the
- // various modes here. While we are generalizing here, most of
- // these surface types are proprietary so disable anything suspicious.
- if (IsStructured(m_nSurfaceCID))
- {
- m_bUseDDColorControls = TRUE;
- m_bSurfaceRequiresOverlay = TRUE;
- // Set default DD color controls
- m_Brightness = DEF_BRIGHTNESS;
- m_Contrast = DEF_CONTRAST;
- m_Saturation = DEF_SATURATION;
- m_Hue = DEF_HUE;
- m_Sharpness = DEF_SHARPNESS;
- }
- else
- {
- m_bUseDDColorControls = FALSE;
- m_bSurfaceRequiresOverlay = FALSE;
- }
- memset(&m_rcLast, 0, sizeof(m_rcLast));
- // Store actual settings
- m_bmi = *bmi;
- // for _ConstructRects
- m_bmiLastBlt = m_bmi;
- m_bVideoSurface2 = TRUE;
- // Schedule a recompute clip after I set m_bmiLastBlt to remove
- // deafault alpha site. This prevents us from playing in alpha
- // blending mode for local clips.
- if(m_pSite->m_pTopLevelSite)
- m_pSite->m_pTopLevelSite->ScheduleCallback(CLIP, 0);
- m_bmi.biSizeImage = m_nDDSurfaceSize;
- m_bmi.biWidth = m_surfaceSize.cx;
- m_bmi.biHeight = m_surfaceSize.cy;
- m_bmi.biCompression = m_nSurfaceCID;
- ulNumBuffers = m_nBackBufferCount+1;
- #ifdef _DEBUG
- char szTmp[128]; /* Flawfinder: ignore */
- char acid[5][5] = {{"I420"}, {"YV12"}, {"YVU9"}, {"YUY2"}, {"UYVY"}}; /* Flawfinder: ignore */
- char dvpf[5] = "DVPF"; /* Flawfinder: ignore */
- char *pCurrent = dvpf;
- if (m_nSurfaceCID < 5)
- pCurrent = acid[m_nSurfaceCID];
- wsprintf(szTmp, "SetProperties Create %ld %s buffersn", ulNumBuffers, pCurrent);
- OutputDebugString(szTmp);
- #endif
- HXxSize rcSize = {m_bmi.biWidth, m_bmi.biHeight};
- CreateFallbackSurface(m_nSurfaceCID, &rcSize);
- // Kill render thread if running
- if (m_hRenThread)
- {
- m_bCont = FALSE;
- SetEvent(m_hAbort);
- WaitForSingleObject(m_hRenThread, INFINITE);
- CloseHandle(m_hRenThread);
- m_hRenThread = 0;
- CloseHandle(m_hFrameSem);
- m_hFrameSem = 0;
- }
- HX_RELEASE(m_pTimeLine);
- m_pTimeLine = pTimeLine;
- if (m_pTimeLine)
- m_pTimeLine->AddRef();
- // Create the render thread
- DWORD dwId;
- m_bCont = TRUE;
- ResetEvent(m_hAbort);
- m_hFrameSem = CreateSemaphore(NULL, 0, ulNumBuffers+1, NULL);
- m_hRenThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE )ThreadProc,
- this, 0, &dwId);
- if (m_bBoostRenderThread)
- SetThreadPriority(m_hRenThread, THREAD_PRIORITY_TIME_CRITICAL);
- ReleaseMutex(m_hSurfaceMutex);
- return HXR_OK;
- }
- BOOL CWinSurface2::SetYUVPriorityList(int cidIn)
- {
- IHXPreferences* pPreferences = NULL;
- IHXBuffer* pBuffer = NULL;
- BOOL bUsePriorityScheme = TRUE;
- BOOL bRestore = FALSE;
- BOOL bUseHWPF = FALSE;
- if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
- {
- // Disalbe our surface priority scheme?
- if (pPreferences->ReadPref("VideoBoost\DisableSurfacePriority", pBuffer) == HXR_OK)
- {
- bUsePriorityScheme = !(::atoi((char*) pBuffer->GetBuffer()) == 1);
- }
- HX_RELEASE(pBuffer);
- HX_RELEASE(pPreferences);
- }
- // Set the priority for the yuv format we use
- if (bUsePriorityScheme)
- {
- int aList[5] = {0,0,0,0,0};
- int *pList = aList;
- int nListSize = 5;
- bRestore = FALSE;
- if (NOERROR == WinDraw2_GetColorspacePriorities(cidIn, pList, nListSize) && nListSize)
- {
- SetColorspacePriorities(aList, nListSize, cidIn);
- bRestore = TRUE;
- }
- }
- return bRestore;
- }
- STDMETHODIMP CWinSurface2::GetVideoMem(VideoMemStruct* pVidStruct,
- UINT32 ulFlags)
- {
- memset(pVidStruct, 0, sizeof(*pVidStruct));
- HXBitmapInfoHeader* bmi = &pVidStruct->bmi;
- UCHAR* pVidMem;
- INT32 nPitch = 0;
- // If we lost our surface, re-create them (if we are not
- // in the process of switching overlay via the OverlayManager or
- // in gdi because we lost DirectDraw).
- if (!m_surface.dd.lpDDSurface &&
- !m_bFallbackSurfaceCreated &&
- !m_bSwitchingingOverlay &&
- !m_bLostHWAcceleration)
- {
- // Make sure we have no locked surfaces
- if (WAIT_OBJECT_0 != WaitForSingleObject(m_hSurfaceMutex, 0))
- {
- if (ulFlags & HX_WAIT_NEVER)
- return HXR_BUFFER_NOT_AVAILABLE;
- WaitForSingleObject(m_hSurfaceMutex, INFINITE);
- }
- ReInitSurfaces();
- // Did not work...return an error
- if (!m_surface.dd.lpDDSurface &&
- !m_bFallbackSurfaceCreated &&
- !m_bGdiSurfaceCreated)
- {
- ReleaseMutex(m_hSurfaceMutex);
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- ReleaseMutex(m_hSurfaceMutex);
- }
- // Return an error if there are not buffers available
- if (ulFlags & HX_WAIT_NEVER)
- {
- // Check m_hReinit is signaled. If not, return an error
- if (WAIT_OBJECT_0 != WaitForSingleObject(m_hReinit, 0))
- return HXR_BUFFER_NOT_AVAILABLE;
- // Make sure we have no locked surfaces
- if (WAIT_OBJECT_0 != WaitForSingleObject(m_hSurfaceMutex, 0))
- return HXR_BUFFER_NOT_AVAILABLE;
- // If we lost our surface, return an error
- if (!m_surface.dd.lpDDSurface &&
- !m_bFallbackSurfaceCreated &&
- !m_bGdiSurfaceCreated)
- {
- ReleaseMutex(m_hSurfaceMutex);
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- }
- // Wait until a buffer is available
- else
- {
- // Wait until our surfaces are created
- WaitForSingleObject(m_hReinit, INFINITE);
- // Wait for last lock
- WaitForSingleObject(m_hSurfaceMutex, INFINITE);
- // If we lost our surface, return an error
- if (!m_surface.dd.lpDDSurface &&
- !m_bFallbackSurfaceCreated &&
- !m_bGdiSurfaceCreated)
- {
- ReleaseMutex(m_hSurfaceMutex);
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- }
- if (m_bFlushing || m_bWasInVidSurf2)
- {
- ReleaseMutex(m_hSurfaceMutex);
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- INT32 nIndex = -1;
- HX_RESULT hr = HXR_OK;
- pVidMem = NULL;
- nPitch = 0;
- if (m_pSite->_BordersActive() |
- m_pSite->_FadeTransitionActive() |
- (m_pSite->AreVideoControlsActive() && !m_bUseDDColorControls) |
- m_pSite->IsHigherZOrderTranstitionActive() |
- (m_LinkedSites.GetCount() > 0) |
- (m_pLinkedOverlay != NULL))
- {
- // Drop to VideoSurface1 for transitions
- if (m_pSite->m_pUser)
- {
- //Can't satisfy a HX_WAIT_NEVER and block without a
- //response object. :-)
- if( ulFlags & HX_WAIT_NEVER )
- {
- ReleaseMutex(m_hSurfaceMutex);
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- HXxEvent event = {HX_SURFACE_MODE_CHANGE, NULL, NULL,
- (void*)HX_VIDEOSURFACE1_RECOMMENDED, 0, 0};
- m_bWasInVidSurf2 = TRUE;
- _WaitForFlush();
- // Unlock the surface mutex so we can be torn down
- ReleaseMutex(m_hSurfaceMutex);
- m_pSite->m_pUser->HandleEvent(&event);
- // The renderer switched to VideoSurface1 so don't give them a buffer
- if (event.handled)
- {
- // Reset or last scale since we are not bltting for a time
- m_dLastXScale = 0.0;
- m_dLastYScale = 0.0;
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- else
- {
- m_bWasInVidSurf2 = FALSE;
- // Need to lock the mutex since the switch failed
- WaitForSingleObject(m_hSurfaceMutex, INFINITE);
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- WinDraw_ResetSurfaceIndexes(pWindraw, &m_surface);
- }
- }
- }
- // Can we restore DirectDraw
- if (m_bLostHWAcceleration)
- {
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- m_bLostHWAcceleration = !pSurface->_IsHardwareAccelerationAvail();
- if (!m_bLostHWAcceleration)
- {
- if (HXR_OK != WaitForQueuedFrames())
- Flush();
- DestroyGdiSurface();
- pSurface->_AcquireHardwareAcceleration();
- ReInitSurfaces();
- }
- }
- LOCK_VIDEO_BUFFER:
- int nBltMode = GetBestBltMode();
- BOOL bLockTLSMutex = FALSE;
- bLockTLSMutex = CanLockSurface(nIndex, nBltMode, (ulFlags & HX_WAIT_NEVER) != HX_WAIT_NEVER);
- if (m_bFlushing)
- {
- ReleaseMutex(m_hSurfaceMutex);
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- if (bLockTLSMutex)
- {
- BOOL bRet = m_pSite->_TLSIsLocked();
- if( bRet && (ulFlags&HX_WAIT_NEVER) )
- {
- ReleaseMutex(m_hSurfaceMutex);
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- m_pSite->_TLSLock();
- }
- else if (ulFlags & HX_WAIT_NEVER)
- {
- ReleaseMutex(m_hSurfaceMutex);
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- else
- {
- //XXXgfw Removing a noisy assert for now. It appears that
- //NVidea GForce 2 MX 100/200 cards will fail to lock a surface
- //while resizing a video. This failure does not lead to video
- //artifacts or any other visible problems. However, with the
- //assert it makes it nearly impossible to debug.
- //HX_ASSERT(!bLockTLSMutex && (ulFlags & HX_WAIT_FOREVER));
- // Some "error" is preventing us from locking the surface
- ReleaseMutex(m_hSurfaceMutex);
- return HXR_BUFFER_NOT_AVAILABLE;
- }
- // Use system mem if selected
- if (m_bUseSysMemSurface)
- {
- hr = LockSysMemSurface(pVidMem, nPitch, (ulFlags & HX_WAIT_NEVER) != HX_WAIT_NEVER);
- if (HXR_OK == hr)
- {
- //m_bmi.biCompression = m_nSysMemSurfID;
- m_bmi.biWidth = m_allocatedSysMemSurfSize.cx;
- m_bmi.biHeight = m_allocatedSysMemSurfSize.cy;
- *bmi = m_bmi;
- bmi->biCompression = m_nSysMemSurfID;
- }
- }
- // If DD is not avail, use rgb blts
- else if (nBltMode == HX_BASIC_BLT)
- {
- hr = LockGdiSurface(pVidMem, nPitch, (ulFlags & HX_WAIT_NEVER) != HX_WAIT_NEVER);
- if (HXR_OK == hr)
- {
- MakeBitmap((LPBITMAPINFO)&m_bmi, sizeof(BMI), m_nGdiSurfaceCID,
- m_allocatedGdiSize.cx, m_allocatedGdiSize.cy, NULL, NULL);
- *bmi = m_bmi;
- m_bmiLastBlt = m_bmi;
- }
- else if (DDERR_WRONGMODE == hr)
- {
- HandleDisplayModeChange();
- }
- }
- // If overlay is not enabled, use offscreen memory
- else if (nBltMode == HX_BLT_YUV_STRETCH)
- {
- hr = LockFallbackSurface(pVidMem, nPitch, (ulFlags & HX_WAIT_NEVER) != HX_WAIT_NEVER);
- if (HXR_OK == hr)
- {
- m_nScratchIndex = nIndex;
- MakeBitmap((LPBITMAPINFO)&m_bmi, sizeof(BMI), m_nFallbackSurfaceCID,
- m_allocatedFallbackSize.cx, m_allocatedFallbackSize.cy, NULL, NULL);
- *bmi = m_bmi;
- m_bmiLastBlt = m_bmi;
- // Restore thread priority
- if (m_nLastBltMode == HX_BASIC_BLT && m_bBoostRenderThread)
- SetThreadPriority(m_hRenThread, THREAD_PRIORITY_TIME_CRITICAL);
- }
- else if (DDERR_WRONGMODE == hr)
- {
- HandleDisplayModeChange();
- }
- // Check if we lost DirectDraw
- else
- {
- if (HandleDirectDrawLoss(bLockTLSMutex))
- {
- if (bLockTLSMutex)
- bLockTLSMutex = FALSE;
- goto LOCK_VIDEO_BUFFER;
- }
- }
- }
- else
- {
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- hr = WinDraw_GetLockedSurface(pWindraw, &m_surface, pVidMem, nIndex,
- (ulFlags & HX_WAIT_NEVER) != HX_WAIT_NEVER);
- if (pVidMem)
- {
- nPitch = m_surface.dd.lPitch;
- MakeBitmap((LPBITMAPINFO)&m_bmi, sizeof(BMI), m_nSurfaceCID,
- m_surfaceSize.cx, m_surfaceSize.cy, NULL, NULL);
- *bmi = m_bmi;
- m_bmiLastBlt = m_bmi;
- if (m_pHwMemObj)
- {
- pVidMem = (UCHAR*)m_pHwMemObj->DeviceToRenderer(pVidMem, nPitch);
- }
- // Restore thread priority
- if (m_nLastBltMode == HX_BASIC_BLT && m_bBoostRenderThread)
- SetThreadPriority(m_hRenThread, THREAD_PRIORITY_TIME_CRITICAL);
- }
- // If the display mode was changed on us, destory and recreate the surfaces
- else if (DDERR_WRONGMODE == hr)
- {
- HandleDisplayModeChange();
- }
- // Could not lock a surface
- else if (DDERR_WASSTILLDRAWING == hr)
- {
- hr = HXR_BUFFER_NOT_AVAILABLE;
- }
- // Check if we lost DirectDraw
- else
- {
- if (HandleDirectDrawLoss(bLockTLSMutex))
- {
- if (bLockTLSMutex)
- bLockTLSMutex = FALSE;
- goto LOCK_VIDEO_BUFFER;
- }
- else
- {
- // Turn off overlay
- m_bMultipleOverlay = TRUE;
- if (bLockTLSMutex)
- m_pSite->_TLSUnlock();
- goto LOCK_VIDEO_BUFFER;
- }
- }
- }
- if (HXR_OK == hr)
- {
- // TLS mutex should be locked here...
- HX_ASSERT(bLockTLSMutex);
- // Since RGB formats are not supported in MapFourCCtoCID,
- // store the CID in biCompression.
- if (!IsYUV(MapFourCCtoCID(m_bmi.biCompression)))
- {
- bmi->biCompression = GetBitmapColor((LPBITMAPINFO)&m_bmi);
- }
- // Do we need an alpha blending region
- if (m_bDoAlphaCheck && !m_pHwMemObj)
- {
- CreateAlphaList(pVidStruct);
- }
- pVidStruct->pVidMem = pVidMem;
- pVidStruct->lPitch = nPitch;
- }
- else
- {
- // Did not lock a surface
- ReleaseMutex(m_hSurfaceMutex);
- hr = HXR_FAIL;
- if (bLockTLSMutex)
- {
- m_pSite->_TLSUnlock();
- }
- }
- return hr;
- }
- STDMETHODIMP CWinSurface2::ColorConvert(INT32 fourCCIn,
- HXxSize *pSrcSize,
- HXxRect *prSrcRect,
- SourceInputStruct *pInput,
- INT32 fourCCOut,
- UCHAR *pDestBuffer,
- HXxSize *pDestSize,
- HXxRect *prDestRect,
- int nDestPitch)
- {
- // If the dest surface is a normal buffer, perform the transfer
- if (!IsStructured(MapFourCCtoCID(fourCCOut)))
- return CVideoSurface2::ColorConvert(fourCCIn, pSrcSize, prSrcRect,
- pInput, fourCCOut, pDestBuffer,
- pDestSize, prDestRect, nDestPitch);
- // Handle this proprietary surface write
- HX_ASSERT(m_pHwMemObj);
- m_pHwMemObj->ProcessCommand((UCHAR*)pInput,
- fourCCIn,
- pSrcSize,
- prSrcRect,
- pDestBuffer,
- fourCCOut,
- pDestSize,
- prDestRect);
- // Need to set pItem->bAlpha if we blended the frame!!!
- if (m_pHwMemObj->QueryOperation() & PERFORMED_HW_ALPHA_BLEND)
- {
- m_bFrameHasHWAlphaBlend = TRUE;
- }
- if (m_bUseDDColorControls)
- {
- m_pSite->CheckColorSettings();
- // Did color controls change
- float fBright = m_pSite->GetBrightness();
- float fContrast = m_pSite->GetContrast();
- float fSaturation = m_pSite->GetSaturation();
- float fHue = m_pSite->GetHue();
- float fSharpness = m_pSite->GetSharpness();
- if (m_Brightness != fBright ||
- m_Contrast != fContrast ||
- m_Saturation != fSaturation ||
- m_Hue != fHue ||
- m_Sharpness != fSharpness)
- {
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- // Change DD color controls
- WinDrawSurface_SetColorControls(pWindraw,
- &m_surface,
- fBright,
- fContrast,
- fSaturation,
- fHue,
- fSharpness);
- m_Brightness = fBright;
- m_Contrast = fContrast;
- m_Saturation = fSaturation;
- m_Hue = fHue;
- m_Sharpness = fSharpness;
- }
- }
- return HXR_OK;
- }
- BOOL CWinSurface2::CanLockSurface(INT32 nIndex, int nBltMode, BOOL bBlock)
- {
- UCHAR* pVidMem;
- HRESULT hr = HXR_FAIL;
- if (m_bUseSysMemSurface)
- {
- if (m_pSysMemSurf)
- {
- if (bBlock)
- {
- HANDLE aWait[2] = {m_pSysMemSurf[m_nNextSysMemBuffer].hEmpty, m_hAbort};
- hr = WaitForMultipleObjects(2, aWait, FALSE, INFINITE);
- }
- else
- hr = WaitForSingleObject(m_pSysMemSurf[m_nNextSysMemBuffer].hEmpty, 0);
- if (WAIT_OBJECT_0 == hr)
- hr = HXR_OK;
- }
- else
- hr = HXR_OK;
- }
- // If DD is not avail, use rgb blts
- else if (HX_BASIC_BLT == nBltMode)
- {
- if (m_bGdiSurfaceCreated)
- {
- if (bBlock)
- {
- HANDLE aWait[2] = {m_GDIsurface.gdi.lpGDIBackBuffer[m_nNextGdiSurface]->hEmpty, m_hAbort};
- hr = WaitForMultipleObjects(2, aWait, FALSE, INFINITE);
- }
- else
- hr = WaitForSingleObject(m_GDIsurface.gdi.lpGDIBackBuffer[m_nNextGdiSurface]->hEmpty, 0);
- if (WAIT_OBJECT_0 == hr)
- hr = HXR_OK;
- }
- else
- hr = HXR_OK;
- }
- else if (HX_BLT_YUV_STRETCH == nBltMode)
- {
- if (bBlock)
- {
- HANDLE aObjects[2] = {m_hFallbackEmpty, m_hAbort};
- hr = WaitForMultipleObjects(2, aObjects, FALSE, INFINITE);
- }
- else
- hr = WaitForSingleObject(m_hFallbackEmpty, 0);
- if (WAIT_OBJECT_0 == hr)
- hr = HXR_OK;
- }
- else
- {
- CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW* pWindraw = pSurface->GetWinDraw();
- int nNextIndex = nIndex;
- hr = WinDraw_CanLockSurface(pWindraw, &m_surface, pVidMem, nNextIndex, bBlock);
- }
- if (hr == HXR_OK)
- return TRUE;
- else
- return FALSE;
- }
- STDMETHODIMP CWinSurface2::ReleaseVideoMem(VideoMemStruct* pVidStruct)
- {
- return ReleaseSurface(pVidStruct, TRUE);
- }
- STDMETHODIMP CWinSurface2::Present(VideoMemStruct *pVidStruct,
- INT32 lTime,
- UINT32 ulFlags,
- HXxRect *prDestRect,
- HXxRect *prSrcRect)
- {
- //#define _DEBUG_TIMEAHEAD
- #ifdef _DEBUG_TIMEAHEAD
- UINT32 ulCurrentTime;
- HRESULT timelineResult = m_pTimeLine->GetTimeLineValue(ulCurrentTime);
- static INT32 lMaxQueueAhead = 0;
- if ((timelineResult != HXR_TIMELINE_SUSPENDED)
- && (lTime - (INT32) ulCurrentTime) > lMaxQueueAhead)
- {
- lMaxQueueAhead = lTime - (INT32) ulCurrentTime;
- HX_TRACE("New max queue ahead: %d", lMaxQueueAhead);
- }
- #endif // _DEBUG_TIMEAHEAD
- if (m_bWasInVidSurf2)
- return HXR_FAIL;
- m_pSite->m_bBltHasBeenCalled = TRUE;
- if (ulFlags & HX_MODE_IMMEDIATE)
- {
- if (m_pListOfFrames->GetCount())
- return HXR_FAIL;
- else if( (HXEmptyRegion(m_pSite->m_Region) && !pVidStruct->ulCount && !m_bFrameHasHWAlphaBlend)
- || !m_pSite->IsSiteVisible())
- return HXR_COULD_NOT_DISPLAY;
- else
- {
- lTime = 0;
- }
- }
- else if (ulFlags & HX_MODE_REFRESH)
- {
- HRESULT hr = HXR_FAIL;
- // We do not have a visible region so we can not refresh
- if( (HXEmptyRegion(m_pSite->m_Region) ) || !m_pSite->IsSiteVisible())
- return HXR_COULD_NOT_DISPLAY;
- // We have not displayed a frame yet so we can not refresh
- else if (HX_NO_BLT == m_nLastBltMode)
- return HXR_COULD_NOT_DISPLAY;
- // If we are waiting on a surface re-init, fail
- else if (WAIT_OBJECT_0 != WaitForSingleObject(m_hReinit, 0))
- return HXR_BUFFER_NOT_AVAILABLE;
- else if (HX_OVERLAY_BLT == m_nLastBltMode)
- {
- // Need to lose overlay...so fail the refresh
- if ((IsShrinking() && !_AllowsOverlayShrinking()) ||
- m_bMultipleOverlay)
- return HXR_FAIL;
- }
- else if (HX_BLT_YUV_STRETCH == m_nLastBltMode)
- {
- // Need to restore overlay...so fail the refresh
- if ((!IsShrinking() || _AllowsOverlayShrinking()) &&
- !m_bMultipleOverlay)
- return HXR_FAIL;
- }
- int nNumRects = 0;
- HXxRect* paSrcRects = NULL;
- HXxRect* paDestRects = NULL;
- // Try to display a queued frame
- if (m_pListOfFrames->GetCount())
- {
- hr = PresentIfReady();
- }
- if (hr != HXR_OK)
- {
- CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- if (!pSurface)
- return HXR_FAIL;
- WINDRAW *pWindraw = pSurface->GetWinDraw();
- // If no dest rect is specified, use surface
- if (!prDestRect->right && !prDestRect->bottom)
- {
- HXxSize rcSize = {0,0};
- m_pSite->GetSize(rcSize);
- prDestRect->right = rcSize.cx;
- prDestRect->bottom = rcSize.cy;
- }
- // Refresh the last rgb image
- //if (m_bLostHWAcceleration)
- if (HX_BASIC_BLT == m_nLastBltMode)
- {
- // Do we have a gdi surface to refresh
- if (m_nLastGdiSurface >= 0)
- {
- // If no src rect is specified, use surface
- if (!prSrcRect->right && !prSrcRect->bottom)
- {
- prSrcRect->right = m_allocatedGdiSize.cx;
- prSrcRect->bottom = m_allocatedGdiSize.cy;
- }
- SetLastScale(prSrcRect, prDestRect);
- _ConstructRects( *prSrcRect,
- *prDestRect,
- FALSE,
- nNumRects,
- &paSrcRects,
- &paDestRects);
- memcpy(&m_lastSrcRect, paSrcRects, sizeof(*paSrcRects)); /* Flawfinder: ignore */
- // Do an rgb blt for each display rect
- for( int j=0 ; j<nNumRects ; j++ )
- {
- hr = WinDrawSurface_Blt(pWindraw, &m_GDIsurface, (RECT*)&paDestRects[j], (RECT*)&paSrcRects[j], m_nLastGdiSurface);
- }
- HX_VECTOR_DELETE(paSrcRects);
- HX_VECTOR_DELETE(paDestRects);
- }
- }
- // If we have a visible overlay, update it
- else if (WinDraw2_IsSurfaceVisible(pWindraw, &m_surface) && !m_bYUVBlending)
- {
- // If no src rect is specified, use surface
- if (!prSrcRect->right && !prSrcRect->bottom)
- {
- prSrcRect->right = m_surfaceSize.cx;
- prSrcRect->bottom = m_surfaceSize.cy;
- }
- SetLastScale(prSrcRect, prDestRect);
- _ConstructRects( *prSrcRect,
- *prDestRect,
- FALSE,
- nNumRects,
- &paSrcRects,
- &paDestRects);
- if (nNumRects != 1)
- {
- HXxPoint screenOffset = m_pSite->GetScreenOffset();
- paSrcRects[0] = *prSrcRect;
- paDestRects[0] = *prDestRect;
- paSrcRects[0].left += screenOffset.x;
- paSrcRects[0].top += screenOffset.y;
- paSrcRects[0].right += screenOffset.x;
- paSrcRects[0].bottom += screenOffset.y;
- }
- hr = ForceUpdateOverlay( &paDestRects[0],
- &paSrcRects[0], HX_OVER_SHOW|HX_OVER_KEYDEST);
- if (HX_NO_BLT == m_nLastBltMode)
- hr = HXR_FAIL;
- else
- {
- memcpy(&m_lastSrcRect, paSrcRects, sizeof(*paSrcRects)); /* Flawfinder: ignore */
- if (hr == HXR_OK)
- {
- if (m_bNeedColorKeyFilled && m_pSite->IsSiteVisible())
- {
- _FillColorKey();
- }
- }
- }
- HX_VECTOR_DELETE(paSrcRects);
- HX_VECTOR_DELETE(paDestRects);
- #if !defined(_GOLD) && 0
- m_TimeStamps.AddSample();
- #endif
- }
- else
- {
- // If we are in fallback mode, make them manually redraw
- if (m_bFallbackSurfaceCreated && HX_OVERLAY_BLT!=m_nBltMode && !m_bYUVBlending)
- {
- // If no src rect is specified, use surface
- if (!prSrcRect->right && !prSrcRect->bottom)
- {
- prSrcRect->right = m_allocatedFallbackSize.cx;
- prSrcRect->bottom = m_allocatedFallbackSize.cy;
- }
- SetLastScale(prSrcRect, prDestRect);
- _ConstructRects( *prSrcRect,
- *prDestRect,
- FALSE,
- nNumRects,
- &paSrcRects,
- &paDestRects);
- memcpy(&m_lastSrcRect, paSrcRects, sizeof(*paSrcRects)); /* Flawfinder: ignore */
- EnterCriticalSection(&m_csFallback);
- for( int j=0 ; j<nNumRects ; j++ )
- {
- hr = WinDrawSurface_Blt(pWindraw, &m_fallbackSurface, (RECT*)&paDestRects[j], (RECT*)&paSrcRects[j]);
- }
- LeaveCriticalSection(&m_csFallback);
- HX_VECTOR_DELETE(paSrcRects);
- HX_VECTOR_DELETE(paDestRects);
- #if !defined(_GOLD) && 0
- m_TimeStamps.AddSample();
- #endif
- }
- }
- }
- return hr;
- }
- if (m_bFlushing)
- {
- return HXR_COULD_NOT_DISPLAY;
- }
- INT32 nIndex = -1;
- // Add this frame to the list and alert the render thread
- tFrameElement *pItem = new tFrameElement;
- memset(pItem, 0, sizeof(*pItem));
- pItem->lTimeStamp = lTime;
- pItem->nBltMode = HX_OVERLAY_BLT;
- pItem->ulFlags = ulFlags;
- pItem->rcSrc = *prSrcRect;
- pItem->rcDst = *prDestRect;
- pItem->bAlpha = m_bFrameHasHWAlphaBlend;
- pItem->count = pVidStruct->ulCount;
- pItem->bmi = m_bmi;
- // If we are in system memory mode, we must blt to hardware ourselves
- if (m_bUseSysMemSurface)
- {
- m_bUseSysMemSurface = FALSE;
- BOOL bAlphaCheck = m_bDoAlphaCheck;
- // Grab a hw buffer and convert the sys mem image to hw yuv.
- UCHAR *pScratchVidMem = NULL;
- INT32 nPitch = 0;
- HXBitmapInfoHeader bmiTemp;
- memset( &bmiTemp, 0, sizeof( bmiTemp ) );
- // We need a hw mem buffer, so disable the alpha blending check
- // that returns system mem.
- m_bDoAlphaCheck = FALSE;
- VideoMemStruct vs;
- memset(&vs, 0, sizeof(vs));
- GetVideoMem(&vs, HX_WAIT_FOREVER);
- pScratchVidMem = vs.pVidMem;
- nPitch = vs.lPitch;
- bmiTemp = vs.bmi;
- if (pScratchVidMem)
- {
- HXxSize srcSize = {bmiTemp.biWidth, bmiTemp.biHeight};
- SourceInputStruct input = {&m_pSysMemSurf[m_nNextSysMemBuffer].pBuffer,
- &m_nSysMemSurfPitch, 1};
- ColorConvert(m_nSysMemSurfID,
- &m_allocatedSysMemSurfSize,
- prSrcRect,
- &input,
- bmiTemp.biCompression,
- pScratchVidMem,
- &srcSize,
- prDestRect,
- nPitch);
- ReleaseSurface(&vs, FALSE);
- }
- m_bDoAlphaCheck = bAlphaCheck;
- if (!pScratchVidMem)
- goto FAILURE;
- pItem->nIndex = m_nNextSysMemBuffer;
- if (++m_nNextSysMemBuffer == m_nSysMemSurfCount)
- m_nNextSysMemBuffer = 0;
- }
- // Alpha blend if necessary
- if (pVidStruct->pAlphaList && pVidStruct->ulCount)
- {
- HXxSize size = {pVidStruct->bmi.biWidth, pVidStruct->bmi.biHeight};
- YuvAlphaBlend(pVidStruct->pAlphaList,
- pVidStruct->ulCount,
- pVidStruct->pVidMem,
- pVidStruct->bmi.biCompression,
- pVidStruct->lPitch,
- &size);
- }
- // If our last lock was not using overlay, use our offscreen blt
- if (m_bScratchSurface)
- {
- if (!m_fallbackSurface.dd.lpDDSurface)
- goto FAILURE;
- pItem->nBltMode = HX_BLT_YUV_STRETCH;
- pItem->pAlphaList = pVidStruct->pAlphaList;
- ResetEvent(m_hFallbackEmpty);
- }
- // Our last lock was using gdi
- else if (m_bGDISurface)
- {
- pItem->nBltMode = HX_BASIC_BLT;
- pItem->pAlphaList = pVidStruct->pAlphaList;
- pItem->nIndex = m_nNextGdiSurface;
- }
- else
- {
- // Advance the overlay surface list
- int nNewIndex = nIndex;
- if (!m_surface.dd.lpDDSurface)
- goto FAILURE;
- CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- if (!pSurface)
- goto FAILURE;
- WINDRAW *pWindraw = pSurface->GetWinDraw();
- if (HXR_OK != WinDraw_AdvanceSurface (pWindraw, &m_surface, nNewIndex))
- goto FAILURE;
- pItem->nIndex = nNewIndex;
- pItem->nBltMode = HX_OVERLAY_BLT;
- }
- // Increase the mutex lock count so another thread does not lock
- // it before we queue this frame or prevent us from drawing immediately.
- WaitForSingleObject(m_hSurfaceMutex, INFINITE);
- // We delete the alphalist in DisplayFrame in yuv_stretch mode.
- ReleaseSurface(pVidStruct, FALSE, (pItem->nBltMode!=HX_BLT_YUV_STRETCH));
- // Immediate display...don't queue
- if (ulFlags & HX_MODE_IMMEDIATE)
- {
- HRESULT hr;
- tFrameElement lastItem;
- for (int i=0; i<5; i++)
- {
- pItem->dwDDFlags = DDFLIP_WAIT;
- lastItem = *pItem;
- hr = DisplayFrame(pItem);
- // Need to try again
- if (DDERR_WASSTILLDRAWING == hr)
- {
- *pItem = lastItem;
- WaitForSingleObject(m_hAbort, 10);
- }
- // Probably can not async flip, so turn it off
- else if (DDERR_INVALIDPARAMS == hr && m_bUseVBlankFlip)
- {
- *pItem = lastItem;
- m_bUseVBlankFlip = FALSE;
- }
- else
- {
- // Abort this overaly surface on a failure
- if (DD_OK != hr && pItem->nBltMode == HX_OVERLAY_BLT)
- {
- CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- if (!pSurface)
- goto FAILURE;
- WINDRAW *pWindraw = pSurface->GetWinDraw();
- WinDraw_DisplaySurface(pWindraw, &m_surface, pItem->dwDDFlags, pItem->nIndex, TRUE);
- }
- break;
- }
- }
- ReleaseMutex(m_hSurfaceMutex);
- delete pItem;
- #if !defined(_GOLD) && 0
- m_TimeStamps.AddSample();
- #endif
- return HXR_OK;
- }
- EnterCriticalSection(&m_csList);
- m_pListOfFrames->AddTail((void*)pItem);
- LeaveCriticalSection(&m_csList);
- ReleaseSemaphore(m_hFrameSem, 1, NULL);
- ReleaseMutex(m_hSurfaceMutex);
- #if !defined(_GOLD) && 0
- m_TimeStamps.AddSample();
- #endif
- return HXR_OK;
- FAILURE:
- delete pItem;
- return HXR_FAIL;
- }
- STDMETHODIMP_(void) CWinSurface2::Flush()
- {
- m_bFlushing = TRUE;
- //This needs to be before the wait on m_hSurfaceMutex because if
- //you hit stop before we start blt'ing frames you could be waiting
- //a long time before it wakes up. At least in the case for live
- //streams where we don't have the server/ff seek back to the
- //nearest keyframe and send data. Some streams have keyframes
- //every 10seconds or so.
- PulseEvent(m_hAbort);
- WaitForSingleObject(m_hSurfaceMutex, INFINITE);
- CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- WINDRAW *pWindraw = pSurface->GetWinDraw();
- // Cancel and pending frames
- WinDraw_CacelPendingDisplay (pWindraw, &m_surface);
- PulseEvent(m_hForceRender);
- Sleep(5);
- // Wait until our queue count reaches 0
- int nCount = m_pListOfFrames->GetCount();
- while (nCount)
- {
- WinDraw_CacelPendingDisplay (pWindraw, &m_surface);
- PulseEvent(m_hAbort);
- PulseEvent(m_hForceRender);
- Sleep(5);
- nCount = m_pListOfFrames->GetCount();
- }
- ResetBufferTimes(0);
- ReleaseMutex(m_hSurfaceMutex);
- m_bFlushing = FALSE;
- }
- void CWinSurface2::ResetBufferTimes(INT32 nTime)
- {
- // Reset all buffer times
- if (m_surface.dwBackBufferCount)
- {
- for (UINT32 i=0; i<m_surface.dwBackBufferCount+1; i++)
- m_surface.dd.lpChain[i].dTimeAvailable = nTime;
- }
- }
- STDMETHODIMP CWinSurface2::PresentIfReady()
- {
- HX_RESULT hr = E_FAIL;
- if (!m_pTimeLine | m_bIngnorePresentIfReady)
- return hr;
- UINT32 ulTime = 0;
- if (HXR_TIMELINE_SUSPENDED != m_pTimeLine->GetTimeLineValue(ulTime))
- {
- if (((m_nLastDisplayTime > 0) && (m_nLastDisplayTime - (INT32)ulTime < 0)))
- {
- #ifdef LOG_JITTER_DATA
- FILE *fp = fopen(JITTER_LOG_FILE, "a+");
- if (fp)
- {
- fprintf(fp, "PresentIfReady Interrupt clock %ld last display %ldn", ulTime, m_nLastDisplayTime);
- fclose(fp);
- }
- #endif
- PulseEvent(m_hForceRender);
- Sleep(0);
- #ifdef _DEBUG
- //OutputDebugString("PresentIfReady Interruptn");
- #endif
- hr = HXR_OK;
- }
- }
- return hr;
- }
- HX_RESULT CWinSurface2::DisplayFrame(tFrameElement* pItem)
- {
- HRESULT hr = HXR_OK,
- hrTimeLine = HXR_OK;
- HXxSize rcSize = {0,0};
- int nNumRects = 0;
- BOOL bSub1x = FALSE;
- m_pSite->_TLSLock();
- CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
- if (!pSurface)
- {
- m_pSite->_TLSUnlock();
- return HXR_FAIL;
- }
- WINDRAW *pWindraw = pSurface->GetWinDraw();
- // Ensure our site is visible before displaying
- BOOL bVisibleSite = (!HXEmptyRegion(m_pSite->m_Region)|| pItem->count || pItem->bAlpha)
- && m_pSite->IsSiteVisible()
- && !m_pSite->_FadeTransitionActive();
- if (pItem->nBltMode == HX_OVERLAY_BLT)
- {
- // If no src rect is specified, use surface
- if (!pItem->rcSrc.right && !pItem->rcSrc.bottom)
- {
- pItem->rcSrc.right = m_surfaceSize.cx;
- pItem->rcSrc.bottom = m_surfaceSize.cy;
- }
- // Put the frame on the screen
- int nIndex = pItem->nIndex-1;
- if (nIndex < 0)
- nIndex = m_nBackBufferCount;
- if (pItem->dwDDFlags & DDFLIP_WAIT == DDFLIP_WAIT)
- {
- // Immediate mode blits have no calculated timaAvailable; use
- // the current time:
- pItem->dTimeAvailable = GetMSTickDouble32();
- }
- m_surface.dd.lpChain[nIndex].dTimeAvailable = pItem->dTimeAvailable;
- m_surface.dd.lpChain[pItem->nIndex].dTimeAvailable = 0;
- hr = WinDraw_DisplaySurface(pWindraw, &m_surface, pItem->dwDDFlags, pItem->nIndex, m_bFlushing);
- #ifdef LOG_JITTER_DATA
- UINT32 ulTimeAfter = 0;
- m_pTimeLine->GetTimeLineValue(ulTimeAfter);
- FILE *fp = fopen(JITTER_LOG_FILE, "a+");
- if (fp)
- {
- UINT32 dwScanLine = 0;
- WinDraw2_GetScanLine(pWindraw, &dwScanLine);
- fprintf(fp, "Calling flip: scan line %ld clock after %ld ts %ld jitter %ldnn", dwScanLine, ulTimeAfter, pItem->lTimeStamp, (INT32)(pItem->lTimeStamp-ulTimeAfter));
- fclose(fp);
- }
- #endif //LOG_JITTER_DATA
- if (DD_OK == hr && bVisibleSite)
- {
- m_nLastBltMode = HX_OVERLAY_BLT;
- // Make sure we are painting colorkey in fullscreen mode.
- // We will fix this when fillcolor key is fixed.
- if (m_pSite->m_pTopLevelSite &&
- m_pSite->m_pTopLevelSite->m_bInFullScreen)
- {
- if (++m_ulFillColoryKeyCount < 15)
- memset(&m_rcLast, 0, sizeof(m_rcLast));
- }
- else
- m_ulFillColoryKeyCount = 0;
- if (!IsShrinking() || _AllowsOverlayShrinking())
- {
- // Restore overlay
- if (HX_OVERLAY_BLT != m_nBltMode)
- {
- ForceGDIMode(FALSE);
- }
- // If no src rect is specified, use surface
- if (!pItem->rcDst.right && !pItem->rcDst.bottom)
- {
- m_pSite->GetSize(rcSize);