winsurf2.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:134k
源码类别:

Symbian

开发平台:

Visual C++

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