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

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. /* for MS VC++ 6.0, pntypes needs to be included before windows include files */
  36. #include "hxtypes.h"
  37. #include "hxcom.h" 
  38. #include "hxwintyp.h"
  39. #include "hxvsurf.h"
  40. #include "hxassert.h"
  41. #include "hxthread.h"
  42. #include "hxtick.h"
  43. #include "dllpath.h"
  44. #include "hxerror.h"
  45. #include "hxstrutl.h"
  46. /* Windows include files: */
  47. #include <windows.h>
  48. #include "ddraw.h"
  49. #define COMPILE_MULTIMON_STUBS
  50. #include <multimon.h>
  51. /* standard libraries: */
  52. #include <stdio.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <assert.h>
  56. #include <math.h>            
  57. #include "hxcom.h"
  58. #include "hxheap.h"
  59. #ifdef _DEBUG
  60. #undef HX_THIS_FILE
  61. static const char HX_THIS_FILE[] = __FILE__;
  62. #endif
  63. /* our stuff:*/
  64. #include "hxcolor.h"
  65. #include "colormap.h"
  66. #include "windraw2.h"
  67. #include "ddpdb.h"         /* DirectDraw profiles database */
  68. /* DirectDraw profile: */
  69. static LPDDDEVICEPROFILE lpddprofDirectDrawProfile = NULL;
  70. //#define _CHECK_PERFORMANCE
  71. //#define _REMOVE_WINDRAW_CLIPPER 
  72. // Exception handler mutex
  73. static CRITICAL_SECTION g_ehandlerMutex;
  74. static INT32 g_ehandlerMutexCnt = 0;
  75. static INT32 g_ehandlerSilent = 1;
  76. static INT32 g_ehandlerCount = 0;
  77. #include "hxmap.h"
  78. typedef void (HXEXPORT_PTR INITCOLORCONVERTERFN)();
  79. typedef int (HXEXPORT_PTR SETRGB8PALETTEFN) (int,UINT32*,int*);
  80. INITCOLORCONVERTERFN pfInitColorConverter = 0;
  81. SETRGB8PALETTEFN pfSetRGB8Palette = 0;
  82. HMODULE z_hHxColor = 0;
  83. struct CEnumDisplaySetting
  84. {
  85.     
  86.     CEnumDisplaySetting();
  87.     ~CEnumDisplaySetting();
  88.     
  89.     CHXMapStringToOb m_Settings;
  90.     
  91.     void GetSettings(CHXSimpleList* pList);
  92. };
  93. CEnumDisplaySetting::CEnumDisplaySetting()
  94. {
  95.     DEVMODE modeDesc;
  96.     DWORD   index = 0;
  97.     char    buffer[64]; /* Flawfinder: ignore */
  98.     while(EnumDisplaySettings(0, index, &modeDesc))
  99.     {
  100. sprintf(buffer, "%dx%dx%d", modeDesc.dmPelsWidth, modeDesc.dmPelsHeight, modeDesc.dmBitsPerPel); /* Flawfinder: ignore */
  101. void* ptemp;
  102. if (!m_Settings.Lookup(buffer, ptemp))
  103. {
  104.     CModesDesc* pDesc = new CModesDesc;
  105.     pDesc->m_nWidth = modeDesc.dmPelsWidth;
  106.     pDesc->m_nHeight    = modeDesc.dmPelsHeight;
  107.     pDesc->m_nBitCount  = modeDesc.dmBitsPerPel;
  108.     m_Settings.SetAt(buffer, pDesc);
  109. }
  110. index++;
  111.     }
  112. }
  113. CEnumDisplaySetting::~CEnumDisplaySetting()
  114. {
  115.     CHXMapStringToOb::Iterator ndx = m_Settings.Begin();
  116.     for(; ndx != m_Settings.End(); ++ndx)
  117.     {
  118. CModesDesc* pDesc = (CModesDesc*) (*ndx);
  119. delete pDesc;
  120.     }
  121.     
  122.     m_Settings.RemoveAll();
  123. }
  124. void CEnumDisplaySetting::GetSettings(CHXSimpleList* pList)
  125. {
  126.     CHXMapStringToOb::Iterator i;
  127.     i = m_Settings.Begin();
  128.     for(; i!= m_Settings.End(); ++i)
  129.     {
  130. CModesDesc* pOldDesc = (CModesDesc*) *i;
  131. CModesDesc* pNewDesc = new CModesDesc;
  132. pNewDesc->m_nWidth = pOldDesc->m_nWidth;
  133. pNewDesc->m_nHeight = pOldDesc->m_nHeight;
  134. pNewDesc->m_nBitCount = pOldDesc->m_nBitCount;
  135. pList->AddTail(pNewDesc);
  136.     }
  137. }
  138. CEnumDisplaySetting zm_DisplaySettings;
  139. /***************************************
  140. *
  141. * Routines for using DirectDraw on a multimonitor system
  142. *
  143. */
  144. /* DDRAW.H might not include these: */
  145. #ifndef DDENUM_ATTACHEDSECONDARYDEVICES
  146. #define DDENUM_ATTACHEDSECONDARYDEVICES     0x00000001L
  147. #endif
  148. #if DIRECTDRAW_VERSION <= 0x0500
  149. typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKEXA) (GUID FAR *, LPSTR, LPSTR, LPVOID, HANDLE);
  150. typedef HRESULT (WINAPI * LPDIRECTDRAWENUMERATEEXA) ( LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags);
  151. #define HMONITOR HANDLE
  152. #endif
  153. typedef HRESULT (*PDRAWCREATE) (IID *,LPDIRECTDRAW *,LPUNKNOWN);
  154. typedef HRESULT (*PDRAWENUM) (LPDDENUMCALLBACKA, LPVOID);
  155. /*
  156. * FindDeviceCallback functions:
  157. */
  158. typedef struct
  159. {
  160.     LPSTR   lpszDevice;
  161.     GUID*   lpGUID;
  162.     GUID    GUID;
  163.     BOOL    fFound;
  164.     
  165. } FINDDEVICEDATA;
  166. static BOOL CALLBACK FindDeviceCallback (GUID* lpGUID, LPSTR lpszName,
  167.  LPSTR lpszDevice, LPVOID lParam)
  168. {
  169.     FINDDEVICEDATA *p = (FINDDEVICEDATA*) lParam;
  170.     
  171.     if (lstrcmpiA (p->lpszDevice, lpszDevice) == 0) {
  172.         if (lpGUID) {
  173.             p->GUID = *lpGUID;
  174.             p->lpGUID = &p->GUID;
  175.         } else
  176.             p->lpGUID = NULL;
  177.         p->fFound = TRUE;
  178. return FALSE;
  179.     }
  180.     return TRUE;
  181. }
  182. static BOOL CALLBACK FindDeviceCallbackEx (GUID* lpGUID, LPSTR lpszName,
  183.    LPSTR lpszDevice, LPVOID lParam, HMONITOR hMonitor)
  184. {
  185.     FINDDEVICEDATA *p = (FINDDEVICEDATA*) lParam;
  186.     
  187.     if (lstrcmpiA (p->lpszDevice, lpszDevice) == 0) {
  188.         if (lpGUID) {
  189.             p->GUID = *lpGUID;
  190.             p->lpGUID = &p->GUID;
  191.         } else
  192.             p->lpGUID = NULL;
  193. p->fFound = TRUE;
  194. return FALSE;
  195.     }
  196.     return TRUE;
  197. }
  198. HRESULT WINAPI EnumSurfacesCallback(LPDIRECTDRAWSURFACE lpDDSurface,
  199.                                     LPDDSURFACEDESC lpDDSurfaceDesc,
  200.                                     LPVOID pSurface)
  201. {
  202.     LPDIRECTDRAWSURFACE *lpSurf = (LPDIRECTDRAWSURFACE*)pSurface;
  203.     if (lpDDSurface)
  204.     {
  205.         *lpSurf = lpDDSurface;
  206.         lpDDSurface->Release();
  207.     }
  208.     return DDENUMRET_OK;
  209. }
  210. /*
  211. * DirectDrawCreateFromDevice
  212. *
  213. * create a DirectDraw object for a particular device
  214. */
  215. static IDirectDraw * DirectDrawCreateFromDevice (LPSTR lpszDevice,
  216.  PDRAWCREATE DirectDrawCreateP, PDRAWENUM DirectDrawEnumerateP)
  217. {
  218.     IDirectDraw *pdd = NULL;
  219.     
  220.     /* check if device name is specified: */
  221.     if (lpszDevice != NULL) {
  222.         /* try to find device with a given name: */
  223.         FINDDEVICEDATA find;
  224.         find.lpszDevice = lpszDevice;
  225.         find.fFound = FALSE;
  226.         DirectDrawEnumerateP (FindDeviceCallback, (LPVOID)&find);
  227.         /* check if found: */
  228.         if (find.fFound) {
  229.     
  230. /* In 4bpp mode the following DDraw call causes a
  231. * message box to be popped up by DDraw (!?!).
  232. * It's DDraw's fault, but we don't like it.
  233.     * So we make sure it doesn't happen. */
  234.             UINT ErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS);
  235.             DirectDrawCreateP (find.lpGUID, &pdd, NULL);
  236.             SetErrorMode (ErrorMode);
  237.         }
  238.     } else
  239.         DirectDrawCreateP (NULL, &pdd, NULL);
  240.     
  241.     /* return whatever we have found: */
  242.     return pdd;
  243. }
  244. /*
  245. * DirectDrawCreateFromDeviceEx
  246. *
  247. * create a DirectDraw object for a particular device
  248. */
  249. static IDirectDraw * DirectDrawCreateFromDeviceEx (LPSTR lpszDevice, PDRAWCREATE DirectDrawCreateP, LPDIRECTDRAWENUMERATEEXA DirectDrawEnumerateExP)
  250. {
  251.     IDirectDraw *pdd = NULL;
  252.     
  253.     /* check if device name is specified: */
  254.     if (lpszDevice != NULL) {
  255.         /* try to find device with a given name: */
  256.         FINDDEVICEDATA find;
  257.         find.lpszDevice = lpszDevice;
  258.         find.fFound   = FALSE;
  259.         DirectDrawEnumerateExP (FindDeviceCallbackEx, (LPVOID)&find, DDENUM_ATTACHEDSECONDARYDEVICES);
  260.         /* check if found: */
  261.         if (find.fFound) {
  262.     
  263. /* In 4bpp mode the following DDraw call causes a
  264. * message box to be popped up by DDraw (!?!).
  265. * It's DDraw's fault, but we don't like it.
  266.     * So we make sure it doesn't happen. */
  267.             UINT ErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS);
  268.             DirectDrawCreateP (find.lpGUID, &pdd, NULL);
  269.             SetErrorMode (ErrorMode);
  270.         }
  271.     } else
  272.         DirectDrawCreateP (NULL, &pdd, NULL);
  273.     
  274.     /* return whatever we have found: */
  275.     return pdd;
  276. }
  277. /***************************************
  278. *
  279. * Routines for dynamic loading and unloading of the DirectDraw library.
  280. *
  281. */
  282. typedef DWORD (WINAPI *PGETFILEVERSIONINFOSIZE) (LPTSTR,LPDWORD);
  283. typedef BOOL (WINAPI *PGETFILEVERSIONINFO) (LPTSTR,DWORD,DWORD,LPVOID);
  284. typedef BOOL (WINAPI *PVERQUERYVALUE) (LPVOID,LPTSTR,LPVOID,PUINT);
  285. /* forward prototypes: */
  286. HRESULT LockSurface(LPWINDRAW lpwd, LPDIRECTDRAWSURFACE lpSurface, DDSURFACEDESC *pddsd, BOOL bBlock=TRUE);
  287. HRESULT IsFlipDone(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds, ENUMSURFACE* lpSurfEnum, BOOL bBlock=TRUE);
  288. HRESULT IsFrontBuffer(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds, ENUMSURFACE* lpSurfEnum, BOOL bBlock=TRUE);
  289. HRESULT RestoreSurfaces(LPWINDRAW lpwd, LPWINDRAWSURFACE lpSurface);
  290. HRESULT LoadDirectDraw (LPSTR lpszDevice, LPDIRECTDRAW *ppDirectDraw, HINSTANCE *phDirectDraw);
  291. void    ReleaseDirectDraw (LPDIRECTDRAW *ppDirectDraw, LPDIRECTDRAW2 *ppDirectDraw2, HINSTANCE *phDirectDraw);
  292. void    DumpDDInfo(LPWINDRAW lpwd, LPDIRECTDRAWSURFACE lpSurface, char *pFunction);
  293. /*
  294. * We can't be sure that DirectDraw is always available
  295. * so we can't statically link to the library.
  296. * Therefore we load the library, get the function entry
  297. * point addresses and call them to create the driver objects.
  298. * We return S_OK if we manage to load DirectDraw correctly
  299. * otherwise we return E_NOINTERFACE
  300. * We initialise a DirectDraw instance by explicitely loading
  301. * the library and calling GetProcAddress on the DirectDrawCreate
  302. * entry point that it exports
  303. *
  304. * On a multi monitor system, we can get the DirectDraw object
  305. * for any monitor (device) with the optional lpszDevice parameter
  306. */
  307. static HRESULT LoadDirectDraw (LPSTR lpszDevice,
  308.        LPDIRECTDRAW *ppDirectDraw, HINSTANCE *phDirectDraw)
  309. {
  310.     UINT ErrorMode;
  311.     PDRAWCREATE pDrawCreate;
  312.     PDRAWENUM pDrawEnum;
  313.     LPDIRECTDRAWENUMERATEEXA pDrawEnumEx;
  314.     HRESULT hr = NOERROR;
  315.     
  316.     /* 
  317.     * Check the display mode if it is less than 8 bits do not call into direct draw.
  318.     */
  319.     
  320.     HDC hdc = GetDC(0);
  321.     int bpp = GetDeviceCaps(hdc, BITSPIXEL);
  322.     ReleaseDC(0, hdc);
  323.     
  324.     if (bpp < 8)
  325.     {
  326. *ppDirectDraw = 0;
  327. return E_NOINTERFACE; /* whatever */
  328.     }
  329.     
  330.     /* is DirectDraw already loaded? */
  331.     if (*ppDirectDraw) {
  332.         /* ... */
  333.         return NOERROR;
  334.     }
  335.     
  336.     /* make sure the library is available: */
  337.     ErrorMode = SetErrorMode (SEM_NOOPENFILEERRORBOX);
  338.     *phDirectDraw = LoadLibrary (TEXT ("DDRAW.DLL"));
  339.     SetErrorMode (ErrorMode);
  340.     if (*phDirectDraw == NULL) {
  341.         /* ... */
  342.         return E_NOINTERFACE;
  343.     }
  344.     
  345.     /* get the DLL address for the creator function: */
  346.     pDrawCreate = (PDRAWCREATE) GetProcAddress (*phDirectDraw, "DirectDrawCreate");
  347.     /* force ANSI, we assume it: */
  348.     pDrawEnum = (PDRAWENUM) GetProcAddress (*phDirectDraw, "DirectDrawEnumerateA");
  349.     pDrawEnumEx = (LPDIRECTDRAWENUMERATEEXA)GetProcAddress (*phDirectDraw, "DirectDrawEnumerateExA");
  350.     
  351.     /* we don't need DirectDrawEnumerateEx, that's just for multimon stuff: */
  352.     if (pDrawCreate == NULL || pDrawEnum == NULL) {
  353.         /* ... */
  354.         ReleaseDirectDraw (ppDirectDraw, NULL, phDirectDraw);
  355.         return E_NOINTERFACE;
  356.     }
  357.     
  358.     /* create a DirectDraw display provider for this device,
  359.     * using the fancy multimon-aware version, if it exists: */
  360.     if (pDrawEnumEx)
  361.         *ppDirectDraw = DirectDrawCreateFromDeviceEx (lpszDevice, pDrawCreate, pDrawEnumEx);
  362.     else
  363.         *ppDirectDraw = DirectDrawCreateFromDevice (lpszDevice, pDrawCreate, pDrawEnum);
  364.     if (*ppDirectDraw == NULL) 
  365.     {
  366.         ReleaseDirectDraw (ppDirectDraw, NULL, phDirectDraw);
  367.         return E_NOINTERFACE;
  368.     }
  369.     
  370.     return NOERROR;
  371. }
  372. /*
  373. * Called to release any DirectDraw provider we previously loaded.
  374. * We may be called at any time especially when something goes
  375. * horribly wrong and when we need to clean up before returning
  376. * so we can't guarantee that all state variables are consistent
  377. * so free only those really allocated. This should only be called
  378. * once all the reference counts have been released.
  379. */
  380. void ReleaseDirectDraw (LPDIRECTDRAW *ppDirectDraw, LPDIRECTDRAW2 *ppDirectDraw2,  HINSTANCE *phDirectDraw)
  381. {
  382.     /* release any DirectDraw provider interface: */
  383.     if (ppDirectDraw && *ppDirectDraw) {
  384.         
  385.         IDirectDraw_Release (*ppDirectDraw);
  386.         *ppDirectDraw = NULL;
  387.     }
  388.     
  389.     if (ppDirectDraw2 && *ppDirectDraw2) 
  390.     {
  391.         (*ppDirectDraw2)->Release();
  392.         *ppDirectDraw2 = NULL;
  393.     }
  394.     
  395.     /* decrement module load count: */
  396.     if (*phDirectDraw) {
  397.         FreeLibrary (*phDirectDraw);
  398.         *phDirectDraw = NULL;
  399.     }
  400. }
  401. #if 0
  402. /*
  403. * Are we running on Direct Draw version 1?  We need to find out as
  404. * we rely on specific bug fixes in DirectDraw 2 for fullscreen playback. To
  405. * find out, we simply see if it supports IDirectDraw2.  Only version 2 and
  406. * higher support this.
  407. */
  408. BOOL IsDirectDrawVersion1 (LPDIRECTDRAW pDirectDraw)
  409. {
  410.     IDirectDraw2 *p;
  411.     HRESULT hr;
  412.     
  413.     /* check if DirectDraw is available: */
  414.     if (pDirectDraw == NULL)
  415.         return FALSE;
  416.     
  417.     /* query and release interface: */
  418.     p = NULL;
  419.     hr = IDirectDraw_QueryInterface(pDirectDraw, IID_IDirectDraw2, (void *)&p);
  420.     if (p)
  421.         IDirectDraw2_Release (p);
  422.     
  423.     /* returns TRUE, if !IDrectDraw2; FALSE otherwise */
  424.     return hr != NOERROR;
  425. }
  426. #endif
  427. /***************************************
  428. *
  429. * Routines for using GDI on a multimonitor system
  430. *
  431. */
  432. /*
  433. * Get display DC.
  434. * Use:
  435. *  HDC GetDisplayDC (LPSTR lpszDevice)
  436. * Input:
  437. *  lpszDevice - device name to use (in a multimonitor system)
  438. * Returns:
  439. *  NULL, if error; !NULL - display device DC.
  440. */
  441. static HDC GetDisplayDC (LPSTR lpszDevice)
  442. {
  443.     HDC hdcDisplay;
  444.     
  445.     /* get a DC on the right monitor - it's ugly, but this is the way
  446.     * you have to do it */
  447.     if (lpszDevice == NULL || lstrcmpiA (lpszDevice, "DISPLAY") == 0)
  448.         hdcDisplay = CreateDCA ("DISPLAY", NULL, NULL, NULL);
  449.     else
  450.         hdcDisplay = CreateDCA (NULL, lpszDevice, NULL, NULL);
  451.     
  452.     return hdcDisplay;
  453. }
  454. /*
  455. * Get pixel format for a given device context.
  456. * Use:
  457. *  HRESULT GetDeviceFormat (HDC hDC, LPBMI lpbmi);
  458. * Input:
  459. *  hDC - device context to query
  460. *  lpbmi - pointer to a bitmapinfo structure to initialize
  461. * Returns:
  462. *  NOERROR, if success, E_FAIL otherwise.
  463. */
  464. static HRESULT GetDeviceFormat (HDC hDC, LPBMI lpbmi)
  465. {
  466.     HBITMAP hBM;
  467.     
  468.     /* initialize the bitmapinfo structure: */
  469.     memset (lpbmi, 0, sizeof (BMI));
  470.     lpbmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
  471.     lpbmi->bmiHeader.biBitCount = 0;
  472.     
  473.     /* retrieve display format parameters: */
  474.     hBM = CreateCompatibleBitmap (hDC,1,1);
  475.     GetDIBits (hDC,hBM,0,1,NULL, (BITMAPINFO *)& (lpbmi->bmiHeader),DIB_RGB_COLORS);
  476.     /* this call will get the color table or the proper bitfields */
  477.     GetDIBits (hDC,hBM,0,1,NULL, (BITMAPINFO *)& (lpbmi->bmiHeader),DIB_RGB_COLORS);
  478.     DeleteObject (hBM);
  479.     
  480.     /* check the validity of the format & exit: */
  481.     return CheckBitmap ((BITMAPINFO *)& (lpbmi->bmiHeader))? NOERROR: E_FAIL;
  482. }
  483. /*
  484. * Retrieves display pixel format. This is normally called
  485. * when we receive WM_DEVMODECHANGED device change messages.
  486. *
  487. * The optional szDevice parameter tells us which monitor we are interested
  488. * in for a multi monitor system.
  489. *
  490. * The calling program mush use global syncronization objects to prevent
  491. * re-entering this code.
  492. */
  493. static HRESULT GetDisplayFormat (LPBMI lpbmi, LPSTR lpszDevice)
  494. {
  495.     HDC hdcDisplay;
  496.     HRESULT hr;
  497.     
  498.     /* get a DC of a given monitor: */
  499.     if ((hdcDisplay = GetDisplayDC (lpszDevice)) == NULL)
  500.         return E_FAIL;
  501.     
  502.     /* retrieve display format parameters: */
  503.     hr = GetDeviceFormat (hdcDisplay, lpbmi);
  504.     
  505.     /* delete hdcDisplay & exit: */
  506.     DeleteDC (hdcDisplay);
  507.     return hr;
  508. }
  509. /*
  510. * Generates the "standard" WinDraw palette.
  511. * Since we will have to deal with multiple datatypes, each having
  512. * its own combination of colors, what we really need is some "uniform"
  513. * palette, we could use to render all these objects with minimum loss
  514. * of quality.
  515. * This function generates so-called 6x6x6-color palette that contains
  516. * all possible combinations of 6 uniformly-displaced values for each
  517. * color component (R, G, and B). To avoid interference with Windows
  518. * system palette (first and last 10 entries in the palette), we will
  519. * insert our colors in 10..225 range, and mark them as non-collapsable
  520. * in hope to boost the performance (ideally, this should prevent GDI
  521. * from compressing the palette, and eliminate extra mapping).
  522. */
  523. static HRESULT CreateDefaultPalette (LPPALETTEENTRY lppe,
  524.      int *pnLoColor, int *pnHiColor, LPSTR lpszDevice)
  525. {
  526.     HDC hdc;
  527.     HRESULT hr = E_FAIL;
  528.     unsigned int i, r, g, b;
  529.     
  530.     /* get a DC of a given monitor: */
  531.     if ((hdc = GetDisplayDC (lpszDevice)) != NULL) {
  532.         /* apparently some displays have odd numbers of system colors: */
  533.         if (GetDeviceCaps (hdc, NUMRESERVED) == 20) {
  534.     
  535.             /* retrieve system colors: */
  536.             memset (lppe, 0, 256 * sizeof (RGBQUAD));
  537.             GetSystemPaletteEntries (hdc, 0, 10, lppe);
  538.             GetSystemPaletteEntries (hdc, 246, 10, lppe + 246);
  539.     
  540.             /* generate 6x6x6 (~2.58 bits/channel) palette: */
  541.             i = 10;
  542.             for (b = 0; b <= 0xFF; b += 0x33)
  543. for (g = 0; g <= 0xFF; g += 0x33)
  544.     for (r = 0; r <= 0xFF; r += 0x33) {
  545. /* create a palette entry: */
  546. lppe [i].peGreen = g;
  547. lppe [i].peBlue  = b;
  548. lppe [i].peRed   = r;
  549. lppe [i].peFlags = PC_NOCOLLAPSE; /* !!! */
  550. i ++;
  551.     }
  552.     
  553.     /* store the range of our colors: */
  554.     *pnLoColor = 10;
  555.     *pnHiColor = i;
  556.     
  557.     hr = NOERROR;
  558.         }
  559.         DeleteDC (hdc);
  560.     }
  561.     return hr;
  562. }
  563. char*   
  564. CollectDDInfo(LPWINDRAW lpwd, LPDIRECTDRAWSURFACE lpSurface, char *pFunction, char* pSeparator)
  565. {
  566.     char*       pszDDInfo = NULL;
  567.     CHXString   pDDInfo;
  568.     char        szTemp[MAX_DISPLAY_NAME];    /* Flawfinder: ignore */
  569.     char        szTmp[MAX_DISPLAY_NAME];     /* Flawfinder: ignore */
  570.     // write date and time of log
  571.     SYSTEMTIME time;
  572.     memset(&time, 0, sizeof(time));
  573.     GetSystemTime(&time);
  574.     GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &time, "ddd',' MMM dd yyyy, ", szTmp, sizeof(szTmp));
  575.     SafeSprintf(szTemp, MAX_DISPLAY_NAME, "nLog Entry: %s", szTmp);
  576.     pDDInfo = szTemp;
  577.     
  578.     GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &time, "hh:mm:ss tt", szTmp, sizeof(szTmp));
  579.     SafeSprintf(szTemp, MAX_DISPLAY_NAME, "%s%s", szTmp, pSeparator);
  580.     pDDInfo += szTemp;
  581.     
  582.     // write systime members
  583.     SafeSprintf(szTemp, MAX_DISPLAY_NAME, "Systime: %d %d %d %d %d %d %d %d%s",
  584.                 time.wYear, time.wMonth, time.wDayOfWeek, time.wDay,
  585.                 time.wHour, time.wMinute, time.wSecond, time.wMilliseconds, pSeparator);
  586.     pDDInfo += szTemp;
  587.     
  588.     // write function that caused fault
  589.     SafeSprintf(szTemp, MAX_DISPLAY_NAME, "Function: %s%s", pFunction, pSeparator);
  590.     pDDInfo += szTemp;
  591.     // write OS version
  592.     OSVERSIONINFO ver;
  593.     memset(&ver, 0, sizeof(ver));
  594.     ver.dwOSVersionInfoSize = sizeof(ver);
  595.     GetVersionEx(&ver);
  596.     SafeSprintf(szTemp, MAX_DISPLAY_NAME, 
  597.                 "OS MajorVersion: %ld MinorVersion: %ld BuildNum: %ld PlatformId: %ld Build: %s%s",
  598.                 ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber, ver.dwPlatformId, ver.szCSDVersion, pSeparator);
  599.     pDDInfo += szTemp;
  600.     // write processor info
  601.     SYSTEM_INFO sysinfo;
  602.     memset(&sysinfo, 0, sizeof(sysinfo));
  603.     GetSystemInfo(&sysinfo);
  604.     SafeSprintf(szTemp, MAX_DISPLAY_NAME, "Processor Type: %ld Level: %ld Revision: %ld Count: %ld%s",
  605.                  sysinfo.dwProcessorType, 
  606.                  sysinfo.wProcessorLevel, 
  607.                  sysinfo.wProcessorRevision, 
  608.                  sysinfo.dwNumberOfProcessors,
  609.                  pSeparator);
  610.     pDDInfo += szTemp;
  611.     // write DD version
  612.     TCHAR szVersion[256] = __TEXT(""); /* Flawfinder: ignore */
  613.     HKEY hKey = 0;
  614.     
  615.     RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
  616.         __TEXT("Software\Microsoft\DirectX"),
  617.         0, KEY_READ, &hKey);
  618.     if (hKey)
  619.     {
  620.         DWORD dwType = REG_SZ;
  621.         DWORD dwSize = sizeof(szVersion);
  622.         RegQueryValueEx(hKey, __TEXT("Version"), NULL, &dwType, (BYTE*)szVersion, &dwSize);
  623.         RegCloseKey(hKey);
  624.     }
  625.     SafeSprintf(szTemp, MAX_DISPLAY_NAME, "DirectDraw Version %s%s", szVersion, pSeparator);
  626.     pDDInfo += szTemp;
  627.     if (lpSurface)
  628.     {
  629.         // Get DD4* from the surface
  630.         void* pVoid = NULL;
  631.         IDirectDrawSurface2* lpSurface2 = NULL;
  632.             
  633. #if DIRECTDRAW_VERSION > 0x0500
  634.         IDirectDraw4* pDD4 = NULL;
  635.         IDirectDraw* pDD = NULL;
  636. #endif //DIRECTDRAW_VERSION > 0x0500
  637.         DDDEVICEIDENTIFIER ddID;
  638.         memset(&ddID, 0, sizeof(ddID));
  639.         lpSurface->QueryInterface(IID_IDirectDrawSurface2, (void**)&lpSurface2);
  640.         
  641.         if (lpSurface2)
  642.         {
  643.             lpSurface2->GetDDInterface(&pVoid);
  644.             lpSurface2->Release();
  645.         }
  646. #if DIRECTDRAW_VERSION > 0x0500            
  647.         if (pVoid)
  648.             ((IUnknown*)pVoid)->QueryInterface(IID_IDirectDraw, (void**)&pDD);
  649.         if (pDD)
  650.         {
  651.             pDD->QueryInterface(IID_IDirectDraw4, (void **)&pDD4);
  652.             pDD->Release();
  653.         }
  654.         
  655.         // Query for the driver descripton
  656.         if (pDD4)
  657.         {
  658.             pDD4->GetDeviceIdentifier(&ddID, DDGDI_GETHOSTIDENTIFIER);
  659.             pDD4->Release();
  660.         }
  661.         // DD4 not supportted (probably NT4)...use more drastic measures
  662.         else
  663. #endif //DIRECTDRAW_VERSION > 0x0500
  664.         {
  665.             // Check if we are runnning NT
  666.             OSVERSIONINFO osVersion;
  667.             memset(&osVersion,0, sizeof(OSVERSIONINFO));
  668.             osVersion.dwOSVersionInfoSize  = sizeof(OSVERSIONINFO);
  669.             if (GetVersionEx(&osVersion) && osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT)
  670.             {
  671.                 char szChipType[MAXCHIPTYPE]; /* Flawfinder: ignore */
  672.                 
  673.                 // Try to get WinNT device information
  674.                 GetWinNTDeviceID (&ddID, szChipType);
  675.             }
  676.         }
  677.         
  678.         // write DD driver
  679.         unsigned short data4 =  ddID.guidDeviceIdentifier.Data4[0]<<8  |
  680.                                 ddID.guidDeviceIdentifier.Data4[1];
  681.         unsigned long  data5 =  ddID.guidDeviceIdentifier.Data4[2]<<24 | 
  682.                                 ddID.guidDeviceIdentifier.Data4[3]<<16 |
  683.                                 ddID.guidDeviceIdentifier.Data4[4]<<8  |
  684.                                 ddID.guidDeviceIdentifier.Data4[5];
  685.         unsigned short data6 =  ddID.guidDeviceIdentifier.Data4[6]<<8  |
  686.                                 ddID.guidDeviceIdentifier.Data4[7];
  687.         SafeSprintf(szTemp, MAX_DISPLAY_NAME,
  688.                     "DirectDraw Driver: %s VendorID: %ld GUID {""%lx-%x-%x-%x-%lx%x""}%s",
  689.                     ddID.szDescription, 
  690.                     ddID.dwVendorId,
  691.                     ddID.guidDeviceIdentifier.Data1,
  692.                     ddID.guidDeviceIdentifier.Data2,
  693.                     ddID.guidDeviceIdentifier.Data3,
  694.                     data4,
  695.                     data5,
  696.                     data6,
  697.                     pSeparator);
  698.         pDDInfo += szTemp;
  699.         
  700.         // write display properties
  701.         DDSURFACEDESC ddsd;
  702.         memset(&ddsd, 0, sizeof(ddsd));
  703.         ddsd.dwSize = sizeof(ddsd);
  704.         lpSurface->GetSurfaceDesc(&ddsd);
  705.         char fourCC[5] = {(char)(ddsd.ddpfPixelFormat.dwFourCC & 0x000000FF), /* Flawfinder: ignore */
  706.                          ((char)(ddsd.ddpfPixelFormat.dwFourCC & 0x0000FF00)>>8),
  707.                          ((char)(ddsd.ddpfPixelFormat.dwFourCC & 0x00FF0000)>>16),
  708.                           (char)(ddsd.ddpfPixelFormat.dwFourCC>>24),
  709.                           ''};
  710.         SafeSprintf(szTemp, MAX_DISPLAY_NAME, 
  711.                     "DisplayMode: %s %s BackBuffers: %ld Width: %ld Height: %ld%s",
  712.                     (ddsd.ddsCaps.dwCaps & DDSCAPS_OVERLAY) ? "Overlay" : "Offscreen",
  713.                     fourCC,
  714.                     (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) ? ddsd.dwBackBufferCount : 0,
  715.                     ddsd.dwWidth,
  716.                     ddsd.dwHeight,
  717.                     pSeparator);
  718.         pDDInfo += szTemp;
  719.     }
  720.             
  721.     BMI bmi;
  722.     memset(&bmi, 0, sizeof(bmi));
  723.     GetDisplayFormat(&bmi, NULL);
  724.     // write monitor properties
  725.     SafeSprintf(szTemp, MAX_DISPLAY_NAME,
  726.                 "Screen Width %ld Height %ld BPP: %ld%s",
  727.                  GetSystemMetrics(SM_CXSCREEN),
  728.                  GetSystemMetrics(SM_CYSCREEN),
  729.                  bmi.bmiHeader.biBitCount,
  730.                  pSeparator);
  731.     pDDInfo += szTemp;
  732.     pszDDInfo = new char[pDDInfo.GetLength()+1];
  733.     if (pszDDInfo)
  734.     {
  735.         strncpy(pszDDInfo, pDDInfo, pDDInfo.GetLength()+1);
  736.     }
  737.     
  738.     return pszDDInfo;
  739. }
  740. void DumpDDInfo(LPWINDRAW lpwd, LPDIRECTDRAWSURFACE lpSurface, char *pFunction)
  741. {
  742.     // A DirectDraw exception occured...bad bad bad
  743.     //HX_ASSERT(0);
  744.     // Serialize access to ddinfo.txt
  745.     if (g_ehandlerMutexCnt)
  746.         EnterCriticalSection(&g_ehandlerMutex);
  747.     // Write a file in the plugins dir
  748.     char    szPath[256]; /* Flawfinder: ignore */
  749.     char    szFilePerm[] = "r+";
  750.     int     nEntries = 1;
  751.     char    szTmp[MAX_DISPLAY_NAME];     /* Flawfinder: ignore */
  752.     char*   pszDDInfo = NULL;
  753.     const char* pPath = NULL;
  754.     pPath = GetDLLAccessPath()->GetPath(DLLTYPE_PLUGIN);
  755.     SafeStrCpy(szPath, pPath, 256);
  756.     SafeStrCat(szPath, "ddinfo.txt", 256);
  757.     FILE *fp = fopen(szPath, "r"); /* Flawfinder: ignore */
  758.     if (fp)
  759.     {
  760.         const int nMaxChars = 2048;
  761.         int nMaxEntries = 50;
  762.         // check log entry count
  763.         fscanf(fp, "%s %d", szTmp, &nEntries);
  764.         // Limit log file entries to nMaxEntries
  765.         if (++nEntries > nMaxEntries)
  766.         {
  767.             char *pTime = NULL;
  768.             SYSTEMTIME time;
  769.             double dTime = 0;
  770.             double dOldTime = 3000*8760;    // 3000 A.D. in hours
  771.             int nOldestOffset = 0;
  772.             int nLoc = 0;
  773.             char pBuffer[nMaxChars]; /* Flawfinder: ignore */
  774.             memset(&time, 0, sizeof(time));
  775.             
  776.             // read first <cr>
  777.             fgets(pBuffer, nMaxChars, fp);
  778.             // Find the oldest entry if the file
  779.             while (!feof(fp))
  780.             {
  781.                 nLoc = ftell(fp);
  782.                 fgets(pBuffer, nMaxChars, fp);
  783.                 
  784.                 // Find start of date
  785.                 pTime = strstr(pBuffer, "Systime: "); 
  786.                 if (pTime)
  787.                 {
  788.                     // Read systime values for this log entry
  789.                     pTime += 9;
  790.                     sscanf(pTime, "%d %d %d %d %d %d %d %d",
  791.                            &time.wYear, &time.wMonth, &time.wDayOfWeek,
  792.                            &time.wDay, &time.wHour, &time.wMinute,
  793.                            &time.wSecond, &time.wMilliseconds);
  794.                     // Change date to hours for comparison
  795.                     dTime = time.wYear*8760 + 
  796.                             time.wMonth*720 + 
  797.                             time.wDay*24 +
  798.                             time.wHour +
  799.                             time.wSecond/60.0 +
  800.                             time.wMilliseconds/60000.0;
  801.                     
  802.                     // Compare with the current oldest entry
  803.                     if (dTime < dOldTime)
  804.                     {
  805.                         dOldTime = dTime;
  806.                         nOldestOffset = nLoc;
  807.                     }
  808.                 }
  809.             }
  810.             // Remove oldest log entry: move contents of ddinfo to a temp file,
  811.             // delete ddinfo.txt, ren. temp file to ddinfo.txt.
  812.             pPath = GetDLLAccessPath()->GetPath(DLLTYPE_PLUGIN);
  813.             SafeStrCpy(szTmp, pPath, 256);
  814.             SafeStrCat(szTmp, "ddtemp.txt", 256);
  815.             FILE *fpTemp = fopen(szTmp, "w"); /* Flawfinder: ignore */
  816.             if (fpTemp)
  817.             {
  818.                 fseek(fp, 0, SEEK_SET);
  819.                 while (!feof(fp))
  820.                 {
  821.                     nLoc = ftell(fp);
  822.                     if (fgets(pBuffer, nMaxChars, fp))
  823.                     {
  824.                         // Skip oldest entry
  825.                         if (nLoc != nOldestOffset)
  826.                             fputs(pBuffer, fpTemp);
  827.                     }
  828.                 }
  829.             }
  830.             fclose(fp);
  831.             if (fpTemp)
  832.             {
  833.                 fclose(fpTemp);
  834.                 DeleteFile(szPath);
  835.                 rename(szTmp, szPath);
  836.             }
  837.             nEntries = nMaxEntries;
  838.         }
  839.         else
  840.             fclose(fp);
  841.     }
  842.     else
  843.     {
  844.         szFilePerm[0] = 'w';
  845.         szFilePerm[1] = '';
  846.     }
  847.     fp = fopen(szPath, szFilePerm); /* Flawfinder: ignore */
  848.     if (fp)
  849.     {
  850.         fseek(fp, 0, SEEK_SET);
  851.         fprintf(fp, "%s%dt ", "Entries ", nEntries);
  852.         fseek(fp, -1, SEEK_END);
  853.         pszDDInfo = CollectDDInfo(lpwd, lpSurface, pFunction, "t");
  854.         if (pszDDInfo)
  855.         {
  856.             fprintf(fp, "%s", pszDDInfo);
  857.         }
  858.         HX_VECTOR_DELETE(pszDDInfo);
  859.         fclose(fp);
  860.     }
  861.     if (g_ehandlerCount < g_ehandlerSilent)
  862.     {
  863.         // Need to throw error
  864.         if (lpwd && lpwd->pErrMsg)
  865.         {
  866.             lpwd->pErrMsg->Report(HXLOG_INFO, HXR_WINDRAW_EXCEPTION, 0,
  867.                                   szPath, NULL);
  868.         }
  869.     }
  870.     if (lpwd && lpwd->pErrMsg)
  871.         InterlockedIncrement(&g_ehandlerCount);
  872.     if (g_ehandlerMutexCnt)
  873.         LeaveCriticalSection(&g_ehandlerMutex);
  874. }
  875. /*
  876. * Load system and/or bitmap palette.
  877. */
  878. static int nSystemColors = 0;   /* !0 when system palette is loaded */
  879. static PALETTEENTRY SystemPalette [256];
  880. static RGBQUAD SystemPaletteRGB[256];
  881. static int SystemPaletteIndices [256];
  882. static int LoadPalette (LPWINDRAW lpwd)
  883. {
  884.     HDC hDC;
  885.     int i, n = 0;
  886.     
  887.     /* get system palette first: */
  888.     if ((hDC = GetDC (NULL)) != NULL) 
  889.     {
  890.         n = GetSystemPaletteEntries (hDC, 0, 256, SystemPalette);
  891.         ReleaseDC (NULL,hDC);
  892.     }
  893.     
  894.     /* check if system palette is loaded: */
  895.     /* generate palette index: */
  896.     for (i=0; i<n; i++)
  897.     {
  898. SystemPaletteIndices[i] = i;
  899. SystemPaletteRGB[i].rgbBlue = SystemPalette[i].peBlue;
  900. SystemPaletteRGB[i].rgbGreen = SystemPalette[i].peGreen;
  901. SystemPaletteRGB[i].rgbRed = SystemPalette[i].peRed;
  902. SystemPaletteRGB[i].rgbReserved = 0;
  903.     }
  904.     
  905.     /* update color conversion tables: */
  906.     if (pfSetRGB8Palette)
  907.     {
  908. (*pfSetRGB8Palette)(n, (unsigned long *)SystemPalette, SystemPaletteIndices);
  909.     }
  910.     
  911.     /* indicate that palette is set: */
  912.     nSystemColors = n;
  913.     
  914.     /* return # of colors loaded: */
  915.     return n;
  916. }
  917. HRESULT CreateDirectDrawPalette (LPWINDRAW pwd, LPDIRECTDRAWSURFACE pSurface)
  918. {
  919.     HRESULT ddrval = E_FAIL;
  920.     
  921.     if (!pSurface || !pwd)
  922.     {
  923.         return ddrval;
  924.     }
  925.     
  926.     try
  927.     {
  928.     /* load system palette if necessary: */
  929.     if (nSystemColors) {
  930.         /* create DirectDraw palette object: */
  931.         if ((ddrval = IDirectDraw_CreatePalette (pwd->dd.lpDD2, DDPCAPS_8BIT, SystemPalette, &(pwd->dd.lpDDPal), NULL)) == DD_OK) 
  932.         {
  933.             /* check if we can attach palette to a primary surface: */
  934.             if ((ddrval = IDirectDrawSurface_SetPalette (pSurface, pwd->dd.lpDDPal)) != DD_OK) 
  935.             {
  936.                 /* release it and return error code: */
  937.                 IDirectDrawPalette_Release (pwd->dd.lpDDPal);
  938.             }
  939.         }
  940.     }
  941.     }
  942.     catch (...)
  943.     {
  944.         DumpDDInfo(pwd, pSurface, "CreateDirectDrawPalette");
  945.         ddrval = E_FAIL;
  946.     }
  947.     return ddrval;
  948. }
  949. /*
  950. * Instructs color converters to use new destination palette:
  951. */
  952. static void SetColorConverterPalette (PALETTEENTRY *pPalette, int l, int h)
  953. {
  954.     int i, palIdx [256];
  955.     /* Instruct the color conversion library to use set of our
  956.     * "standard" colors ( [l,h] range) from the logical palette:  */
  957.     for (i=l; i<h; i++) palIdx [i] = i;
  958.     
  959.     if (pfSetRGB8Palette)
  960.     {
  961. (*pfSetRGB8Palette)(h-l, (ULONG32*) (pPalette + l), palIdx + l);
  962.     }
  963. }
  964. /*
  965. * Checks if system palette contains our colors.
  966. */
  967. static BOOL HasPaletteChanged (LPWINDRAW lpwd)
  968. {
  969.     PALETTEENTRY lppe [256], *lppe2;
  970.     register int i;
  971.     
  972.     /* clear memory: */
  973.     memset(lppe, 0, sizeof(lppe));
  974.     
  975.     /* retrive system palette: */
  976.     if ((lpwd->fMode & WINDRAW_DIRECTDRAW) && lpwd->dd.lpDDPal != NULL &&
  977.         /* use DirectDraw: */
  978.         IDirectDrawPalette_GetEntries (lpwd->dd.lpDDPal, 0, lpwd->loColor,
  979. lpwd->hiColor - lpwd->loColor, lppe + lpwd->loColor) == DD_OK) {
  980.         ; /* we're all done here */
  981.     } else {
  982.         /* use GDI: */
  983.         HDC hdc = GetDisplayDC (lpwd->lpszDisplayDevice);
  984.         GetSystemPaletteEntries (hdc, lpwd->loColor, lpwd->hiColor, lppe);
  985.         DeleteDC (hdc);
  986.     }
  987.     
  988.     /* check if our colors are still there: */
  989.     lppe2 = lpwd->lgplDefaultPalette.palPalEntry;
  990.     for (i=lpwd->loColor; i<lpwd->hiColor; i++)
  991.         if (lppe [i].peGreen != lppe2 [i].peGreen ||
  992.             lppe [i].peBlue  != lppe2 [i].peBlue  ||
  993.             lppe [i].peRed   != lppe2 [i].peRed) {
  994.             break;
  995.         }
  996. return i == lpwd->hiColor;
  997. }
  998. /*
  999. * Handles Windows palette change messages.
  1000. * Use:
  1001. *  LRESULT WinDraw2_OnPaletteChange (LPWINDRAW lpwd, HWND hwnd, UINT Message);
  1002. * Input:
  1003. *  lpwd - pointer to a WINDRAW structure we work with
  1004. *  hwnd - with WM_PALETTECHANGED: identifies a window that CAUSED the
  1005. *         palette to change; window that received a message otherwise
  1006. *  Message - either WM_QUERYNEWPALETTE or WM_PALETTECHANGED
  1007. * Returns:
  1008. *  TRUE, if we do realise our palette; FALSE, otherwise.
  1009. * Notes:
  1010. *  If our window is foreground application then we should get first
  1011. *  choice of colors in the system palette entries.
  1012. *  We get best performance when our logical palette includes the
  1013. *  standard VGA colors (at the beginning and end) otherwise GDI may have
  1014. *  to map from our palette to the device palette while drawing.
  1015. */
  1016. LRESULT WinDraw2_OnPaletteChange (LPWINDRAW lpwd, HWND hwnd, UINT Message)
  1017. {
  1018.     if (lpwd && (lpwd->fMode & WINDRAW_OPENED) && hwnd == lpwd->hWnd && 
  1019.        (Message == WM_QUERYNEWPALETTE || Message == WM_PALETTECHANGED))
  1020.     {
  1021.         if (LoadPalette(lpwd))
  1022.         {
  1023.             /* check if we are using DirectDraw: */
  1024.             if (lpwd->fMode & WINDRAW_DIRECTDRAW) 
  1025.             {
  1026.                 if (FAILED(CreateDirectDrawPalette(lpwd, lpwd->dd.lpDDSPrimary)))
  1027.                     return 0;
  1028.             }
  1029.             if (lpwd->m_pSurfaceList)
  1030.             {
  1031.                 for(CHXSimpleList::Iterator i = lpwd->m_pSurfaceList->Begin(); i!= lpwd->m_pSurfaceList->End(); ++i)
  1032.                 {
  1033.                     LPWINDRAWSURFACE lpwds = (LPWINDRAWSURFACE) *i;
  1034.                     if (lpwds)
  1035.                     {
  1036.                         if (lpwds->fMode & WINDRAWSURFACE_DIRECTDRAW)
  1037.                         {
  1038.                             CreateDirectDrawPalette(lpwd, lpwds->dd.lpDDSurface);
  1039.                             CreateDirectDrawPalette(lpwd, lpwds->dd.lpDDBackBuffer);
  1040.                         }
  1041.                         else
  1042.                         {
  1043.                             HBITMAP hOldBitmap;
  1044.                             for(int i = 0; i<(int)lpwds->dwBackBufferCount; i++)
  1045.                             {
  1046.                                 if (lpwds->gdi.lpGDIBackBuffer[i])
  1047.                                 {
  1048.                                     hOldBitmap = (HBITMAP) SelectObject (lpwd->gdi.hMemoryDC, lpwds->gdi.lpGDIBackBuffer[i]->hBitMap);
  1049.                                     SetDIBColorTable(lpwd->gdi.hMemoryDC, 0, nSystemColors, SystemPaletteRGB);
  1050.                                     SelectObject(lpwd->gdi.hMemoryDC, hOldBitmap);
  1051.                                 }
  1052.                             }
  1053.                         }
  1054.                     }
  1055.                 }
  1056.                 return (LRESULT) 1;
  1057.             }
  1058.         }
  1059.     }
  1060.     return 0;
  1061. }
  1062. /*
  1063. * When the window size changes we adjust our WINDRAW variables that
  1064. * contain the dimensions of the client rectangle for our window so
  1065. * that we come to render an image we will know whether to stretch.
  1066. */
  1067. LRESULT WinDraw2_OnSize (LPWINDRAW lpwd, DWORD dwWidth, DWORD dwHeight)
  1068. {
  1069.     /* check parameters: */
  1070.     if (lpwd == NULL)
  1071.         return (LRESULT) 0;
  1072.     
  1073.     /* update client area size: */
  1074.     lpwd->dwWindowWidth = dwWidth;
  1075.     lpwd->dwWindowHeight = dwHeight;
  1076.     
  1077.     /* ... */
  1078.     
  1079.     return (LRESULT) 1;
  1080. }
  1081. /*
  1082. * This function handles the WM_CLOSE message:
  1083. */
  1084. LRESULT WinDraw2_OnClose (LPWINDRAW lpwd)
  1085. {
  1086.     /* check parameters: */
  1087.     if (lpwd == NULL || lpwd->hWnd == NULL)
  1088.         return (LRESULT) 0;
  1089.     
  1090.     /* hide window before destroying it: */
  1091.     ShowWindow (lpwd->hWnd, SW_HIDE);
  1092.     
  1093.     return TRUE;
  1094. }
  1095. HRESULT CALLBACK 
  1096. DisplayModeEnumeratorCallback(LPDDSURFACEDESC pddsd, LPVOID Context)
  1097. {
  1098.     CHXSimpleList* pList = (CHXSimpleList*) Context;
  1099.     
  1100.     CModesDesc* pDesc = new CModesDesc;
  1101.     
  1102.     pDesc->m_nWidth = pddsd->dwWidth;
  1103.     pDesc->m_nHeight = pddsd->dwHeight;
  1104.     pDesc->m_nBitCount = pddsd->ddpfPixelFormat.dwRGBBitCount;
  1105.     pDesc->m_fourCC = pddsd->ddpfPixelFormat.dwFourCC;
  1106.     
  1107.     pList->AddTail(pDesc);
  1108.     
  1109.     return DDENUMRET_OK;
  1110. /*
  1111. * Initialize WinDraw engine.
  1112. * Use:
  1113. *  HRESULT WinDraw2_Open (LPWINDRAW lpwd, HWND hWnd, DWORD fMode,
  1114. *      LPSTR lpszDisplay, LPBMI lpbiDisplayFormat);
  1115. * Input:
  1116. *  lpwd - pointer to a WINDRAW structure to initialize
  1117. *  hWnd - a window handle to use
  1118. *  fMode - WinDraw mode to set (e.g. WINDRAW_FULLSCREEN)
  1119. *  lpszDisplay - monitor to use (NULL or zero string = use all monitors)
  1120. *  lpbiDisplayFormat - preferred display mode in full screen
  1121. * Returns:
  1122. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  1123. */
  1124. HRESULT WinDraw2_Open (LPWINDRAW lpwd, HWND hWnd, DWORD fMode,
  1125.        LPSTR lpszDisplay, LPBMI lpbiDisplayFormat)
  1126. {
  1127.     /* check parameters: */
  1128.     if (lpwd == NULL || hWnd == NULL || (lpwd->fMode & WINDRAW_OPENED))
  1129.         return E_INVALIDARG;
  1130.     
  1131.     HRESULT hrFail = E_FAIL;
  1132.     if (!g_ehandlerMutexCnt)
  1133.     {
  1134.         InitializeCriticalSection(&g_ehandlerMutex);
  1135.     }
  1136.     InterlockedIncrement(&g_ehandlerMutexCnt);
  1137.     
  1138.     z_hHxColor = LoadLibrary("colorcvt.dll");
  1139.     if (!z_hHxColor)
  1140.          z_hHxColor = LoadLibrary("hxltcolor.dll");
  1141.     if (z_hHxColor)
  1142.     {
  1143. pfInitColorConverter = (INITCOLORCONVERTERFN) GetProcAddress(z_hHxColor,"InitColorConverter");
  1144. pfSetRGB8Palette = (SETRGB8PALETTEFN) GetProcAddress(z_hHxColor,"SetRGB8Palette");
  1145.     }
  1146.     
  1147.     /* initialize WinDraw structure: */
  1148.     memset (lpwd, 0, sizeof (WINDRAW));
  1149.     lpwd->hWnd = hWnd;
  1150.     lpwd->m_pModesList     = new CHXSimpleList;
  1151.     lpwd->m_pSurfaceList    = new CHXSimpleList;
  1152.     lpwd->nSchedulerResolution = 0;
  1153.     
  1154.     InitializeCriticalSection(&lpwd->csPrimary);
  1155.     /* check if want to use DirectDraw: */
  1156.     if (fMode & WINDRAW_DIRECTDRAW) 
  1157.     {
  1158.         lpwd->fMode |= WINDRAW_DIRECTDRAW;
  1159.         /* initialize DirectDraw objects: */
  1160. LPDIRECTDRAW pDirectDraw = NULL;
  1161.         try
  1162.         {
  1163.         if (LoadDirectDraw (lpszDisplay, &pDirectDraw, & (lpwd->dd.hDD)) != NOERROR)
  1164.             goto dd_fail;
  1165.         }
  1166.         catch (...)
  1167.         {
  1168.             DumpDDInfo(lpwd, NULL, "WinDraw2_Open");
  1169.             goto dd_fail;
  1170.         }
  1171.         pDirectDraw->QueryInterface(IID_IDirectDraw2, (void**)&lpwd->dd.lpDD2);
  1172. pDirectDraw->Release();
  1173. pDirectDraw = 0;
  1174. /* 
  1175. * DirectX 1.0 installed (e.g. boxes with the original (Aug 95) release of Win95).
  1176. * don't support that!
  1177. */
  1178. if (!lpwd->dd.lpDD2)
  1179. {
  1180.     goto dd_fail;
  1181. }
  1182.         /* initialize our color conversion engine: */
  1183. if (pfInitColorConverter)
  1184.     (*pfInitColorConverter)();
  1185.         /* get display format: */
  1186.         lpwd->lpszDisplayDevice = lpszDisplay;
  1187.         lpwd->cidDisplayColor = CID_UNKNOWN;
  1188.         if (GetDisplayFormat (&lpwd->bmiDisplayFormat, lpwd->lpszDisplayDevice) != NOERROR ||
  1189.             (lpwd->cidDisplayColor = GetBitmapColor ((LPBITMAPINFO)&lpwd->bmiDisplayFormat)) == CID_UNKNOWN) 
  1190. {
  1191.     
  1192.             /* this is very bad... */
  1193.             #ifdef _DEBUG
  1194.             OutputDebugString ("WinDraw: cannot obtain display pixel format.n");
  1195.             #endif
  1196.             goto dd_fail;
  1197.         }
  1198. /* find out what FourCC codes are supported */
  1199. lpwd->dd.lpDD2->GetFourCCCodes(&(lpwd->numCodes), lpwd->lpCodes);
  1200. if (lpwd->numCodes)
  1201. {
  1202.     lpwd->lpCodes = (LPDWORD) malloc (lpwd->numCodes*4);
  1203.     lpwd->lpCID = (LPDWORD) malloc (lpwd->numCodes*4);
  1204.     
  1205.     lpwd->dd.lpDD2->GetFourCCCodes(&(lpwd->numCodes), lpwd->lpCodes);
  1206.     
  1207.     for(unsigned int i = 0; i<lpwd->numCodes; i++)
  1208.     {
  1209. lpwd->lpCID[i] = MapFourCCtoCID(lpwd->lpCodes[i]);
  1210.     }
  1211. }
  1212. /* Get the device caps */
  1213. memset(&lpwd->dd.m_caps, 0, sizeof(DDCAPS));
  1214. lpwd->dd.m_caps.dwSize = sizeof(DDCAPS_DX3);
  1215. lpwd->dd.lpDD2->GetCaps(&(lpwd->dd.m_caps), 0);
  1216. /*
  1217. *  If we have neither overlay nor streatching then we will use DibEngine (good call? time will tell)
  1218. */
  1219.         if (! ( (lpwd->dd.m_caps.dwCaps & DDCAPS_OVERLAY) || (lpwd->dd.m_caps.dwCaps &  DDCAPS_BLTSTRETCH) ))
  1220. {
  1221.     goto dd_fail;
  1222. }
  1223. /* set normal cooperative level  */
  1224.         if (DD_OK != lpwd->dd.lpDD2->SetCooperativeLevel(lpwd->hWnd, DDSCL_NORMAL)) 
  1225. {
  1226.     goto dd_fail;
  1227.         }
  1228.         try
  1229.         {
  1230.         if (DD_OK == WindrawSurface_CreatePrimarySurface(lpwd))
  1231. {
  1232.             /* DirectDraw profile/mode masks: */
  1233.             DWORD dwOverlayMask, dwBltMask;
  1234.             DDPIXELFORMAT ddpf;
  1235.     /* color formats: */
  1236.     int cidOut = CID_UNKNOWN;
  1237.     
  1238.             /* get pixel format of the primary surface: */
  1239.             memset (&ddpf, 0, sizeof (DDPIXELFORMAT));
  1240.             ddpf.dwSize = sizeof (DDPIXELFORMAT);
  1241.             ddpf.dwFlags = DDPF_RGB | DDPF_FOURCC;
  1242.             if (lpwd->dd.lpDDSPrimary->GetPixelFormat(&ddpf) != DD_OK)
  1243.                 goto dd_fail;
  1244.     
  1245.             /* convert it to our color ID: */
  1246.             cidOut = GetDirectDrawColor (&ddpf);
  1247.             if (cidOut < CID_RGB32 || cidOut > CID_RGB8)
  1248.                 goto dd_fail;
  1249.     
  1250.             /* check if DirectDraw profile needs to be loaded: */
  1251.             if (!lpddprofDirectDrawProfile || DDPDB_IsNewProfile ()) {
  1252.                 /* get DirectDraw device profile: */
  1253. lpwd->dd.lpDD2->QueryInterface(IID_IDirectDraw, (void**)&pDirectDraw);
  1254. HX_ASSERT(pDirectDraw);
  1255. lpddprofDirectDrawProfile = DDPDB_GetDeviceProfile(pDirectDraw);
  1256. pDirectDraw->Release();
  1257. pDirectDraw = 0;
  1258.             }
  1259.     
  1260.             /* get mode masks: */
  1261.             dwOverlayMask = lpddprofDirectDrawProfile->fOverlays [cidOut-CID_RGB32];
  1262.             dwBltMask = lpddprofDirectDrawProfile->fBlts [cidOut-CID_RGB32];
  1263.     
  1264.     //            if (dwOverlayMask == 0 || dwBltMask == 0)
  1265.     /* We currently disable DirectDraw if bltMask is 0.
  1266.     * Need to add support for selecting DirectDraw features based on
  1267.     * the info in the database.
  1268.     */
  1269.             if (dwOverlayMask == 0)
  1270.                 goto dd_fail;
  1271.     
  1272.     /* Enum the display modes  */
  1273.     zm_DisplaySettings.GetSettings(lpwd->m_pModesList);
  1274.     
  1275.     /*
  1276.     *  For SOME reason EnumDisplayModes is causing a number of cards to go CRAZY.
  1277.     * So we now we call a function which calls enum display modes early and caches 
  1278.     * the results. For some reason this does not cause things to go INSANE. Who knows why.
  1279.     */
  1280.     
  1281.     //     lpwd->dd.lpDD2->EnumDisplayModes(0, NULL, lpwd->m_pModesList, DisplayModeEnumeratorCallback);      
  1282. }
  1283. else
  1284. {
  1285.             goto dd_fail;
  1286. }
  1287.         }
  1288.         catch(...)
  1289.         {
  1290.             DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "WinDraw2_Open");
  1291.             goto dd_fail;
  1292.         }
  1293.         
  1294.         goto success;
  1295. dd_fail:
  1296.         /* release DirectDraw library, if loaded: */
  1297.         if (lpwd->dd.lpDD2 != NULL && lpwd->dd.hDD != NULL)
  1298.             ReleaseDirectDraw(&(lpwd->dd.lpDD), &(lpwd->dd.lpDD2), & (lpwd->dd.hDD));
  1299.         /* exit with error: */
  1300.         return hrFail;
  1301.     } else { /* use GDI: */
  1302.         /* grab DCs: */
  1303. if ((lpwd->gdi.hDC = GetDC (lpwd->hWnd)) == NULL ||
  1304.     (lpwd->gdi.hMemoryDC = CreateCompatibleDC (lpwd->gdi.hDC)) == NULL ||
  1305.     (lpwd->gdi.hMemoryDC2 = CreateCompatibleDC (lpwd->gdi.hDC)) == NULL)
  1306.             goto gdi_fail;
  1307.         /* set default StretchBlt () mode: */
  1308. SetStretchBltMode (lpwd->gdi.hDC, COLORONCOLOR);
  1309.         SetStretchBltMode (lpwd->gdi.hMemoryDC,COLORONCOLOR);
  1310.         SetStretchBltMode (lpwd->gdi.hMemoryDC2,COLORONCOLOR);
  1311.         /* get display format: */
  1312.         lpwd->lpszDisplayDevice = lpszDisplay;
  1313.         lpwd->cidDisplayColor = CID_UNKNOWN;
  1314.         if (GetDisplayFormat (&lpwd->bmiDisplayFormat, lpwd->lpszDisplayDevice) != NOERROR ||
  1315.             (lpwd->cidDisplayColor = GetBitmapColor ((LPBITMAPINFO)&lpwd->bmiDisplayFormat)) == CID_UNKNOWN) {
  1316.     
  1317.             /* this is very bad... */
  1318.             #ifdef _DEBUG
  1319.             OutputDebugString ("WinDraw: cannot obtain display pixel format.n");
  1320.             #endif
  1321.             goto gdi_fail;
  1322.         }
  1323.         /* initialize our color conversion engine: */
  1324. if (pfInitColorConverter)
  1325.     (*pfInitColorConverter)();
  1326.         goto success;
  1327.         /* something really bad has happened... */
  1328. gdi_fail:
  1329.         /* delete palette: */
  1330.         if (lpwd->gdi.hPalette) {
  1331.             DeleteObject (lpwd->gdi.hPalette);
  1332.     lpwd->gdi.hPalette = NULL;
  1333. }
  1334. /* release DCs, if taken: */   
  1335. if (lpwd->gdi.hDC != NULL) 
  1336. {   
  1337.     ReleaseDC (lpwd->hWnd, lpwd->gdi.hDC);   
  1338.     lpwd->gdi.hDC = NULL;   
  1339.         
  1340. if (lpwd->gdi.hMemoryDC != NULL) {
  1341.             DeleteDC (lpwd->gdi.hMemoryDC);
  1342.     lpwd->gdi.hMemoryDC = NULL;
  1343. }
  1344.         if (lpwd->gdi.hMemoryDC2 != NULL) {
  1345.             DeleteDC (lpwd->gdi.hMemoryDC2);
  1346.     lpwd->gdi.hMemoryDC2 = NULL;
  1347. }
  1348.         /* exit with error: */
  1349.         return E_FAIL;
  1350.     }
  1351.     
  1352. success:
  1353.     
  1354.     /* activate WinDraw & exit: */
  1355.     lpwd->fMode |= WINDRAW_OPENED;
  1356.     WinDraw2_OnPaletteChange(lpwd, lpwd->hWnd, WM_PALETTECHANGED);
  1357.     return NOERROR;
  1358. }
  1359. void DeleteDisplayModes(LPWINDRAW lpwd)
  1360. {
  1361.     CHXSimpleList::Iterator i;
  1362.     
  1363.     if (!lpwd->m_pModesList || !lpwd->m_pModesList->GetCount())
  1364.         return;
  1365.     for(i=lpwd->m_pModesList->Begin(); i!= lpwd->m_pModesList->End(); ++i)
  1366.     {
  1367. CModesDesc* pDesc = (CModesDesc*) *i;
  1368. HX_DELETE(pDesc);
  1369.     }
  1370.     lpwd->m_pModesList->RemoveAll();
  1371. }
  1372. /*
  1373. * Close WinDraw library.
  1374. * Use:
  1375. *  HRESULT WinDrawClose (LPWINDRAW lpwd);
  1376. * Input:
  1377. *  lpwd - pointer to a WINDRAW engine to deactivate
  1378. * Returns:
  1379. *  NOERROR if OK, or E_FAIL.
  1380. */
  1381. HRESULT WinDraw2_Close (LPWINDRAW lpwd)
  1382. {
  1383.     /* check parameters: */
  1384.     if (lpwd == NULL || !(lpwd->fMode & WINDRAW_OPENED))
  1385.         // return E_INVALIDARG;
  1386.         goto cleanup;
  1387.     if (z_hHxColor)
  1388.     {
  1389.         FreeLibrary(z_hHxColor);
  1390.         z_hHxColor = 0;
  1391.         pfInitColorConverter = 0;
  1392.         pfSetRGB8Palette = 0;
  1393.     }
  1394.     /* check mode: */
  1395.     if (lpwd->fMode & WINDRAW_DIRECTDRAW)
  1396.     {
  1397.         free(lpwd->lpCodes);
  1398.         free(lpwd->lpCID);
  1399.        /* 
  1400.         * Release the Primary Surface
  1401.         */
  1402.         if (lpwd->dd.lpDDSPrimary)
  1403.         {
  1404.             int rel = lpwd->dd.lpDDSPrimary->Release();
  1405.             lpwd->dd.lpDDSPrimary = NULL;
  1406.         }
  1407.         /* release DirectDraw library, if loaded: */
  1408.         if (lpwd->dd.lpDD2 != NULL && lpwd->dd.hDD != NULL)
  1409.         ReleaseDirectDraw (&(lpwd->dd.lpDD), &(lpwd->dd.lpDD2), &(lpwd->dd.hDD));
  1410.     }
  1411.     else
  1412.     { /* GDI: */
  1413.         /* delete palette: */
  1414.         if (lpwd->gdi.hPalette)
  1415.         {
  1416.             DeleteObject (lpwd->gdi.hPalette);
  1417.             lpwd->gdi.hPalette = NULL;
  1418.         }
  1419.         /* release DCs, if taken: */
  1420.         if (lpwd->gdi.hDC != NULL) 
  1421.         {   
  1422.             ReleaseDC (lpwd->hWnd, lpwd->gdi.hDC);   
  1423.             lpwd->gdi.hDC = NULL;   
  1424.         } 
  1425.         if (lpwd->gdi.hMemoryDC != NULL) 
  1426.         {
  1427.             DeleteDC (lpwd->gdi.hMemoryDC);
  1428.             lpwd->gdi.hMemoryDC = NULL;
  1429.         }
  1430.         if (lpwd->gdi.hMemoryDC2 != NULL) 
  1431.         {
  1432.             DeleteDC (lpwd->gdi.hMemoryDC2);
  1433.             lpwd->gdi.hMemoryDC2 = NULL;
  1434.         }
  1435.     }
  1436.     cleanup:
  1437.     /* deactivate WinDraw & exit: */
  1438.     lpwd->fMode = 0;
  1439.     /* remove display mode data */
  1440.     DeleteDisplayModes(lpwd);
  1441.     HX_DELETE(lpwd->m_pModesList);
  1442.     HX_DELETE(lpwd->m_pSurfaceList);
  1443.     DeleteCriticalSection(&lpwd->csPrimary);
  1444.     InterlockedDecrement(&g_ehandlerMutexCnt);
  1445.     if (!g_ehandlerMutexCnt)
  1446.     {
  1447.         DeleteCriticalSection(&g_ehandlerMutex);
  1448.     }
  1449.     
  1450.     
  1451.     return NOERROR;
  1452. }
  1453. /*
  1454. * Get display/primary surface format.
  1455. * Use:
  1456. *  HRESULT WinDraw2_GetDisplayFormat (LPWINDRAW lpwd, LPBMI lpbiDisplayFormat);
  1457. * Input:
  1458. *  lpwd - pointer to a WINDRAW structure to initialize
  1459. *  lpbiDisplayFormat - a structure to contain display format
  1460. * Returns:
  1461. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  1462. */
  1463. HRESULT WinDraw2_GetDisplayFormat (LPWINDRAW lpwd, LPBMI lpbiDisplayFormat)
  1464. {
  1465.     int sz;
  1466.     
  1467.     /* check parameters: */
  1468.     if (lpwd == NULL || !(lpwd->fMode & WINDRAW_OPENED) ||
  1469.         lpbiDisplayFormat == NULL)
  1470.         return E_INVALIDARG;
  1471.     
  1472.     /* check the size of BITMAPINFO structure to copy: */
  1473.     sz = lpbiDisplayFormat->bmiHeader.biSize;
  1474.     if (sz < (int)sizeof(BITMAPINFOHEADER) || sz > (int)lpwd->bmiDisplayFormat.bmiHeader.biSize)
  1475.         sz = lpwd->bmiDisplayFormat.bmiHeader.biSize;
  1476.     
  1477.     /* copy bitmap info: */
  1478.     
  1479.     /* Since it seems that our convention was to set biSize to the sizeof 
  1480.     * BITMAPINFOHEADER instead of the actual size of the structure (which
  1481.     * causes us to lose the color table of bit fields) we will use the size
  1482.     * of the structure.
  1483.     */
  1484.     // memcpy(lpbiDisplayFormat, &(lpwd->bmiDisplayFormat), sz);
  1485.     GetDisplayFormat(&lpwd->bmiDisplayFormat, lpwd->lpszDisplayDevice);
  1486.     
  1487.     memcpy(lpbiDisplayFormat, &(lpwd->bmiDisplayFormat), sizeof(BMI) ); /* Flawfinder: ignore */
  1488.     
  1489.     return NOERROR;
  1490. }
  1491. /*
  1492. * GDISURFACE functions:
  1493. */
  1494. #define hMEMORY ((HANDLE) 0xFFFFFFFF)   /* says to open as memory file  */
  1495. /*
  1496. * This function allocates a shared memory block for use by the source filter
  1497. * generating DIBs for us to render. The memory block is created in shared
  1498. * memory so that GDI doesn't have to copy the memory when we do a BitBlt
  1499. */
  1500. static LPGDISURFACE GDISurface_Alloc (LPBITMAPINFO pbmi)
  1501. {
  1502.     LPGDISURFACE lpGDISurface;  /* pointer to a new GDISURFACE  */
  1503.     HANDLE      hMapping;       /* handle to mapped object      */
  1504.     HBITMAP     hBitmap;        /* DIB section bitmap handle    */
  1505.     BYTE        *pBase;         /* pointer to the actual image  */
  1506.     
  1507.     /* allocate a new GDISURFACE structure to use: */
  1508.     lpGDISurface = (LPGDISURFACE)malloc (sizeof (GDISURFACE));
  1509.     if (lpGDISurface != NULL) {
  1510.         /* create a file mapping object and map into our address space: */
  1511.         hMapping = CreateFileMapping (hMEMORY, NULL, PAGE_READWRITE, (DWORD) 0, pbmi->bmiHeader.biSizeImage, NULL);
  1512.         if (hMapping != NULL) {
  1513.     
  1514.             /* create a DIB section using given image format */
  1515.             hBitmap = CreateDIBSection ((HDC) NULL, pbmi, DIB_RGB_COLORS, (VOID **) &pBase, hMapping, (DWORD) 0);
  1516.             if (hBitmap != NULL && pBase != NULL) {
  1517.                 /* initialise the GDISURFACE structure: */
  1518.                 lpGDISurface->hBitMap = hBitmap;
  1519.                 lpGDISurface->hMapping = hMapping;
  1520.                 lpGDISurface->lpBase = pBase;
  1521.                 lpGDISurface->lpAlphaSurface = NULL;
  1522.                 lpGDISurface->hEmpty = CreateEvent(NULL, TRUE, TRUE, NULL);
  1523.                 
  1524.                 /* lpGDISurface->PaletteVersion = PALETTE_VERSION; */
  1525.                 GetObject (hBitmap, sizeof (DIBSECTION), (VOID *)& (lpGDISurface->DibSection));
  1526.                 /* success: */
  1527.                 return lpGDISurface;
  1528.             }
  1529.             /* close file mapping... */
  1530.             CloseHandle (hMapping);
  1531.         }
  1532.         /* free buffer: */
  1533.         free (lpGDISurface);
  1534.     }
  1535.     return NULL;
  1536. }
  1537. /*
  1538. * Releases previously allocated GDI buffer.
  1539. * Main application should consider calling GdiFlush ();
  1540. * before releasing these buffers.
  1541. */
  1542. static void GDISurface_Free (LPGDISURFACE lpGDISurface)
  1543. {
  1544.     /* check pointer to a buffer structure to use: */
  1545.     if (lpGDISurface != NULL) {
  1546.         /* close dibsection: */
  1547.         DeleteObject (lpGDISurface->hBitMap);
  1548.         /* close file mapping: */
  1549.         CloseHandle (lpGDISurface->hMapping);
  1550.         /* close alpha channel */
  1551.         free(lpGDISurface->lpAlphaSurface);
  1552.         /* close event */
  1553.         CloseHandle(lpGDISurface->hEmpty);
  1554.         /* free buffer: */
  1555.         free (lpGDISurface);
  1556.     }
  1557. }
  1558. static BOOL GDISurface_AlphaBltIndirect(LPWINDRAW lpwd, LPGDISURFACE lpGDISurfaceDest,
  1559. LPGDISURFACE lpGDISurfaceSrc, LPRECT lpDestRect, LPRECT lpSrcRect)
  1560. {
  1561. #if 0     
  1562.     INT32 destX, destY;
  1563.     INT32 destStride, srcStride, alphaStride;
  1564.     UINT32 *srcBuf, *destBuf;
  1565.     UCHAR  *alphaBuf;
  1566.     UCHAR alpha, invalpha;
  1567.     UCHAR *pSrc, *pDest;
  1568.     
  1569.     int destCID = GetBitmapColor((LPBITMAPINFO) &lpGDISurfaceDest->DibSection.dsBmih);
  1570.     int srcCID  = GetBitmapColor((LPBITMAPINFO) &lpGDISurfaceSrc->DibSection.dsBmih);
  1571.     
  1572.     assert(destCID == srcCID); // not supported
  1573.     
  1574.     switch (destCID)
  1575.     {
  1576.     case CID_RGB565:
  1577.     case CID_RGB555:
  1578. destStride  = (lpGDISurfaceDest->DibSection.dsBmih.biWidth - (lpDestRect->right - lpDestRect->left)) * 2;
  1579. srcStride   = (lpGDISurfaceSrc->DibSection.dsBmih.biWidth - (lpSrcRect->right - lpSrcRect->left)) * 2;
  1580. srcBuf     = (UINT32*)(lpGDISurfaceSrc->lpBase + ( (lpSrcRect->right - lpSrcRect->left) * lpSrcRect->top 
  1581.     + lpSrcRect->left ) * 2);
  1582. destBuf     = (UINT32*)(lpGDISurfaceDest->lpBase + ( (lpDestRect->right - lpDestRect->left) * lpDestRect->top 
  1583.     + lpDestRect->left) *2);
  1584. break;
  1585.     case CID_RGB32:
  1586. destStride  = (lpGDISurfaceDest->DibSection.dsBmih.biWidth - (lpDestRect->right - lpDestRect->left)) * 4;
  1587. srcStride   = (lpGDISurfaceSrc->DibSection.dsBmih.biWidth - (lpSrcRect->right - lpSrcRect->left)) * 4;
  1588. srcBuf     = (UINT32*)(lpGDISurfaceSrc->lpBase + ( (lpSrcRect->right - lpSrcRect->left) * lpSrcRect->top 
  1589.     + lpSrcRect->left ) *4);
  1590. destBuf     = (UINT32*)(lpGDISurfaceDest->lpBase + ( (lpDestRect->right - lpDestRect->left) * lpDestRect->top 
  1591.     + lpDestRect->left ) *4);
  1592. break;
  1593.     case CID_RGB24:
  1594. break;
  1595.     default:
  1596. assert(CID_NOTSUPPORTED);
  1597.     }
  1598.     
  1599.     alphaBuf = lpGDISurfaceSrc->lpAlphaSurface;
  1600.     alphaStride = lpGDISurfaceDest->DibSection.dsBmih.biWidth - (lpSrcRect->right - lpSrcRect->left);
  1601.     
  1602.     switch (destCID)
  1603.     {
  1604.     case CID_RGB32:
  1605. {
  1606.     for (destY = lpDestRect->top; destY < lpDestRect->bottom; destY++ )
  1607.     {
  1608. for (destX = lpDestRect->left;destX < lpDestRect->right;destX++, srcBuf++, destBuf++, alphaBuf++)
  1609. {
  1610.     alpha = *alphaBuf>128 ? *alphaBuf + 1 : *alphaBuf;
  1611.     invalpha = 256 - alpha;
  1612.     *destBuf = 
  1613. ((((*srcBuf & 0x00ff0000) * alpha)     >> 8 ) & 0x00ff0000) +
  1614. ((((*destBuf    & 0x00ff0000) * invalpha)   >> 8 ) & 0x00ff0000) +
  1615. ((((*srcBuf & 0x0000ff00) * alpha)     >> 8 ) & 0x0000ff00) +
  1616. ((((*destBuf    & 0x0000ff00) * invalpha)   >> 8 ) & 0x0000ff00) +
  1617. ((((*srcBuf & 0x000000ff) * alpha)     >> 8 ) & 0x000000ff) +
  1618. ((((*destBuf    & 0x000000ff) * invalpha)   >> 8 ) & 0x000000ff);
  1619. }   
  1620. destBuf     += destStride;
  1621. srcBuf     += srcStride;
  1622. alphaBuf    += alphaStride;
  1623.     }
  1624.     break;
  1625. }
  1626.     case CID_RGB24:
  1627. {
  1628.     pSrc    = lpGDISurfaceSrc->lpBase;
  1629.     pDest   = lpGDISurfaceDest->lpBase;
  1630.     pDest   += (lpGDISurfaceDest->DibSection.dsBmih.biWidth * (lpGDISurfaceDest->DibSection.dsBmih.biHeight - lpDestRect->top) + lpDestRect->left)* 3;
  1631.     pSrc    += (lpGDISurfaceSrc->DibSection.dsBmih.biWidth * (lpGDISurfaceSrc->DibSection.dsBmih.biHeight - lpSrcRect->top) + lpSrcRect->left)* 3;
  1632.     
  1633.     for (destY = lpDestRect->top; destY < lpDestRect->bottom; destY++ )
  1634.     {
  1635. for (destX = lpDestRect->left;destX < lpDestRect->right;destX++, alphaBuf++)
  1636. {   
  1637.     //     alpha = *alphaBuf;
  1638.     alpha = 128;
  1639.     invalpha = 256 - alpha;
  1640.     
  1641.     *pDest = (*pSrc * alpha) >> 8 + (*pDest * invalpha) >> 8;
  1642.     pDest++; pSrc++;
  1643.     *pDest = (*pSrc * alpha) >> 8 + (*pDest * invalpha) >> 8;
  1644.     pDest++; pSrc++;
  1645.     *pDest = (*pSrc * alpha) >> 8 + (*pDest * invalpha) >> 8;
  1646.     pDest++; pSrc++;
  1647. }
  1648. pDest -= (lpGDISurfaceDest->DibSection.dsBmih.biWidth + (lpDestRect->right - lpDestRect->left))*3;
  1649. pSrc -= (lpGDISurfaceSrc->DibSection.dsBmih.biWidth + (lpSrcRect->right - lpSrcRect->left))*3;
  1650. alphaBuf +=alphaStride;
  1651.     }
  1652.     break;
  1653. }
  1654.     case CID_RGB565:
  1655.     case CID_RGB555:
  1656. {
  1657. /*
  1658. * The following bugs are plain (and all stem from the same problem)
  1659. *
  1660. * 1. If the dest/src rects are not both even.
  1661. *  2. If the width of the blt is not even
  1662.     */
  1663.     for (destY = lpDestRect->top; destY < lpDestRect->bottom; destY++ )
  1664.     {
  1665. for (destX = lpDestRect->left;destX < lpDestRect->right;destX+=2, srcBuf++, destBuf++, alphaBuf++)
  1666. {
  1667.     alpha = *alphaBuf>128 ? *alphaBuf + 1 : *alphaBuf;
  1668.     invalpha = 256 - alpha;
  1669.     *destBuf = 
  1670. ((((*srcBuf & 0xf8000000) * alpha)     >> 8 ) & 0xf8000000) +
  1671. ((((*destBuf    & 0xf8000000) * invalpha)   >> 8 ) & 0xf8000000) +
  1672. ((((*srcBuf & 0x07e00000) * alpha)     >> 8 ) & 0x07e00000) +
  1673. ((((*destBuf    & 0x07e00000) * invalpha)   >> 8 ) & 0x07e00000) +
  1674. ((((*srcBuf & 0x001f0000) * alpha)     >> 8 ) & 0x001f0000) +
  1675. ((((*destBuf    & 0x001f0000) * invalpha)   >> 8 ) & 0x001f0000) +
  1676. ((((*srcBuf & 0x0000f800) * alpha)     >> 8 ) & 0x0000f800) +
  1677. ((((*destBuf    & 0x0000f800) * invalpha)   >> 8 ) & 0x0000f800) +
  1678. ((((*srcBuf & 0x000007e0) * alpha)     >> 8 ) & 0x000007e0) +
  1679. ((((*destBuf    & 0x000007e0) * invalpha)   >> 8 ) & 0x000007e0) +
  1680. ((((*srcBuf & 0x0000001f) * alpha)     >> 8 ) & 0x0000001f) +
  1681. ((((*destBuf    & 0x0000001f) * invalpha)   >> 8 ) & 0x0000001f);
  1682. }
  1683. destBuf     += destStride;
  1684. srcBuf     += srcStride;
  1685. alphaBuf    += alphaStride;
  1686.     }
  1687.     break;
  1688. }
  1689.     }
  1690. #endif
  1691.     return NOERROR;
  1692. }
  1693. /*
  1694. * Blits image data into the window.
  1695. * Use:
  1696. *  BOOL DDSurface_BltIndirect(LPWINDRAW lpwd, LPGDISURFACE lpGDISurface,
  1697. *       LPRECT lpSourceRect, LPRECT lpTargetRect)
  1698. * Input:
  1699. *  lpwd - pointer to the WINDRAW structure
  1700. *  lpDDSurfaceSrc - a structure containing DIBSECTION of image to blit
  1701. *  lpDDSurfaceDst - a 
  1702. *  lpSrcRect - a source image region to blit
  1703. *  lpDstRect - a target window region to fill with image
  1704. * Returns:
  1705. *  TRUE, if success; FALSE, otherwise.
  1706. */
  1707. static BOOL DDSurface_BltIndirect(  
  1708.   LPWINDRAW lpwd, 
  1709.   LPDIRECTDRAWSURFACE lpDDSurfaceDst,
  1710.   LPDIRECTDRAWSURFACE lpDDSurfaceSrc, 
  1711.   LPRECT lpDstRect, 
  1712.   LPRECT lpSrcRect
  1713.   )
  1714. {
  1715.     /* 
  1716.     * this will currently only work if the two color formats are 
  1717.     * the same.
  1718.     */
  1719.     
  1720.     /* set update mode: */
  1721.     DWORD dwFlags = DDBLT_WAIT | DDBLT_ROP;
  1722.     
  1723.     /* set effects: */
  1724.     DDBLTFX ddBltFx;
  1725.     ZeroMemory(&ddBltFx, sizeof(DDBLTFX));
  1726.     ddBltFx.dwSize  = sizeof (DDBLTFX);
  1727.     ddBltFx.dwROP   = SRCCOPY;
  1728.     
  1729.     /* try to blit data from an offscreen surface: */
  1730.     HRESULT retVal;
  1731.     try
  1732.     {
  1733.     
  1734.     retVal = lpDDSurfaceDst->Blt(lpDstRect, lpDDSurfaceSrc, lpSrcRect, dwFlags, &ddBltFx);
  1735.     }
  1736.     catch(...)
  1737.     {
  1738.         char szTmp[256]; /* Flawfinder: ignore */
  1739.         sprintf(szTmp, "DDSurface_BltIndirect srcRect %ld %ld %ld %ld dstRc %ld %ld %ld %ld", /* Flawfinder: ignore */
  1740.                        lpSrcRect->left, lpSrcRect->top, lpSrcRect->right, lpSrcRect->bottom,
  1741.                        lpDstRect->left, lpDstRect->top, lpDstRect->right, lpDstRect->bottom);
  1742.         DumpDDInfo(lpwd, lpDDSurfaceDst, "DDSurface_BltIndirect");
  1743.         retVal = HXR_FAIL;
  1744.     }
  1745.     return retVal;
  1746. }
  1747. /*
  1748. * Blits image data into the window.
  1749. * Use:
  1750. *  BOOL GDISurface_BltIndirect(LPWINDRAW lpwd, LPGDISURFACE lpGDISurface,
  1751. *       LPRECT lpSourceRect, LPRECT lpTargetRect)
  1752. * Input:
  1753. *  lpwd - pointer to the WINDRAW structure
  1754. *  lpGDISurface - a structure containing DIBSECTION of image to blit
  1755. *  lpSourceRect - a source image region to blit
  1756. *  lpTargetRect - a target window region to fill with image
  1757. * Returns:
  1758. *  TRUE, if success; FALSE, otherwise.
  1759. */
  1760. static BOOL GDISurface_BltIndirect(LPWINDRAW lpwd, LPGDISURFACE lpGDISurfaceDest,
  1761.    LPGDISURFACE lpGDISurfaceSrc, LPRECT lpSourceRect, LPRECT lpTargetRect)
  1762. {
  1763.     
  1764.     BOOL bResult;                   /* return value             */
  1765.     /* get sizes of source/destination rectangles: */
  1766.     LONG lTargetWidth  = lpTargetRect->right  - lpTargetRect->left;
  1767.     LONG lTargetHeight = lpTargetRect->bottom - lpTargetRect->top;
  1768.     LONG lSourceWidth  = lpSourceRect->right  - lpSourceRect->left;
  1769.     LONG lSourceHeight = lpSourceRect->bottom - lpSourceRect->top;
  1770.     
  1771.     /* select bitmap to blit: */
  1772.     HBITMAP hOldBitmap = (HBITMAP) SelectObject (lpwd->gdi.hMemoryDC, lpGDISurfaceDest->hBitMap);
  1773.     HBITMAP hOldBitmap2 = (HBITMAP) SelectObject (lpwd->gdi.hMemoryDC2, lpGDISurfaceSrc->hBitMap);
  1774.     
  1775.     if (lpGDISurfaceSrc->lpAlphaSurface)
  1776.     {
  1777. return GDISurface_AlphaBltIndirect(lpwd, lpGDISurfaceDest, lpGDISurfaceSrc, lpTargetRect, lpSourceRect);
  1778.     }
  1779.     
  1780.     /* is the window the same size as the video: */
  1781.     if (lTargetWidth == lSourceWidth && lTargetHeight == lSourceHeight) 
  1782.     {
  1783.         /* put the image straight into the destination: */
  1784.         bResult = BitBlt (
  1785.             lpwd->gdi.hMemoryDC,    /* target device HDC        */
  1786.             lpTargetRect->left,     /* x sink position          */
  1787.             lpTargetRect->top,      /* y sink position          */
  1788.             lTargetWidth,           /* destination width        */
  1789.             lTargetHeight,          /* destination height       */
  1790.             lpwd->gdi.hMemoryDC2,   /* source device context    */
  1791.             lpSourceRect->left,     /* x source position        */
  1792.             lpSourceRect->top,      /* y source position        */
  1793.             SRCCOPY);               /* simple copy              */
  1794.     } 
  1795.     else 
  1796.     {
  1797.         /* stretch the image when copying to the destination: */
  1798.         bResult = StretchBlt (
  1799.             lpwd->gdi.hMemoryDC,    /* target device HDC        */
  1800.             lpTargetRect->left,     /* x sink position          */
  1801.             lpTargetRect->top,      /* y sink position          */
  1802.             lTargetWidth,           /* destination width        */
  1803.             lTargetHeight,          /* destination height       */
  1804.             lpwd->gdi.hMemoryDC2,   /* source device HDC        */
  1805.             lpSourceRect->left,     /* x source position        */
  1806.             lpSourceRect->top,      /* y source position        */
  1807.             lSourceWidth,           /* source width             */
  1808.             lSourceHeight,          /* source height            */
  1809.             SRCCOPY);               /* simple copy              */
  1810.     }
  1811.     /* put the old bitmap back into the device context so we don't leak */
  1812.     SelectObject (lpwd->gdi.hMemoryDC, hOldBitmap);
  1813.     SelectObject (lpwd->gdi.hMemoryDC2, hOldBitmap2);
  1814.     
  1815.     /* pass the result of Bit/StretchBlt: */
  1816.     return bResult;
  1817. }
  1818. /*
  1819. * Blits image data into the window.
  1820. * Use:
  1821. *  BOOL DDSurface_Blt(LPWINDRAW lpwd, LPDIRECTDRAWSURFACE lpDDSurface,
  1822. *       LPRECT lpSourceRect, LPRECT lpTargetRect)
  1823. * Input:
  1824. *  lpwd - pointer to the WINDRAW structure
  1825. *  lpDDSurface  - a structure containing DIBSECTION of image to blit
  1826. *  lpSourceRect - a source image region to blit
  1827. *  lpTargetRect - a target window region to fill with image
  1828. * Returns:
  1829. *  TRUE, if success; FALSE, otherwise.
  1830. */
  1831. BOOL DDSurface_Blt(LPWINDRAW lpwd, LPDIRECTDRAWSURFACE lpDDSurface,
  1832.    LPRECT lpSourceRect, LPRECT lpTargetRect)
  1833. {
  1834.     /* 
  1835.     * this will currently only work if the two color formats are 
  1836.     * the same.
  1837.     */
  1838.     /* set update mode: */
  1839.     DWORD dwFlags = DDBLT_WAIT;
  1840.     
  1841.     /* set effects: */
  1842.     DDBLTFX ddBltFx;
  1843.     ZeroMemory(&ddBltFx, sizeof(DDBLTFX));
  1844.     ddBltFx.dwSize  = sizeof (DDBLTFX);
  1845.     ddBltFx.dwDDFX  = DDBLTFX_NOTEARING;
  1846.     //ddBltFx.dwROP   = SRCCOPY;
  1847.     
  1848.     /* try to blit data from an offscreen surface: */
  1849.     
  1850.     RECT rect, destRect;
  1851.     GetWindowRect(lpwd->hWnd, &rect);
  1852.     destRect.left   = lpTargetRect->left    + rect.left;
  1853.     destRect.right  = lpTargetRect->right   + rect.left;
  1854.     destRect.top    = lpTargetRect->top     + rect.top;
  1855.     destRect.bottom = lpTargetRect->bottom  + rect.top;
  1856.     
  1857.     /* handle monitor spanning blts */
  1858.     RECT srcRect = *lpSourceRect;
  1859.     double ratio;
  1860.     
  1861.     UINT32 uHorzRes = xGetSystemMetrics(SM_CXVIRTUALSCREEN);
  1862.     UINT32 uVertRes = xGetSystemMetrics(SM_CYVIRTUALSCREEN);
  1863.     
  1864.     if (destRect.left < 0)
  1865.     {
  1866.         ratio = ((double)abs(destRect.left)) / (double)(destRect.right - destRect.left);
  1867.         destRect.left = 0;
  1868.         srcRect.left = (int) (((double) (lpSourceRect->right-lpSourceRect->left)) * ratio);
  1869.     }
  1870.     if (destRect.right> uHorzRes)
  1871.     {
  1872.         ratio = ((double)(destRect.right - uHorzRes)) / (double)(destRect.right - destRect.left);
  1873.         destRect.right = uHorzRes;
  1874.         srcRect.right = (int) (((double) (lpSourceRect->right-lpSourceRect->left)) * (1.0 - ratio));
  1875.     }
  1876.     if (destRect.top < 0)
  1877.     {
  1878.         ratio = ((double)abs(destRect.top)) / (double)(destRect.bottom - destRect.top);
  1879.         destRect.top = 0;
  1880.         srcRect.top = (int) (((double) (lpSourceRect->bottom-lpSourceRect->top)) * ratio);
  1881.     }
  1882.     if (destRect.bottom > uVertRes)
  1883.     {
  1884.         ratio = ((double)(destRect.bottom - uVertRes)) / (double)(destRect.bottom - destRect.top);
  1885.         destRect.bottom = uVertRes;
  1886.         srcRect.bottom = (int) (((double) (lpSourceRect->bottom-lpSourceRect->top)) * (1.0 - ratio));
  1887.     }
  1888. #ifdef _CHECK_PERFORMANCE
  1889.     static LARGE_INTEGER QueryPerformanceCounterResult = {0,0};
  1890.     static LARGE_INTEGER QueryPerformanceFrequencyResult = {0,0};
  1891.     
  1892.     QueryPerformanceFrequency(&QueryPerformanceFrequencyResult);
  1893.     
  1894.     double frequency = ((double)QueryPerformanceFrequencyResult.LowPart + 4294967296.0*QueryPerformanceFrequencyResult.HighPart);
  1895.     QueryPerformanceCounter(&QueryPerformanceCounterResult);
  1896.     
  1897.     double startTime = ((double)QueryPerformanceCounterResult.LowPart + 4294967296.0*QueryPerformanceCounterResult.HighPart)/frequency;
  1898. #endif
  1899.     
  1900. #ifdef _CHECK_PERFORMANCE
  1901.     FILE* f1 = fopen("c:\status.txt", "a+"); /* Flawfinder: ignore */
  1902.     fprintf(f1, "DDSurface_Blt: (%d, %d, %d, %d) -> (%d, %d, %d, %d)n", lpSourceRect->left, lpSourceRect->top, lpSourceRect->right, lpSourceRect->bottom , lpTargetRect->left, lpTargetRect->top, lpTargetRect->right, lpTargetRect->bottom);
  1903.     fclose(f1);
  1904. #endif
  1905.     
  1906.     HRESULT retVal = E_FAIL;
  1907.     
  1908.     EnterCriticalSection(&lpwd->csPrimary);
  1909.     if (!lpwd->dd.lpDDSPrimary)
  1910.     {
  1911.         WindrawSurface_CreatePrimarySurface(lpwd);
  1912.     }
  1913.     
  1914.     if (lpwd->dd.lpDDSPrimary)
  1915.     {
  1916.         try
  1917.         {
  1918.         retVal = lpwd->dd.lpDDSPrimary->Blt(&destRect, lpDDSurface, &srcRect, dwFlags, &ddBltFx);
  1919.         if (retVal != DD_OK)
  1920.         {
  1921.             lpDDSurface->Restore();
  1922.             lpwd->dd.lpDDSPrimary->Restore();
  1923.             retVal = lpwd->dd.lpDDSPrimary->Blt(&destRect, lpDDSurface, &srcRect, dwFlags, &ddBltFx);
  1924.         }
  1925.         }
  1926.         catch (...)
  1927.         {
  1928.             char szTmp[256]; /* Flawfinder: ignore */
  1929.             sprintf(szTmp, "DDSurface_Blt srcRect %ld %ld %ld %ld dstRc %ld %ld %ld %ld", /* Flawfinder: ignore */
  1930.                        lpSourceRect->left, lpSourceRect->top, lpSourceRect->right, lpSourceRect->bottom,
  1931.                        lpTargetRect->left, lpTargetRect->top, lpTargetRect->right, lpTargetRect->bottom);
  1932.             
  1933.             DumpDDInfo(lpwd, lpDDSurface, szTmp);
  1934.             retVal = HXR_FAIL;
  1935.         }
  1936.     }
  1937.     LeaveCriticalSection(&lpwd->csPrimary);
  1938.     
  1939. #ifdef _CHECK_PERFORMANCE
  1940.     QueryPerformanceCounter(&QueryPerformanceCounterResult);
  1941.     double endTime = ((double)QueryPerformanceCounterResult.LowPart + 4294967296.0*QueryPerformanceCounterResult.HighPart)/frequency;
  1942.     
  1943.     static UINT32 z_nANumTimes = 0;
  1944.     static double z_fATotalTime;
  1945.     static double z_fAAverageTime;
  1946.     
  1947.     z_nANumTimes++;
  1948.     z_fATotalTime += endTime - startTime;
  1949.     z_fAAverageTime = z_fATotalTime / (double) z_nANumTimes;
  1950.     
  1951.     if (! (z_nANumTimes % 25))
  1952.     {
  1953. FILE* f1 = ::fopen("c:\performance.txt", "a+"); /* Flawfinder: ignore */
  1954. ::fprintf(f1, "WINDRAW2 - ACTUAL BLT TIME: %d blts. Total CPU time: %f, CPU/Blt: %f -- Blt/s Second Max: %fn", z_nANumTimes, z_fATotalTime, z_fAAverageTime, 1.0/z_fAAverageTime);
  1955. fclose(f1);
  1956.     }
  1957. #endif
  1958.     
  1959.     return retVal;
  1960. }
  1961. /*
  1962. * Blits image data into the window.
  1963. * Use:
  1964. *  BOOL GDISurface_Blt (LPWINDRAW lpwd, LPGDISURFACE lpGDISurface,
  1965. *       LPRECT lpSourceRect, LPRECT lpTargetRect)
  1966. * Input:
  1967. *  lpwd - pointer to the WINDRAW structure
  1968. *  lpGDISurface - a structure containing DIBSECTION of image to blit
  1969. *  lpSourceRect - a source image region to blit
  1970. *  lpTargetRect - a target window region to fill with image
  1971. * Returns:
  1972. *  TRUE, if success; FALSE, otherwise.
  1973. */
  1974. static BOOL GDISurface_Blt (LPWINDRAW lpwd, LPGDISURFACE lpGDISurface,
  1975.     LPRECT lpSourceRect, LPRECT lpTargetRect)
  1976. {
  1977.     BOOL bResult;                   /* return value             */
  1978.     HBITMAP hOldBitmap;             /* store the old bitmap     */
  1979.     
  1980.     /* get sizes of source/destination rectangles: */
  1981.     LONG lTargetWidth  = lpTargetRect->right  - lpTargetRect->left;
  1982.     LONG lTargetHeight = lpTargetRect->bottom - lpTargetRect->top;
  1983.     LONG lSourceWidth  = lpSourceRect->right  - lpSourceRect->left;
  1984.     LONG lSourceHeight = lpSourceRect->bottom - lpSourceRect->top;
  1985.     
  1986.     /* select bitmap to blit: */
  1987.     hOldBitmap = (HBITMAP) SelectObject (lpwd->gdi.hMemoryDC, lpGDISurface->hBitMap);
  1988.     
  1989.     if (lpGDISurface->DibSection.dsBmih.biBitCount <= 8)
  1990.     {
  1991. SetDIBColorTable(lpwd->gdi.hMemoryDC, 0, nSystemColors, SystemPaletteRGB);
  1992.     }
  1993.     /* is the window the same size as the video: */
  1994.     if (lTargetWidth == lSourceWidth && lTargetHeight == lSourceHeight) {
  1995. /* put the image straight into the window: */
  1996.         bResult = BitBlt (
  1997.             lpwd->gdi.hDC,     /* target device HDC        */
  1998.             lpTargetRect->left,     /* x sink position          */
  1999.             lpTargetRect->top,      /* y sink position          */
  2000.             lTargetWidth,           /* destination width        */
  2001.             lTargetHeight,          /* destination height       */
  2002.             lpwd->gdi.hMemoryDC,    /* source device context    */
  2003.             lpSourceRect->left,     /* x source position        */
  2004.             lpSourceRect->top,      /* y source position        */
  2005.             SRCCOPY);               /* simple copy              */
  2006.     } else {
  2007.         /* stretch the image when copying to the window: */
  2008.         bResult = StretchBlt (
  2009.             lpwd->gdi.hDC,     /* target device HDC        */
  2010.             lpTargetRect->left,     /* x sink position          */
  2011.             lpTargetRect->top,      /* y sink position          */
  2012.             lTargetWidth,           /* destination width        */
  2013.             lTargetHeight,          /* destination height       */
  2014.             lpwd->gdi.hMemoryDC,    /* source device HDC        */
  2015.             lpSourceRect->left,     /* x source position        */
  2016.             lpSourceRect->top,      /* y source position        */
  2017.             lSourceWidth,           /* source width             */
  2018.             lSourceHeight,          /* source height            */
  2019.             SRCCOPY);               /* simple copy              */
  2020.     }
  2021.     /* put the old bitmap back into the device context so we don't leak */
  2022.     SelectObject (lpwd->gdi.hMemoryDC, hOldBitmap);
  2023.     /* pass the result of Bit/StretchBlt: */
  2024.     return bResult;
  2025. }
  2026. /*
  2027. * Creates a new DD surface to be used for image data.
  2028. * Use:
  2029. *   HRESULT WinDraw2_CreateDDSurface(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  2030. *    LPBMI lpImageFormat, DWORD fSurfaceType, int nBackBuffers, DWORD dwCKey);
  2031. * Input:
  2032. *  lpwd - pointer to a base WINDRAW structure
  2033. *  lpwds - pointer to a WINDRAWSURFACE structure to initialize
  2034. *  lpImageFormat - pointer to BITMAPINFO structure describing image format
  2035. *  fSurfaceType - combination of desired properties for a surface
  2036. *  nBackBuffers - number of flippable backbuffers to allocate for this surface
  2037. *  dwCKey - a color key to use (if transparent surface)
  2038. * Returns:
  2039. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  2040. */
  2041. HRESULT WinDraw2_CreateDDSurface (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  2042.   LPBMI lpImageFormat, DWORD fSurfaceType, int nBackBuffers, DWORD dwCKey)
  2043. {
  2044.    /*
  2045.     *  Are we in windraw Mode?
  2046.     */
  2047.     
  2048.     if (!(lpwd->fMode & WINDRAW_DIRECTDRAW))
  2049.         return E_INVALIDARG;
  2050.     
  2051.     /* Is the color format supported by direct draw? */
  2052.     
  2053.     unsigned int surfaceCID = GetBitmapColor((LPBITMAPINFO) lpImageFormat);
  2054.     
  2055.     int directDrawSupported = 0;
  2056.     
  2057.     for(unsigned int i = 0; i<lpwd->numCodes; i++)
  2058.     {
  2059. if (surfaceCID == lpwd->lpCID[i])
  2060. {
  2061.     directDrawSupported = 1;
  2062.     break;
  2063. }
  2064.     }
  2065.     
  2066.     /*
  2067.     if (!IsGDI(lpwds->cidSurfaceColor) && !directDrawSupported)
  2068.     return E_FAIL;
  2069.     */
  2070.     
  2071.     /* Create the surface  */
  2072.     DDSURFACEDESC ddsd;
  2073.     
  2074.     ZeroMemory(&ddsd, sizeof(ddsd));
  2075.     ddsd.dwSize = sizeof (DDSURFACEDESC);
  2076.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; 
  2077.     ddsd.dwWidth = lpImageFormat->bmiHeader.biWidth;
  2078.     ddsd.dwHeight = lpImageFormat->bmiHeader.biHeight;
  2079.     
  2080.     if (IsYUV(surfaceCID))
  2081.     {
  2082. ddsd.dwFlags |= DDSD_PIXELFORMAT;
  2083. ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  2084. SetDirectDrawColor(&ddsd.ddpfPixelFormat, surfaceCID);
  2085.     }
  2086.     /*
  2087.     *  Which type of surface was requested?
  2088.     */
  2089.     if (fSurfaceType & WINDRAWSURFACE_OVERLAY)
  2090.     {
  2091. ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY; 
  2092. if (nBackBuffers)
  2093. {
  2094.     ddsd.dwFlags     |= DDSD_BACKBUFFERCOUNT;
  2095.     ddsd.dwBackBufferCount  = nBackBuffers;
  2096.     ddsd.ddsCaps.dwCaps     = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX; 
  2097. }
  2098.     }
  2099.     else
  2100.     {
  2101. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  2102.     }
  2103.     
  2104.     /*
  2105.     * Which type of memory do you want?
  2106.     */
  2107.     if (fSurfaceType & WINDRAWSURFACE_VIDEOMEMORY)
  2108.     {
  2109. ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  2110.     }
  2111.     else if (fSurfaceType & WINDRAWSURFACE_NONLOCALVIDMEM)
  2112.     {
  2113. ddsd.ddsCaps.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
  2114.     }
  2115.     // do not specify memory type for WINDRAWSURFACE_DEFAULTMEMORY
  2116.     else if (!(fSurfaceType & WINDRAWSURFACE_DEFAULTMEMORY)) 
  2117.     {
  2118. ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  2119.     }
  2120.     int res;
  2121.     try
  2122.     {
  2123.     res = lpwd->dd.lpDD2->CreateSurface(&ddsd, &lpwds->dd.lpDDSurface, NULL);
  2124.     }
  2125.     catch (...)
  2126.     {
  2127.         char szTmp[256]; /* Flawfinder: ignore */
  2128.         sprintf(szTmp, "WinDraw2_CreateDDSurface w %ld h %ld  cid %ld bb %ld caps %lx", /* Flawfinder: ignore */
  2129.                         ddsd.dwWidth, ddsd.dwHeight, surfaceCID, nBackBuffers, ddsd.ddsCaps.dwCaps);
  2130.     
  2131.         DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, szTmp);
  2132.         res = HXR_FAIL;
  2133.     }
  2134.     if (DD_OK != res)
  2135.     {
  2136. lpwds->dd.lpDDSurface = NULL;
  2137. return E_FAIL;
  2138.     }
  2139.     
  2140.     lpwds->dwBackBufferCount = nBackBuffers;
  2141.     lpwds->fMode = WINDRAWSURFACE_OPENED | fSurfaceType;
  2142.     lpwds->cidSurfaceColor = surfaceCID;
  2143.     memcpy(&lpwds->bmiSurfaceFormat, lpImageFormat, sizeof(BMI)); /* Flawfinder: ignore */
  2144.     
  2145.     /* check to see if we have an attached surface */
  2146.     lpwds->dd.lpDDBackBuffer = NULL; /* just in case !! */
  2147.     if (nBackBuffers)
  2148.     {
  2149.         DDSCAPS ddscaps;
  2150.         ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  2151.         // Build flipping chain - set surfaces
  2152.         lpwds->dd.lpChain = new ENUMSURFACE[nBackBuffers+1];
  2153.         lpwds->dwFrontBuffer = 0;
  2154.         lpwds->dwNextBuffer = 1;
  2155.         lpwds->hOverlayIndexMutex = CreateMutex(NULL, FALSE, NULL);
  2156.         lpwds->hOverlayMutex = CreateMutex(NULL, FALSE, NULL);
  2157.         lpwds->dd.hAbort = CreateEvent(NULL, TRUE, FALSE, NULL);
  2158.         lpwds->dd.lpChain[0].lpSurface = lpwds->dd.lpDDSurface;
  2159.         lpwds->dd.lpDDSurface->GetAttachedSurface(&ddscaps, &lpwds->dd.lpDDBackBuffer);
  2160.         lpwds->dd.lpDDBackBuffer->Release();
  2161.         if (nBackBuffers > 1)
  2162.         {
  2163.             for (int i=1; i<nBackBuffers+1; i++)
  2164.             {
  2165.                 lpwds->dd.lpChain[i-1].lpSurface->EnumAttachedSurfaces((void*)&lpwds->dd.lpChain[i].lpSurface, EnumSurfacesCallback);
  2166.             }
  2167.         }
  2168.         else
  2169.         {
  2170.             lpwds->dd.lpChain[1].lpSurface = lpwds->dd.lpDDBackBuffer;
  2171.         }
  2172.         // Build flipping chain - set hw mem locations
  2173.         for (int i=0; i<nBackBuffers+1; i++)
  2174.         {
  2175.             memset(&ddsd, 0, sizeof(ddsd));
  2176.             ddsd.dwSize = sizeof(ddsd);
  2177.             lpwds->dd.lpChain[i].hEmpty = CreateEvent(NULL, TRUE, TRUE, NULL);
  2178.             lpwds->dd.lpChain[i].pHwMemBuffer = NULL;
  2179.             lpwds->dd.lpChain[i].dTimeAvailable = 0.0;
  2180.         }
  2181.     }
  2182.     
  2183.     lpwd->m_pSurfaceList->AddTail(lpwds);
  2184.     WinDraw2_OnPaletteChange(lpwd, lpwd->hWnd, WM_PALETTECHANGED);
  2185.     
  2186.     // Store the default cc values
  2187.     memset(&lpwds->dd.ddcc, 0, sizeof(lpwds->dd.ddcc));
  2188.     lpwds->dd.ddcc.dwSize = sizeof(lpwds->dd.ddcc);
  2189.     
  2190.     IDirectDrawColorControl *pcc = NULL;
  2191.     res = NOERROR;
  2192.     try
  2193.     {
  2194.     lpwds->dd.lpDDSurface->QueryInterface(IID_IDirectDrawColorControl, (void**)&pcc);
  2195.     if (pcc)
  2196.     {
  2197.         pcc->GetColorControls(&lpwds->dd.ddcc);
  2198.         pcc->Release();
  2199.     }
  2200.     }
  2201.     catch (...)
  2202.     {
  2203.         char szTmp[256]; /* Flawfinder: ignore */
  2204.         sprintf(szTmp, "WinDraw2_CreateDDSurface w %ld h %ld  cid %ld bb %ld caps %lx", /* Flawfinder: ignore */
  2205.                         ddsd.dwWidth, ddsd.dwHeight, surfaceCID, nBackBuffers, ddsd.ddsCaps.dwCaps);
  2206.         
  2207.         DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, szTmp);
  2208.         
  2209.         HX_RELEASE(pcc);
  2210.         memset(&lpwds->dd.ddcc, 0, sizeof(lpwds->dd.ddcc));
  2211.     }
  2212.     return res;
  2213. }
  2214. HRESULT WinDraw2_SetColorKey (LPWINDRAW lpwd, DWORD dwLowColor, DWORD dwHighColor)
  2215. {
  2216.     HRESULT hr = E_FAIL;
  2217.     if (lpwd == NULL)
  2218.     {
  2219.         HX_ASSERT(0);
  2220.         return E_INVALIDARG;
  2221.     }
  2222.     if (lpwd->fMode & WINDRAW_DIRECTDRAW)
  2223.     {
  2224.         DDCOLORKEY ddColorKey;
  2225.         /* convert color key values: */
  2226.         ddColorKey.dwColorSpaceLowValue  = dwLowColor;
  2227.         ddColorKey.dwColorSpaceHighValue = dwHighColor;
  2228.         EnterCriticalSection(&lpwd->csPrimary);
  2229.         /* set color key: */
  2230.         if (lpwd->dd.lpDDSPrimary)
  2231.         {
  2232.     try
  2233.             {
  2234.             hr = lpwd->dd.lpDDSPrimary->SetColorKey(DDCKEY_DESTOVERLAY, &ddColorKey);
  2235.             }
  2236.             catch(...)
  2237.             {
  2238.                 DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "WinDraw2_SetColorKey");
  2239.                 hr = HXR_FAIL;
  2240.             }
  2241.         }
  2242.         LeaveCriticalSection(&lpwd->csPrimary);
  2243.     }
  2244.     return hr;
  2245. }
  2246. HRESULT WinDraw2_SetOverlayPosition(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds, UINT32 x, UINT32 y)
  2247. {
  2248.     HRESULT hr = E_FAIL;
  2249.     if (lpwd == NULL)
  2250.     {
  2251.         HX_ASSERT(0);
  2252.         return E_INVALIDARG;
  2253.     }
  2254.     
  2255.     if (lpwds->fMode & WINDRAWSURFACE_OPENED && lpwds->fMode & WINDRAWSURFACE_OVERLAY)
  2256.     {
  2257.         try
  2258.         {
  2259.         hr = lpwds->dd.lpDDSurface->SetOverlayPosition(x,y);
  2260.         }
  2261.         catch(...)
  2262.         {
  2263.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDraw2_SetOverlayPosition");
  2264.             hr = HXR_FAIL;
  2265.         }
  2266.     }
  2267.     return hr;
  2268. }
  2269. HRESULT WinDraw2_UpdateOverlay(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds, RECT* pDestRect, RECT* pSrcRect, DWORD flags)
  2270. {
  2271. //      {
  2272. //          char szBuff[256];
  2273. //          sprintf( szBuff,"UpdateOverlay src (%d, %d)-(%d, %d)  dest(%d, %d)-(%d, %d) flags: %pn",
  2274. //                   pSrcRect->left,
  2275. //                   pSrcRect->top,
  2276. //                   pSrcRect->right,
  2277. //                   pSrcRect->bottom,
  2278. //                   pDestRect->left,
  2279. //                   pDestRect->top,
  2280. //                   pDestRect->right,
  2281. //                   pDestRect->bottom, 
  2282. //    flags
  2283. //                   );
  2284. //          _DumpString(szBuff);
  2285. //      } 
  2286.     if ((lpwd == NULL) | (lpwds == NULL))
  2287.     {
  2288.         HX_ASSERT(0);
  2289.         return E_INVALIDARG;
  2290.     }
  2291.     
  2292.     if (lpwds->fMode & WINDRAWSURFACE_OPENED && lpwds->fMode & WINDRAWSURFACE_OVERLAY)
  2293.     {
  2294.         EnterCriticalSection(&lpwd->csPrimary);
  2295.         HRESULT res;
  2296.         try
  2297.         {
  2298.         if (lpwds->dd.lpDDSurface)
  2299.         {
  2300.             res = lpwds->dd.lpDDSurface->UpdateOverlay(pSrcRect, lpwd->dd.lpDDSPrimary, pDestRect, flags, NULL);
  2301.             if (DDERR_SURFACELOST == res)
  2302.             {
  2303.                 res = RestoreSurfaces(lpwd, lpwds);
  2304.                 if (res == DD_OK)
  2305.                 {
  2306.                     lpwds->dd.lpDDSurface->UpdateOverlay(pSrcRect, lpwd->dd.lpDDSPrimary, pDestRect, flags, NULL);
  2307.                     // Let caller know we lost our surfaces
  2308.                     res = DDERR_SURFACELOST;
  2309.                 }
  2310.             }
  2311.         }
  2312.         }
  2313.         catch(...)
  2314.         {
  2315.             char szTmp[256]; /* Flawfinder: ignore */
  2316.             sprintf(szTmp, "WinDraw2_UpdateOverlay srcRect %ld %ld %ld %ld dstRc %ld %ld %ld %ld", /* Flawfinder: ignore */
  2317.                            pSrcRect->left, pSrcRect->top, pSrcRect->right, pSrcRect->bottom,
  2318.                            pDestRect->left, pDestRect->top, pDestRect->right, pDestRect->bottom);
  2319.             
  2320.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, szTmp);
  2321.             res = HXR_FAIL;
  2322.         }
  2323.         LeaveCriticalSection(&lpwd->csPrimary);
  2324.         return res;
  2325.     }
  2326.     return E_FAIL;
  2327. }
  2328. HRESULT WinDraw2_GetOverlayPosition(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds, POINT* pLocation)
  2329. {
  2330.     HRESULT hr = E_FAIL;
  2331.     if ((lpwd == NULL) | (lpwds == NULL))
  2332.     {
  2333.         HX_ASSERT(0);
  2334.         return E_INVALIDARG;
  2335.     }
  2336.     
  2337.     if (lpwds->fMode & WINDRAWSURFACE_OPENED && lpwds->fMode & WINDRAWSURFACE_OVERLAY)
  2338.     {
  2339. try
  2340.         {
  2341.         hr = lpwds->dd.lpDDSurface->GetOverlayPosition((LONG*) &pLocation->x, (LONG*) &pLocation->y);
  2342.         }
  2343.         catch(...)
  2344.         {
  2345.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDraw2_GetOverlayPosition");
  2346.             hr = HXR_FAIL;
  2347.         }
  2348.     }
  2349.     return hr;
  2350. }
  2351. BOOL WinDraw2_IsSurfaceVisible(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds)
  2352. {
  2353.     if ((lpwd == NULL) | (lpwds == NULL))
  2354.     {
  2355.         HX_ASSERT(0);
  2356.         return E_INVALIDARG;
  2357.     }
  2358.     
  2359.     if (lpwds->fMode & WINDRAWSURFACE_OPENED && 
  2360.         lpwds->fMode & WINDRAWSURFACE_OVERLAY &&
  2361.         lpwds->dd.lpDDSurface)
  2362.     {
  2363. DDSCAPS ddcaps;
  2364. memset(&ddcaps, 0, sizeof(DDSCAPS));
  2365. try
  2366.         {
  2367.         lpwds->dd.lpDDSurface->GetCaps(&ddcaps);
  2368.         }
  2369.         catch(...)
  2370.         {
  2371.             DumpDDInfo(lpwd, lpwds->dd.lpDDSurface, "WinDraw2_IsSurfaceVisible");
  2372.             return FALSE;
  2373.         }
  2374.         if (DDSCAPS_VISIBLE & ddcaps.dwCaps)
  2375. {
  2376.     return TRUE;
  2377. }
  2378.     }
  2379.     return FALSE;
  2380. }
  2381. BOOL WinDraw2_IsDDAvailable(LPWINDRAW lpwd)
  2382. {
  2383.     if (lpwd &&
  2384.         lpwd->fMode & WINDRAW_OPENED && 
  2385.         lpwd->fMode & WINDRAW_DIRECTDRAW &&
  2386.         lpwd->dd.lpDD2)
  2387.     {
  2388.         BOOL bRet = TRUE;
  2389.         
  2390. #if DIRECTDRAW_VERSION > 0x0500        
  2391.         IDirectDraw4 *pDD4 = NULL;
  2392.         lpwd->dd.lpDD2->QueryInterface(IID_IDirectDraw4, (void**)&pDD4);
  2393.         // First, check if another app has DD in exclusive mode
  2394.         if (pDD4)
  2395.         {
  2396.             try
  2397.             {
  2398.             HRESULT hr = pDD4->TestCooperativeLevel();
  2399.             bRet = !(hr == DDERR_EXCLUSIVEMODEALREADYSET);
  2400.             }
  2401.             catch(...)
  2402.             {
  2403.                 DumpDDInfo(lpwd, lpwd->dd.lpDDSPrimary, "WinDraw2_IsDDAvailable");
  2404.                 bRet = TRUE;
  2405.             }
  2406.             pDD4->Release();
  2407.         }
  2408. #endif //DIRECTDRAW_VERSION > 0x0500
  2409.         // Check if we have hardware assisted blitting
  2410.         if (bRet)
  2411.         {
  2412.             UINT32  ulCaps = 0,
  2413.                     ulTemp;
  2414.             if (HXR_OK == Windraw_GetCaps(lpwd, &ulCaps, &ulTemp, &ulTemp))
  2415.                 bRet = (ulCaps & HX_OVERLAY | ulCaps & HX_BLTFOURCC);
  2416.         }
  2417.         return bRet;
  2418.     }
  2419.     
  2420.     return FALSE;
  2421. }
  2422. /*
  2423. * Creates a new GDI surface to be used for image data.
  2424. * Use:
  2425. *   HRESULT WinDraw2_CreateGDISurface(LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  2426. *    LPBMI lpImageFormat, DWORD fSurfaceType, int nBackBuffers, DWORD dwCKey);
  2427. * Input:
  2428. *  lpwd - pointer to a base WINDRAW structure
  2429. *  lpwds - pointer to a WINDRAWSURFACE structure to initialize
  2430. *  lpImageFormat - pointer to BITMAPINFO structure describing image format
  2431. *  fSurfaceType - combination of desired properties for a surface
  2432. *  nBackBuffers - number of flippable backbuffers to allocate for this surface
  2433. *  dwCKey - a color key to use (if transparent surface)
  2434. * Returns:
  2435. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  2436. */
  2437. HRESULT WinDraw2_CreateGDISurface (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  2438.    LPBMI lpImageFormat, DWORD fSurfaceType, int nBackBuffers, DWORD dwCKey)
  2439. {
  2440.     int i;
  2441.     
  2442.     if (lpwd->fMode & WINDRAW_DIRECTDRAW)
  2443.         return E_INVALIDARG;
  2444.     
  2445.     /* check if surface of given color format can be created: */
  2446.     if (!IsGDI(lpwds->cidSurfaceColor))
  2447.         return E_FAIL;
  2448.     
  2449.     /* allocate GDI surfaces: */
  2450.     for (i=0; i<=(int)lpwds->dwBackBufferCount; i++) 
  2451.     {
  2452.         LPGDISURFACE lpgdis;
  2453.         /* allocate a new surface: */
  2454.         if ((lpgdis = GDISurface_Alloc ((LPBITMAPINFO)lpImageFormat)) == NULL)
  2455.             goto release_buffers;
  2456.         /* store pointer to a new surface */
  2457.         lpwds->gdi.lpGDIBackBuffer [i] = lpgdis;
  2458.     }
  2459.     
  2460.     /* store surface parameters & exit: */
  2461.     lpwds->fMode |= WINDRAWSURFACE_OPENED;
  2462.     lpwds->gdi.lPitch = GetBitmapPitch ((LPBITMAPINFO)lpImageFormat);
  2463.     lpwd->m_pSurfaceList->AddTail(lpwds);
  2464.     WinDraw2_OnPaletteChange(lpwd, lpwd->hWnd, WM_PALETTECHANGED);
  2465.     return NOERROR;
  2466.     
  2467. release_buffers:
  2468.     /* release GDI buffers: */
  2469.     for ( i--; i>=0; i--) 
  2470.     {
  2471.         if (lpwds->gdi.lpGDIBackBuffer [i] != NULL) 
  2472. {
  2473.             GDISurface_Free(lpwds->gdi.lpGDIBackBuffer [i]);
  2474.             lpwds->gdi.lpGDIBackBuffer [i] = NULL;
  2475.         }
  2476.     }
  2477.     
  2478.     return E_FAIL;
  2479. }
  2480. /*
  2481. * Creates a new surface to be used for image data.
  2482. * Use:
  2483. *   HRESULT WinDraw2_CreateSurface (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  2484. *    LPBMI lpImageFormat, DWORD fSurfaceType, int nBackBuffers, DWORD dwCKey);
  2485. * Input:
  2486. *  lpwd - pointer to a base WINDRAW structure
  2487. *  lpwds - pointer to a WINDRAWSURFACE structure to initialize
  2488. *  lpImageFormat - pointer to BITMAPINFO structure describing image format
  2489. *  fSurfaceType - combination of desired properties for a surface
  2490. *  nBackBuffers - number of flippable backbuffers to allocate for this surface
  2491. *  dwCKey - a color key to use (if transparent surface)
  2492. * Returns:
  2493. *  NOERROR if OK, or the last relevant DirectDraw error code, or E_FAIL.
  2494. */
  2495. HRESULT WinDraw2_CreateSurface (LPWINDRAW lpwd, LPWINDRAWSURFACE lpwds,
  2496. LPBMI lpImageFormat, DWORD fSurfaceType, int nBackBuffers, DWORD dwCKey)
  2497. {
  2498.     int sz;
  2499.     
  2500.     /* check parameters: */