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

Symbian

开发平台:

Visual C++

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