winsurf2.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:135k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxtypes.h"
  36. #include <math.h>
  37. #include "ddraw.h"
  38. #include "hxcom.h"
  39. #include "hxmtypes.h"
  40. #include "hxwintyp.h"
  41. #include "hxvsurf.h"
  42. #include "hxslist.h"
  43. #include "ddhlpr.h"
  44. #include "winsurf.h"
  45. #include "vidsurf2.h"
  46. #include "winsurf2.h"
  47. #include "winsite.h"
  48. #include "colormap.h"
  49. #include "windraw2.h"
  50. #include "hxprefs.h"
  51. #include "hxtick.h"
  52. #include "hxheap.h"
  53. #include "hxevent.h"
  54. #include "hwmemobj.h"
  55. // these are defined in basesurf.cpp and should probably be moved to a .h file
  56. #define HX_OVER_KEYDEST    1
  57. #define HX_OVER_HIDE       2
  58. #define HX_OVER_SHOW       4  
  59. #define OVERLAY_NOT_VISIBLE 0
  60. #ifdef _DEBUG
  61. #undef HX_THIS_FILE             
  62. static const char HX_THIS_FILE[] = __FILE__;
  63. #include "winthrd.h"
  64. #endif
  65. #define OS_THREAD_QUANTUM 10
  66. #define MAX_PREEMPTION_CHECK_ATTEMPTS 3
  67. #define TIME_JITTER_FILTER_THRESHOLD 0.45
  68. #define MIN_ALLOWED_REGRESSION  0.95
  69. //#define HARDCODE_GRANULE
  70. #define SCHEDULE_GRANULE        5
  71. //#define LOG_JITTER_DATA
  72. #define JITTER_LOG_FILE "c:\temp\ts.txt"
  73. /****************************************************************************
  74.  *  Debug
  75.  */
  76. //#define ENABLE_SYNC_TRACE
  77. #ifdef ENABLE_SYNC_TRACE
  78. #define MAX_SYNC_TRACE_ENTRIES 10000
  79. ULONG32 ulSyncTraceIdx = 0;
  80. double syncTraceArray[MAX_SYNC_TRACE_ENTRIES][3];
  81. void DumpSyncEntries(void)
  82. {
  83.     FILE* pFile = NULL;
  84.     ULONG32 ulIdx;
  85.     if (ulSyncTraceIdx > 0)
  86.     {
  87. pFile = fopen("/tmp/getscanline.txt", "wb"); /* Flawfinder: ignore */
  88.     }
  89.     if (pFile)
  90.     {
  91. for (ulIdx = 0; ulIdx < (ulSyncTraceIdx < MAX_SYNC_TRACE_ENTRIES ?
  92.              ulSyncTraceIdx : MAX_SYNC_TRACE_ENTRIES); ulIdx++)
  93. {
  94.     fprintf(pFile, "%lft%lft%lfn", syncTraceArray[ulIdx][0],
  95.       syncTraceArray[ulIdx][1],
  96.                                               syncTraceArray[ulIdx][2]
  97.                                             );
  98. }
  99. fclose(pFile);
  100.     }
  101.     ulSyncTraceIdx = 0;
  102. }
  103. #endif // ENABLE_SYNC_TRACE
  104. //#define ENABLE_ERROR_TRACE
  105. #ifdef ENABLE_ERROR_TRACE
  106. #define MAX_ERROR_TRACE_ENTRIES 10000
  107. double g_error[MAX_ERROR_TRACE_ENTRIES][3];
  108. double g_alternateError[MAX_ERROR_TRACE_ENTRIES];
  109. ULONG32 g_ulFrameCount;
  110. UINT32 g_sleepError[MAX_ERROR_TRACE_ENTRIES];
  111. ULONG32 g_ulSleepCount;
  112. void DumpErrorEntries(void)
  113. {
  114.     FILE* pFile = NULL;
  115.     ULONG32 ulIdx;
  116.     if (g_ulFrameCount > 0)
  117.     {
  118. pFile = fopen("/tmp/vblankerror.txt", "wb"); /* Flawfinder: ignore */
  119.     }
  120.     if (pFile)
  121.     {
  122. for (ulIdx = 0; ulIdx < (g_ulFrameCount < MAX_SYNC_TRACE_ENTRIES ?
  123.              g_ulFrameCount : MAX_SYNC_TRACE_ENTRIES); ulIdx++)
  124. {
  125.     fprintf(pFile, "%lft%lft%lfn", g_error[ulIdx][0],
  126.                                          g_error[ulIdx][1],
  127.                                          g_error[ulIdx][2]);
  128. }
  129.               
  130. fclose(pFile);
  131.     }
  132.     g_ulFrameCount = 0;
  133. }
  134. #endif // ENABLE_ERROR_TRACE
  135. // Using "this" in constructor initialzer
  136. #pragma warning(disable:4355)
  137. CWinSurface2::CWinSurface2(IUnknown* pContext, CHXBaseSite* pSite)
  138.  :  CWinSurface(pContext,pSite)
  139.  ,  CVideoSurface2((IUnknown*)(IHXVideoSurface*)this)
  140.  ,  m_hRenThread(0)
  141.  ,  m_hFrameSem(0)
  142.  ,  m_hReinit(0)
  143.  ,  m_hAbort(0)
  144.  ,  m_hForceRender(0)
  145.  ,  m_hSurfaceMutex(0)
  146.  ,  m_bCont(FALSE)
  147.  ,  m_bBoostRenderThread(TRUE)
  148.  ,  m_bDoAlphaCheck(TRUE)
  149.  ,  m_bQueryMonitorFreq(FALSE)
  150.  ,  m_bUseVBlankFlip(TRUE)
  151.  ,  m_bIngnorePresentIfReady(FALSE)
  152.  ,  m_bScratchSurface(FALSE)
  153.  ,  m_bGDISurface(FALSE)
  154.  ,  m_nScratchIndex(0)
  155.  ,  m_nLastDisplayTime(0)
  156.  ,  m_pListOfFrames(NULL)                                                             
  157.  ,  m_pTimeLine(NULL)
  158.  ,  m_hFallbackEmpty(0)
  159.  ,  m_nFallbackSurfaceCID(0)
  160.  ,  m_bFallbackSurfaceCreated(FALSE)
  161.  ,  m_pSysMemSurf(NULL)
  162.  ,  m_nSysMemSurfSize(0)
  163.  ,  m_nSysMemSurfCount(0)
  164.  ,  m_nSysMemSurfPitch(0)
  165.  ,  m_nSysMemSurfID(0)
  166.  ,  m_nNextSysMemBuffer(0)
  167.  ,  m_bUseSysMemSurface(FALSE)
  168.  ,  m_nGdiSurfaceCount(0)
  169.  ,  m_nLastGdiSurface(-1)
  170.  ,  m_nNextGdiSurface(0)
  171.  ,  m_nGdiSurfaceCID(0)
  172.  ,  m_bGdiSurfaceCreated(FALSE)
  173.  ,  m_ulFillColoryKeyCount(0)
  174.  ,  m_bFlushing(FALSE)
  175.  ,  m_bFrameHasHWAlphaBlend(FALSE)
  176.  ,  m_bSurfaceRequiresOverlay(FALSE)
  177.  ,  m_bSwitchingingOverlay(FALSE)
  178.  ,  m_bUseDDColorControls(FALSE)
  179.  ,  m_bWaitingForFlush(FALSE)
  180.  ,  m_bWasInVidSurf2(FALSE)
  181.  ,  m_dLastXScale(0.0)
  182.  ,  m_dLastYScale(0.0)
  183.  ,  m_nOverlayBackBuffersCreated(0)
  184.  ,  m_dLastBlitError(0)
  185. {
  186.     // initialize data so we don't have invalid ptrs floating around.
  187.     memset(&m_surface,0,sizeof(m_surface));
  188.     memset(&m_GDIsurface,0,sizeof(m_GDIsurface));
  189.     memset(&m_fallbackSurface,0,sizeof(m_fallbackSurface));
  190.     memset(&m_allocatedFallbackSize, 0, sizeof(m_allocatedFallbackSize));
  191.     memset(&m_allocatedSysMemSurfSize, 0, sizeof(m_allocatedSysMemSurfSize));
  192.     memset(&m_allocatedFallbackSize, 0, sizeof(m_allocatedFallbackSize));
  193.     memset(&m_rcLast, 0, sizeof(m_rcLast));
  194.     InitializeCriticalSection(&m_csDisplay);
  195.     InitializeCriticalSection(&m_csFallback);
  196.     InitializeCriticalSection(&m_csList);
  197.     InitializeCriticalSection(&m_csScale);
  198.     m_hAbort = CreateEvent(NULL, TRUE, FALSE, NULL);
  199.     m_hForceRender = CreateEvent(NULL, TRUE, FALSE, NULL);
  200.     m_hReinit = CreateEvent(NULL, TRUE, TRUE, NULL);
  201.     m_hFallbackEmpty = CreateEvent(NULL, TRUE, TRUE, NULL);
  202.     m_hSurfaceMutex = CreateMutex(NULL, FALSE, NULL);
  203.     m_pListOfFrames = new CHXSimpleList;
  204.     // Read some preferences
  205.     IHXPreferences*    pPreferences    = NULL;
  206.     IHXBuffer*         pBuffer         = NULL;
  207.     if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
  208.     {   
  209.         // Use vblank flags for flipping
  210.         if (pPreferences->ReadPref("VideoBoost\DisableVBlankFlip", pBuffer) == HXR_OK)
  211.         {
  212.             m_bUseVBlankFlip = !(::atoi((char*) pBuffer->GetBuffer()) == 1);
  213.         }
  214.         HX_RELEASE(pBuffer);
  215.       
  216.         // Turn-off render thread priority boosting
  217.         if (pPreferences->ReadPref("VideoBoost\DisablePriorityBoost", pBuffer) == HXR_OK)
  218.         {
  219.             m_bBoostRenderThread = !(::atoi((char*) pBuffer->GetBuffer()) == 1);
  220.         }
  221.         HX_RELEASE(pBuffer);
  222.         // Limit number of hw buffers
  223.         if (pPreferences->ReadPref("VideoBoost\MaxBuffers", pBuffer) == HXR_OK)
  224.         {
  225.             m_nMaxBackBuffers = ::atoi((char*) pBuffer->GetBuffer()) - 1;
  226.             m_nMaxBackBuffers = max(1, m_nMaxBackBuffers);
  227.         }
  228.         HX_RELEASE(pBuffer);
  229.     }
  230.     HX_RELEASE(pPreferences);
  231. }
  232. CWinSurface2::~CWinSurface2()
  233. {
  234.     if (m_hRenThread)
  235.     {
  236.         m_bCont = FALSE;
  237.         SetEvent(m_hAbort);
  238.         WaitForSingleObject(m_hRenThread, INFINITE);
  239.         CloseHandle(m_hFrameSem);
  240.         m_hFrameSem = 0;
  241.         CloseHandle(m_hRenThread);
  242.         m_hRenThread = 0;
  243.         DestroyFallbackSurface();
  244.         DestroySysMemSurface();
  245.         DestroyGdiSurface();
  246.     }
  247.     if (m_hAbort)
  248.     {
  249.         CloseHandle(m_hAbort);
  250.         m_hAbort = 0;
  251.     }
  252.     if (m_hForceRender)
  253.     {        
  254.         CloseHandle(m_hForceRender);
  255.         m_hForceRender = 0;
  256.     }
  257.     if (m_hReinit)
  258.     {
  259.         CloseHandle(m_hReinit);
  260.         m_hReinit = 0;
  261.     }
  262.     if (m_hFallbackEmpty)
  263.     {
  264.         CloseHandle(m_hFallbackEmpty);
  265.         m_hFallbackEmpty = NULL;
  266.     }
  267.     if (m_hSurfaceMutex)
  268.     {
  269.         CloseHandle(m_hSurfaceMutex);
  270.         m_hSurfaceMutex = 0;
  271.     }
  272.     HX_DELETE(m_pListOfFrames);
  273.     
  274.     DeleteCriticalSection(&m_csDisplay);
  275.     DeleteCriticalSection(&m_csFallback);
  276.     DeleteCriticalSection(&m_csList);
  277.     DeleteCriticalSection(&m_csScale);
  278.     HX_RELEASE(m_pTimeLine);
  279. }
  280. STDMETHODIMP CWinSurface2::QueryInterface(REFIID riid, void** ppvObj)
  281. {
  282.     if (IsEqualIID(riid, IID_IHXVideoSurface2))
  283.     {
  284.         return CVideoSurface2::QueryInterface(riid, ppvObj);
  285.     }
  286.     return CWinSurface::QueryInterface(riid, ppvObj);
  287. }
  288. STDMETHODIMP_(ULONG32) CWinSurface2::AddRef()
  289. {
  290.     return CWinSurface::AddRef();
  291. }
  292. STDMETHODIMP_(ULONG32) CWinSurface2::Release()
  293. {
  294.     return CWinSurface::Release();
  295. }
  296. STDMETHODIMP CWinSurface2::BeginOptimizedBlt(HXBitmapInfoHeader* pBitmapInfo)
  297. {
  298.     if (m_bWasInVidSurf2 &&
  299.         pBitmapInfo &&
  300.         m_pOptimizedFormat)
  301.     {
  302.         // Are the new parameters the same as the old paramaters? If not
  303.         // then delete the old surfaces.
  304.         if (pBitmapInfo->biWidth       != m_pOptimizedFormat->biWidth       || 
  305.             pBitmapInfo->biHeight      != m_pOptimizedFormat->biHeight      || 
  306.             pBitmapInfo->biPlanes      != m_pOptimizedFormat->biPlanes      || 
  307.             pBitmapInfo->biBitCount    != m_pOptimizedFormat->biBitCount    || 
  308.             pBitmapInfo->biCompression != m_pOptimizedFormat->biCompression ||
  309.             m_bWasInVidSurf2)
  310.         {
  311.             if (m_bWasInVidSurf2)
  312.                 _WaitForFlush();
  313.             DestroySurfaces();
  314.             if (m_bWasInVidSurf2)
  315.             {
  316.                 m_bVideoSurface2 = FALSE;
  317.                 m_bFlipOverlay = FALSE;
  318.                 m_nBackBufferCount = 0;
  319.             }
  320.         }
  321.     }
  322.     return CWinSurface::BeginOptimizedBlt(pBitmapInfo);
  323. }
  324. STDMETHODIMP CWinSurface2::Blt( UCHAR*               pImageData,
  325.                                 HXBitmapInfoHeader* pBitmapInfo,
  326.                                 REF(HXxRect)         rDestRect,
  327.                                 REF(HXxRect)         rSrcRect)
  328. {
  329.     m_pSite->_TLSLock();
  330.     // Handle VS2->VS1 transions
  331.     if (m_bWasInVidSurf2)
  332.     {
  333.         if (!m_pSite->_BordersActive() && 
  334.             !m_pSite->_FadeTransitionActive() &&
  335.             (!m_pSite->AreVideoControlsActive() || m_bUseDDColorControls) &&
  336.             !m_pSite->IsHigherZOrderTranstitionActive() &&
  337.             m_pSite->m_pUser && !m_LinkedSites.GetCount() &&
  338.             !m_pLinkedOverlay)
  339.         {
  340.             HXxEvent event = {HX_SURFACE_MODE_CHANGE, NULL, NULL,
  341.                               (void*)HX_VIDEOSURFACE1_NOT_RECOMMENDED, 0, 0};
  342.         
  343.             m_bWasInVidSurf2 = FALSE;
  344.             // If we just turned off color controls inform the color converter
  345.             m_pSite->CheckColorSettings();
  346.             m_pSite->m_pUser->HandleEvent(&event);
  347.             // The renderer switched to VideoSurface1 so don't give them a buffer
  348.             if (event.handled)
  349.             {
  350.                 m_pSite->_TLSUnlock();
  351.                 return HXR_FAIL;
  352.             }
  353.             else
  354.                 m_bWasInVidSurf2 = TRUE;
  355.         }
  356.         else if (m_bVideoSurface2)
  357.         {
  358.             m_pSite->_TLSUnlock(); 
  359.             _WaitForFlush();
  360.             m_bVideoSurface2 = FALSE;
  361.             m_pSite->_TLSLock(); 
  362.         }
  363.     }
  364.     HX_RESULT hr = CWinSurface::Blt(pImageData, pBitmapInfo, rDestRect, rSrcRect);
  365.     m_pSite->_TLSUnlock();
  366.     return hr;
  367. }
  368. void CWinSurface2::_CreateBuffer()
  369. {
  370.     if (m_hRenThread)
  371.     {
  372.         WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  373.         EnterCriticalSection(&m_csDisplay);
  374.     }
  375.    
  376.     CWinSurface::_CreateBuffer();
  377.     BOOL bCreated = FALSE;
  378.     
  379.     if (m_surface.fMode & WINDRAW_DIRECTDRAW)
  380.     {
  381.         bCreated = (m_surface.dd.lpDDSurface != NULL);
  382.     }
  383.     else
  384.     {
  385.         bCreated = (m_surface.gdi.lpGDIBackBuffer[0] != NULL);
  386.     }
  387.     if (bCreated)
  388.     {
  389.         if (m_hRenThread)
  390.         {
  391.             // We create our surface, start servicing GetVidMem calls
  392.             SetEvent(m_hReinit);
  393.         }
  394.     }
  395.     if (m_hRenThread)
  396.     {
  397.         ReleaseMutex(m_hSurfaceMutex);
  398.         LeaveCriticalSection(&m_csDisplay);
  399.     }
  400. }
  401. HX_RESULT CWinSurface2::_CreateOverlay(BOOL bOverlay, int cid, int x, int y)
  402. {
  403.     if (m_hRenThread)
  404.     {
  405.         WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  406.         EnterCriticalSection(&m_csDisplay);
  407.     }
  408.     HX_RESULT hr = CWinSurface::_CreateOverlay(bOverlay, cid, x, y);
  409.     if (HXR_OK == hr && m_hRenThread)
  410.     {
  411.         // We created our surface, start servicing GetVidMem calls
  412.         SetEvent(m_hReinit);
  413.     }
  414.     if (m_hRenThread)
  415.     {
  416.         LeaveCriticalSection(&m_csDisplay);
  417.         ReleaseMutex(m_hSurfaceMutex);
  418.     }
  419.         
  420.     return hr;
  421. }
  422. HX_RESULT 
  423. CWinSurface2::ByPassCompositionSurface(UCHAR*               pImageData,
  424.                                        HXBitmapInfoHeader* pBitmapInfo,
  425.                                        REF(HXxRect)         rDestRect,
  426.                                        REF(HXxRect)         rSrcRect,
  427.                                        UCHAR*               pSurface,
  428.                                        INT32                nSurfPitch)
  429.                                                  
  430. {
  431.     // Check for vidsurf2-only dest surfaces
  432.     if (CID_I420 == GETBITMAPCOLOR( pBitmapInfo) &&
  433.         m_pHwMemObj)
  434.     {
  435.         HXxSize srcSize = {pBitmapInfo->biWidth, pBitmapInfo->biHeight};
  436.     
  437.         UCHAR* pYUV[3] = {pImageData,
  438.                           pYUV[0] + pBitmapInfo->biHeight*nSurfPitch,
  439.                           pYUV[1] + pBitmapInfo->biHeight*nSurfPitch/4};
  440.         INT32 nYUVPitch[3] = {nSurfPitch, nSurfPitch/2, nSurfPitch/2};
  441.         SourceInputStruct input = {pYUV, nYUVPitch, 3};
  442.         INT32 nPitch;
  443.         UCHAR* pVidMem = 
  444.          (UCHAR*)m_pHwMemObj->DeviceToRenderer(pImageData,
  445.                                                nPitch,
  446.                                                WRITE_VIDEO_TO_STRUCT);
  447.         
  448.         AlignRect(&rSrcRect, pBitmapInfo->biWidth, pBitmapInfo->biHeight);
  449.         AlignRect(&rDestRect, m_surfaceSize.cx, m_surfaceSize.cy);
  450.         HX_RESULT hr =  
  451.             ColorConvert(MapCIDtoFourCC(GETBITMAPCOLOR(pBitmapInfo)),
  452.                          &srcSize, &rSrcRect,
  453.                          &input, MapCIDtoFourCC(m_nSurfaceCID), pVidMem,
  454.                          &m_surfaceSize, &rDestRect, nSurfPitch);
  455.         m_pHwMemObj->RendererToDevice(pVidMem);
  456.         return hr;
  457.     }
  458.     return CWinSurface::ByPassCompositionSurface(pImageData,
  459.                                                  pBitmapInfo,
  460.                                                  rDestRect,
  461.                                                  rSrcRect,
  462.                                                  pSurface,
  463.                                                  nSurfPitch);
  464. }
  465. void CWinSurface2::_ReleaseSurface(CBaseRootSurface* pSurface)
  466. {
  467.     if (m_hRenThread)
  468.     {
  469.         Flush();
  470.         // Make the next GetVidMem wait on new surface creation
  471.         WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  472.         ResetEvent(m_hReinit);
  473.         Flush();
  474.         EnterCriticalSection(&m_csDisplay);
  475.     }
  476.     WINDRAW* pWindraw = ((CWinBaseRootSurface*)pSurface)->GetWinDraw();
  477.     DestroyFallbackSurface();
  478.     DestroyGdiSurface();
  479.     
  480.     CWinSurface::_ReleaseSurface(pSurface);
  481.     memset(&m_lastSrcRect, 0, sizeof(m_lastSrcRect));
  482.     if (m_hRenThread)
  483.     {
  484.         LeaveCriticalSection(&m_csDisplay);
  485.         ReleaseMutex(m_hSurfaceMutex);
  486.     }
  487.     m_dLastXScale = 0.0;
  488.     m_dLastYScale = 0.0;
  489. }
  490. void CWinSurface2::_ReleaseSurface(CWinBaseRootSurface* pSurface)
  491. {
  492.     if (m_hRenThread)
  493.     {
  494.         Flush();
  495.         // Make the next GetVidMem wait on new surface creation
  496.         WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  497.         ResetEvent(m_hReinit);
  498.       
  499.         Flush();
  500.         EnterCriticalSection(&m_csDisplay);
  501.     }
  502.     WINDRAW* pWindraw = pSurface->GetWinDraw();
  503.     DestroyFallbackSurface();
  504.     DestroyGdiSurface();
  505.     
  506.     CWinSurface::_ReleaseSurface(pSurface);
  507.     memset(&m_lastSrcRect, 0, sizeof(m_lastSrcRect));
  508.     if (m_hRenThread)
  509.     {
  510.         LeaveCriticalSection(&m_csDisplay);
  511.         ReleaseMutex(m_hSurfaceMutex);
  512.     }
  513.     m_dLastXScale = 0.0;
  514.     m_dLastYScale = 0.0;
  515. }
  516. void CWinSurface2::_ReleaseSurface()
  517. {
  518.     if (m_hRenThread)
  519.     {
  520.         Flush();
  521.         // Make the next GetVidMem wait on new surface creation
  522.         WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  523.         ResetEvent(m_hReinit);
  524.       
  525.         Flush();
  526.         EnterCriticalSection(&m_csDisplay);
  527.     }
  528.    
  529.     CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  530.     if (pSurface)
  531.     {
  532.         WINDRAW* pWindraw = pSurface->GetWinDraw();
  533.         if (pWindraw)
  534.         {
  535.             DestroyFallbackSurface();
  536.             DestroyGdiSurface();
  537.             memset(&m_lastSrcRect, 0, sizeof(m_lastSrcRect));
  538.             CWinSurface::_ReleaseSurface();
  539.         }
  540.     }
  541.     if (m_hRenThread)
  542.     {
  543.         LeaveCriticalSection(&m_csDisplay);
  544.         ReleaseMutex(m_hSurfaceMutex);
  545.     }
  546.     m_dLastXScale = 0.0;
  547.     m_dLastYScale = 0.0;
  548. }
  549. void CWinSurface2::ReInitSurfaces()
  550. {
  551.     if ( (m_surface.fMode & WINDRAW_DIRECTDRAW) &&  m_surface.dd.lpDDSurface && m_bVideoSurface2)
  552.     {
  553.         return;
  554.     }
  555.     // Set yuv priority for vidsurf2 mode
  556.     if (m_hRenThread)
  557.     {
  558.         // Lock the surface mutex
  559.         WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  560.         
  561.         m_pSite->_TLSLock();
  562.         int cid = GetBitmapColor((LPBITMAPINFO)m_pOptimizedFormat);
  563.         BOOL bRestore = SetYUVPriorityList(cid);
  564.         m_nBackBufferCount = m_nOverlayBackBuffersCreated;
  565.         CWinSurface::ReInitSurfaces();
  566.         if (bRestore)
  567.             RestoreColorspacePriorities(cid);
  568.         // We switched to a mode that does not support overlay...yikes!
  569.         if (m_bVideoSurface2 &&
  570.             (m_nBltMode != HX_OVERLAY_BLT || !m_nBackBufferCount))
  571.         {
  572.             m_bMultipleOverlay = TRUE;
  573.             ForceGDIMode(TRUE);
  574.         }
  575.         else
  576.         {
  577.             m_bMultipleOverlay = FALSE;
  578.         }
  579.         
  580.         HXxSize rcSize = m_surfaceSize;
  581.         CreateFallbackSurface(m_nSurfaceCID, &rcSize);
  582.         m_pSite->_TLSUnlock();
  583.         ResetBufferTimes(0);
  584.         ReleaseMutex(m_hSurfaceMutex);
  585.     }
  586.     else
  587.         CWinSurface::ReInitSurfaces();
  588. }
  589. BOOL CWinSurface2::_IsDisplaySurfaceYuv()
  590. {
  591.     if (!m_bVideoSurface2)
  592.         return CWinSurface::_IsDisplaySurfaceYuv();
  593.     return IsYUV(MapFourCCtoCID(m_bmi.biCompression));
  594. }
  595. BOOL CWinSurface2::_AllowsOverlayShrinking()
  596. {
  597.     if (m_bSurfaceRequiresOverlay)
  598.         return TRUE;
  599.     else
  600.         return CWinSurface::_AllowsOverlayShrinking();
  601. }
  602. void CWinSurface2::_WaitForQueuedFrames()
  603. {
  604.     WaitForQueuedFrames();
  605. }
  606. void CWinSurface2::_LockBlitter()
  607. {
  608.     if (m_hSurfaceMutex)
  609.     {
  610.         // In the unlikely event that all of our hw buffers are
  611.         // full AND GetVideoMem is blocking with m_hSurfaceMutex
  612.         // while waiting for the time line to start, break
  613.         // out of the time line wait loop.
  614.         BOOL bOldValue = m_bWaitingForFlush;
  615.         m_bWaitingForFlush = TRUE;
  616.         WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  617.         
  618.         m_bWaitingForFlush = bOldValue;
  619.     }
  620. }
  621. void CWinSurface2::_UnlockBlitter()
  622. {
  623.     if (m_hSurfaceMutex)
  624.         ReleaseMutex(m_hSurfaceMutex);
  625. }
  626. void CWinSurface2::_FlushSurfaces()
  627. {
  628.     Flush();
  629. }
  630. STDMETHODIMP CWinSurface2::SetProperties(HXBitmapInfoHeader* bmi,
  631.                                         REF(UINT32) ulNumBuffers,
  632.                                         IHXRenderTimeLine* pTimeLine)
  633. {
  634.     // Block GetVideoMem calls
  635.     WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  636.     ulNumBuffers = min(m_nMaxBackBuffers+1, (INT32)ulNumBuffers);
  637.       
  638.     CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  639.     if (!pSurface)
  640.     {
  641.         ReleaseMutex(m_hSurfaceMutex);
  642.         return HXR_FAIL;
  643.     }
  644.     WINDRAW* pWindraw = pSurface->GetWinDraw();    
  645.     
  646.     // If we already have surfaces, destroy and recreate if necessary
  647.     if (m_hRenThread)
  648.     {
  649.         if (bmi->biWidth != m_bmi.biWidth ||
  650.             bmi->biHeight != m_bmi.biHeight ||
  651.             m_surface.dwBackBufferCount == 0 ||
  652.             ulNumBuffers != (UINT32)m_nBackBufferCount+1 ||
  653.             WAIT_OBJECT_0 != WaitForSingleObject(m_hReinit, 0))
  654.         {
  655.             // Wait for display buffers to render
  656.             if (HXR_OK != WaitForQueuedFrames())
  657.                 Flush();
  658.             DestroySurfaces();
  659.             m_nBackBufferCount = 0;
  660.             memset(&m_bmi, 0, sizeof(m_bmi));
  661.             memset(&m_lastSrcRect, 0, sizeof(m_lastSrcRect));
  662.         }
  663.         else
  664.         {
  665.             HX_RELEASE(m_pTimeLine);
  666.             m_pTimeLine = pTimeLine;
  667.             if (m_pTimeLine)
  668.                 m_pTimeLine->AddRef();
  669.             
  670.             m_bVideoSurface2 = TRUE;
  671.             // If we are keeping our existing video buffers, reset
  672.             // the flipping chain indexes if we have DirectDraw.
  673.             if (!m_bLostHWAcceleration)
  674.                 WinDraw_ResetSurfaceIndexes(pWindraw, &m_surface);
  675.             ReleaseMutex(m_hSurfaceMutex);
  676.             return HXR_OK;
  677.         }
  678.     }
  679.     
  680.     // If we do not have a render thread and we have an optimized
  681.     // format, we are in VS1 mode so fail the VS2 init.
  682.     else if (m_pOptimizedFormat)
  683.     {
  684.         ReleaseMutex(m_hSurfaceMutex);
  685.         return HXR_FAIL;
  686.     }
  687.     // Try and create an overlay flpping chain of pRequest->nNumBuffers buffers
  688.     m_nBackBufferCount = ulNumBuffers - 1;
  689.     if (m_nBackBufferCount)
  690.         m_bFlipOverlay = TRUE;
  691.     m_bSpamUpdateOverlay = FALSE;
  692.     
  693.     int cid = GetBitmapColor((LPBITMAPINFO)bmi);
  694.     BOOL bRestore = SetYUVPriorityList(cid);
  695.     BeginOptimizedBlt(bmi);
  696.     int nBltMode = m_nBltMode;
  697.     if (bRestore)
  698.         RestoreColorspacePriorities(cid);
  699.     if (nBltMode != HX_OVERLAY_BLT ||
  700.         !m_nBackBufferCount)
  701.     {
  702.         DestroySurfaces();
  703.         ulNumBuffers = 0;
  704.         m_bVideoSurface2 = FALSE;
  705.         
  706.         ReleaseMutex(m_hSurfaceMutex);
  707.         return HXR_FAIL;
  708.     }
  709.     m_nOverlayBackBuffersCreated = m_nBackBufferCount;
  710.     bmi->biCompression = MapCIDtoFourCC(m_nSurfaceCID);
  711.     // How odd, a dd driver that returns the wrong caps.
  712.     // I have not seen anything like since the last time I tried
  713.     // to use the caps.
  714.     //
  715.     // We will always try interval flips and swith to flip
  716.     // waits if flip returns an error.
  717. #if DIRECTDRAW_VERSION > 0x0500
  718.     // Can we use the flip interval flag
  719.     if ((pWindraw->dd.m_caps.dwCaps2 & DDCAPS2_FLIPINTERVAL) != DDCAPS2_FLIPINTERVAL)
  720.     {
  721.         m_bUseVBlankFlip = FALSE;
  722.     }
  723. #else
  724.     m_bUseVBlankFlip = FALSE;
  725. #endif
  726.     if (pWindraw->dwMaxScanLine && pWindraw->dMsPerVBlank > 0.0)
  727.         m_bOptimalVideoScheduler = TRUE;
  728.     
  729.     // If we are using a DirectDraw surface represented by a structure,
  730.     // several of our post-processing functions will not work. Set the
  731.     // various modes here.  While we are generalizing here, most of
  732.     // these surface types are proprietary so disable anything suspicious.
  733.     if (IsStructured(m_nSurfaceCID))
  734.     {
  735.         m_bUseDDColorControls = TRUE;
  736.         m_bSurfaceRequiresOverlay = TRUE;
  737.         // Set default DD color controls
  738.         m_Brightness = DEF_BRIGHTNESS;
  739.         m_Contrast = DEF_CONTRAST;
  740.         m_Saturation = DEF_SATURATION;
  741.         m_Hue = DEF_HUE;
  742.         m_Sharpness = DEF_SHARPNESS;
  743.     }
  744.     else
  745.     {
  746.         m_bUseDDColorControls = FALSE;
  747.         m_bSurfaceRequiresOverlay = FALSE;
  748.     }
  749.     memset(&m_rcLast, 0, sizeof(m_rcLast));
  750.     // Store actual settings
  751.     m_bmi = *bmi;
  752.     // for _ConstructRects
  753.     m_bmiLastBlt = m_bmi;
  754.     m_bVideoSurface2 = TRUE;
  755.     
  756.     // Schedule a recompute clip after I set m_bmiLastBlt to remove
  757.     // deafault alpha site.  This prevents us from playing in alpha
  758.     // blending mode for local clips.
  759.     if(m_pSite->m_pTopLevelSite)
  760.         m_pSite->m_pTopLevelSite->ScheduleCallback(CLIP, 0);
  761.     m_bmi.biSizeImage = m_nDDSurfaceSize;
  762.     m_bmi.biWidth = m_surfaceSize.cx;
  763.     m_bmi.biHeight = m_surfaceSize.cy;
  764.     m_bmi.biCompression = m_nSurfaceCID;
  765.     ulNumBuffers = m_nBackBufferCount+1;
  766. #ifdef _DEBUG
  767.     char szTmp[128]; /* Flawfinder: ignore */
  768.     char acid[5][5] = {{"I420"}, {"YV12"}, {"YVU9"}, {"YUY2"}, {"UYVY"}}; /* Flawfinder: ignore */
  769.     char dvpf[5] = "DVPF"; /* Flawfinder: ignore */
  770.     char *pCurrent = dvpf;
  771.     if (m_nSurfaceCID < 5)
  772.         pCurrent = acid[m_nSurfaceCID];
  773.         
  774.     wsprintf(szTmp, "SetProperties Create %ld %s buffersn", ulNumBuffers, pCurrent);
  775.     OutputDebugString(szTmp);
  776. #endif
  777.     HXxSize rcSize = {m_bmi.biWidth, m_bmi.biHeight};
  778.     CreateFallbackSurface(m_nSurfaceCID, &rcSize);
  779.     // Kill render thread if running
  780.     if (m_hRenThread)
  781.     {
  782.         m_bCont = FALSE;
  783.         SetEvent(m_hAbort);
  784.         WaitForSingleObject(m_hRenThread, INFINITE);
  785.         CloseHandle(m_hRenThread);
  786.         m_hRenThread = 0;
  787.         CloseHandle(m_hFrameSem);
  788.         m_hFrameSem = 0;
  789.     }
  790.     HX_RELEASE(m_pTimeLine);
  791.     m_pTimeLine = pTimeLine;
  792.     if (m_pTimeLine)
  793.         m_pTimeLine->AddRef();
  794.     
  795.     // Create the render thread
  796.     DWORD   dwId;
  797.     m_bCont = TRUE;
  798.     ResetEvent(m_hAbort);
  799.     m_hFrameSem = CreateSemaphore(NULL, 0, ulNumBuffers+1, NULL);
  800.     m_hRenThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE )ThreadProc,
  801.                                 this, 0, &dwId);
  802.     if (m_bBoostRenderThread)
  803.         SetThreadPriority(m_hRenThread, THREAD_PRIORITY_TIME_CRITICAL);
  804.     ReleaseMutex(m_hSurfaceMutex);
  805.     return HXR_OK;
  806. }
  807. BOOL CWinSurface2::SetYUVPriorityList(int cidIn)
  808. {
  809.     IHXPreferences*    pPreferences    = NULL;
  810.     IHXBuffer*         pBuffer         = NULL;
  811.     BOOL bUsePriorityScheme = TRUE;
  812.     BOOL bRestore = FALSE;
  813.     BOOL bUseHWPF = FALSE;
  814.     if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
  815.     {   
  816.         // Disalbe our surface priority scheme?
  817.         if (pPreferences->ReadPref("VideoBoost\DisableSurfacePriority", pBuffer) == HXR_OK)
  818.         {
  819.             bUsePriorityScheme = !(::atoi((char*) pBuffer->GetBuffer()) == 1);
  820.         }
  821.         HX_RELEASE(pBuffer);
  822.         HX_RELEASE(pPreferences);
  823.     }
  824.     // Set the priority for the yuv format we use
  825.     if (bUsePriorityScheme)
  826.     {
  827.         int aList[5] = {0,0,0,0,0};
  828.         int *pList = aList;
  829.         int nListSize = 5;
  830.         bRestore = FALSE;
  831.     
  832.         if (NOERROR == WinDraw2_GetColorspacePriorities(cidIn, pList, nListSize) && nListSize)
  833.         {
  834.             SetColorspacePriorities(aList, nListSize, cidIn);
  835.             bRestore = TRUE;
  836.         }
  837.     }
  838.     return bRestore;
  839. }
  840. STDMETHODIMP CWinSurface2::GetVideoMem(VideoMemStruct* pVidStruct,
  841.                                       UINT32 ulFlags)
  842. {
  843.     memset(pVidStruct, 0, sizeof(*pVidStruct));
  844.     HXBitmapInfoHeader* bmi = &pVidStruct->bmi;
  845.     UCHAR* pVidMem;
  846.     INT32 nPitch = 0;
  847.     // If we lost our surface, re-create them (if we are not
  848.     // in the process of switching overlay via the OverlayManager or
  849.     // in gdi because we lost DirectDraw).
  850.     if (!m_surface.dd.lpDDSurface &&
  851.         !m_bFallbackSurfaceCreated &&
  852.         !m_bSwitchingingOverlay &&
  853.         !m_bLostHWAcceleration)
  854.     {                     
  855.         // Make sure we have no locked surfaces
  856.         if (WAIT_OBJECT_0 != WaitForSingleObject(m_hSurfaceMutex, 0))
  857.         {
  858.             if (ulFlags & HX_WAIT_NEVER)
  859.                 return HXR_BUFFER_NOT_AVAILABLE;
  860.             WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  861.         }        
  862.         ReInitSurfaces();
  863.         // Did not work...return an error
  864.         if (!m_surface.dd.lpDDSurface &&
  865.             !m_bFallbackSurfaceCreated &&
  866.             !m_bGdiSurfaceCreated)
  867.         {
  868.             ReleaseMutex(m_hSurfaceMutex);
  869.             return HXR_BUFFER_NOT_AVAILABLE;
  870.         }
  871.         ReleaseMutex(m_hSurfaceMutex);
  872.     }
  873.     // Return an error if there are not buffers available
  874.     if (ulFlags & HX_WAIT_NEVER)
  875.     {
  876.         // Check m_hReinit is signaled.  If not, return an error
  877.         if (WAIT_OBJECT_0 != WaitForSingleObject(m_hReinit, 0))
  878.             return HXR_BUFFER_NOT_AVAILABLE;
  879.         
  880.         // Make sure we have no locked surfaces
  881.         if (WAIT_OBJECT_0 != WaitForSingleObject(m_hSurfaceMutex, 0))
  882.             return HXR_BUFFER_NOT_AVAILABLE;
  883.         // If we lost our surface, return an error
  884.         if (!m_surface.dd.lpDDSurface &&
  885.             !m_bFallbackSurfaceCreated &&
  886.             !m_bGdiSurfaceCreated)
  887.         {
  888.             ReleaseMutex(m_hSurfaceMutex);
  889.             return HXR_BUFFER_NOT_AVAILABLE;
  890.         }
  891.     }
  892.     // Wait until a buffer is available
  893.     else
  894.     {
  895.         // Wait until our surfaces are created
  896.         WaitForSingleObject(m_hReinit, INFINITE);
  897.         
  898.         // Wait for last lock
  899.         WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  900.         // If we lost our surface, return an error
  901.         if (!m_surface.dd.lpDDSurface &&
  902.             !m_bFallbackSurfaceCreated &&
  903.             !m_bGdiSurfaceCreated)
  904.         {
  905.             ReleaseMutex(m_hSurfaceMutex);
  906.             return HXR_BUFFER_NOT_AVAILABLE;
  907.         }
  908.     }
  909.     if (m_bFlushing || m_bWasInVidSurf2)
  910.     {
  911.         ReleaseMutex(m_hSurfaceMutex);
  912.         return HXR_BUFFER_NOT_AVAILABLE;
  913.     }
  914.     INT32 nIndex = -1;
  915.     HX_RESULT hr = HXR_OK;
  916.     pVidMem = NULL;
  917.     nPitch = 0;
  918.     if (m_pSite->_BordersActive() | 
  919.         m_pSite->_FadeTransitionActive() |
  920.         (m_pSite->AreVideoControlsActive() && !m_bUseDDColorControls) |
  921.         m_pSite->IsHigherZOrderTranstitionActive() |
  922.         (m_LinkedSites.GetCount() > 0) |
  923.         (m_pLinkedOverlay != NULL))
  924.     {
  925.         // Drop to VideoSurface1 for transitions
  926.         if (m_pSite->m_pUser)
  927.         {
  928.             //Can't satisfy a HX_WAIT_NEVER and block without a
  929.             //response object. :-)
  930.             if( ulFlags & HX_WAIT_NEVER )
  931.             {
  932.                 ReleaseMutex(m_hSurfaceMutex);
  933.                 return HXR_BUFFER_NOT_AVAILABLE;
  934.             }
  935.             
  936.             HXxEvent event = {HX_SURFACE_MODE_CHANGE, NULL, NULL,
  937.                               (void*)HX_VIDEOSURFACE1_RECOMMENDED, 0, 0};
  938.         
  939.             m_bWasInVidSurf2 = TRUE;
  940.             _WaitForFlush();
  941.             // Unlock the surface mutex so we can be torn down
  942.             ReleaseMutex(m_hSurfaceMutex);
  943.             
  944.             m_pSite->m_pUser->HandleEvent(&event);
  945.             // The renderer switched to VideoSurface1 so don't give them a buffer
  946.             if (event.handled)
  947.             {
  948.                 // Reset or last scale since we are not bltting for a time
  949.                 m_dLastXScale = 0.0;
  950.                 m_dLastYScale = 0.0;
  951.                 return HXR_BUFFER_NOT_AVAILABLE;
  952.             }
  953.             else
  954.             {
  955.                 m_bWasInVidSurf2 = FALSE;
  956.                 
  957.                 // Need to lock the mutex since the switch failed
  958.                 WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  959.                 CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  960.                 WINDRAW* pWindraw = pSurface->GetWinDraw();    
  961.                 
  962.                 WinDraw_ResetSurfaceIndexes(pWindraw, &m_surface);
  963.             }
  964.         }
  965.     }
  966.     // Can we restore DirectDraw
  967.     if (m_bLostHWAcceleration)
  968.     {
  969.         CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();        
  970.         m_bLostHWAcceleration = !pSurface->_IsHardwareAccelerationAvail();
  971.         
  972.         if (!m_bLostHWAcceleration)
  973.         {
  974.             if (HXR_OK != WaitForQueuedFrames())
  975.                 Flush();
  976.             DestroyGdiSurface();
  977.             pSurface->_AcquireHardwareAcceleration();
  978.             ReInitSurfaces();
  979.         }
  980.     }
  981. LOCK_VIDEO_BUFFER:
  982.     int nBltMode = GetBestBltMode();
  983.     BOOL bLockTLSMutex = FALSE;
  984.     bLockTLSMutex = CanLockSurface(nIndex, nBltMode, (ulFlags & HX_WAIT_NEVER) != HX_WAIT_NEVER);
  985.     
  986.     if (m_bFlushing)
  987.     {
  988.         ReleaseMutex(m_hSurfaceMutex);
  989.         return HXR_BUFFER_NOT_AVAILABLE;
  990.     }
  991.     if (bLockTLSMutex)
  992.     {
  993.         BOOL bRet = m_pSite->_TLSIsLocked();
  994.         if( bRet && (ulFlags&HX_WAIT_NEVER) )
  995.         {
  996.             ReleaseMutex(m_hSurfaceMutex);
  997.             return HXR_BUFFER_NOT_AVAILABLE;
  998.         }
  999.         m_pSite->_TLSLock();
  1000.     }
  1001.     else if (ulFlags & HX_WAIT_NEVER)
  1002.     {
  1003.         ReleaseMutex(m_hSurfaceMutex);
  1004.         return HXR_BUFFER_NOT_AVAILABLE;
  1005.     }
  1006.     else
  1007.     {
  1008.         //XXXgfw Removing a noisy assert for now. It appears that
  1009.         //NVidea GForce 2 MX 100/200 cards will fail to lock a surface
  1010.         //while resizing a video. This failure does not lead to video
  1011.         //artifacts or any other visible problems. However, with the
  1012.         //assert it makes it nearly impossible to debug. 
  1013.         //HX_ASSERT(!bLockTLSMutex && (ulFlags & HX_WAIT_FOREVER));
  1014. // Some "error" is preventing us from locking the surface
  1015.         ReleaseMutex(m_hSurfaceMutex);
  1016.         return HXR_BUFFER_NOT_AVAILABLE;
  1017.     }
  1018.     // Use system mem if selected
  1019.     if (m_bUseSysMemSurface)
  1020.     {
  1021.         hr = LockSysMemSurface(pVidMem, nPitch, (ulFlags & HX_WAIT_NEVER) != HX_WAIT_NEVER);
  1022.         
  1023.         if (HXR_OK == hr)
  1024.         {
  1025.             //m_bmi.biCompression = m_nSysMemSurfID;
  1026.             m_bmi.biWidth = m_allocatedSysMemSurfSize.cx;
  1027.             m_bmi.biHeight = m_allocatedSysMemSurfSize.cy;
  1028.             *bmi = m_bmi;
  1029.             bmi->biCompression = m_nSysMemSurfID;
  1030.         }
  1031.     }
  1032.     // If DD is not avail, use rgb blts
  1033.     else if (nBltMode == HX_BASIC_BLT)
  1034.     {
  1035.         hr = LockGdiSurface(pVidMem, nPitch, (ulFlags & HX_WAIT_NEVER) != HX_WAIT_NEVER);
  1036.         
  1037.         if (HXR_OK == hr)
  1038.         {
  1039.             MakeBitmap((LPBITMAPINFO)&m_bmi, sizeof(BMI), m_nGdiSurfaceCID,
  1040.              m_allocatedGdiSize.cx, m_allocatedGdiSize.cy, NULL, NULL);
  1041.             
  1042.             *bmi = m_bmi;
  1043.             m_bmiLastBlt = m_bmi;
  1044.         }
  1045.         else if (DDERR_WRONGMODE == hr)
  1046.         {
  1047.             HandleDisplayModeChange();
  1048.         }
  1049.     }
  1050.     // If overlay is not enabled, use offscreen memory
  1051.     else if (nBltMode == HX_BLT_YUV_STRETCH)
  1052.     {
  1053.         hr = LockFallbackSurface(pVidMem, nPitch, (ulFlags & HX_WAIT_NEVER) != HX_WAIT_NEVER);
  1054.         if (HXR_OK == hr)
  1055.         {
  1056.             m_nScratchIndex = nIndex;
  1057.             MakeBitmap((LPBITMAPINFO)&m_bmi, sizeof(BMI), m_nFallbackSurfaceCID,
  1058.              m_allocatedFallbackSize.cx, m_allocatedFallbackSize.cy, NULL, NULL);
  1059.             
  1060.             *bmi = m_bmi;
  1061.             m_bmiLastBlt = m_bmi;
  1062.             // Restore thread priority
  1063.             if (m_nLastBltMode == HX_BASIC_BLT && m_bBoostRenderThread)
  1064.                 SetThreadPriority(m_hRenThread, THREAD_PRIORITY_TIME_CRITICAL);
  1065.         }
  1066.         else if (DDERR_WRONGMODE == hr)
  1067.         {
  1068.             HandleDisplayModeChange();
  1069.         }
  1070.         // Check if we lost DirectDraw
  1071.         else
  1072.         {
  1073.             if (HandleDirectDrawLoss(bLockTLSMutex))
  1074.             {
  1075.                 if (bLockTLSMutex)
  1076.                     bLockTLSMutex = FALSE;
  1077.                 goto LOCK_VIDEO_BUFFER;
  1078.             }
  1079.         }
  1080.     }
  1081.     else
  1082.     {
  1083.         CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  1084.         WINDRAW* pWindraw = pSurface->GetWinDraw();    
  1085.         
  1086.         hr = WinDraw_GetLockedSurface(pWindraw, &m_surface, pVidMem, nIndex,
  1087.                                       (ulFlags & HX_WAIT_NEVER) != HX_WAIT_NEVER);
  1088.         
  1089.         if (pVidMem)
  1090.         {
  1091.             nPitch = m_surface.dd.lPitch;
  1092.             MakeBitmap((LPBITMAPINFO)&m_bmi, sizeof(BMI), m_nSurfaceCID,
  1093.              m_surfaceSize.cx, m_surfaceSize.cy, NULL, NULL);
  1094.             *bmi = m_bmi;
  1095.             m_bmiLastBlt = m_bmi;
  1096.             if (m_pHwMemObj)
  1097.             {
  1098.                 pVidMem = (UCHAR*)m_pHwMemObj->DeviceToRenderer(pVidMem, nPitch);
  1099.             }
  1100.             // Restore thread priority
  1101.             if (m_nLastBltMode == HX_BASIC_BLT && m_bBoostRenderThread)
  1102.                 SetThreadPriority(m_hRenThread, THREAD_PRIORITY_TIME_CRITICAL);
  1103.         }
  1104.         
  1105.         // If the display mode was changed on us, destory and recreate the surfaces
  1106.         else if (DDERR_WRONGMODE == hr)
  1107.         {
  1108.             HandleDisplayModeChange();
  1109.         }
  1110.         
  1111.         // Could not lock a surface
  1112.         else if (DDERR_WASSTILLDRAWING == hr)
  1113.         {
  1114.             hr = HXR_BUFFER_NOT_AVAILABLE;
  1115.         }
  1116.         // Check if we lost DirectDraw
  1117.         else
  1118.         {
  1119.             if (HandleDirectDrawLoss(bLockTLSMutex))
  1120.             {
  1121.                 if (bLockTLSMutex)
  1122.                     bLockTLSMutex = FALSE;
  1123.                 goto LOCK_VIDEO_BUFFER;
  1124.             }
  1125.             else
  1126.             {
  1127.                 // Turn off overlay
  1128.                 m_bMultipleOverlay = TRUE;
  1129.                 if (bLockTLSMutex)
  1130.                     m_pSite->_TLSUnlock();
  1131.                 goto LOCK_VIDEO_BUFFER;
  1132.             }
  1133.         }
  1134.     }
  1135.     if (HXR_OK == hr)
  1136.     {
  1137.         // TLS mutex should be locked here...
  1138.         HX_ASSERT(bLockTLSMutex);
  1139.         // Since RGB formats are not supported in MapFourCCtoCID,
  1140.         // store the CID in biCompression.
  1141.         if (!IsYUV(MapFourCCtoCID(m_bmi.biCompression)))
  1142.         {
  1143.             bmi->biCompression = GetBitmapColor((LPBITMAPINFO)&m_bmi);
  1144.         }
  1145.         // Do we need an alpha blending region
  1146.         if (m_bDoAlphaCheck && !m_pHwMemObj)
  1147.         {
  1148.             CreateAlphaList(pVidStruct);
  1149.         }
  1150.         pVidStruct->pVidMem = pVidMem;
  1151.         pVidStruct->lPitch = nPitch;
  1152.     }
  1153.     else
  1154.     {
  1155.         // Did not lock a surface
  1156.         ReleaseMutex(m_hSurfaceMutex);
  1157.         hr = HXR_FAIL;
  1158.         if (bLockTLSMutex)
  1159.         {
  1160.             m_pSite->_TLSUnlock();
  1161.         }                                   
  1162.     }
  1163.     return hr;
  1164. }
  1165. STDMETHODIMP CWinSurface2::ColorConvert(INT32  fourCCIn, 
  1166.                                        HXxSize *pSrcSize,
  1167.                                        HXxRect *prSrcRect,
  1168.                                        SourceInputStruct *pInput,
  1169.                                        INT32   fourCCOut,
  1170.                                        UCHAR   *pDestBuffer, 
  1171.                                        HXxSize *pDestSize, 
  1172.                                        HXxRect *prDestRect, 
  1173.                                        int     nDestPitch)
  1174. {
  1175.     // If the dest surface is a normal buffer, perform the transfer
  1176.     if (!IsStructured(MapFourCCtoCID(fourCCOut)))
  1177.         return CVideoSurface2::ColorConvert(fourCCIn, pSrcSize, prSrcRect,
  1178.                                             pInput, fourCCOut, pDestBuffer, 
  1179.                                             pDestSize, prDestRect, nDestPitch);
  1180.     // Handle this proprietary surface write
  1181.     HX_ASSERT(m_pHwMemObj);
  1182.     m_pHwMemObj->ProcessCommand((UCHAR*)pInput,
  1183.                                 fourCCIn, 
  1184.                                 pSrcSize,
  1185.                                 prSrcRect,
  1186.                                 pDestBuffer,
  1187.                                 fourCCOut,
  1188.                                 pDestSize, 
  1189.                                 prDestRect);
  1190.     // Need to set pItem->bAlpha if we blended the frame!!!
  1191.     if (m_pHwMemObj->QueryOperation() & PERFORMED_HW_ALPHA_BLEND)
  1192.     {
  1193.         m_bFrameHasHWAlphaBlend = TRUE;
  1194.     }
  1195.     if (m_bUseDDColorControls)
  1196.     {
  1197.         m_pSite->CheckColorSettings();
  1198.         // Did color controls change
  1199.         float fBright = m_pSite->GetBrightness();
  1200.         float fContrast = m_pSite->GetContrast();
  1201.         float fSaturation = m_pSite->GetSaturation();
  1202.         float fHue = m_pSite->GetHue();
  1203.         float fSharpness = m_pSite->GetSharpness();
  1204.     
  1205.         if (m_Brightness != fBright ||
  1206.             m_Contrast != fContrast ||
  1207.             m_Saturation != fSaturation ||
  1208.             m_Hue != fHue ||
  1209.             m_Sharpness != fSharpness)
  1210.         {
  1211.             CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  1212.             WINDRAW* pWindraw = pSurface->GetWinDraw();    
  1213.         
  1214.             // Change DD color controls
  1215.             WinDrawSurface_SetColorControls(pWindraw,
  1216.                                             &m_surface,
  1217.                                             fBright,
  1218.                                             fContrast,
  1219.                                             fSaturation,
  1220.                                             fHue,
  1221.                                             fSharpness);
  1222.             m_Brightness = fBright;
  1223.             m_Contrast = fContrast;
  1224.             m_Saturation = fSaturation;
  1225.             m_Hue = fHue;
  1226.             m_Sharpness = fSharpness;
  1227.         }
  1228.     }
  1229.     return HXR_OK;
  1230. }
  1231. BOOL CWinSurface2::CanLockSurface(INT32 nIndex, int nBltMode, BOOL bBlock)
  1232. {
  1233.     UCHAR* pVidMem;
  1234.     HRESULT hr = HXR_FAIL;
  1235.     if (m_bUseSysMemSurface)
  1236.     {
  1237.         if (m_pSysMemSurf)
  1238.         {
  1239.             if (bBlock)
  1240.             {
  1241.                 HANDLE  aWait[2] = {m_pSysMemSurf[m_nNextSysMemBuffer].hEmpty, m_hAbort};
  1242.                 hr = WaitForMultipleObjects(2, aWait, FALSE, INFINITE);
  1243.             }
  1244.             else
  1245.                 hr = WaitForSingleObject(m_pSysMemSurf[m_nNextSysMemBuffer].hEmpty, 0);
  1246.     
  1247.             if (WAIT_OBJECT_0 == hr)
  1248.                 hr = HXR_OK;
  1249.         }
  1250.         else
  1251.             hr = HXR_OK;
  1252.     }
  1253.     // If DD is not avail, use rgb blts
  1254.     else if (HX_BASIC_BLT == nBltMode)
  1255.     {
  1256.         if (m_bGdiSurfaceCreated)
  1257.         {
  1258.             if (bBlock)
  1259.             {
  1260.                 HANDLE  aWait[2] = {m_GDIsurface.gdi.lpGDIBackBuffer[m_nNextGdiSurface]->hEmpty, m_hAbort};
  1261.                 hr = WaitForMultipleObjects(2, aWait, FALSE, INFINITE);
  1262.             }
  1263.             else
  1264.                 hr = WaitForSingleObject(m_GDIsurface.gdi.lpGDIBackBuffer[m_nNextGdiSurface]->hEmpty, 0);
  1265.     
  1266.             if (WAIT_OBJECT_0 == hr)
  1267.                 hr = HXR_OK;
  1268.         }
  1269.         else
  1270.             hr = HXR_OK;
  1271.     }    
  1272.     else if (HX_BLT_YUV_STRETCH == nBltMode)
  1273.     {
  1274.         if (bBlock)
  1275.         {
  1276.             HANDLE  aObjects[2] = {m_hFallbackEmpty, m_hAbort};
  1277.             hr = WaitForMultipleObjects(2, aObjects, FALSE, INFINITE);
  1278.         }
  1279.         else
  1280.             hr = WaitForSingleObject(m_hFallbackEmpty, 0);
  1281.         if (WAIT_OBJECT_0 == hr)
  1282.             hr = HXR_OK;
  1283.     }
  1284.     else
  1285.     {
  1286.         CWinBaseRootSurface* pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  1287.         WINDRAW* pWindraw = pSurface->GetWinDraw();    
  1288.         int nNextIndex = nIndex;
  1289.         hr = WinDraw_CanLockSurface(pWindraw, &m_surface, pVidMem, nNextIndex, bBlock);
  1290.     }
  1291.     if (hr == HXR_OK)
  1292.         return TRUE;
  1293.     else    
  1294.         return FALSE;
  1295. }
  1296. STDMETHODIMP CWinSurface2::ReleaseVideoMem(VideoMemStruct* pVidStruct)
  1297. {
  1298.     return ReleaseSurface(pVidStruct, TRUE);
  1299. }
  1300. STDMETHODIMP CWinSurface2::Present(VideoMemStruct *pVidStruct,
  1301.                                    INT32 lTime,
  1302.                                    UINT32 ulFlags,
  1303.                                    HXxRect *prDestRect,
  1304.                                    HXxRect *prSrcRect)
  1305. {
  1306. //#define _DEBUG_TIMEAHEAD
  1307. #ifdef _DEBUG_TIMEAHEAD
  1308.     UINT32 ulCurrentTime;
  1309.     HRESULT timelineResult = m_pTimeLine->GetTimeLineValue(ulCurrentTime);
  1310.     static INT32 lMaxQueueAhead = 0;
  1311.     if ((timelineResult != HXR_TIMELINE_SUSPENDED) 
  1312.         && (lTime - (INT32) ulCurrentTime) > lMaxQueueAhead)
  1313.     {
  1314.         lMaxQueueAhead = lTime - (INT32) ulCurrentTime;
  1315.         HX_TRACE("New max queue ahead: %d", lMaxQueueAhead);
  1316.     }
  1317. #endif // _DEBUG_TIMEAHEAD
  1318.     if (m_bWasInVidSurf2) 
  1319.         return HXR_FAIL;
  1320.     m_pSite->m_bBltHasBeenCalled = TRUE;
  1321.     if (ulFlags & HX_MODE_IMMEDIATE)
  1322.     {
  1323.         if (m_pListOfFrames->GetCount())
  1324.             return HXR_FAIL;
  1325.         else if( (HXEmptyRegion(m_pSite->m_Region) && !pVidStruct->ulCount  && !m_bFrameHasHWAlphaBlend)
  1326.                  || !m_pSite->IsSiteVisible())
  1327.             return HXR_COULD_NOT_DISPLAY;
  1328.         else
  1329.         {
  1330.             lTime = 0;
  1331.         }
  1332.     }
  1333.     else if (ulFlags & HX_MODE_REFRESH)
  1334.     {
  1335.         HRESULT hr = HXR_FAIL;
  1336.         // We do not have a visible region so we can not refresh
  1337.         if( (HXEmptyRegion(m_pSite->m_Region) ) || !m_pSite->IsSiteVisible())
  1338.             return HXR_COULD_NOT_DISPLAY;
  1339.         
  1340.         // We have not displayed a frame yet so we can not refresh
  1341.         else if (HX_NO_BLT == m_nLastBltMode)
  1342.             return HXR_COULD_NOT_DISPLAY;
  1343.         
  1344.         // If we are waiting on a surface re-init, fail
  1345.         else if (WAIT_OBJECT_0 != WaitForSingleObject(m_hReinit, 0))
  1346.             return HXR_BUFFER_NOT_AVAILABLE;
  1347.         
  1348.         else if (HX_OVERLAY_BLT == m_nLastBltMode)
  1349.         {
  1350.             // Need to lose overlay...so fail the refresh
  1351.             if ((IsShrinking() && !_AllowsOverlayShrinking()) ||
  1352.                 m_bMultipleOverlay)
  1353.                 return HXR_FAIL;
  1354.         }
  1355.         else if (HX_BLT_YUV_STRETCH == m_nLastBltMode)
  1356.         {
  1357.             // Need to restore overlay...so fail the refresh
  1358.             if ((!IsShrinking() || _AllowsOverlayShrinking()) &&
  1359.                 !m_bMultipleOverlay)
  1360.                 return HXR_FAIL;
  1361.         }
  1362.         int      nNumRects   = 0;
  1363.         HXxRect* paSrcRects  = NULL;
  1364.         HXxRect* paDestRects = NULL;
  1365.         
  1366.         // Try to display a queued frame
  1367.         if (m_pListOfFrames->GetCount())
  1368.         {
  1369.             hr = PresentIfReady();
  1370.         }
  1371.         
  1372.         if (hr != HXR_OK)
  1373.         {
  1374.             CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  1375.             if (!pSurface)
  1376.                 return HXR_FAIL;
  1377.             WINDRAW *pWindraw = pSurface->GetWinDraw();
  1378.             
  1379.             // If no dest rect is specified, use surface
  1380.             if (!prDestRect->right && !prDestRect->bottom)
  1381.             {
  1382.                 HXxSize rcSize = {0,0};
  1383.                 m_pSite->GetSize(rcSize);
  1384.     
  1385.                 prDestRect->right = rcSize.cx;
  1386.                 prDestRect->bottom = rcSize.cy;
  1387.             }
  1388.             
  1389.             // Refresh the last rgb image
  1390.             //if (m_bLostHWAcceleration)
  1391.             if (HX_BASIC_BLT == m_nLastBltMode)
  1392.             {
  1393.                 // Do we have a gdi surface to refresh
  1394.                 if (m_nLastGdiSurface >= 0)
  1395.                 {
  1396.                     // If no src rect is specified, use surface
  1397.                     if (!prSrcRect->right && !prSrcRect->bottom)
  1398.                     {
  1399.                         prSrcRect->right = m_allocatedGdiSize.cx;
  1400.                         prSrcRect->bottom = m_allocatedGdiSize.cy;
  1401.                     }
  1402.                     SetLastScale(prSrcRect, prDestRect);
  1403.                 
  1404.                     _ConstructRects( *prSrcRect,
  1405.                                      *prDestRect,
  1406.                                      FALSE,
  1407.                                      nNumRects,
  1408.                                      &paSrcRects,
  1409.                                      &paDestRects);
  1410.                     memcpy(&m_lastSrcRect, paSrcRects, sizeof(*paSrcRects)); /* Flawfinder: ignore */
  1411.                     // Do an rgb blt for each display rect
  1412.                     for( int j=0 ; j<nNumRects ; j++ )
  1413.                     {
  1414.                         hr = WinDrawSurface_Blt(pWindraw, &m_GDIsurface, (RECT*)&paDestRects[j], (RECT*)&paSrcRects[j], m_nLastGdiSurface);
  1415.                     }
  1416.                     HX_VECTOR_DELETE(paSrcRects);
  1417.                     HX_VECTOR_DELETE(paDestRects);
  1418.                 }
  1419.             }
  1420.             
  1421.             // If we have a visible overlay, update it
  1422.             else if (WinDraw2_IsSurfaceVisible(pWindraw, &m_surface) && !m_bYUVBlending)
  1423.             {
  1424.                 // If no src rect is specified, use surface
  1425.                 if (!prSrcRect->right && !prSrcRect->bottom)
  1426.                 {
  1427.                     prSrcRect->right = m_surfaceSize.cx;
  1428.                     prSrcRect->bottom = m_surfaceSize.cy;
  1429.                 }
  1430.                 SetLastScale(prSrcRect, prDestRect);
  1431.                 _ConstructRects( *prSrcRect,
  1432.                                  *prDestRect,
  1433.                                  FALSE,
  1434.                                  nNumRects,
  1435.                                  &paSrcRects,
  1436.                                  &paDestRects);
  1437.                 if (nNumRects != 1)
  1438.                 {
  1439.                     HXxPoint screenOffset = m_pSite->GetScreenOffset();
  1440.                     paSrcRects[0] = *prSrcRect;
  1441.                     paDestRects[0] = *prDestRect;
  1442.                     
  1443.                     paSrcRects[0].left += screenOffset.x;
  1444.                     paSrcRects[0].top += screenOffset.y;
  1445.                     paSrcRects[0].right += screenOffset.x;
  1446.                     paSrcRects[0].bottom += screenOffset.y;
  1447.                 }
  1448.                 
  1449.                 hr = ForceUpdateOverlay( &paDestRects[0],
  1450.                                          &paSrcRects[0], HX_OVER_SHOW|HX_OVER_KEYDEST);
  1451.                 if (HX_NO_BLT == m_nLastBltMode)
  1452.                     hr = HXR_FAIL;
  1453.                 else
  1454.                 {
  1455.                     memcpy(&m_lastSrcRect, paSrcRects, sizeof(*paSrcRects)); /* Flawfinder: ignore */
  1456.                     if (hr == HXR_OK)
  1457.                     {
  1458.                         if (m_bNeedColorKeyFilled && m_pSite->IsSiteVisible())
  1459.                         {
  1460.                             _FillColorKey();
  1461.                         }
  1462.                     }
  1463.                 }
  1464.                 HX_VECTOR_DELETE(paSrcRects);
  1465.                 HX_VECTOR_DELETE(paDestRects);
  1466. #if !defined(_GOLD) && 0
  1467.                 m_TimeStamps.AddSample();
  1468. #endif
  1469.             }
  1470.             else
  1471.             {
  1472.                 // If we are in fallback mode, make them manually redraw
  1473.                 if (m_bFallbackSurfaceCreated && HX_OVERLAY_BLT!=m_nBltMode && !m_bYUVBlending)
  1474.                 {
  1475.                     // If no src rect is specified, use surface
  1476.                     if (!prSrcRect->right && !prSrcRect->bottom)
  1477.                     {
  1478.                         prSrcRect->right = m_allocatedFallbackSize.cx;
  1479.                         prSrcRect->bottom = m_allocatedFallbackSize.cy;
  1480.                     }
  1481.                     SetLastScale(prSrcRect, prDestRect);
  1482.                     _ConstructRects( *prSrcRect,
  1483.                                      *prDestRect,
  1484.                                      FALSE,
  1485.                                      nNumRects,
  1486.                                      &paSrcRects,
  1487.                                      &paDestRects);
  1488.                 
  1489.                     memcpy(&m_lastSrcRect, paSrcRects, sizeof(*paSrcRects)); /* Flawfinder: ignore */
  1490.                     EnterCriticalSection(&m_csFallback);
  1491.                     for( int j=0 ; j<nNumRects ; j++ )
  1492.                     {
  1493.                         hr = WinDrawSurface_Blt(pWindraw, &m_fallbackSurface, (RECT*)&paDestRects[j], (RECT*)&paSrcRects[j]);
  1494.                     }
  1495.                     LeaveCriticalSection(&m_csFallback);
  1496.         
  1497.                     HX_VECTOR_DELETE(paSrcRects);
  1498.                     HX_VECTOR_DELETE(paDestRects);
  1499. #if !defined(_GOLD) && 0
  1500.                     m_TimeStamps.AddSample();
  1501. #endif
  1502.                 }
  1503.             }
  1504.         }
  1505.     
  1506.         return hr;
  1507.     }
  1508.     if (m_bFlushing)
  1509.     {
  1510.         return HXR_COULD_NOT_DISPLAY;
  1511.     }
  1512.     
  1513.     INT32   nIndex = -1;
  1514.     // Add this frame to the list and alert the render thread
  1515.     tFrameElement *pItem = new tFrameElement;
  1516.     memset(pItem, 0, sizeof(*pItem));
  1517.     pItem->lTimeStamp = lTime;
  1518.     pItem->nBltMode = HX_OVERLAY_BLT;
  1519.     pItem->ulFlags = ulFlags;
  1520.     pItem->rcSrc = *prSrcRect;
  1521.     pItem->rcDst = *prDestRect;
  1522.     pItem->bAlpha = m_bFrameHasHWAlphaBlend;
  1523.     pItem->count  = pVidStruct->ulCount;
  1524.     pItem->bmi = m_bmi;
  1525.     // If we are in system memory mode, we must blt to hardware ourselves
  1526.     if (m_bUseSysMemSurface)
  1527.     {
  1528.         m_bUseSysMemSurface = FALSE;
  1529.         BOOL bAlphaCheck = m_bDoAlphaCheck;
  1530.         // Grab a hw buffer and convert the sys mem image to hw yuv.
  1531.         UCHAR *pScratchVidMem = NULL;
  1532.         INT32 nPitch = 0;
  1533.         HXBitmapInfoHeader bmiTemp;
  1534.         memset( &bmiTemp, 0, sizeof( bmiTemp ) );
  1535.         // We need a hw mem buffer, so disable the alpha blending check
  1536.         // that returns system mem.
  1537.         m_bDoAlphaCheck = FALSE;
  1538.     
  1539.         VideoMemStruct vs;
  1540.         memset(&vs, 0, sizeof(vs));
  1541.         GetVideoMem(&vs, HX_WAIT_FOREVER);
  1542.         pScratchVidMem = vs.pVidMem;
  1543.         nPitch = vs.lPitch;
  1544.         bmiTemp = vs.bmi;
  1545.         if (pScratchVidMem)
  1546.         {
  1547.             HXxSize srcSize = {bmiTemp.biWidth, bmiTemp.biHeight};
  1548.             SourceInputStruct input = {&m_pSysMemSurf[m_nNextSysMemBuffer].pBuffer,
  1549.                                        &m_nSysMemSurfPitch, 1};
  1550.                             
  1551.             ColorConvert(m_nSysMemSurfID,
  1552.                          &m_allocatedSysMemSurfSize,
  1553.                          prSrcRect,
  1554.                          &input,
  1555.                          bmiTemp.biCompression,
  1556.                          pScratchVidMem, 
  1557.                          &srcSize,
  1558.                          prDestRect,
  1559.                          nPitch);
  1560.         
  1561.             ReleaseSurface(&vs, FALSE);
  1562.         }
  1563.     
  1564.         m_bDoAlphaCheck = bAlphaCheck;
  1565.         if (!pScratchVidMem)
  1566.             goto FAILURE;
  1567.     
  1568.         pItem->nIndex = m_nNextSysMemBuffer;
  1569.         if (++m_nNextSysMemBuffer == m_nSysMemSurfCount)
  1570.             m_nNextSysMemBuffer = 0;
  1571.     }
  1572.     // Alpha blend if necessary
  1573.     if (pVidStruct->pAlphaList && pVidStruct->ulCount)
  1574.     {
  1575.         HXxSize size = {pVidStruct->bmi.biWidth, pVidStruct->bmi.biHeight};
  1576.         
  1577.         YuvAlphaBlend(pVidStruct->pAlphaList,
  1578.                       pVidStruct->ulCount,
  1579.                       pVidStruct->pVidMem,
  1580.                       pVidStruct->bmi.biCompression,
  1581.                       pVidStruct->lPitch,
  1582.                       &size);
  1583.     }
  1584.     // If our last lock was not using overlay, use our offscreen blt
  1585.     if (m_bScratchSurface)
  1586.     {
  1587.         if (!m_fallbackSurface.dd.lpDDSurface)
  1588.             goto FAILURE;
  1589.         pItem->nBltMode = HX_BLT_YUV_STRETCH;
  1590.         pItem->pAlphaList = pVidStruct->pAlphaList;
  1591.         ResetEvent(m_hFallbackEmpty);
  1592.     }
  1593.     // Our last lock was using gdi
  1594.     else if (m_bGDISurface)
  1595.     {
  1596.         pItem->nBltMode = HX_BASIC_BLT;
  1597.         pItem->pAlphaList = pVidStruct->pAlphaList;
  1598.         pItem->nIndex = m_nNextGdiSurface;
  1599.     }
  1600.     else
  1601.     {
  1602.         // Advance the overlay surface list
  1603.         int nNewIndex = nIndex;
  1604.         if (!m_surface.dd.lpDDSurface)
  1605.             goto FAILURE;
  1606.         CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  1607.         if (!pSurface)
  1608.             goto FAILURE;
  1609.         WINDRAW *pWindraw = pSurface->GetWinDraw();
  1610.         if (HXR_OK != WinDraw_AdvanceSurface (pWindraw, &m_surface, nNewIndex))
  1611.             goto FAILURE;
  1612.         pItem->nIndex = nNewIndex;
  1613.         pItem->nBltMode = HX_OVERLAY_BLT;
  1614.     }
  1615.     
  1616.     // Increase the mutex lock count so another thread does not lock
  1617.     // it before we queue this frame or prevent us from drawing immediately.
  1618.     WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  1619.     // We delete the alphalist in DisplayFrame in yuv_stretch mode.
  1620.     ReleaseSurface(pVidStruct, FALSE, (pItem->nBltMode!=HX_BLT_YUV_STRETCH));
  1621.     // Immediate display...don't queue
  1622.     if (ulFlags & HX_MODE_IMMEDIATE)
  1623.     {
  1624.         HRESULT hr;
  1625.         tFrameElement lastItem;
  1626.         for (int i=0; i<5; i++)
  1627.         {
  1628.             pItem->dwDDFlags = DDFLIP_WAIT;
  1629.             lastItem = *pItem;
  1630.             hr = DisplayFrame(pItem);
  1631.             // Need to try again
  1632.             if (DDERR_WASSTILLDRAWING == hr)
  1633.             {
  1634.                 *pItem = lastItem;
  1635.                 WaitForSingleObject(m_hAbort, 10);
  1636.             }
  1637.             // Probably can not async flip, so turn it off
  1638.             else if (DDERR_INVALIDPARAMS == hr && m_bUseVBlankFlip)
  1639.             {
  1640.                 *pItem = lastItem;
  1641.                 m_bUseVBlankFlip = FALSE;
  1642.             }
  1643.             else
  1644.             {
  1645.                 // Abort this overaly surface on a failure
  1646.                 if (DD_OK != hr && pItem->nBltMode == HX_OVERLAY_BLT)
  1647.                 {
  1648.                     CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  1649.                     if (!pSurface)
  1650.                         goto FAILURE;
  1651.                     WINDRAW *pWindraw = pSurface->GetWinDraw();
  1652.                 
  1653.                     WinDraw_DisplaySurface(pWindraw, &m_surface, pItem->dwDDFlags, pItem->nIndex, TRUE);
  1654.                 }
  1655.                 
  1656.                 break;
  1657.             }
  1658.         } 
  1659.         ReleaseMutex(m_hSurfaceMutex);
  1660.         delete pItem;
  1661.         
  1662. #if !defined(_GOLD) && 0
  1663.         m_TimeStamps.AddSample();
  1664. #endif
  1665.         return HXR_OK;
  1666.     }
  1667.     EnterCriticalSection(&m_csList);
  1668.     m_pListOfFrames->AddTail((void*)pItem);
  1669.     LeaveCriticalSection(&m_csList);
  1670.     ReleaseSemaphore(m_hFrameSem, 1, NULL);
  1671.     ReleaseMutex(m_hSurfaceMutex);
  1672. #if !defined(_GOLD) && 0
  1673.     m_TimeStamps.AddSample();
  1674. #endif
  1675.     return HXR_OK;
  1676.   FAILURE:
  1677.     delete pItem;
  1678.     return HXR_FAIL;
  1679. }
  1680. STDMETHODIMP_(void) CWinSurface2::Flush()
  1681. {
  1682.     m_bFlushing = TRUE;
  1683.     //This needs to be before the wait on m_hSurfaceMutex because if
  1684.     //you hit stop before we start blt'ing frames you could be waiting
  1685.     //a long time before it wakes up. At least in the case for live
  1686.     //streams where we don't have the server/ff seek back to the
  1687.     //nearest keyframe and send data. Some streams have keyframes
  1688.     //every 10seconds or so.
  1689.     PulseEvent(m_hAbort);
  1690.     WaitForSingleObject(m_hSurfaceMutex, INFINITE);
  1691.  
  1692.     CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  1693.     WINDRAW *pWindraw = pSurface->GetWinDraw();
  1694.     
  1695.     // Cancel and pending frames
  1696.     WinDraw_CacelPendingDisplay (pWindraw, &m_surface);
  1697.     PulseEvent(m_hForceRender);
  1698.     Sleep(5);
  1699.     // Wait until our queue count reaches 0
  1700.     int nCount = m_pListOfFrames->GetCount();
  1701.     while (nCount)
  1702.     {
  1703.         WinDraw_CacelPendingDisplay (pWindraw, &m_surface);
  1704.         PulseEvent(m_hAbort);
  1705.         PulseEvent(m_hForceRender);
  1706.         Sleep(5);
  1707.         nCount = m_pListOfFrames->GetCount();
  1708.     }
  1709.     
  1710.     ResetBufferTimes(0);
  1711.     ReleaseMutex(m_hSurfaceMutex);
  1712.     m_bFlushing = FALSE;
  1713. }
  1714. void CWinSurface2::ResetBufferTimes(INT32 nTime)
  1715. {
  1716.     // Reset all buffer times
  1717.     if (m_surface.dwBackBufferCount)
  1718.     {
  1719.         for (UINT32 i=0; i<m_surface.dwBackBufferCount+1; i++)
  1720.             m_surface.dd.lpChain[i].dTimeAvailable = nTime;
  1721.     }
  1722. }
  1723. STDMETHODIMP CWinSurface2::PresentIfReady()
  1724. {
  1725.     HX_RESULT hr = E_FAIL;
  1726.     if (!m_pTimeLine | m_bIngnorePresentIfReady)
  1727.         return hr;
  1728.     UINT32 ulTime = 0;
  1729.     if (HXR_TIMELINE_SUSPENDED != m_pTimeLine->GetTimeLineValue(ulTime))
  1730.     {
  1731.         if (((m_nLastDisplayTime > 0) && (m_nLastDisplayTime - (INT32)ulTime < 0)))
  1732.         {
  1733.             #ifdef LOG_JITTER_DATA
  1734.             FILE *fp = fopen(JITTER_LOG_FILE, "a+");
  1735.             if (fp)
  1736.             {
  1737.                 fprintf(fp, "PresentIfReady Interrupt clock %ld last display %ldn", ulTime, m_nLastDisplayTime);
  1738.                 fclose(fp);
  1739.             }
  1740.             #endif
  1741.             
  1742.             PulseEvent(m_hForceRender);
  1743.             Sleep(0);
  1744. #ifdef _DEBUG
  1745.             //OutputDebugString("PresentIfReady Interruptn");
  1746. #endif
  1747.             hr = HXR_OK;
  1748.         }
  1749.     }
  1750.     
  1751.     return hr;
  1752. }
  1753. HX_RESULT CWinSurface2::DisplayFrame(tFrameElement* pItem)
  1754. {
  1755.     HRESULT hr = HXR_OK,
  1756.             hrTimeLine = HXR_OK;
  1757.     HXxSize rcSize = {0,0};
  1758.     int     nNumRects   = 0;
  1759.     BOOL    bSub1x = FALSE;
  1760.     m_pSite->_TLSLock(); 
  1761.     CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface();
  1762.     if (!pSurface)
  1763.     {
  1764.         m_pSite->_TLSUnlock(); 
  1765.         return HXR_FAIL;
  1766.     }
  1767.     WINDRAW *pWindraw = pSurface->GetWinDraw();
  1768.     // Ensure our site is visible before displaying
  1769.     BOOL    bVisibleSite = (!HXEmptyRegion(m_pSite->m_Region)|| pItem->count || pItem->bAlpha)
  1770.                            && m_pSite->IsSiteVisible()
  1771.                            && !m_pSite->_FadeTransitionActive();
  1772.     if (pItem->nBltMode == HX_OVERLAY_BLT)
  1773.     {
  1774.         // If no src rect is specified, use surface
  1775.         if (!pItem->rcSrc.right && !pItem->rcSrc.bottom)
  1776.         {
  1777.             pItem->rcSrc.right = m_surfaceSize.cx;
  1778.             pItem->rcSrc.bottom = m_surfaceSize.cy;
  1779.         }
  1780.         // Put the frame on the screen
  1781.         int nIndex = pItem->nIndex-1;
  1782.         if (nIndex < 0)
  1783.             nIndex = m_nBackBufferCount;
  1784.         if (pItem->dwDDFlags & DDFLIP_WAIT == DDFLIP_WAIT)
  1785.         {
  1786.             // Immediate mode blits have no calculated timaAvailable; use 
  1787.             // the current time:
  1788.             pItem->dTimeAvailable = GetMSTickDouble32();
  1789.         }
  1790.         m_surface.dd.lpChain[nIndex].dTimeAvailable = pItem->dTimeAvailable;
  1791.         m_surface.dd.lpChain[pItem->nIndex].dTimeAvailable = 0;
  1792.         hr = WinDraw_DisplaySurface(pWindraw, &m_surface, pItem->dwDDFlags, pItem->nIndex, m_bFlushing);
  1793. #ifdef LOG_JITTER_DATA
  1794.         UINT32 ulTimeAfter = 0;
  1795.         m_pTimeLine->GetTimeLineValue(ulTimeAfter);
  1796.         FILE *fp = fopen(JITTER_LOG_FILE, "a+");
  1797.         if (fp)
  1798.         {
  1799.             UINT32 dwScanLine = 0;
  1800.             WinDraw2_GetScanLine(pWindraw, &dwScanLine);
  1801.         
  1802.             fprintf(fp, "Calling flip: scan line %ld clock after %ld ts %ld jitter %ldnn", dwScanLine, ulTimeAfter, pItem->lTimeStamp, (INT32)(pItem->lTimeStamp-ulTimeAfter));
  1803.             fclose(fp);
  1804.         }
  1805. #endif //LOG_JITTER_DATA
  1806.         if (DD_OK == hr && bVisibleSite)
  1807.         {
  1808.             m_nLastBltMode = HX_OVERLAY_BLT;
  1809.             // Make sure we are painting colorkey in fullscreen mode.
  1810.             // We will fix this when fillcolor key is fixed.
  1811.             if (m_pSite->m_pTopLevelSite &&
  1812.                 m_pSite->m_pTopLevelSite->m_bInFullScreen)
  1813.             {
  1814.                 if (++m_ulFillColoryKeyCount < 15)
  1815.                     memset(&m_rcLast, 0, sizeof(m_rcLast));
  1816.             }
  1817.             else
  1818.                 m_ulFillColoryKeyCount = 0;
  1819.             if (!IsShrinking() || _AllowsOverlayShrinking())
  1820.             {
  1821.                 // Restore overlay
  1822.                 if (HX_OVERLAY_BLT != m_nBltMode)
  1823.                 {
  1824.                     ForceGDIMode(FALSE);
  1825.                 }
  1826.                 // If no src rect is specified, use surface
  1827.                 if (!pItem->rcDst.right && !pItem->rcDst.bottom)
  1828.                 {
  1829.                     m_pSite->GetSize(rcSize);
  1830.         
  1831.                     pItem->rcDst.right = rcSize.cx;
  1832.                     pItem->rcDst.bottom = rcSize.cy;
  1833.                 }
  1834.                 
  1835.                 SetLastScale(&pItem->rcSrc, &pItem->rcDst);