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

Symbian

开发平台:

Visual C++

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