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

Symbian

开发平台:

C/C++

  1.     if (lpwd == NULL || lpwds == NULL || lpImageFormat == NULL ||
  2.         nBackBuffers > MAX_BACKBUFFERCOUNT || lpwd->hWnd == NULL ||
  3.         !(lpwd->fMode & WINDRAW_OPENED) || (lpwds->fMode & WINDRAWSURFACE_OPENED))
  4.         return E_INVALIDARG;
  5.     
  6.     /* check image format: */
  7.     sz = lpImageFormat->bmiHeader.biSize;
  8.     memset (lpwds, 0, sizeof (WINDRAWSURFACE));
  9.     if (sz < (int)sizeof(BITMAPINFOHEADER) || sz > (int)sizeof(BMI) ||
  10.         (lpwds->cidSurfaceColor = GetBitmapColor((LPBITMAPINFO)lpImageFormat)) == CID_UNKNOWN)
  11.         return E_INVALIDARG;
  12.     
  13.     /* initialize WinDrawSurface structure: */
  14.     memcpy (&(lpwds->bmiSurfaceFormat), lpImageFormat, sz); /* Flawfinder: ignore */
  15.     lpwds->dwBackBufferCount = nBackBuffers;
  16.     
  17.     /* check type of surface we will need to create: */
  18.     if (fSurfaceType & WINDRAWSURFACE_DIRECTDRAW)
  19.     {
  20. return WinDraw2_CreateDDSurface(lpwd, lpwds, lpImageFormat, fSurfaceType, nBackBuffers, dwCKey);
  21.     }
  22.     else
  23.     {
  24. return WinDraw2_CreateGDISurface(lpwd, lpwds, lpImageFormat, fSurfaceType, nBackBuffers, dwCKey);
  25.     }
  26. }
  27. /*
  28. * Creates a new surface to be used for image data.
  29. * Use:
  30. *   HRESULT WinDraw2_CreateSurface (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  31. *    LPBMI lpImageFormat, DWORD fSurfaceType, int nBackBuffers, DWORD dwCKey);
  32. * Input:
  33. *  lpwd - pointer to a base WINDRAW structure
  34. *  lpwds - pointer to a WINDRAWSURFACE structure to initialize
  35. *  lpImageFormat - pointer to BITMAPINFO structure describing image format
  36. *  fSurfaceType - combination of desired properties for a surface
  37. *  nBackBuffers - number of flippable backbuffers to allocate for this surface
  38. *  dwCKey - a color key to use (if transparent surface)
  39. * Returns:
  40. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  41. */
  42. HRESULT Windraw_AttachSurface(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  43.       BITMAPINFOHEADER* lpImageFormat, void* pImageData)
  44. {
  45.     HRESULT retVal = E_INVALIDARG;
  46.     
  47.     
  48.     /* check parameters: */
  49.     if (lpwd == NULL || lpwds == NULL || lpImageFormat == NULL ||
  50.         lpwd->hWnd == NULL || !(lpwd->fMode & WINDRAW_OPENED) || 
  51. !(lpwds->fMode & WINDRAWSURFACE_OPENED))
  52.         return retVal;
  53.     
  54.     /* check type of surface we will need to create: */
  55.     if (lpwds->fMode & WINDRAWSURFACE_DIRECTDRAW)
  56.     {
  57. DDSURFACEDESC ddsd;
  58. ZeroMemory(&ddsd, sizeof(ddsd));
  59. ddsd.dwSize = sizeof(ddsd);
  60. ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE | DDSD_PIXELFORMAT;
  61. ddsd.dwHeight = lpImageFormat->biHeight;
  62. ddsd.dwWidth = lpImageFormat->biWidth;
  63. ddsd.lPitch = GetBitmapPitch((LPBITMAPINFO)lpImageFormat);
  64. ddsd.lpSurface = pImageData;
  65. SetDirectDrawColor(&ddsd.ddpfPixelFormat, GetBitmapColor((LPBITMAPINFO)lpImageFormat));
  66. IDirectDrawSurface3* pSurf3 = NULL;
  67. if (SUCCEEDED(lpwds->dd.lpDDSurface->QueryInterface(IID_IDirectDrawSurface3, (void**)&pSurf3)))
  68. {
  69.     try
  70.             {
  71.             retVal = pSurf3->SetSurfaceDesc(&ddsd, 0);
  72.             }
  73.             catch(...)
  74.             {
  75.                 DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "Windraw_AttachSurface");
  76.                 retVal = HXR_FAIL;
  77.             }
  78.     pSurf3->Release();
  79. }
  80. return retVal;
  81.     }
  82.     else
  83.     {
  84. return retVal;
  85.     }
  86. }
  87. /*
  88. * Adds alpha data to a specified surface.
  89. * Use:
  90. *   HRESULT WinDraw2_AttachAlphaSurface (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  91. *    UCHAR* pAlphaData);
  92. * Input:
  93. *  lpwd - pointer to a base WINDRAW structure
  94. *  lpwds - pointer to a WINDRAWSURFACE structure to initialize
  95. * Returns:
  96. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  97. */
  98. HRESULT WinDraw2_CreateAlphaSurface(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds)
  99. {
  100.     /* check parameters: */
  101.     if (lpwd == NULL || lpwds == NULL || lpwd->hWnd == NULL ||
  102.         !(lpwd->fMode & WINDRAW_OPENED) || (!(lpwds->fMode & WINDRAWSURFACE_OPENED)))
  103.         return E_INVALIDARG;
  104.     
  105.     if (lpwds->fMode & WINDRAWSURFACE_DIRECTDRAW) 
  106.     {
  107.         /* blit DirectDraw surfaces: */ ;
  108.     } else 
  109.     { /* GDI: */
  110. GDISURFACE* pGDISurf = lpwds->gdi.lpGDIBackBuffer [FRONTBUFFER];
  111.         pGDISurf->lpAlphaSurface = (UCHAR*) malloc(pGDISurf->DibSection.dsBmih.biWidth * pGDISurf->DibSection.dsBmih.biHeight);
  112.     }
  113.     
  114.     return NOERROR;
  115. }
  116. /*
  117. * Adds alpha data to a specified surface.
  118. * Use:
  119. *   HRESULT WinDraw2_AttachAlphaSurface (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  120. *    UCHAR* pAlphaData);
  121. * Input:
  122. *  lpwd - pointer to a base WINDRAW structure
  123. *  lpwds - pointer to a WINDRAWSURFACE structure to initialize
  124. * Returns:
  125. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  126. */
  127. HRESULT WinDraw2_GetAlphaSurface(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds, UCHAR** pSurface)
  128. {
  129.     /* check parameters: */
  130.     if (lpwd == NULL || lpwds == NULL || lpwd->hWnd == NULL ||
  131.         !(lpwd->fMode & WINDRAW_OPENED) || (!(lpwds->fMode & WINDRAWSURFACE_OPENED)))
  132.         return E_INVALIDARG;
  133.     
  134.     if (lpwds->fMode & WINDRAWSURFACE_DIRECTDRAW) 
  135.     {
  136.         /* blit DirectDraw surfaces: */ ;
  137.     } else 
  138.     { /* GDI: */
  139. GDISURFACE* pGDISurf = lpwds->gdi.lpGDIBackBuffer [FRONTBUFFER];
  140.         *pSurface = pGDISurf->lpAlphaSurface;
  141.     }
  142.     
  143.     return NOERROR;
  144. }
  145. /*
  146. * Release a WinDraw surface.
  147. * Use:
  148. *  HRESULT WinDraw2_ReleaseSurface (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds);
  149. * Input:
  150. *  lpwd - pointer to a base WINDRAW structure
  151. *  lpwds - pointer to a WINDRAWSURFACE structure to remove
  152. * Returns:
  153. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  154. */
  155. HRESULT WinDraw2_ReleaseSurface (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds)
  156. {
  157.     /* check parameters: */
  158.     if (lpwd == NULL || lpwds == NULL || lpwd->hWnd == NULL ||
  159.         !(lpwd->fMode & WINDRAW_OPENED) || !(lpwds->fMode & WINDRAWSURFACE_OPENED))
  160.         return E_INVALIDARG;
  161.     
  162.     /* check if DirectDraw surface: */
  163.     if (lpwds->fMode & WINDRAWSURFACE_DIRECTDRAW) 
  164.     {
  165.         if (lpwds->dd.lpChain)
  166.         {
  167.             for (int i=0; i<(int)lpwds->dwBackBufferCount+1; i++)
  168.             {
  169.                 // Wait until the flip has been called on this surface
  170.                 WaitForSingleObject(lpwds->dd.lpChain[i].hEmpty, INFINITE);
  171.                 CloseHandle(lpwds->dd.lpChain[i].hEmpty);
  172.             }
  173.             CloseHandle(lpwds->dd.hAbort);
  174.             lpwds->dd.hAbort = 0;
  175.             delete [] lpwds->dd.lpChain;
  176.             lpwds->dd.lpChain = NULL;
  177.         CloseHandle(lpwds->hOverlayIndexMutex);
  178.         CloseHandle(lpwds->hOverlayMutex);
  179.         lpwds->hOverlayIndexMutex = 0;
  180.         lpwds->hOverlayMutex = 0;
  181.         lpwds->dwFrontBuffer = 0;
  182.         lpwds->dwNextBuffer = 0;
  183.         }
  184.         /* release DirectDraw objects: */ ;
  185. int res;
  186.         
  187.         try
  188.         {
  189.         res = lpwds->dd.lpDDSurface->Release();
  190.         }
  191.         catch(...)
  192.         {
  193.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDraw2_ReleaseSurface");
  194.             res = 0;
  195.         }
  196. lpwds->dd.lpDDSurface = 0;
  197. lpwds->dd.lpDDBackBuffer = 0;
  198.     } else 
  199.     { /* GDI: */
  200.         int i;
  201.         /* release GDI surfaces: */
  202.         for (i=lpwds->dwBackBufferCount; i>=0; i--) 
  203. {
  204.             if (lpwds->gdi.lpGDIBackBuffer [i] != NULL) {
  205.                 GDISurface_Free(lpwds->gdi.lpGDIBackBuffer [i]);
  206.                 lpwds->gdi.lpGDIBackBuffer [i] = NULL;
  207.             }
  208.         }
  209.     }
  210.     
  211.     /* reset mode & exit: */
  212.     lpwds->fMode = 0;
  213.     
  214.     LISTPOSITION pos = lpwd->m_pSurfaceList->Find(lpwds);
  215.     if (pos)
  216.         lpwd->m_pSurfaceList->RemoveAt(pos);
  217. lpwds->dwBackBufferCount = 0;
  218.     
  219.     return NOERROR;
  220. }
  221. HRESULT WinDraw2_GetMonitorProperties (LPWINDRAW lpwd)
  222. {
  223.     HRESULT hr;
  224.     DWORD dwTemp = 0;
  225.     if (!lpwd || !lpwd->dd.lpDD2)
  226.         return E_FAIL;
  227.     lpwd->ulBadConsecutiveVblankCount = 0;
  228.     lpwd->dwMaxScanLine = 0;
  229.     lpwd->dwReportedHeight = GetSystemMetrics(SM_CYSCREEN);
  230.     LARGE_INTEGER   llStart,
  231.                     llTime,
  232.                     llTemp;
  233.     llStart.QuadPart = 0;
  234.     llTime.QuadPart = 0;
  235.     llTemp.QuadPart = 0;
  236.     QueryPerformanceFrequency(&llTemp);
  237.     LONGLONG llClockFreq = llTemp.QuadPart;
  238.     // Try to get the max scan line but limit the time spent
  239.     // in the loop.  Some cards always return 0 from GetScanLine.
  240.     QueryPerformanceCounter(&llStart);
  241.     do
  242.     {
  243.         hr = lpwd->dd.lpDD2->GetScanLine(&dwTemp);
  244.         
  245.         if (DD_OK == hr ||
  246.             DDERR_VERTICALBLANKINPROGRESS == hr)
  247.         {
  248.             // The G400 occasionally reports an obscenely high value here;
  249.             // we filter to 130% of the reported display height 
  250.             if (dwTemp > lpwd->dwMaxScanLine 
  251.                 && dwTemp <= lpwd->dwReportedHeight*1.3)
  252.                 lpwd->dwMaxScanLine = dwTemp;
  253.         }
  254.         else
  255.             break;
  256.         QueryPerformanceCounter(&llTime);
  257.         if ((llTime.QuadPart - llStart.QuadPart)*1000 / llClockFreq > 1000)
  258.             break;
  259.     } while (dwTemp >= lpwd->dwMaxScanLine);
  260.     // GetScanLine problem
  261.     if (!lpwd->dwMaxScanLine)
  262.         return HXR_FAIL;
  263.     // Set max scan line to a max of the line and screen screen height
  264.     // we assume a minimum of one vblank line; max line is zero based
  265.     lpwd->dwMaxScanLine = max(lpwd->dwMaxScanLine, (DWORD)GetSystemMetrics(SM_CYSCREEN));
  266.     //HX_TRACE("Max scan line: %lun", lpwd->dwMaxScanLine);
  267.     // Query the monitor's refresh rate
  268.     lpwd->dd.lpDD2->GetMonitorFrequency(&dwTemp);
  269.     //HX_TRACE("Reported refresh rate: %lun", dwTemp);
  270.     if (dwTemp)
  271.     {
  272.         lpwd->dRefreshRate = dwTemp;
  273.         lpwd->dMsPerVBlank = 1000.0 / lpwd->dRefreshRate;
  274.     }
  275.     // Approximate the refresh rate
  276.     const int   LIST_SIZE = 6;
  277.     LONGLONG    aList[LIST_SIZE],
  278.                 llAvgVBlank = 0;
  279.     lpwd->dd.lpDD2->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL);
  280.     QueryPerformanceCounter(&llStart);
  281.     // Grab the times for LIST_SIZE vblanks
  282.     for (int i=0; i<LIST_SIZE; i++)
  283.     {
  284.         hr = lpwd->dd.lpDD2->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL);
  285.         if (DD_OK == hr)
  286.         {
  287.             QueryPerformanceCounter(&llTime);
  288.             aList[i] = llTime.QuadPart;
  289.             if (i>0)
  290.             {
  291.                 llAvgVBlank += aList[i] - aList[i-1];
  292.             }
  293.         }
  294.     }
  295.     llAvgVBlank /= LIST_SIZE-1;
  296.     LONGLONG    llModAvg = 0;
  297.     int         nCount = 0;
  298.     // Weed out bogus values
  299.     for (i=0; i<LIST_SIZE; i++)
  300.     {
  301.         if (i>0)
  302.         {
  303.             if (abs((int)(aList[i] - aList[i-1] - llAvgVBlank)) <= .3 * llAvgVBlank)
  304.             {
  305.                 ++nCount;
  306.                 llModAvg += aList[i] - aList[i-1];
  307.             }
  308.         }
  309.     }
  310.     LONGLONG    llTmp  = llStart.QuadPart,
  311.                 llTmp1 = llTime.QuadPart;
  312.     double      dEstRate = (double)(nCount*llClockFreq) / (llModAvg);
  313.     //HX_TRACE("Estimated refresh rate: %fn", dEstRate);
  314.     // Map to a common refresh rate
  315.     const int   BASE_RATES = 5;
  316.     double      dBestRate = -1;
  317.     double      aRateList[BASE_RATES] = {24, 25, 29.97, 30, 85};
  318.     double      dBestError = 100.0,
  319.                 dError;
  320.             
  321.     // Try 10x base rates
  322.     for (int j=1; j<11; j++)
  323.     {
  324.         for (i=0; i<BASE_RATES; i++)
  325.         {
  326.             dError = dEstRate - aRateList[i]*j;
  327.             if (fabs(dError) < dBestError)
  328.             {
  329.                 dBestError = fabs(dError);
  330.                 dBestRate = aRateList[i]*j;
  331.             }
  332.         }
  333.     }
  334.     //HX_TRACE("Best refresh rate match: %fn", dBestRate);
  335.     // If we are within 1.5% if a known rate, use it.  This will not handle 
  336.     // cases where the estimate is *closer* to reality than the reported rate 
  337.     // due to integer truncation or rounding in GetMonitorFrequency().  
  338.     // We do, however, handle 29.97 below.
  339.     if (dBestRate > -1 && 
  340.         dBestError / dBestRate <= .015)
  341.         dEstRate = dBestRate;
  342.     // Compare estimate with DD value and use estimate
  343.     // if the the two are not close.
  344.     if (fabs(dEstRate - lpwd->dRefreshRate) > 5
  345.         || dEstRate == 29.97)       // Special case 29.97; Windows reports 
  346.                                     // integer frequencies.
  347.     {
  348.         lpwd->dRefreshRate = dEstRate;
  349.         lpwd->dMsPerVBlank = 1000.0 / lpwd->dRefreshRate;
  350.     }
  351.     //HX_TRACE("Final refresh rate chosen: %fn", lpwd->dRefreshRate);
  352.     return NOERROR;
  353. }
  354. /*
  355. * Get WinDrawSurface capabilities.
  356. * Use:
  357. *  HRESULT WinDrawSurface_GetCaps (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  358. *      DWORD *lpdwCaps);
  359. * Input:
  360. *  lpwd - pointer to a WINDRAW structure to query
  361. *  lpwds - pointer to a WINDRAWSURFACE structure to query
  362. *  lpdwCaps - a variable to contain WinDrawSurface capabilities
  363. * Returns:
  364. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  365. */
  366. HRESULT WinDrawSurface_GetCaps (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  367. DWORD *lpdwCaps)
  368. {
  369.     /* check parameters: */
  370.     if (lpwd == NULL || lpwds == NULL || lpdwCaps == NULL || lpwd->hWnd == NULL ||
  371.         !(lpwd->fMode & WINDRAW_OPENED) || !(lpwds->fMode & WINDRAWSURFACE_OPENED))
  372.         return E_INVALIDARG;
  373.     
  374.     /* store surface caps and exit: */
  375.     *lpdwCaps = lpwds->fMode;
  376.     return NOERROR;
  377. }
  378. HRESULT Windraw_GetCaps(LPWINDRAW lpwd, UINT32* pfSurfaceCaps, UINT32* nMin, UINT32* nMax)
  379. {
  380.     /* check parameters: */
  381.     if (lpwd == NULL || pfSurfaceCaps == NULL || !(lpwd->fMode & WINDRAW_OPENED) || !(lpwd->fMode & WINDRAW_DIRECTDRAW))
  382.         return E_INVALIDARG;
  383.     
  384.     HRESULT hr = NOERROR;
  385.     
  386.     /* Get the current device caps */
  387.     if (lpwd->dd.lpDD2)
  388.     {
  389.         memset(&lpwd->dd.m_caps, 0, sizeof(DDCAPS));
  390.         lpwd->dd.m_caps.dwSize = sizeof(DDCAPS_DX3);
  391.         
  392.         try
  393.         {
  394.         lpwd->dd.lpDD2->GetCaps(&(lpwd->dd.m_caps), 0);
  395.         }
  396.         catch(...)
  397.         {
  398.             DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "Windraw_GetCaps");
  399.             hr = HXR_FAIL;
  400.             memset(&lpwd->dd.m_caps, 0, sizeof(DDCAPS));
  401.         }
  402.     }
  403.     
  404.     *pfSurfaceCaps = 0;
  405.     if (lpwd->dd.m_caps.dwCaps & DDCAPS_OVERLAY)
  406.     {
  407. *pfSurfaceCaps |= HX_OVERLAY;  
  408.     }
  409.     
  410.     if (lpwd->dd.m_caps.dwCaps & DDCAPS_OVERLAYSTRETCH)
  411.     {
  412. *pfSurfaceCaps |= HX_OVERLAY_STRETCH;  
  413.     }
  414.     
  415.     if (lpwd->dd.m_caps.dwCaps & DDCAPS_BLTFOURCC)
  416.     {
  417. *pfSurfaceCaps |= HX_BLTFOURCC;  
  418.     }
  419.     
  420.     *nMin = lpwd->dd.m_caps.dwMinOverlayStretch;
  421.     *nMax = lpwd->dd.m_caps.dwMaxOverlayStretch;
  422.     
  423.     return hr;
  424. }
  425. /*
  426. * Get WinDrawSurface format.
  427. * Use:
  428. *  HRESULT WinDrawSurface_GetFormat (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  429. *      LPBMI lpbiSurfaceFormat);
  430. * Input:
  431. *  lpwd - pointer to a WINDRAW structure to query
  432. *  lpwds - pointer to a WINDRAWSURFACE structure to query
  433. *  lpbiFormat - a structure to contain surface resolution and color format
  434. * Returns:
  435. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  436. */
  437. HRESULT WinDrawSurface_GetFormat (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  438.   LPBMI lpbiSurfaceFormat)
  439. {
  440.     int sz;
  441.     
  442.     /* check parameters: */
  443.     if (lpwd == NULL || lpwds == NULL ||
  444.         !(lpwd->fMode & WINDRAW_OPENED) || !(lpwds->fMode & WINDRAWSURFACE_OPENED) ||
  445.         lpbiSurfaceFormat == NULL)
  446.         return E_INVALIDARG;
  447.     
  448.     /* check the size of BITMAPINFO structure to copy: */
  449.     sz = lpbiSurfaceFormat->bmiHeader.biSize;
  450.     if (sz < (int)sizeof(BITMAPINFOHEADER) || sz > (int)lpwds->bmiSurfaceFormat.bmiHeader.biSize)
  451.         sz = lpwds->bmiSurfaceFormat.bmiHeader.biSize;
  452.     
  453.     /* copy bitmap info: */
  454.     memcpy(lpbiSurfaceFormat, &(lpwds->bmiSurfaceFormat), sz); /* Flawfinder: ignore */
  455.     return NOERROR;
  456. }
  457. /*
  458. * Locks pointer to a buffer.
  459. * Use:
  460. *  HRESULT WinDrawSurface_Lock (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  461. *      int nBufferNo, LPVOID *lpSurfPtr, LONG  *lplSurfPitch);
  462. * Input:
  463. *  lpwd - pointer to a base WINDRAW structure
  464. *  lpwds - pointer to a WINDRAWSURFACE structure to lock
  465. *  nBufferNo - # of the surface buffer to lock
  466. *  lpSurfPtr - a variable to contain a base pointer to the surface's data
  467. *  lplSurfPitch - a variable to contain the pitch of the surface
  468. * Returns:
  469. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  470. * Notes:
  471. * This functions shall be called before copying data into the surface.
  472. * Unlock it as soon as you are done with moving data in!!!
  473. */
  474. HRESULT WinDrawSurface_Lock (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  475.      int nBufferNo, LPVOID *lpSurfPtr, LONG  *lplSurfPitch)
  476. {
  477.     /* check parameters: */
  478.     if (lpwd == NULL || lpwds == NULL || nBufferNo > (int)lpwds->dwBackBufferCount ||
  479.         lpSurfPtr == NULL || lplSurfPitch == NULL || lpwd->hWnd == NULL ||
  480.         !(lpwd->fMode & WINDRAW_OPENED) || !(lpwds->fMode & WINDRAWSURFACE_OPENED))
  481.         return E_INVALIDARG;
  482.     
  483.     /* check if DirectDraw surface: */
  484.     if (lpwds->fMode & WINDRAWSURFACE_DIRECTDRAW) 
  485.     {
  486.         /* lock DirectDraw surfaces: */
  487.         DDSURFACEDESC ddsd;
  488.         ZeroMemory(&ddsd, sizeof(DDSURFACEDESC));
  489.         ddsd.dwSize = sizeof(DDSURFACEDESC);
  490.         ddsd.dwFlags= DDSD_PITCH;
  491. LPDIRECTDRAWSURFACE lpDDSurface = NULL;
  492. if (lpwds->dd.lpDDBackBuffer)
  493. {
  494.             lpDDSurface = lpwds->dd.lpDDBackBuffer;
  495.             if (!lpDDSurface)
  496.                 return E_INVALIDARG;
  497.             // For backbuffer locking, we need to keep our locks consistent
  498.             // with videosurface2 locks since we are possibly here after a switch.
  499.             if (DD_OK == LockSurface(lpwd, lpDDSurface, &ddsd, TRUE))
  500.             {
  501.                 *lplSurfPitch = ddsd.lPitch;
  502.                 lpwds->dd.lpSurfaceData = *lpSurfPtr = (void*) ddsd.lpSurface;
  503.                 return NOERROR;
  504.             }
  505.             if (DDERR_WRONGMODE == lpDDSurface->Restore())
  506.             {
  507.                 return DDERR_WRONGMODE;
  508.             }
  509.             if (DD_OK == LockSurface(lpwd, lpDDSurface, &ddsd, TRUE))
  510.             {
  511.                 /*
  512.                 *  Consider checking DDSCAPS_VISIBLE if this is not set (and it is not on NT)
  513.                 *  then something is SERIOUSLY MESSED UP!
  514.                 */
  515.                 *lplSurfPitch = ddsd.lPitch;
  516.                 lpwds->dd.lpSurfaceData = *lpSurfPtr = (void*) ddsd.lpSurface;
  517.                 return NOERROR;
  518.             }
  519.         }
  520. else
  521. {
  522.             lpDDSurface = lpwds->dd.lpDDSurface;
  523.             if (!lpDDSurface)
  524.                 return E_INVALIDARG;
  525.             HRESULT hr;
  526.             try
  527.             {
  528.                 hr = lpDDSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
  529.             }
  530.             catch(...)
  531.             {
  532.                 DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDrawSurface_Lock");
  533.                 hr = HXR_FAIL;
  534.                 *lplSurfPitch = 0;
  535.                 lpwds->dd.lpSurfaceData = NULL;
  536.                 return hr;
  537.             }
  538.             if (DD_OK == hr)
  539.             {
  540.                 /*
  541.                 *  Consider checking DDSCAPS_VISIBLE if this is not set (and it is not on NT)
  542.                 *  then something is SERIOUSLY MESSED UP!
  543.                 */
  544.                 *lplSurfPitch = ddsd.lPitch;
  545.                 lpwds->dd.lpSurfaceData = *lpSurfPtr = (void*) ddsd.lpSurface;
  546.                 return NOERROR;
  547.             }
  548.             if (DDERR_WRONGMODE == lpDDSurface->Restore())
  549.             {
  550.                 return DDERR_WRONGMODE;
  551.             }
  552.             try
  553.             {
  554.             hr = lpDDSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
  555.             }
  556.             catch(...)
  557.             {
  558.                 DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDrawSurface_Lock");
  559.                 hr = HXR_FAIL;
  560.                 *lplSurfPitch = 0;
  561.                 lpwds->dd.lpSurfaceData = NULL;
  562.                 return hr;
  563.             }
  564.             if (DD_OK == hr)
  565.             {
  566.                 /*
  567.                 *  Consider checking DDSCAPS_VISIBLE if this is not set (and it is not on NT)
  568.                 *  then something is SERIOUSLY MESSED UP!
  569.                 */
  570.                 *lplSurfPitch = ddsd.lPitch;
  571.                 lpwds->dd.lpSurfaceData = *lpSurfPtr = (void*) ddsd.lpSurface;
  572.                 return NOERROR;
  573.             }
  574.         }
  575.     } else { /* GDI: */
  576.         /* check requested GDI surface: */
  577.         if (lpwds->gdi.lpGDIBackBuffer [nBufferNo] != NULL) {
  578.     
  579.             /* retrieve parameters and exit: */
  580.             *lpSurfPtr = lpwds->gdi.lpGDIBackBuffer [nBufferNo]->lpBase;
  581.             *lplSurfPitch = lpwds->gdi.lPitch;
  582.             return NOERROR;
  583.         }
  584.     }
  585.     return E_FAIL;
  586. }
  587. /*
  588. * Unlocks the buffer.
  589. * Use:
  590. *  HRESULT WinDrawSurface_Lock (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  591. *      int nBufferNo, LPVOID *lpSurfPtr, LONG  *lplSurfPitch);
  592. * Input:
  593. *  lpwd - pointer to a base WINDRAW structure
  594. *  lpwds - pointer to a WINDRAWSURFACE structure to unlock
  595. *  nBufferNo - # of the surface buffer to unlock
  596. * Returns:
  597. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  598. */
  599. HRESULT WinDrawSurface_Unlock (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  600.        int nBufferNo)
  601. {
  602.     /* check parameters: */
  603.     if (lpwd == NULL || lpwds == NULL ||
  604.         nBufferNo > (int)lpwds->dwBackBufferCount || lpwd->hWnd == NULL ||
  605.         !(lpwd->fMode & WINDRAW_OPENED) || !(lpwds->fMode & WINDRAWSURFACE_OPENED))
  606.         return E_INVALIDARG;
  607.     
  608.     /* check if DirectDraw surface: */
  609.     if (lpwds->fMode & WINDRAWSURFACE_DIRECTDRAW) 
  610.     {
  611.         /* unlock DirectDraw surfaces: */ ;
  612. LPDIRECTDRAWSURFACE lpDDSurface = NULL;
  613. if (lpwds->dd.lpDDBackBuffer)
  614. {
  615.     lpDDSurface = lpwds->dd.lpDDBackBuffer;
  616. }
  617. else
  618. {
  619.     lpDDSurface = lpwds->dd.lpDDSurface;
  620. }
  621. try
  622.         {
  623.         if (DD_OK == lpDDSurface->Unlock(lpwds->dd.lpSurfaceData))
  624. {
  625.     lpwds->dd.lpSurfaceData = NULL;
  626.     if (lpwds->dd.lpDDBackBuffer)
  627.     {
  628. HRESULT res = lpwds->dd.lpDDSurface->Flip(NULL, 0);
  629.     }
  630.     return NOERROR;
  631. }
  632.         }
  633.         catch(...)
  634.         {
  635.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDrawSurface_Unlock");
  636.             return HXR_FAIL;
  637.         }
  638.     } 
  639.     else 
  640.     { /* GDI: */
  641.         /* check requested GDI surface: */
  642.         if (lpwds->gdi.lpGDIBackBuffer [nBufferNo] != NULL) {
  643.     
  644.             /* unlock GDI surface & exit: */
  645.             return NOERROR;
  646.         }
  647.     }
  648.     return E_FAIL;
  649. }
  650. /*
  651. * Gives a DC to the surface.
  652. * Use:
  653. *  HRESULT WinDrawSurface_GetDC(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  654. *      HDC* pDC);
  655. * Input:
  656. *  lpwd    - pointer to a base WINDRAW structure
  657. *  lpwds   - pointer to a WINDRAWSURFACE structure to unlock
  658. *  HDC*    - pointer to a DC which will be created.
  659. * Returns:
  660. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  661. */
  662. HRESULT WinDrawSurface_GetDC(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  663.      HDC* pDC)
  664. {
  665.     /* check parameters: */
  666.     if (lpwd == NULL || lpwds == NULL || lpwd->hWnd == NULL ||
  667.         !(lpwd->fMode & WINDRAW_OPENED) || !(lpwds->fMode & WINDRAWSURFACE_OPENED))
  668.         return E_INVALIDARG;
  669.     
  670.     /* check if DirectDraw surface: */
  671.     if (lpwds->fMode & WINDRAWSURFACE_DIRECTDRAW) 
  672.     {
  673.         /* Get DC from Direct Draw: */ ;
  674. HRESULT hr;
  675.         try
  676.         {
  677.         hr = lpwds->dd.lpDDSurface->GetDC(pDC);
  678.         }
  679.         catch(...)
  680.         {
  681.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDrawSurface_GetDC");
  682.             hr = HXR_FAIL;
  683.         }
  684.         return hr;
  685.     } 
  686.     else 
  687.     { /* GDI: */
  688. lpwd->gdi.hOldBitmap = (HBITMAP) SelectObject(lpwd->gdi.hMemoryDC, lpwds->gdi.lpGDIBackBuffer[FRONTBUFFER]->hBitMap);
  689. *pDC = lpwd->gdi.hMemoryDC;
  690. return NOERROR;
  691.     }
  692. }
  693. /*
  694. * Releases a DC obtained by WinDrawSurface_GetDC
  695. * Use:
  696. *  HRESULT WinDrawSurface_ReleaseDC(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  697. *      HDC pDC);
  698. * Input:
  699. *  lpwd    - pointer to a base WINDRAW structure
  700. *  lpwds   - pointer to a WINDRAWSURFACE structure to unlock
  701. *  HDC     - pointer to a DC which is to be released.
  702. * Returns:
  703. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  704. */
  705. HRESULT WinDrawSurface_ReleaseDC(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  706.  HDC hDC)
  707. {
  708.     /* check parameters: */
  709.     if (lpwd == NULL || lpwds == NULL || lpwd->hWnd == NULL ||
  710.         !(lpwd->fMode & WINDRAW_OPENED) || !(lpwds->fMode & WINDRAWSURFACE_OPENED))
  711.         return E_INVALIDARG;
  712.     
  713.     /* check if DirectDraw surface: */
  714.     if (lpwds->fMode & WINDRAWSURFACE_DIRECTDRAW) 
  715.     {
  716.         /* Release DC through Direct Draw: */ ;
  717. HRESULT hr;
  718.         try
  719.         {
  720.         hr = lpwds->dd.lpDDSurface->ReleaseDC(hDC);
  721.         }
  722.         catch(...)
  723.         {
  724.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDrawSurface_ReleaseDC");
  725.             hr = HXR_FAIL;
  726.         }
  727.         return hr;
  728.     } 
  729.     else 
  730.     { /* GDI: */
  731. assert(lpwd->gdi.hMemoryDC == hDC);
  732. SelectObject (lpwd->gdi.hMemoryDC, lpwd->gdi.hOldBitmap);
  733. return NOERROR;
  734.     }
  735. }
  736. /*
  737. * Blits the surface data to the screen (primary surface).
  738. * Use:
  739. *  HRESULT WinDrawSurface_Blt (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  740. *      LPRECT lpDestRect, LPRECT lpSrcRect);
  741. * Input:
  742. *  lpwd - pointer to a base WINDRAW structure
  743. *  lpwds - pointer to a WINDRAWSURFACE structure containing data to blit
  744. *  lpDestRect - rectangle on the primary surface to be blitted to
  745. *  lpSrcRect - rectangle on the source surface to be blitted from
  746. * Returns:
  747. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  748. */
  749. HRESULT WinDrawSurface_Blt (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  750.     LPRECT lpDestRect, LPRECT lpSrcRect, int nGdiBufferNo)
  751. {
  752.     /* check parameters: */
  753.     if (lpwd == NULL || lpwds == NULL ||
  754.         lpDestRect == NULL || lpSrcRect == NULL || lpwd->hWnd == NULL ||
  755.         !(lpwd->fMode & WINDRAW_OPENED) || !(lpwds->fMode & WINDRAWSURFACE_OPENED))
  756.         return E_INVALIDARG;
  757.     
  758.     
  759.     /* check if DirectDraw surface: */
  760.     if (lpwds->fMode & WINDRAWSURFACE_DIRECTDRAW) 
  761.     {
  762.         /* blit DirectDraw surfaces: */ ;
  763. if (lpwds->dd.lpDDSurface)
  764. {
  765.         return DDSurface_Blt(lpwd, lpwds->dd.lpDDSurface, lpSrcRect, lpDestRect);
  766. }
  767.     
  768.     } else 
  769.     { /* GDI: */
  770.         /* check GDI front surface: */
  771.         if (lpwds->gdi.lpGDIBackBuffer [nGdiBufferNo] != NULL) {
  772.             /* blit GDI surface: */
  773.             if (GDISurface_Blt (lpwd, lpwds->gdi.lpGDIBackBuffer [nGdiBufferNo], lpSrcRect, lpDestRect))
  774.                 return NOERROR;
  775.         }
  776.     }
  777.     return E_FAIL;
  778. }
  779. /*
  780. * Blits one secondary surface to another.
  781. * Use:
  782. *  HRESULT WinDrawSurface_BltIndirect (LPWINDRAW lpwd,
  783. *      LPWINDRAWSURFACE lpwdsDestSurf, LPWINDRAWSURFACE lpwdsSrcSurf,
  784. *      LPRECT lpDestRect, LPRECT lpSrcRect);
  785. * Input:
  786. *  lpwd - pointer to a base WINDRAW structure
  787. *  lpwdsDestSurf - pointer to a destination WINDRAW structure
  788. *  lpwdsSrcSurf - pointer to a source WINDRAW structure
  789. *  lpDestRect - rectangle on the primary surface to be blitted to
  790. *  lpSrcRect - rectangle on the source surface to be blitted from
  791. * Returns:
  792. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  793. */
  794. HRESULT WinDrawSurface_BltIndirect (LPWINDRAW lpwd,
  795.     LPWINDRAWSURFACE lpwdsDestSurf, LPWINDRAWSURFACE lpwdsSrcSurf,
  796.     LPRECT lpDestRect, LPRECT lpSrcRect,int nGdiBufferNo)
  797. {
  798.     /* check parameters: */
  799.     if (lpwd == NULL || lpwdsDestSurf == NULL || lpwdsSrcSurf == NULL ||
  800.         lpDestRect == NULL || lpSrcRect == NULL || lpwd->hWnd == NULL ||
  801.         !(lpwd->fMode & WINDRAW_OPENED) || !(lpwdsSrcSurf->fMode & WINDRAWSURFACE_OPENED)
  802. || !(lpwdsDestSurf->fMode & WINDRAWSURFACE_OPENED))
  803.         return E_INVALIDARG;
  804.     
  805.     /* check if DirectDraw surface: */
  806.     if (lpwdsSrcSurf->fMode & WINDRAWSURFACE_DIRECTDRAW) 
  807.     {
  808.         /* blit DirectDraw surfaces: */ ;
  809. if (NOERROR == DDSurface_BltIndirect(lpwd, lpwdsDestSurf->dd.lpDDSurface, lpwdsSrcSurf->dd.lpDDSurface, lpDestRect, lpSrcRect))
  810. {
  811.     return NOERROR;
  812. }
  813.     } else 
  814.     { /* GDI: */
  815.         if (GDISurface_BltIndirect(lpwd, lpwdsDestSurf->gdi.lpGDIBackBuffer [nGdiBufferNo], 
  816.     lpwdsSrcSurf->gdi.lpGDIBackBuffer [nGdiBufferNo], lpSrcRect, lpDestRect))
  817.             return NOERROR;
  818.     }
  819.     return E_FAIL;
  820. }
  821. /*
  822. * Get Description of all modes availiable on the system
  823. * Use:
  824. *  HRESULT WinDraw2_GetModes(LPWINDRAW lpwd, CModesDesc* pModesDesc, UINT32* nNumModes);
  825. * Input:
  826. *  lpwd - pointer to a WINDRAW engine to work with 
  827. *  pModesDesc - pointer to a block of memory into which the mode description data will 
  828. *  be filled.
  829. *  nNumModes  - the number of elements which the pModesDesc can contain. If this is too small
  830. *  then proper value will be placed within it.
  831. * Returns:
  832. *  NOERROR if OK, or E_FAIL.
  833. */
  834. HRESULT WinDraw2_GetModes(LPWINDRAW lpwd, CModesDesc* pModesDesc, UINT32* nNumModes)
  835. {
  836. /* 
  837. * For testing we will allow the following:
  838. * if we are in GDI mode we will create a temp
  839. * DirectDrawObject. And we will query it for the data.
  840.     */
  841.     if (!(lpwd->fMode & WINDRAW_DIRECTDRAW) && !lpwd->m_pModesList->GetCount())
  842.     {
  843. WINDRAW tempWindraw;
  844. memset(&tempWindraw, 0, sizeof(WINDRAW));
  845. WinDraw2_Open(&tempWindraw, (HWND) lpwd->hWnd, WINDRAW_DIRECTDRAW, NULL, NULL);
  846. /* Enum the display modes  */
  847. DeleteDisplayModes(lpwd);
  848. if (tempWindraw.dd.lpDD2)
  849. {
  850. /*
  851. *  For SOME reason EnumDisplayModes is causing a number of cards to go CRAZY.
  852. * So we now we call a function which calls enum display modes early and caches 
  853. * the results. For some reason this does not cause things to go INSANE. Who knows why.
  854.     */
  855.     zm_DisplaySettings.GetSettings(lpwd->m_pModesList);
  856.     //     tempWindraw.dd.lpDD2->EnumDisplayModes(0, NULL, lpwd->m_pModesList, DisplayModeEnumeratorCallback); 
  857. }
  858. else
  859. {
  860.     // create a node based on the current display setting
  861.     // use GDI to get the current mode that we are in.
  862.     HDC     hDC     = GetDC(NULL);
  863.     int     width     = GetDeviceCaps(hDC, HORZRES);
  864.     int     height     = GetDeviceCaps(hDC, VERTRES);
  865.     int     bitCount     = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
  866.     CModesDesc* pDesc = new CModesDesc;
  867.     pDesc->m_nWidth = width;
  868.     pDesc->m_nHeight = height;
  869.     pDesc->m_nBitCount = bitCount;
  870.     pDesc->m_fourCC = 0;
  871.     lpwd->m_pModesList->AddTail(pDesc);
  872.     ReleaseDC(NULL, hDC);
  873. }
  874. WinDraw2_Close(&tempWindraw);
  875.     }
  876.     
  877.     if (*nNumModes != (UINT32)lpwd->m_pModesList->GetCount())
  878.     {
  879. *nNumModes = lpwd->m_pModesList->GetCount();
  880. return NOERROR;
  881.     }
  882.     
  883.     CHXSimpleList::Iterator i;
  884.     for(i=lpwd->m_pModesList->Begin(); i!= lpwd->m_pModesList->End(); ++i)
  885.     {
  886. CModesDesc* pDesc = (CModesDesc*) *i;
  887. pModesDesc->m_nWidth = pDesc->m_nWidth;
  888. pModesDesc->m_nHeight = pDesc->m_nHeight;
  889. pModesDesc->m_nBitCount = pDesc->m_nBitCount;
  890. pModesDesc->m_fourCC = pDesc->m_fourCC;
  891. pModesDesc++;
  892.     }
  893.     return NOERROR;
  894. }
  895. /*
  896. * Sets Windraw to DD exclusive and sets the display mode to what is specified (if availiable)
  897. * Use:
  898. *  HRESULT WinDraw2_SetResolution(LPWINDRAW lpwd, UINT32 width, UINT32 height, UINT32 depth);
  899. * Input:
  900. *  lpwd    - pointer to a WINDRAW engine to work with 
  901. *  width   - target width
  902. *  height  - target height
  903. *  depth   - target pixel depth
  904. *
  905. * Returns:
  906. *  NOERROR if OK, or E_FAIL.
  907. */
  908. HRESULT WinDraw2_GetResolution(LPWINDRAW lpwd, UINT32* width, UINT32* height, UINT32* depth)
  909. {
  910.     if (! (lpwd->fMode & WINDRAW_DIRECTDRAW) || !width || !height || !depth)
  911.     {
  912.         return E_FAIL;
  913.     }
  914.     DDSURFACEDESC  ddDesc;
  915.     memset(&ddDesc,0,sizeof(ddDesc));
  916.     ddDesc.dwSize = sizeof(ddDesc);
  917.     
  918.     HRESULT hr;
  919.     try
  920.     {
  921.     hr = lpwd->dd.lpDD2->GetDisplayMode(&ddDesc);
  922.     }
  923.     catch(...)
  924.     {
  925.         DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "WinDraw2_GetResolution");
  926.         return HXR_FAIL;
  927.     }
  928.     if (DD_OK != hr)
  929.         return E_FAIL;
  930.     *width = ddDesc.dwWidth;
  931.     *height = ddDesc.dwHeight;
  932.     *depth = ddDesc.ddpfPixelFormat.dwRGBBitCount;
  933.     return NO_ERROR;
  934. }
  935. HRESULT WinDraw2_SetResolution(LPWINDRAW lpwd, UINT32 width, UINT32 height, UINT32 depth, HWND hwnd)
  936. {
  937.     if (! (lpwd->fMode & WINDRAW_DIRECTDRAW) )
  938.     {
  939. return E_FAIL;
  940.     }
  941.     
  942.     HRESULT hr = E_FAIL;
  943.     EnterCriticalSection(&lpwd->csPrimary);
  944.     try
  945.     {
  946.     hr = lpwd->dd.lpDD2->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
  947.     if (NOERROR == hr)
  948.     {
  949.         if (lpwd->dd.lpDDSPrimary)
  950.         {
  951.             int ref = lpwd->dd.lpDDSPrimary->Release();
  952.             if (!ref)
  953.                 lpwd->dd.lpDDSPrimary = 0;
  954.         }
  955.         // we're not going to change the bit depth so we need to overide the depth variable
  956.         UINT32 tmp,tmpDepth;
  957.         if (NO_ERROR == WinDraw2_GetResolution(lpwd, &tmp, &tmp, &tmpDepth))
  958.             depth = tmpDepth;
  959.         lpwd->dd.lpDD2->SetDisplayMode(width, height, depth, NULL, NULL);
  960.         WindrawSurface_CreatePrimarySurface(lpwd);
  961.     }
  962.     }
  963.     catch(...)
  964.     {
  965.         DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "WinDraw2_SetResolution");
  966.         hr = HXR_FAIL;
  967.     }
  968.     LeaveCriticalSection(&lpwd->csPrimary);
  969.     
  970.     return hr;
  971. }
  972. HRESULT WinDraw2_RestoreResolution(LPWINDRAW lpwd)
  973. {
  974.     if (! (lpwd->fMode & WINDRAW_DIRECTDRAW) )
  975.     {
  976. return E_FAIL;
  977.     }
  978.     
  979.     HRESULT res;
  980.     EnterCriticalSection(&lpwd->csPrimary);
  981.     try
  982.     {
  983.     lpwd->dd.lpDD2->SetCooperativeLevel(lpwd->hWnd, DDSCL_NORMAL);
  984.     
  985.     if (lpwd->dd.lpDDSPrimary)
  986.     {
  987.         int ref = lpwd->dd.lpDDSPrimary->Release();
  988.         if (!ref)
  989.             lpwd->dd.lpDDSPrimary = 0;
  990.     }
  991.     
  992.     lpwd->dd.lpDD2->RestoreDisplayMode();
  993.     
  994.     res = WindrawSurface_CreatePrimarySurface(lpwd);
  995.     }
  996.     catch(...)
  997.     {
  998.         DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "WinDraw2_RestoreResolution");
  999.         res = HXR_FAIL;
  1000.     }
  1001.     
  1002.     LeaveCriticalSection(&lpwd->csPrimary);
  1003.     return res;
  1004. }
  1005. HRESULT WinDraw2_RestorePrimarySurface(LPWINDRAW lpwd)
  1006. {
  1007.     HRESULT hr = DD_OK;
  1008.     if (lpwd && lpwd->fMode & WINDRAW_DIRECTDRAW)
  1009.     {
  1010.         EnterCriticalSection(&lpwd->csPrimary);
  1011.         if (lpwd->dd.lpDDSPrimary)
  1012.         {
  1013.         int ref = lpwd->dd.lpDDSPrimary->Release();
  1014.         if (!ref)
  1015.         lpwd->dd.lpDDSPrimary = 0;
  1016.         }
  1017.     
  1018.         hr =  WindrawSurface_CreatePrimarySurface(lpwd);
  1019.         LeaveCriticalSection(&lpwd->csPrimary);
  1020.     }
  1021.     return hr;
  1022. }
  1023. /*
  1024. * Updates the window that the clipper should use
  1025. * Use:
  1026. *  HRESULT WinDrawSurface_Clipper(LPWINDRAW lpwd, HWND hwnd);
  1027. * Input:
  1028. *  lpwd - pointer to a base WINDRAW structure
  1029. *  hwnd - the window that the clipper should be set to
  1030. * Returns:
  1031. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  1032. */
  1033. HRESULT WinDrawSurface_SetClipper(LPWINDRAW lpwd, HWND hwnd)
  1034. {
  1035.     HRESULT hr = NO_ERROR;
  1036. #ifndef _REMOVE_WINDRAW_CLIPPER 
  1037.     if (! (lpwd->fMode & WINDRAW_DIRECTDRAW) || ! (lpwd->fMode & WINDRAW_OPENED)  )
  1038.     {
  1039.         return E_FAIL;
  1040.     }
  1041.     
  1042.     IDirectDrawClipper* lpClipper;
  1043.     
  1044.     try
  1045.     {
  1046.     hr = lpwd->dd.lpDDSPrimary->GetClipper(&lpClipper);
  1047.     }
  1048.     catch(...)
  1049.     {
  1050.         DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "WinDraw2_SetClipper");
  1051.         hr = HXR_FAIL;
  1052.     }
  1053.     if (DD_OK == hr)
  1054.     {
  1055.         lpClipper->SetHWnd(0, hwnd);
  1056.         lpwd->m_hCurrentClipWindow = hwnd;
  1057.         return NO_ERROR;
  1058.     }
  1059. #endif
  1060.     
  1061.     return hr;
  1062. }
  1063. HRESULT WinDrawSurface_GetClipperWindow(LPWINDRAW lpwd, HWND* pHwnd)
  1064. {
  1065. #ifndef _REMOVE_WINDRAW_CLIPPER 
  1066.     if (! (lpwd->fMode & WINDRAW_DIRECTDRAW)  || ! (lpwd->fMode & WINDRAW_OPENED) )
  1067.     {
  1068. *pHwnd = 0;
  1069. return E_FAIL;
  1070.     }
  1071.     
  1072.     *pHwnd = lpwd->m_hCurrentClipWindow;
  1073. #endif
  1074.     return HXR_OK;
  1075. }
  1076. HRESULT WinDrawSurface_GetColorControls(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  1077.         float &fBright, float &fContrast, float &fSaturation,
  1078.         float &fHue, float &fSharpness)
  1079. {
  1080.     HRESULT hr = HXR_FAIL;
  1081.     if ((lpwd == NULL) | (lpwds == NULL))
  1082.     {
  1083.         HX_ASSERT(0);
  1084.         return E_INVALIDARG;
  1085.     }
  1086.     IDirectDrawColorControl *pcc = NULL;
  1087.     lpwds->dd.lpDDSurface->QueryInterface(IID_IDirectDrawColorControl, (void**)&pcc);
  1088.     if (pcc)
  1089.     {
  1090.         DDCOLORCONTROL ddcc;
  1091.         memset(&ddcc, 0, sizeof(ddcc));
  1092.         ddcc.dwSize = sizeof(ddcc);
  1093.         
  1094.         try
  1095.         {
  1096.         pcc->GetColorControls(&ddcc);
  1097.         HX_RELEASE(pcc);
  1098.         // Map dd values to rma values
  1099.         fBright = (float)((ddcc.lBrightness - 5000.0) / 5000.0);
  1100.         fContrast = (float)((ddcc.lContrast - 10000.0) / 10000.0);
  1101.         fHue = (float)(ddcc.lHue/180.0);
  1102.          
  1103.         fSaturation = (float)((ddcc.lSaturation - 10000.0) / 10000.0);
  1104.         fSharpness = (float)((ddcc.lSharpness - 2.5) / 2.5);
  1105.         hr = HXR_OK;
  1106.         }
  1107.         catch(...)
  1108.         {
  1109.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDrawSurface_GetColorControls");
  1110.             hr = HXR_FAIL;
  1111.             
  1112.             HX_RELEASE(pcc);
  1113.         }
  1114.     }
  1115.     return hr;
  1116. }
  1117. HRESULT WinDrawSurface_SetColorControls(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  1118.         float fBright, float fContrast, float fSaturation,
  1119.         float fHue, float fSharpness)
  1120. {
  1121.     HRESULT hr = HXR_OK;
  1122.     
  1123.     if ((lpwd == NULL) | (lpwds == NULL))
  1124.     {
  1125.         HX_ASSERT(0);
  1126.         return E_INVALIDARG;
  1127.     }
  1128.     // Map dd values to rma values (where zero is default)
  1129.     IDirectDrawColorControl *pcc = NULL;
  1130.     lpwds->dd.lpDDSurface->QueryInterface(IID_IDirectDrawColorControl, (void**)&pcc);
  1131.     if (pcc)
  1132.     {
  1133.         DDCOLORCONTROL ddcc;
  1134.         memset(&ddcc, 0, sizeof(ddcc));
  1135.         ddcc.dwSize = sizeof(ddcc);
  1136.         DDCOLORCONTROL ddccCurrent;
  1137.         memset(&ddccCurrent, 0, sizeof(ddccCurrent));
  1138.         ddccCurrent.dwSize = sizeof(ddccCurrent);
  1139.         try
  1140.         {
  1141.         hr = pcc->GetColorControls(&ddccCurrent);
  1142.         ddcc = ddccCurrent;
  1143.         
  1144.         // (0-10000, 750 is dd default)
  1145.         if (fBright == 0.0)
  1146.             ddcc.lBrightness = lpwds->dd.ddcc.lBrightness;
  1147.         else
  1148.         {
  1149.             // Mapping [-1,1] to [0,10000] with a default of 750
  1150.             if (fBright > 0)
  1151.                 ddcc.lBrightness = (LONG)(fBright * 9250.0 + 750.0);
  1152.             else
  1153.                 ddcc.lBrightness = (LONG)((fBright + 1.0) * 750.0);
  1154.         }
  1155.         // (0-20000, 10000 is dd default - limit to 2k-18k for compatabilty)
  1156.         if (fContrast == 0.0)
  1157.             ddcc.lContrast = lpwds->dd.ddcc.lContrast;
  1158.         else
  1159.             ddcc.lContrast = (LONG)(fContrast * 8000.0 + 10000.0);
  1160.         
  1161.         // (-180-180, 0 is dd default)
  1162.         if (fHue == 0.0)
  1163.             ddcc.lHue = lpwds->dd.ddcc.lHue;
  1164.         else
  1165.             ddcc.lHue = (LONG)(fHue*180.0);
  1166.         // (0-20000, 10000 is dd default limit to 4k-16k for compatabilty)
  1167.         if (fSaturation == 0.0)
  1168.             ddcc.lSaturation = lpwds->dd.ddcc.lSaturation;
  1169.         else
  1170.             ddcc.lSaturation = (LONG)(fSaturation * 6000.0 + 10000.0);
  1171.         // (0-10, 5 is dd default and -1 is rma def)
  1172.         if (fSharpness == 0.0)
  1173.             ddcc.lSharpness = lpwds->dd.ddcc.lSharpness;
  1174.         else
  1175.             ddcc.lSharpness = (LONG)(fSharpness * 5 + 5);
  1176.         if (ddccCurrent.lBrightness != ddcc.lBrightness ||
  1177.             ddccCurrent.lContrast   != ddcc.lContrast ||
  1178.             ddccCurrent.lHue        != ddcc.lHue ||
  1179.             ddccCurrent.lSaturation != ddcc.lSaturation ||
  1180.             ddccCurrent.lSharpness  != ddcc.lSharpness)
  1181.         {
  1182.             hr = pcc->SetColorControls(&ddcc);
  1183.         }
  1184.         }
  1185.         catch(...)
  1186.         {
  1187.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDrawSurface_SetColorControls");
  1188.             hr = HXR_FAIL;
  1189.         }
  1190.         pcc->Release();
  1191.     }
  1192.     return hr;
  1193. }
  1194. HRESULT WindrawSurface_CreatePrimarySurface(LPWINDRAW lpwd)
  1195. {
  1196.     if (lpwd == NULL)
  1197.     {
  1198.         HX_ASSERT(0);
  1199.         return E_INVALIDARG;
  1200.     }
  1201.     EnterCriticalSection(&lpwd->csPrimary);
  1202.     if (lpwd->dd.lpDDSPrimary)
  1203.     {
  1204.         lpwd->dd.lpDDSPrimary->Release();
  1205.         lpwd->dd.lpDDSPrimary = NULL;
  1206.     }
  1207.     /* Create the primary surface  */
  1208.     DDSURFACEDESC ddsd;
  1209.     ZeroMemory(&ddsd, sizeof(ddsd));
  1210.     ddsd.dwSize = sizeof(ddsd);
  1211.     ddsd.dwFlags = DDSD_CAPS;
  1212.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  1213.     
  1214.     int res;
  1215.     IDirectDrawClipper* lpClipper = NULL;
  1216.     
  1217.     try
  1218.     {
  1219.     res = lpwd->dd.lpDD2->CreateSurface (&ddsd, &lpwd->dd.lpDDSPrimary, NULL);
  1220. #ifndef _REMOVE_WINDRAW_CLIPPER 
  1221.     if (res == DD_OK)
  1222.     {
  1223. if (DD_OK == (res = lpwd->dd.lpDD2->CreateClipper(0, &(lpClipper), NULL))) 
  1224. {
  1225.             lpClipper->SetHWnd(0, lpwd->hWnd);
  1226.     lpwd->m_hCurrentClipWindow = lpwd->hWnd;
  1227.     lpwd->dd.lpDDSPrimary->SetClipper(lpClipper);
  1228.     lpClipper->Release(); /* ok the surface has the ref on it now */
  1229.     lpClipper = NULL;
  1230. }
  1231.     }    
  1232. #endif
  1233.     
  1234.     }
  1235.     catch(...)
  1236.     {
  1237.         DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "WindrawSurface_CreatePrimarySurface");
  1238.         res = HXR_FAIL;
  1239.         HX_RELEASE(lpClipper);
  1240.         HX_RELEASE(lpwd->dd.lpDDSPrimary);
  1241.     }
  1242.     LeaveCriticalSection(&lpwd->csPrimary);
  1243.     return res;
  1244. }
  1245. int Windraw_ColorMatch(LPWINDRAW lpwd, COLORREF crColor)
  1246. {
  1247.     HDC hdc;
  1248.     DDSURFACEDESC ddsd;
  1249.     int retVal;
  1250.     HRESULT res;
  1251.     
  1252.     if ( lpwd == NULL ||
  1253.         (!(lpwd->fMode & WINDRAW_OPENED)) || 
  1254.         (!(lpwd->fMode & WINDRAW_DIRECTDRAW)))
  1255.     {
  1256. return 0x0000000;
  1257.     }
  1258.     
  1259.     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  1260.     ddsd.dwSize = sizeof(DDSURFACEDESC);
  1261.     
  1262.     // get primary surface CID.
  1263.     BMI bmi;
  1264.     memset(&bmi, 0, sizeof(BMI));
  1265.     WinDraw2_GetDisplayFormat(lpwd, &bmi);
  1266.     bmi.bmiHeader.biHeight = 2;
  1267.     bmi.bmiHeader.biWidth = 2;
  1268.     
  1269.     WINDRAWSURFACE tempSurf;
  1270.     memset(&tempSurf, 0, sizeof(WINDRAWSURFACE));
  1271.     
  1272.     try
  1273.     {
  1274.     // now attempt to create the surface
  1275.     res = WinDraw2_CreateSurface(lpwd, &tempSurf, &bmi, WINDRAWSURFACE_DIRECTDRAW, 0, 0);
  1276.     res = WinDrawSurface_GetDC(lpwd, &tempSurf, &hdc);
  1277.     COLORREF ref = SetPixel (hdc, 0, 0, crColor);
  1278.     res = WinDrawSurface_ReleaseDC(lpwd, &tempSurf, hdc);
  1279.     
  1280.     res = tempSurf.dd.lpDDSurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
  1281.     retVal = *(PDWORD)ddsd.lpSurface;
  1282.     res = tempSurf.dd.lpDDSurface->Unlock(ddsd.lpSurface);
  1283.     
  1284.     if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
  1285.         retVal &= (1L << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;
  1286.     res = WinDraw2_ReleaseSurface(lpwd, &tempSurf);
  1287.     
  1288.     }
  1289.     catch(...)
  1290.     {
  1291.         DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "Windraw_ColorMatch");
  1292.         retVal = HXR_FAIL;
  1293.         if (tempSurf.dd.lpDDSurface)
  1294.             WinDraw2_ReleaseSurface(lpwd, &tempSurf);
  1295.     }
  1296.     
  1297.     return retVal; 
  1298. }
  1299. int countBits(int input)
  1300. {
  1301.     int count = 0;
  1302.     
  1303.     while(input)
  1304.     {
  1305. input &= input-1;
  1306. count++;
  1307.     }
  1308.     return count;
  1309. }
  1310. int Windraw_GetLowestColor(LPWINDRAW lpwd)
  1311. {
  1312.     DDSURFACEDESC ddsd;
  1313.     int retVal;
  1314.     HRESULT res;
  1315.     
  1316.     if ( lpwd == NULL || 
  1317.         (!(lpwd->fMode & WINDRAW_OPENED)) || 
  1318.         (!(lpwd->fMode & WINDRAW_DIRECTDRAW)))
  1319.     {
  1320. return 0x0000000;
  1321.     }
  1322.     
  1323.     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  1324.     ddsd.dwSize = sizeof(DDSURFACEDESC);
  1325.     
  1326.     // get primary surface CID.
  1327.     BMI bmi;
  1328.     memset(&bmi, 0, sizeof(BMI));
  1329.     WinDraw2_GetDisplayFormat(lpwd, &bmi);
  1330.     bmi.bmiHeader.biHeight = 2;
  1331.     bmi.bmiHeader.biWidth = 2;
  1332.     
  1333.     WINDRAWSURFACE tempSurf;
  1334.     memset(&tempSurf, 0, sizeof(WINDRAWSURFACE));
  1335.     
  1336.     try
  1337.     {
  1338.     // now attempt to create the surface
  1339.     res = WinDraw2_CreateSurface(lpwd, &tempSurf, &bmi, WINDRAWSURFACE_DIRECTDRAW, 0, 0);
  1340.     res = tempSurf.dd.lpDDSurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
  1341.     res = tempSurf.dd.lpDDSurface->Unlock(ddsd.lpSurface);
  1342.     
  1343.     int redMask = ddsd.ddpfPixelFormat.dwRBitMask;
  1344.     int greenMask = ddsd.ddpfPixelFormat.dwGBitMask;
  1345.     int blueMask = ddsd.ddpfPixelFormat.dwBBitMask;
  1346.     
  1347.     retVal = 1 << (9 - countBits(redMask));
  1348.     retVal |= (1 << (9 - countBits(greenMask))) << 8;
  1349.     retVal |= (1 << (9 - countBits(blueMask))) << 16;
  1350.     
  1351.     res = WinDraw2_ReleaseSurface(lpwd, &tempSurf);
  1352.     
  1353.     }
  1354.     catch(...)
  1355.     {
  1356.         DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "Windraw_GetLowestColor");
  1357.         retVal = HXR_FAIL;
  1358.         if (tempSurf.dd.lpDDSurface)
  1359.             WinDraw2_ReleaseSurface(lpwd, &tempSurf);
  1360.     }
  1361.     
  1362.     return retVal; 
  1363. }
  1364. HRESULT WinDraw2_GetScanLine(LPWINDRAW lpwd, DWORD *pdwScanLine)
  1365. {
  1366.     if ((lpwd == NULL) |
  1367.         (lpwd->dd.lpDD2 == NULL) | 
  1368.         (lpwd->dd.lpDDSPrimary == NULL))
  1369.     {
  1370.         *pdwScanLine = 0;
  1371.         return E_INVALIDARG;
  1372.     }
  1373.     
  1374.     HRESULT hr = NOERROR;
  1375.     try
  1376.     {
  1377.     hr = lpwd->dd.lpDD2->GetScanLine(pdwScanLine);
  1378.     if (DD_OK == hr ||
  1379.         DDERR_VERTICALBLANKINPROGRESS == hr)
  1380.     {
  1381.         // The G400 occasionally reports an obscenely high value here;
  1382.         // we filter to 130% of the reported display height
  1383.         if (*pdwScanLine > lpwd->dwReportedHeight*1.3)
  1384.         {
  1385.             *pdwScanLine = 0;
  1386.             return hr;
  1387.         }
  1388.         if (*pdwScanLine > lpwd->dwMaxScanLine) 
  1389.             lpwd->dwMaxScanLine = *pdwScanLine;
  1390.     }
  1391.     else
  1392.         *pdwScanLine = 0;
  1393.     }
  1394.     catch(...)
  1395.     {
  1396.         DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "WinDraw2_GetScanLine");
  1397.         hr = HXR_FAIL;
  1398.         *pdwScanLine = 0;
  1399.     }
  1400.     return hr;
  1401. }
  1402. HRESULT LockSurface(LPWINDRAW lpwd, LPDIRECTDRAWSURFACE lpSurface, DDSURFACEDESC *pddsd, BOOL bBlock)
  1403. {
  1404.     DWORD dwFlags = DDLOCK_WRITEONLY | DDLOCK_NOSYSLOCK;
  1405.     HRESULT hr;
  1406.     if (bBlock)
  1407.         dwFlags |= DDLOCK_WAIT;
  1408.     for (int i=0;; i++)
  1409.     {
  1410.         memset(pddsd, 0, sizeof(*pddsd));
  1411.         pddsd->dwSize = sizeof(*pddsd);
  1412.         try
  1413.         {
  1414.         hr = lpSurface->Lock(NULL, pddsd, dwFlags, NULL);
  1415.         }
  1416.         catch(...)
  1417.         {
  1418.             char szTmp[256]; /* Flawfinder: ignore */
  1419.             sprintf(szTmp, "LockSurface flags %lx", dwFlags); /* Flawfinder: ignore */
  1420.             
  1421.             DumpDDInfo(lpwd, lpSurface, szTmp);
  1422.             hr = HXR_FAIL;
  1423.         }
  1424.         if (hr == DDERR_INVALIDPARAMS)
  1425.         {
  1426.             if (i)
  1427.                 break;
  1428.             dwFlags = 0;
  1429.             dwFlags |= DDLOCK_WAIT;
  1430.         }
  1431.         else
  1432.             break;
  1433.     }
  1434.     return hr;
  1435. }
  1436. HRESULT RestoreSurfaces(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds)
  1437. {
  1438.     HRESULT hr;
  1439.     EnterCriticalSection(&lpwd->csPrimary);
  1440.     try
  1441.     {
  1442.     // Restore the surfaces if we lost them
  1443.     hr = lpwd->dd.lpDDSPrimary->Restore();
  1444.     if (hr == DD_OK)
  1445.         hr = lpwds->dd.lpDDSurface->Restore();
  1446.     }
  1447.     catch(...)
  1448.     {
  1449.         DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "RestoreSurfaces");
  1450.         hr = HXR_FAIL;
  1451.     }
  1452.     LeaveCriticalSection(&lpwd->csPrimary);
  1453.     return hr;
  1454. }
  1455. #if defined (HELIX_FEATURE_VS2)
  1456. /*
  1457.  * WinDraw2_GetColorspacePriorities
  1458.  *
  1459.  * Request preferred color spaces from the DD driver
  1460.  */
  1461. HRESULT WinDraw2_GetColorspacePriorities(int cidIn, int *pCPList, int &nSize)
  1462. {
  1463.     LPDIRECTDRAW        lpTemp = 0;
  1464.     LPDIRECTDRAW2       lpDD = 0;
  1465.     HINSTANCE           hDirectDraw = 0;
  1466.     HRESULT             ddrval = 0;
  1467.     DWORD               pFourcc[128];
  1468.     DWORD               dwNumCodes = 0;
  1469.     int                 j=0;
  1470.     unsigned int        yv12 = -1,
  1471.                         yuy2 = -1,
  1472.                         uyvy = -1;
  1473.     try
  1474.     {
  1475.     
  1476.     LoadDirectDraw(NULL, &lpTemp, &hDirectDraw);
  1477.     if (lpTemp)
  1478.     {
  1479.         lpTemp->QueryInterface(IID_IDirectDraw2, (void**)&lpDD);
  1480.         lpTemp->Release();
  1481.     }
  1482.     if(lpDD)
  1483.     {
  1484.         memset(pFourcc, 0, sizeof(pFourcc));
  1485.         // Get the number of supported 4CC codes
  1486.         if (DD_OK != lpDD->GetFourCCCodes(&dwNumCodes, 0))
  1487.         {
  1488.             ReleaseDirectDraw(NULL, &lpDD, &hDirectDraw);
  1489.             return E_FAIL;
  1490.         }
  1491.         // Get the list of supported 4CC codes
  1492.         ddrval = lpDD->GetFourCCCodes(&dwNumCodes, pFourcc);
  1493.         if (ddrval != DD_OK || !dwNumCodes)
  1494.         {
  1495.             ReleaseDirectDraw(NULL, &lpDD, &hDirectDraw);
  1496.             return E_FAIL;
  1497.         }
  1498.         memset(pCPList, 0, nSize * sizeof(*pCPList));
  1499.         // If I420 is not the source format, make it the first priority in hopes
  1500.         // of avoiding an unnecessary color conversion when writing to video memory.
  1501.         if (IsYUV(cidIn) && CID_I420 != cidIn)
  1502.         {
  1503.             pCPList[j++] = cidIn;
  1504.         }
  1505.         
  1506.         if(dwNumCodes && pFourcc && DD_OK == ddrval)
  1507.         {
  1508.             for(int i=0; i < (int)dwNumCodes && j < nSize; i++)
  1509.             {
  1510.                 switch(MapFourCCtoCID(pFourcc[i]))
  1511.                 {
  1512.                     case CID_I420: pCPList[j++] = CID_I420; break;
  1513.                     case CID_YV12: pCPList[j++] = CID_YV12; yv12 = j-1; break;
  1514.                     case CID_UYVY: pCPList[j++] = CID_UYVY; uyvy = j-1; break;
  1515.                     case CID_YUY2: pCPList[j++] = CID_YUY2; yuy2 = j-1; break;
  1516.                 }
  1517.             }
  1518.             nSize = j;
  1519.             BOOL bTrySort = FALSE;
  1520.             DDDEVICEIDENTIFIER ddID;
  1521.             // Do some hard-coded ovverrides.  We want yv12 over packed 
  1522.             // formats, so, if yv12 is in the list put it at the head
  1523.             // EXCEPT for nvidia and Matrox G200, which have poor yv12 support.
  1524. #if DIRECTDRAW_VERSION > 0x0500
  1525.             IDirectDraw4* lpDD4 = NULL;
  1526.             lpDD->QueryInterface(IID_IDirectDraw4, (void **) &lpDD4);
  1527.     
  1528.             if (lpDD4)
  1529.             {
  1530.                 DDDEVICEIDENTIFIER  dddi;
  1531.                 memset(&dddi, 0, sizeof(dddi));
  1532.                 lpDD4->GetDeviceIdentifier(&dddi, DDGDI_GETHOSTIDENTIFIER);
  1533.                 lpDD4->Release();
  1534.                 SafeStrCpy(ddID.szDescription, dddi.szDescription, MAX_DDDEVICEID_STRING);
  1535.                 SafeStrCpy(ddID.szDriver, dddi.szDriver, MAX_DDDEVICEID_STRING);
  1536.                 ddID.dwVendorId = dddi.dwVendorId;
  1537.                 ddID.dwDeviceId = dddi.dwDeviceId;
  1538.                 bTrySort = TRUE;
  1539.             }
  1540.             // DD4 not supportted (probably NT4)...use more drastic measures
  1541.             else
  1542. #endif //DIRECTDRAW_VERSION > 0x0500
  1543.             {
  1544.                 // Check if we are runnning NT
  1545.                 OSVERSIONINFO osVersion;
  1546.                 memset(&osVersion,0, sizeof(OSVERSIONINFO));
  1547.                 osVersion.dwOSVersionInfoSize  = sizeof(OSVERSIONINFO);
  1548.                 if (GetVersionEx(&osVersion) && osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT)
  1549.                 {
  1550.                     char szChipType[MAXCHIPTYPE]; /* Flawfinder: ignore */
  1551.                     
  1552.                     // Try to get WinNT device information
  1553.                     if (GetWinNTDeviceID (&ddID, szChipType))
  1554.                     {
  1555.                         bTrySort = TRUE;
  1556.                     }
  1557.                 }
  1558.             }
  1559.             if (bTrySort &&
  1560.                 yv12 != -1 &&
  1561.                 
  1562.                 // TNT yv12 chroma does not line up
  1563.                 ddID.dwVendorId != 0x10DE &&
  1564.                 // NeoMagic yv12 chroma probs when overlay is cropped
  1565.                 ddID.dwVendorId != 0x10C8 &&
  1566.                 // Riva128 yv12 has software conversion and
  1567.                 // locks always return same ptr.
  1568.                 strcmpi(ddID.szDescription, "NV3") &&
  1569.                 ddID.dwVendorId != 0x12D2 &&
  1570.                 // G200 uses sofware converstion to yv12
  1571.                 !strstr(ddID.szDescription, "Matrox Millennium G200"))
  1572.             {
  1573.                 if (yv12 > uyvy)
  1574.                 {
  1575.                     pCPList[uyvy] = CID_YV12;
  1576.                     pCPList[yv12] = CID_UYVY;
  1577.                     yv12 = uyvy;
  1578.                 }
  1579.                 if (yv12 > yuy2)
  1580.                 {
  1581.                     pCPList[yuy2] = CID_YV12;
  1582.                     pCPList[yv12] = CID_YUY2;
  1583.                 }
  1584.             }
  1585.             
  1586.             // Filter bad Radeon drivers
  1587.             if (ddID.dwVendorId == 0x1002 &&
  1588.                 ddID.szDriver &&
  1589.                 pCPList[0] == CID_DVPF)
  1590.             {
  1591.                 // The only difference is in the dll's file version
  1592.                 char szTmp[256] = "";
  1593.                 SafeStrCpy(szTmp, getenv("windir"), sizeof(szTmp));
  1594.                 int nLen = strlen(szTmp);
  1595.                 
  1596.                 if (szTmp[nLen-1] != '\')
  1597.                 {
  1598.                     szTmp[nLen] = '\';
  1599.                     szTmp[++nLen] = '';
  1600.                 }
  1601.                 // write OS version
  1602.                 OSVERSIONINFO ver;
  1603.                 memset(&ver, 0, sizeof(ver));
  1604.                 ver.dwOSVersionInfoSize = sizeof(ver);
  1605.                 GetVersionEx(&ver);
  1606.                 
  1607.                 if (VER_PLATFORM_WIN32_NT == ver.dwPlatformId)
  1608.                 {
  1609.                     SafeStrCat(szTmp, "system32\", sizeof(szTmp));
  1610.                 }
  1611.                 else
  1612.                 {
  1613.                     SafeStrCat(szTmp, "system\", sizeof(szTmp));
  1614.                 }
  1615.                  
  1616.                 SafeStrCat(szTmp, ddID.szDriver, sizeof(szTmp));
  1617.                 
  1618.                 // Query the file version of this dll
  1619.                 DWORD dwHandle = 0;
  1620.                 DWORD dwSize = GetFileVersionInfoSize(szTmp, &dwHandle);
  1621.                 if (dwSize)
  1622.                 { 
  1623.                     BYTE* pBuf = new BYTE[dwSize];
  1624.                     if (pBuf)
  1625.                     {
  1626.                         if (GetFileVersionInfo(szTmp, NULL, dwSize, pBuf))
  1627.                         {
  1628.                             UINT nLen = 0;
  1629.                             char szQuery[64];
  1630.                             char* pFileVersion = NULL;
  1631.                             
  1632.                             struct LANGANDCODEPAGE
  1633.                             {
  1634.                                 WORD wLanguage;
  1635.                                 WORD wCodePage;
  1636.                             } *lpTranslate;
  1637.                             // Read the list of languages and code pages.
  1638.                             VerQueryValue(pBuf, 
  1639.                                           TEXT("\VarFileInfo\Translation"),
  1640.                                           (LPVOID*)&lpTranslate,
  1641.                                           &nLen);
  1642.                             // Read the file description for each language and code page.
  1643.                             for(UINT32 i=0; i < (nLen/sizeof(struct LANGANDCODEPAGE)); i++ )
  1644.                             {
  1645.                                 // Use first english entry
  1646.                                 if (lpTranslate[i].wLanguage == 0x409)
  1647.                                 {
  1648.                                     SafeSprintf(szQuery, sizeof(szQuery),
  1649.                                                 TEXT("\StringFileInfo\%04x%04x\FileVersion"),
  1650.                                                 lpTranslate[i].wLanguage,
  1651.                                                 lpTranslate[i].wCodePage);
  1652.                                     
  1653.                                     if (VerQueryValue(pBuf, szQuery, (void**)&pFileVersion, &nLen))
  1654.                                         break;
  1655.                                 }    
  1656.                             }
  1657.                             // catalyst drvier 3.0 and 3.1 do not work w/ R1 on winNT
  1658.                             if (!strcmp(pFileVersion, "6.14.01.6255") ||
  1659.                                 !strcmp(pFileVersion, "6.14.01.6292") ||
  1660.                                 
  1661.                             // catalyst drvier 3.2 on 9700's do not work w/ R1 on Win9x/NT    
  1662.                                 (ddID.dwDeviceId == 0x4e44 &&
  1663.                                   (!strcmp(pFileVersion, "6.14.01.6307") || 
  1664.                                    !strcmp(pFileVersion, "4.14.01.3699"))))
  1665.                             {
  1666.                                 pCPList[0] = pCPList[1];
  1667.                             }
  1668.                         }
  1669.                         
  1670.                         delete [] pBuf; 
  1671.                     }
  1672.                 }
  1673.             }
  1674.         }
  1675.         ReleaseDirectDraw(NULL, &lpDD, &hDirectDraw);
  1676.     }
  1677.     else
  1678.         return E_FAIL;
  1679.     }
  1680.     catch(...)
  1681.     {
  1682.         DumpDDInfo(NULL, NULL, "WinDraw2_GetColorspacePriorities");
  1683.         if (lpDD)
  1684.             ReleaseDirectDraw(NULL, &lpDD, &hDirectDraw);
  1685.         return HXR_FAIL;;
  1686.     }
  1687.     return NOERROR;
  1688. }
  1689. HRESULT WinDraw_CanLockSurface (LPWINDRAW lpwd, WINDRAWSURFACE *lpwds, UCHAR* &pBuffer, int& nIndex, BOOL bBlock)
  1690. {
  1691.     HRESULT hr;
  1692.     if ((lpwd == NULL) | (lpwds == NULL)) 
  1693.     {
  1694.         HX_ASSERT(0);
  1695.         return E_INVALIDARG;
  1696.     }
  1697.     // Get the next buffer in the flipping chain
  1698.     if (-1 == nIndex)
  1699.     {
  1700.         hr = WaitForSingleObject(lpwds->hOverlayIndexMutex, 0);
  1701.         // Do not block if flags say so
  1702.         if (WAIT_TIMEOUT == hr)
  1703.         {
  1704.             if (bBlock)
  1705.             {
  1706.                 HANDLE  aWaitObjs[2] = {lpwds->hOverlayIndexMutex, lpwds->dd.hAbort};
  1707.                 hr = WaitForMultipleObjects(2, aWaitObjs, FALSE, INFINITE);
  1708.                 if (WAIT_OBJECT_0+1 == hr)
  1709.                     return DDERR_WASSTILLDRAWING;
  1710.             }
  1711.             else
  1712.                 return DDERR_WASSTILLDRAWING;
  1713.         }
  1714.         
  1715.         nIndex = lpwds->dwNextBuffer;
  1716.         ReleaseMutex(lpwds->hOverlayIndexMutex);
  1717.     }
  1718.     int nNextIndex = nIndex + 1;
  1719.     if (nNextIndex == (int)(lpwds->dwBackBufferCount+1))
  1720.         nNextIndex = 0;
  1721.     
  1722.     // Wait until the buffer ahead of this one has flipped so that we have
  1723.     // a valid wait-until-time
  1724.     if (!bBlock)
  1725.     {
  1726.         hr = WaitForSingleObject(lpwds->dd.lpChain[nNextIndex].hEmpty, 0);
  1727.         if (WAIT_OBJECT_0 != hr)
  1728.             return DDERR_WASSTILLDRAWING;
  1729.     }
  1730.     else
  1731.     {
  1732.         HANDLE  aWaitObjects[2] = {lpwds->dd.lpChain[nNextIndex].hEmpty, lpwds->dd.hAbort};
  1733.         hr = WaitForMultipleObjects(2, aWaitObjects, FALSE, INFINITE);
  1734.     }
  1735.     
  1736.     if (hr != WAIT_OBJECT_0)
  1737.         return HXR_FAIL;
  1738.     double dTimeAvailable = lpwds->dd.lpChain[nIndex].dTimeAvailable;
  1739.     // Check the time of the surface
  1740.     double dTime = GetMSTickDouble32();
  1741.     if (dTimeAvailable > dTime)
  1742.     {
  1743.         //HX_TRACE("Waiting for buffer, %lu", (UINT32) (dTimeAvailable - dTime));
  1744.         if (bBlock)
  1745.         {
  1746.             if (lpwd->nSchedulerResolution)
  1747.                 timeBeginPeriod(lpwd->nSchedulerResolution);
  1748.             
  1749.             DWORD dwWait = (DWORD)(dTimeAvailable - dTime + 1);
  1750.             HX_ASSERT(dwWait < 20000);
  1751.             WaitForSingleObject(lpwds->dd.hAbort, dwWait);
  1752.             if (lpwd->nSchedulerResolution)
  1753.                 timeEndPeriod(lpwd->nSchedulerResolution);
  1754.         }
  1755.         else
  1756.             return DDERR_WASSTILLDRAWING;
  1757.     }
  1758.     hr = IsFlipDone(lpwd, lpwds, &lpwds->dd.lpChain[nIndex], bBlock);
  1759.     if (DD_OK != hr)
  1760.     {
  1761.         // For breakpoints?
  1762.         return hr;
  1763.     }
  1764.     return hr;
  1765. }
  1766. HRESULT WinDraw_GetLockedSurface (LPWINDRAW lpwd, WINDRAWSURFACE *lpwds, UCHAR* &pBuffer, int nIndex, BOOL bBlock)
  1767. {
  1768.     DDSURFACEDESC ddsd;
  1769.     HRESULT hr = HXR_FAIL;
  1770.     HRESULT hRet;
  1771.     BOOL    bLoop = TRUE;
  1772.     if ((lpwd == NULL) | 
  1773.         (lpwds == NULL) | 
  1774.         (lpwds->dd.lpChain == NULL))
  1775.     {
  1776.         HX_ASSERT(0);
  1777.         return E_INVALIDARG;
  1778.     }
  1779.     #ifdef _DEBUG
  1780.     LARGE_INTEGER   lFreq,
  1781.                     lTime;
  1782.     LONGLONG        llTime;
  1783.     QueryPerformanceFrequency(&lFreq);
  1784.     #endif
  1785.     memset(&ddsd, 0, sizeof(ddsd));
  1786.     ddsd.dwSize = sizeof(ddsd);
  1787.     // Get the next buffer in the flipping chain
  1788.     if (-1 == nIndex)
  1789.     {
  1790.         hr = WaitForSingleObject(lpwds->hOverlayIndexMutex, 0);
  1791.         // Do not block if flags say so
  1792.         if (WAIT_TIMEOUT == hr)
  1793.         {
  1794.             if (bBlock)
  1795.             {
  1796.                 HANDLE  aWaitObjs[2] = {lpwds->hOverlayIndexMutex, lpwds->dd.hAbort};
  1797.                 hr = WaitForMultipleObjects(2, aWaitObjs, FALSE, INFINITE);
  1798.                 if (WAIT_OBJECT_0+1 == hr)
  1799.                     return DDERR_WASSTILLDRAWING;
  1800.             }
  1801.             else
  1802.                 return DDERR_WASSTILLDRAWING;
  1803.         }
  1804.         
  1805.         nIndex = lpwds->dwNextBuffer;
  1806.         ReleaseMutex(lpwds->hOverlayIndexMutex);
  1807.     }
  1808.     
  1809.     int nNextIndex = nIndex + 1;
  1810.     if (nNextIndex == (int)(lpwds->dwBackBufferCount+1))
  1811.         nNextIndex = 0;
  1812.     HANDLE  aWaitObjects[2] = {lpwds->dd.lpChain[nNextIndex].hEmpty, lpwds->dd.hAbort};
  1813.     int nCount = 0;
  1814.     // Try and lock the surface while handling various dd errors
  1815.     while (bLoop)
  1816.     {
  1817.         hRet = WaitForSingleObject(lpwds->hOverlayMutex, 0);
  1818.         if (hRet == WAIT_TIMEOUT)
  1819.         {
  1820.             if (!bBlock)
  1821.                 return DDERR_WASSTILLDRAWING;
  1822.             else
  1823.                 WaitForSingleObject(lpwds->hOverlayMutex, INFINITE);
  1824.         }
  1825.         hr = LockSurface(lpwd, lpwds->dd.lpChain[nIndex].lpSurface, &ddsd, FALSE);
  1826.     
  1827.         if (DD_OK != hr)
  1828.             ReleaseMutex(lpwds->hOverlayMutex);
  1829.         // Could not lock the surface right now so wait a bit and try again
  1830.         if (DDERR_WASSTILLDRAWING == hr)
  1831.         {
  1832.             #ifdef _DEBUG
  1833.             QueryPerformanceCounter(&lTime);
  1834.             llTime = lTime.QuadPart;
  1835.             #endif
  1836.             
  1837.             if (!bBlock)
  1838.                 break;
  1839.             if (WaitForSingleObject(lpwds->dd.hAbort, 5) != WAIT_TIMEOUT)
  1840.                 break;
  1841.         }
  1842.         else if (DDERR_SURFACELOST == hr)
  1843.         {
  1844.             hr = RestoreSurfaces(lpwd, lpwds);
  1845.             if (++nCount>1)
  1846.                 hr = HXR_FAIL;
  1847.             // Could not restore, so get out
  1848.             if (hr != DD_OK)
  1849.                 bLoop = FALSE;
  1850.         }
  1851.         // If this surface is locked by another thread...unlock it.
  1852.         // As far as my debugging went, could not find another thread
  1853.         // locking these surfaces, but so says the driver.
  1854.         else if (DDERR_SURFACEBUSY == hr)
  1855.         {
  1856.             hr = lpwds->dd.lpChain[nIndex].lpSurface->Unlock(NULL);
  1857.         }
  1858.         
  1859.         // The lock worked
  1860.         else if (DD_OK == hr)
  1861.         {
  1862.             bLoop = FALSE;
  1863.             // Store hw memory address and pitch
  1864.             lpwds->dd.lpChain[nIndex].pHwMemBuffer = (BYTE*)ddsd.lpSurface;
  1865.             lpwds->dd.lPitch = ddsd.lPitch;
  1866.             pBuffer = (UCHAR*)ddsd.lpSurface;
  1867.         }
  1868.         // Some other error
  1869.         else
  1870.         {
  1871.             bLoop = FALSE;
  1872.         }
  1873.     }
  1874.     return hr;
  1875. }
  1876. HRESULT WinDraw_ReleaseLockedSurface (LPWINDRAW lpwd, WINDRAWSURFACE *lpwds, BYTE *pHwBuf, BOOL bDiscard)
  1877. {
  1878.     HRESULT hr = HXR_OK;
  1879.     BOOL    bLoop = TRUE;
  1880.     int     nCount = 0;
  1881.     if ((lpwd == NULL) | 
  1882.         (lpwds == NULL) | 
  1883.         (lpwds->dd.lpChain == NULL))
  1884.     {
  1885.         HX_ASSERT(0);
  1886.         return E_INVALIDARG;
  1887.     }
  1888.     WaitForSingleObject(lpwds->hOverlayIndexMutex, INFINITE);
  1889.     for (int i=0; i<(int)lpwds->dwBackBufferCount+1; i++)
  1890.     {
  1891.         if (pHwBuf == lpwds->dd.lpChain[i].pHwMemBuffer)
  1892.         {
  1893.             while (bLoop)
  1894.             {
  1895.                 lpwds->dd.lpChain[i].pHwMemBuffer = NULL;
  1896.                 try
  1897.                 {
  1898.                 hr = lpwds->dd.lpChain[i].lpSurface->Unlock(NULL);
  1899.                 }
  1900.                 catch(...)
  1901.                 {
  1902.                     DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDraw_ReleaseLockedSurface");
  1903.                     hr = HXR_FAIL;
  1904.                 }
  1905.                 
  1906.                 ReleaseMutex(lpwds->hOverlayMutex);
  1907.                 if (bDiscard)
  1908.                     SetEvent(lpwds->dd.lpChain[i].hEmpty);
  1909.                 if (DDERR_SURFACELOST == hr)
  1910.                 {
  1911.                     hr = RestoreSurfaces(lpwd, lpwds);
  1912.                     if (++nCount>1)
  1913.                         hr = HXR_FAIL;
  1914.                     
  1915.                     // Could not restore, so get out
  1916.                     if (hr != DD_OK)
  1917.                     {
  1918.                         bLoop = FALSE;
  1919.                         #ifdef _DEBUG
  1920.                         //OutputDebugString("WinDraw_ReleaseLockedSurface::Unlock Failedn");
  1921.                         #endif
  1922.                     }
  1923.                 }
  1924.                 else
  1925.                     bLoop = FALSE;
  1926.             }
  1927.             break;
  1928.         }
  1929.     }
  1930.     
  1931.     ReleaseMutex(lpwds->hOverlayIndexMutex);
  1932.     return hr;
  1933. }
  1934. HRESULT WinDraw_AdvanceSurface (LPWINDRAW lpwd, WINDRAWSURFACE *lpwds, int &nIndex)
  1935. {
  1936.     HRESULT hr = HXR_OK;
  1937.     if ((lpwd == NULL) | (lpwds == NULL)) 
  1938.     {
  1939.         HX_ASSERT(0);
  1940.         return E_INVALIDARG;
  1941.     }
  1942.     WaitForSingleObject(lpwds->hOverlayIndexMutex, INFINITE);
  1943.     try
  1944.     {
  1945.     // Maintain front and next buffer indexes for default case
  1946.     if (-1 == nIndex)
  1947.     {
  1948.         nIndex = lpwds->dwNextBuffer;
  1949.         if (!lpwds->dd.lpChain[nIndex].lpSurface->IsLost())
  1950.         {
  1951.             if (++lpwds->dwNextBuffer == lpwds->dwBackBufferCount+1)
  1952.                 lpwds->dwNextBuffer = 0;    
  1953.         }
  1954.         else
  1955.             hr = HXR_FAIL;
  1956.     }
  1957.     else
  1958.     {
  1959.         if (lpwds->dd.lpChain[nIndex].lpSurface->IsLost())
  1960.             hr = HXR_FAIL;
  1961.     }
  1962.     }
  1963.     catch(...)
  1964.     {
  1965.         DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDraw_AdvanceSurface");
  1966.         hr = HXR_FAIL;
  1967.     }
  1968.     
  1969.     // Mark this surface memory as full
  1970.     if (hr == HXR_OK)
  1971.         ResetEvent(lpwds->dd.lpChain[nIndex].hEmpty);
  1972.     ReleaseMutex(lpwds->hOverlayIndexMutex);
  1973.     return hr;
  1974. }
  1975. HRESULT WinDraw_ResetSurfaceIndexes (LPWINDRAW lpwd, WINDRAWSURFACE *lpwds)
  1976. {
  1977.     HRESULT hr;
  1978.     DDSURFACEDESC ddsd;
  1979.     if ((lpwd == NULL) | (lpwds == NULL))
  1980.     {
  1981.         HX_ASSERT(0);
  1982.         return E_INVALIDARG;
  1983.     }
  1984.     HX_ASSERT( lpwds->dwBackBufferCount );
  1985.     
  1986.     // Reset the hw locations of the flipping chain
  1987.     for (UINT32 i=0; i<lpwds->dwBackBufferCount+1; i++)
  1988.     {
  1989.         memset(&ddsd, 0, sizeof(ddsd));
  1990.         ddsd.dwSize = sizeof(ddsd);
  1991.         hr = LockSurface(lpwd, lpwds->dd.lpChain[i].lpSurface, &ddsd, FALSE);
  1992.         if (DD_OK != hr)
  1993.             hr = LockSurface(lpwd, lpwds->dd.lpChain[i].lpSurface, &ddsd, TRUE);
  1994.         HX_ASSERT(DD_OK == hr);
  1995.         try
  1996.         {
  1997.         lpwds->dd.lpChain[i].lpSurface->Unlock(NULL);
  1998.         }
  1999.         catch(...)
  2000.         {
  2001.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDraw_ResetSurfaceIndexes");
  2002.             // nothing to do
  2003.         }
  2004.         lpwds->dd.lpChain[i].pHwMemBuffer = (BYTE*)ddsd.lpSurface;
  2005.     }
  2006.     
  2007.     // Set our next buffer to lock to the one after the front buffer
  2008.     memset(&ddsd, 0, sizeof(ddsd));
  2009.     ddsd.dwSize = sizeof(ddsd);
  2010.     WaitForSingleObject(lpwds->hOverlayMutex, INFINITE);
  2011.     hr = LockSurface(lpwd, lpwds->dd.lpDDSurface, &ddsd, FALSE);
  2012.     if (DD_OK != hr)
  2013.         hr = LockSurface(lpwd, lpwds->dd.lpDDSurface, &ddsd, TRUE);
  2014.     HX_ASSERT(DD_OK == hr);
  2015.     if (DD_OK == hr)
  2016.     {
  2017.         try
  2018.         {
  2019.         lpwds->dd.lpDDSurface->Unlock(NULL);
  2020.         }
  2021.         catch(...)
  2022.         {
  2023.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDraw_ResetSurfaceIndexes");
  2024.             // nothing to do
  2025.         }
  2026.         for (UINT32 i=0; i<lpwds->dwBackBufferCount+1; i++)
  2027.         {
  2028.             if ((BYTE*)ddsd.lpSurface == lpwds->dd.lpChain[i].pHwMemBuffer)
  2029.             {
  2030.                 lpwds->dwNextBuffer = i+1;
  2031.                 
  2032.                 if (lpwds->dwNextBuffer == lpwds->dwBackBufferCount+1)
  2033.                     lpwds->dwNextBuffer = 0;
  2034.                 lpwds->dd.lpDDBackBuffer = lpwds->dd.lpChain[lpwds->dwNextBuffer].lpSurface;
  2035. break;
  2036.             }
  2037.         }
  2038.         HX_ASSERT(lpwds->dd.lpDDBackBuffer);
  2039.     }
  2040.     ReleaseMutex(lpwds->hOverlayMutex);
  2041.     return HXR_OK;
  2042. }
  2043. HRESULT WinDraw_DisplaySurface (LPWINDRAW lpwd, WINDRAWSURFACE *lpwds, DWORD dwFlags, int nIndex, BOOL bAbort)
  2044. {
  2045.     HRESULT hr = HXR_OK,
  2046.             hWaitRet;
  2047.     BOOL    bLoop = TRUE;
  2048.     int     nCount = 0;
  2049.     HANDLE  aWaitObjs[2] = {lpwds->dd.hAbort, lpwds->hOverlayMutex};
  2050.     if ((lpwd == NULL) | (lpwds == NULL))
  2051.     {
  2052.         HX_ASSERT(0);
  2053.         return E_INVALIDARG;
  2054.     }
  2055.     
  2056.     // Flip the appropriate backbuffer and keep track of the
  2057.     // surface pointer location in the flipping chain.
  2058.     if (1)//-1 == nIndex)
  2059.     {
  2060.         while (bLoop)
  2061.         {
  2062.             try
  2063.             {
  2064.             if (bAbort)
  2065.                 hr = DDERR_WASSTILLDRAWING;
  2066.             else
  2067.             {
  2068.                 hWaitRet = WaitForMultipleObjects(2, aWaitObjs, FALSE, INFINITE);
  2069.                 hr = lpwds->dd.lpDDSurface->Flip(NULL, dwFlags);
  2070.                 if (WAIT_OBJECT_0+1 == hWaitRet &&
  2071.                     DDERR_SURFACEBUSY != hr)
  2072.                     ReleaseMutex(lpwds->hOverlayMutex);
  2073.             }
  2074.             if (DDERR_SURFACELOST == hr)
  2075.             {
  2076.                 hr = RestoreSurfaces(lpwd, lpwds);
  2077.                 if (++nCount>1)
  2078.                     hr = HXR_FAIL;
  2079.                 if (hr != DD_OK)
  2080.                 {
  2081.                     SetEvent(lpwds->dd.lpChain[nIndex].hEmpty);
  2082.                     bLoop = FALSE;
  2083.                 }
  2084.             }
  2085.             else if (DDERR_SURFACEBUSY == hr)
  2086.             {
  2087.                 lpwds->dd.lpChain[nIndex].lpSurface->Unlock(NULL);
  2088.                 hr = lpwds->dd.lpDDSurface->Flip(NULL, dwFlags);
  2089.                 ReleaseMutex(lpwds->hOverlayMutex);
  2090.                 bLoop = FALSE;
  2091.             }
  2092.             else
  2093.                 bLoop = FALSE;
  2094.             }
  2095.             catch(...)
  2096.             {
  2097.                 DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDraw_DisplaySurface");
  2098.                 hr = HXR_FAIL;
  2099.                 bLoop = FALSE;
  2100.             }
  2101.         }
  2102.         
  2103.         if (DDERR_WASSTILLDRAWING != hr &&
  2104.             DDERR_SURFACEBUSY != hr &&
  2105.             DDERR_INVALIDPARAMS != hr)
  2106.         {
  2107.             WaitForSingleObject(lpwds->hOverlayIndexMutex, INFINITE);
  2108.             LPDIRECTDRAWSURFACE lpTemp = lpwds->dd.lpChain[lpwds->dwBackBufferCount].lpSurface;
  2109.             for (int i=lpwds->dwBackBufferCount; i>0; i--)
  2110.             {
  2111.                 lpwds->dd.lpChain[i].lpSurface = lpwds->dd.lpChain[i-1].lpSurface;
  2112.             }
  2113.             lpwds->dd.lpChain[i].lpSurface = lpTemp;
  2114.             if (++lpwds->dwFrontBuffer == lpwds->dwBackBufferCount+1)
  2115.                 lpwds->dwFrontBuffer = 0;
  2116.             
  2117.             ReleaseMutex(lpwds->hOverlayIndexMutex);
  2118.             SetEvent(lpwds->dd.lpChain[nIndex].hEmpty);
  2119.         }
  2120.         else if (bAbort)
  2121.         {
  2122.             WaitForSingleObject(lpwds->hOverlayIndexMutex, INFINITE);
  2123.             if ((INT32)(--lpwds->dwNextBuffer) == -1)
  2124.                 lpwds->dwNextBuffer = lpwds->dwBackBufferCount;    
  2125.             
  2126.             ReleaseMutex(lpwds->hOverlayIndexMutex);
  2127.             
  2128.             SetEvent(lpwds->dd.lpChain[nIndex].hEmpty);
  2129.             hr = HXR_OK;
  2130.         }
  2131.     }
  2132.     else
  2133.     {
  2134.         while (bLoop)
  2135.         {
  2136.             try
  2137.             {
  2138.             if (bAbort)
  2139.                 hr = DDERR_WASSTILLDRAWING;
  2140.             else
  2141.             {    
  2142.                 hWaitRet = WaitForMultipleObjects(2, aWaitObjs, FALSE, INFINITE);
  2143.                 hr = lpwds->dd.lpDDSurface->Flip(lpwds->dd.lpChain[nIndex].lpSurface, dwFlags);
  2144.                 if (WAIT_OBJECT_0+1 == hWaitRet)
  2145.                     ReleaseMutex(lpwds->hOverlayMutex);
  2146.             }
  2147.             if (DDERR_SURFACELOST == hr)
  2148.             {
  2149.                 hr = RestoreSurfaces(lpwd, lpwds);
  2150.                 if (++nCount>1)
  2151.                     hr = HXR_FAIL;
  2152.                 
  2153.                 if (hr != DD_OK)
  2154.                 {
  2155.                     SetEvent(lpwds->dd.lpChain[nIndex].hEmpty);
  2156.                     bLoop = FALSE;
  2157.                 }
  2158.             }
  2159.             else if (DDERR_SURFACEBUSY == hr)
  2160.             {
  2161.                 lpwds->dd.lpChain[nIndex].lpSurface->Unlock(NULL);
  2162.                 hr = lpwds->dd.lpDDSurface->Flip(lpwds->dd.lpChain[nIndex].lpSurface, dwFlags);
  2163.                 bLoop = FALSE;
  2164.             }
  2165.             else
  2166.                 bLoop = FALSE;
  2167.             }
  2168.             catch(...)
  2169.             {
  2170.                 DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDraw_DisplaySurface");
  2171.                 hr = HXR_FAIL;
  2172.                 bLoop = FALSE;
  2173.             }
  2174.         }
  2175.         
  2176.         // Let caller handle these
  2177.         if (DDERR_WASSTILLDRAWING != hr &&
  2178.             DDERR_SURFACEBUSY != hr &&
  2179.             DDERR_INVALIDPARAMS != hr)
  2180.         {
  2181.             WaitForSingleObject(lpwds->hOverlayIndexMutex, INFINITE);
  2182.            
  2183.             // Flip a specific backbuffer - it swaps places
  2184.             // with the front buffer.
  2185.             LPDIRECTDRAWSURFACE lpTemp = lpwds->dd.lpChain[lpwds->dwFrontBuffer].lpSurface;
  2186.             lpwds->dd.lpChain[lpwds->dwFrontBuffer].lpSurface = lpwds->dd.lpChain[nIndex].lpSurface;
  2187.             lpwds->dd.lpChain[nIndex].lpSurface = lpTemp;
  2188.             lpwds->dwFrontBuffer = nIndex;
  2189.             
  2190.             ReleaseMutex(lpwds->hOverlayIndexMutex);
  2191.             SetEvent(lpwds->dd.lpChain[nIndex].hEmpty);
  2192.         }
  2193.         else if (bAbort)
  2194.         {
  2195.             WaitForSingleObject(lpwds->hOverlayIndexMutex, INFINITE);
  2196.             if ((INT32)(--lpwds->dwNextBuffer) == -1)
  2197.                 lpwds->dwNextBuffer = lpwds->dwBackBufferCount;    
  2198.             
  2199.             ReleaseMutex(lpwds->hOverlayIndexMutex);
  2200.            
  2201.             SetEvent(lpwds->dd.lpChain[nIndex].hEmpty);
  2202.             hr = HXR_OK;
  2203.         }
  2204.     }
  2205.     return hr;
  2206. }
  2207. HRESULT WinDraw_CacelPendingDisplay (LPWINDRAW lpwd, WINDRAWSURFACE *lpwds)
  2208. {
  2209.     if (lpwds == NULL) 
  2210.     {
  2211.         HX_ASSERT(0);
  2212.         return E_INVALIDARG;
  2213.     }
  2214.     
  2215.     PulseEvent(lpwds->dd.hAbort);
  2216.     return HXR_OK;
  2217. }
  2218. HRESULT IsFlipDone(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds, ENUMSURFACE* lpSurfEnum, BOOL bBlock)
  2219. {
  2220.     HRESULT hr;
  2221.     int     nCount = 0,
  2222.     nOtherError = 0;
  2223.     
  2224.     WaitForSingleObject(lpwds->hOverlayIndexMutex, INFINITE);
  2225.     try
  2226.     {
  2227.     while (1)
  2228.     {
  2229.         hr = lpSurfEnum->lpSurface->GetFlipStatus(DDGFS_ISFLIPDONE);
  2230.         if (DDERR_SURFACELOST == hr)
  2231.         {
  2232.             hr = RestoreSurfaces(lpwd, lpwds);
  2233.             if (++nCount>1)
  2234.                 hr = HXR_FAIL;
  2235.             
  2236.             // Could not restore, so get out
  2237.             if (hr != DD_OK)
  2238.                 break;
  2239.         }
  2240.         else if (DD_OK == hr)
  2241.         {
  2242.             hr = lpwds->dd.lpDDBackBuffer->GetFlipStatus(DDGFS_ISFLIPDONE);
  2243.             if (DD_OK != hr)
  2244.             {
  2245.                 #ifdef _DEBUG
  2246.                 //OutputDebugString("Backbuffer still drawingn");
  2247.                 #endif
  2248.                 //HX_TRACE("Spinning %lun");
  2249.                 continue;    // Spin?
  2250.             }
  2251.             
  2252.             break;
  2253.         }
  2254.         else
  2255.         {
  2256.             #ifdef _DEBUG
  2257.             //OutputDebugString("Could not lock...previous flip still goingn");
  2258.             #endif
  2259.             hr = DDERR_WASSTILLDRAWING;
  2260.             if (!bBlock)
  2261.                 break;
  2262.             // Some other error...wait a bit and give up after 2 vblanks
  2263.             if (++nOtherError > 2)
  2264.             {
  2265.                 hr = HXR_FAIL;
  2266.                 break;
  2267.             }
  2268.             
  2269.             DWORD dwScan = 0;
  2270.             WinDraw2_GetScanLine(lpwd, &dwScan);
  2271.             // Sleep till next vblank
  2272.             long lSleep = (long)((1.0 - (double)dwScan/(lpwd->dwMaxScanLine+1)) * lpwd->dMsPerVBlank + 1);
  2273.             //HX_TRACE("IsFlipDone; sleeping for %lun", lSleep);
  2274.             if (lpwd->nSchedulerResolution)
  2275.                 timeBeginPeriod(lpwd->nSchedulerResolution);
  2276.             
  2277.             HRESULT hrWait = WaitForSingleObject(lpwds->dd.hAbort, lSleep);
  2278.             if (lpwd->nSchedulerResolution)
  2279.                 timeEndPeriod(lpwd->nSchedulerResolution);
  2280.              if (hrWait!= WAIT_TIMEOUT)
  2281.                 break;
  2282.         }
  2283.     }
  2284.     }
  2285.     catch(...)
  2286.     {
  2287.         DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "IsFlipDone");
  2288.         hr = HXR_FAIL;
  2289.     }
  2290.     
  2291.     ReleaseMutex(lpwds->hOverlayIndexMutex);
  2292.     return hr;
  2293. }
  2294. #if 0
  2295. // This is how we handle the fact that some dd drivers don't properly
  2296. // handle GetFlipStatus and Lock for async flipping.  So, before
  2297. // we lock a surface, make sure it is not the front buffer - this causes
  2298. // tearing with an out of order display flavor.
  2299. HRESULT IsFrontBuffer(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds, ENUMSURFACE* lpSurfEnum, BOOL bBlock)
  2300. {
  2301.     DDSURFACEDESC ddsd;
  2302.     HRESULT hr;
  2303.     int     nCount = 0,
  2304.     nOtherError = 0;
  2305.     try
  2306.     {
  2307.     while (1)
  2308.     {
  2309.         memset(&ddsd, 0, sizeof(ddsd));
  2310.         ddsd.dwSize = sizeof(ddsd);
  2311.         WaitForSingleObject(lpwds->hOverlayMutex, INFINITE);
  2312.         hr = LockSurface(lpwd, lpwds->dd.lpDDSurface, &ddsd, FALSE);
  2313.         if (hr != DD_OK)
  2314.             ReleaseMutex(lpwds->hOverlayMutex);
  2315.         if (DD_OK == hr)
  2316.         {
  2317.             lpwds->dd.lpDDSurface->Unlock(NULL);
  2318.             ReleaseMutex(lpwds->hOverlayMutex);
  2319.             if ((BYTE*)ddsd.lpSurface == lpSurfEnum->pHwMemBuffer)
  2320.             {
  2321.                 #ifdef _DEBUG
  2322.                 //if ((BYTE*)ddsd.lpSurface == lpwds->dd.lpChain[nIndex].pHwMemBuffer)
  2323.                 //    OutputDebugString("Whoops...front buffer memn");
  2324.                 //else
  2325.                 //    OutputDebugString("Whoops...front buffer indexn");
  2326.                 #endif
  2327.                 // This should not happen, but you know how that goes.
  2328.                 // If we are trying to lock the front buffer and all other buffers
  2329.                 // are empty, go ahead and allow it.  Otherwise, we get stuck here.
  2330.                 int nFullBuffers = 0;
  2331.                 for (int i=0; i<lpwds->dwBackBufferCount+1; i++)
  2332.                 {
  2333.                     if (WaitForSingleObject(lpwds->dd.lpChain[i].hEmpty, 0) != WAIT_OBJECT_0)
  2334.                         ++nFullBuffers;
  2335.                 }
  2336.                 if (!nFullBuffers)
  2337.                     break;
  2338.                 if (!bBlock)
  2339.                 {
  2340.                     hr = HXR_FAIL;
  2341.                     break;
  2342.                 }
  2343.         
  2344.                 if (WaitForSingleObject(lpwds->dd.hAbort, 5) != WAIT_TIMEOUT)
  2345.                 {
  2346.                     hr = HXR_FAIL;
  2347.                     break;
  2348.                 }
  2349.             }
  2350.             else
  2351.                 break;
  2352.         }
  2353.         else if (DDERR_SURFACELOST == hr)
  2354.         {
  2355.             hr = RestoreSurfaces(lpwd, lpwds);
  2356.             if (++nCount>1)
  2357.                 hr = HXR_FAIL;
  2358.             
  2359.             // Could not restore, so get out
  2360.             if (hr != DD_OK)
  2361.                 break;
  2362.         }
  2363.         else if (DDERR_WASSTILLDRAWING == hr ||
  2364.          DDERR_SURFACEBUSY == hr)
  2365.         {
  2366.             #ifdef _DEBUG
  2367.             //OutputDebugString("Could not lock...front buffern");
  2368.             #endif
  2369.             if (!bBlock)
  2370.                 break;
  2371.             if (WaitForSingleObject(lpwds->dd.hAbort, 5) != WAIT_TIMEOUT)
  2372.                 break;
  2373.         }
  2374.         else
  2375.         {
  2376.             #ifdef _DEBUG
  2377.             //OutputDebugString("Other error...front buffern");
  2378.             #endif
  2379.             
  2380.     if (!bBlock)
  2381.         break;
  2382.     // Some other error...wait a bit and give up after 20 ms
  2383.     if (++nOtherError > 4)
  2384.     {
  2385. hr = HXR_FAIL;
  2386. break;
  2387.     }
  2388.             if (WaitForSingleObject(lpwds->dd.hAbort, 5) != WAIT_TIMEOUT)
  2389.                 break;
  2390.         }
  2391.     }
  2392.     }
  2393.     catch(...)
  2394.     {
  2395.         DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "IsFrontBuffer");
  2396.         hr = HXR_FAIL;
  2397.     }
  2398.     return hr;
  2399. }
  2400. #endif //0
  2401. #endif //HELIX_FEATURE_VS2