/branches/jet3d_dev_msvc2005/source/Engine/JetEngine/Engine/Drivers/D3DDrv/D3D_MAIN.CPP

# · C++ · 2305 lines · 1526 code · 490 blank · 289 comment · 326 complexity · 6c63ed5225e177f79a42c03674970eba MD5 · raw file

  1. /****************************************************************************************/
  2. /* D3D_Main.cpp */
  3. /* */
  4. /* Author: John Pollard */
  5. /* Description: DD/D3D wrapper */
  6. /* */
  7. /* The contents of this file are subject to the Jet3D Public License */
  8. /* Version 1.01 (the "License"); you may not use this file except in */
  9. /* compliance with the License. You may obtain a copy of the License at */
  10. /* http://www.jet3d.com */
  11. /* */
  12. /* Software distributed under the License is distributed on an "AS IS" */
  13. /* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See */
  14. /* the License for the specific language governing rights and limitations */
  15. /* under the License. */
  16. /* */
  17. /* The Original Code is Jet3D, released December 12, 1999. */
  18. /* Copyright (C) 1996-1999 Eclipse Entertainment, L.L.C. All Rights Reserved */
  19. /* */
  20. /****************************************************************************************/
  21. #include <Windows.h>
  22. #include <Assert.h>
  23. #include <stdio.h>
  24. #include <DDraw.h>
  25. #include <D3D.h>
  26. #include <Math.h>
  27. #include "D3D_Main.h"
  28. #include "D3D_Err.h"
  29. #include "D3D_fx.h"
  30. #include "d3dcache.h"
  31. #include "d3d_Render.h"
  32. #include "D3DCache.h"
  33. #include "d3d_THandle.h"
  34. #include "d3d_PCache.h"
  35. #include "d3d_scene.h"
  36. #include "D3DDrv.h"
  37. #undef ATTEMPT
  38. #define ATTEMPT(x) if (!(x)) goto exit_with_error
  39. #undef RELEASE
  40. #define RELEASE(x) if (x) { x->Release(); x = NULL; }
  41. //================================================================================
  42. // Globals
  43. //================================================================================
  44. D3DMain_GlobalInfo D3DInfo; // Our global structure that knows all... (once initialized)
  45. #define MAX_DRIVERS 64
  46. typedef struct
  47. {
  48. jeBoolean IsPrimary;
  49. GUID Guid;
  50. char Name[MAX_DRIVER_NAME];
  51. } D3DMain_DDEnum;
  52. typedef struct
  53. {
  54. int32 NumDrivers;
  55. D3DMain_DDEnum *Drivers;
  56. } D3DMain_DDEnumInfo;
  57. static D3DMain_DDEnum Drivers[MAX_DRIVERS];
  58. //================================================================================
  59. // Local static functions
  60. //================================================================================
  61. static BOOL D3DMain_CreateD3D(void);
  62. static BOOL D3DMain_EnumDevices(void);
  63. static BOOL D3DMain_ClearBuffers(void);
  64. static BOOL OutputDriverInfo(const char *Filename, DDMain_D3DDriver *Driver);
  65. static BOOL D3DMain_RememberOldMode(HWND hWnd);
  66. static BOOL D3DMain_SetDisplayMode(HWND hWnd, int w, int h, int bpp, BOOL FullScreen);
  67. static BOOL D3DMain_PickDevice(void);
  68. static BOOL D3DMain_CreateDevice(void);
  69. static BOOL D3DMain_CreateBuffers(void);
  70. static void D3DMain_DestroyBuffers(void);
  71. static BOOL D3DMain_CreateZBuffer(void);
  72. static void D3DMain_DestroyZBuffer(void);
  73. static jeBoolean D3DMain_SetDefaultRenderStates(void);
  74. static BOOL D3DMain_RestoreDisplayMode(void);
  75. static BOOL D3DMain_CreateDDFromName(const char *DriverName);
  76. static jeBoolean CreateDDFromDriver(D3DMain_DDEnum *pDriver);
  77. static jeBoolean CreateDDFromName(const char *DriverName, const D3DMain_DDEnumInfo *Info);
  78. static uint32 Log2(uint32 P2);
  79. static int32 SnapToPower2(int32 Width);
  80. //static int32 GetLog(int32 Width, int32 Height);
  81. BOOL D3DMain_RestoreAllSurfaces(void)
  82. {
  83. HRESULT ddrval;
  84. #ifdef _DEBUG
  85. OutputDebugString("--- D3DMain_RestoreAllSurfaces ---\n");
  86. #endif
  87. if (D3DInfo.lpDD)
  88. {
  89. if (!D3DMain_SetDisplayMode(D3DInfo.hWnd, D3DInfo.CurrentWidth, D3DInfo.CurrentHeight, D3DInfo.CurrentBpp, D3DInfo.FullScreen))
  90. return FALSE;
  91. // Restore all the surfaces
  92. ddrval = D3DInfo.lpDD->RestoreAllSurfaces();
  93. if(ddrval!=DD_OK)
  94. {
  95. D3DMain_Log("D3DMain_RestoreAllSurfaces: D3DInfo.lpDD->RestoreAllSurfaces() failed:\n %s\n", D3DErrorToString(ddrval));
  96. return FALSE;
  97. }
  98. }
  99. if ( ! THandle_EvictAll() )
  100. return FALSE;
  101. return TRUE;
  102. }
  103. //================================================================================
  104. // BPPToDDBD
  105. // Convert an integer bit per pixel number to a DirectDraw bit depth flag
  106. //================================================================================
  107. static DWORD BPPToDDBD(int bpp)
  108. {
  109. switch(bpp)
  110. {
  111. case 1:
  112. return DDBD_1;
  113. case 2:
  114. return DDBD_2;
  115. case 4:
  116. return DDBD_4;
  117. case 8:
  118. return DDBD_8;
  119. case 16:
  120. return DDBD_16;
  121. case 24:
  122. return DDBD_24;
  123. case 32:
  124. return DDBD_32;
  125. default:
  126. assert(!"BOGUS bpp");
  127. }
  128. return DDBD_1; // Shutup compiler warning
  129. }
  130. //================================================================================
  131. // D3DMain_InitD3D
  132. // Does all what is needed to get an app ready to go at a specified with height
  133. // NOTE - It only makes 16 bit modes availible
  134. //================================================================================
  135. BOOL D3DMain_InitD3D(HWND hWnd, const char *DriverName, int32 Width, int32 Height)
  136. {
  137. SYSTEMTIME Time;
  138. memset(&D3DInfo, 0, sizeof(D3DMain_GlobalInfo));
  139. memset(Drivers, 0, sizeof(Drivers));
  140. GetSystemTime(&Time);
  141. //unlink(D3DMAIN_LOG_FILENAME);
  142. D3DMain_Log("=================================================================\n");
  143. D3DMain_Log(" D3DInfo v%i.%i\n", DRV_VERSION_MAJOR, DRV_VERSION_MINOR);
  144. D3DMain_Log(" Build Date: "__DATE__", Time: "__TIME__"\n");
  145. D3DMain_Log("=================================================================\n\n");
  146. D3DMain_Log("Current Time: %2i:%2i:%2i\n", Time.wHour, Time.wMinute, Time.wSecond);
  147. D3DMain_Log("Current Date: %2i-%2i-%4i\n", Time.wMonth, Time.wDay, Time.wYear);
  148. D3DMain_Log("\n ** D3D Driver Initializing **\n\n");
  149. D3DInfo.hWnd = hWnd;
  150. // Create DD
  151. ATTEMPT(D3DMain_CreateDDFromName(DriverName));
  152. ATTEMPT(D3DMain_GetTextureMemory());
  153. // We must do this after the DD object is created!!!
  154. ATTEMPT(D3DMain_RememberOldMode(hWnd)); // Store old mode
  155. // Get available fullscreen display modes
  156. ATTEMPT(D3DMain_EnumDisplayModes());
  157. // Create D3D, and enum it's devices
  158. ATTEMPT(D3DMain_CreateD3D());
  159. ATTEMPT(D3DMain_EnumDevices());
  160. if (Width == -1 && Height == -1) // Window Mode
  161. {
  162. // Force Width/Height to client window area size
  163. Width = D3DInfo.OldWindowWidth;
  164. Height = D3DInfo.OldWindowHeight;
  165. ATTEMPT(D3DMain_SetDisplayMode(hWnd, Width, Height, D3DInfo.OldBpp, FALSE));
  166. }
  167. else
  168. {
  169. ATTEMPT(D3DMain_SetDisplayMode(hWnd, Width, Height, 16, TRUE));
  170. }
  171. // Pick a device we will be happy with
  172. ATTEMPT(D3DMain_PickDevice());
  173. // Create front/back buffer
  174. ATTEMPT(D3DMain_CreateBuffers());
  175. // For some reason, we have to create the zbuffer BEFORE the device??? Why???
  176. ATTEMPT(D3DMain_CreateZBuffer());
  177. // Create the device
  178. ATTEMPT(D3DMain_CreateDevice());
  179. // Get the surface formats for textures, and 2d surfaces
  180. ATTEMPT(D3DMain_GetSurfaceFormats());
  181. #if 1
  182. D3DInfo.CanDoMultiTexture = (D3DInfo.Drivers[D3DInfo.CurrentDriver].MaxSimultaneousTextures > 1) ? JE_TRUE : JE_FALSE;
  183. #else
  184. D3DInfo.CanDoMultiTexture = JE_FALSE;
  185. #endif
  186. D3DMain_Log("--- D3DMain_SetRenderState --- \n");
  187. ATTEMPT(D3DMain_SetDefaultRenderStates());
  188. D3DInfo.RenderingIsOK = TRUE;
  189. ATTEMPT(D3DMain_ClearBuffers());
  190. ATTEMPT(D3DMain_GetTextureMemory());
  191. if (!THandle_Startup())
  192. return JE_FALSE;
  193. D3DMain_Log("\n ** Initialization was successful **\n\n");
  194. return TRUE;
  195. exit_with_error:;
  196. D3DMain_Log(" ** Initialization was NOT successful **\n");
  197. D3DMain_ShutdownD3D();
  198. return FALSE;
  199. }
  200. //================================================================================
  201. // D3DMain_ShutdownD3D
  202. //================================================================================
  203. BOOL D3DMain_ShutdownD3D(void)
  204. {
  205. D3DMain_Log("\n--- D3DMain_ShutdownD3D ---\n");
  206. THandle_Shutdown();
  207. // Destroys all objects including Direct Draw.
  208. D3DInfo.RenderingIsOK = FALSE;
  209. RELEASE(D3DInfo.lpD3DDevice);
  210. if (D3DInfo.lpZBuffer)
  211. {
  212. assert(D3DInfo.lpBackBuffer);
  213. D3DInfo.lpBackBuffer->DeleteAttachedSurface(0, D3DInfo.lpZBuffer);
  214. RELEASE(D3DInfo.lpZBuffer);
  215. }
  216. if (D3DInfo.lpFrontBuffer)
  217. D3DInfo.lpFrontBuffer->SetClipper(NULL);
  218. RELEASE(D3DInfo.lpClipper);
  219. RELEASE(D3DInfo.lpBackBuffer);
  220. RELEASE(D3DInfo.lpFrontBuffer);
  221. D3DMain_RestoreDisplayMode();
  222. RELEASE(D3DInfo.lpD3D);
  223. RELEASE(D3DInfo.lpDD);
  224. memset(&D3DInfo, 0, sizeof(D3DMain_GlobalInfo));
  225. D3DMain_Log(" Shutdown was successful...\n\n");
  226. return TRUE;
  227. }
  228. //================================================================================
  229. //================================================================================
  230. jeBoolean D3DMain_Reset(void)
  231. {
  232. D3DMain_Log("\n--- D3DMain_Reset ---\n");
  233. THandle_Shutdown();
  234. PCache_Reset();
  235. if (!THandle_Startup())
  236. return JE_FALSE;
  237. Scene_CurrentFrame = 0;
  238. return JE_TRUE;
  239. }
  240. //================================================================================
  241. // D3DMain_Log
  242. //================================================================================
  243. void D3DMain_Log(LPSTR Str, ... )
  244. {
  245. char Buffer[2048];
  246. FILE *f;
  247. wvsprintf(Buffer, Str, (char*)(&Str+1));
  248. f = fopen(D3DMAIN_LOG_FILENAME, "a+t");
  249. if (!f)
  250. return;
  251. fprintf(f, "%s", Buffer);
  252. fclose(f);
  253. }
  254. //================================================================================
  255. // CompareModes
  256. //================================================================================
  257. static int CompareModes(const void* element1, const void* element2)
  258. {
  259. App_Mode *lpMode1, *lpMode2;
  260. lpMode1 = (App_Mode*)element1;
  261. lpMode2 = (App_Mode*)element2;
  262. if (lpMode1->Bpp > lpMode2->Bpp)
  263. return -1;
  264. else if (lpMode2->Bpp > lpMode1->Bpp)
  265. return 1;
  266. else if (lpMode1->Width > lpMode2->Width)
  267. return -1;
  268. else if (lpMode2->Width > lpMode1->Width)
  269. return 1;
  270. else if (lpMode1->Height > lpMode2->Height)
  271. return -1;
  272. else if (lpMode2->Height > lpMode1->Height)
  273. return 1;
  274. else
  275. return 0;
  276. }
  277. //================================================================================
  278. // EnumDisplayModesCallback
  279. //================================================================================
  280. static HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC2 pddsd, LPVOID lpContext)
  281. {
  282. App_Mode *pMode;
  283. if (!pddsd)
  284. return DDENUMRET_OK;
  285. /** <> CB; nyet!
  286. if (pddsd->dwWidth > 1024 || pddsd->dwHeight > 768)
  287. return DDENUMRET_OK;
  288. **/
  289. if (pddsd->dwWidth > 2048 || pddsd->dwHeight > 1024)
  290. return DDENUMRET_OK;
  291. if (D3DInfo.NumModes >= MAX_APP_MODES)
  292. return DDENUMRET_CANCEL;
  293. pMode = &D3DInfo.Modes[D3DInfo.NumModes++];
  294. // Save this mode at the end of the mode array and increment mode count
  295. pMode->Width = pddsd->dwWidth;
  296. pMode->Height = pddsd->dwHeight;
  297. pMode->Bpp = pddsd->ddpfPixelFormat.dwRGBBitCount;
  298. pMode->ThisDriverCanDo = FALSE;
  299. return DDENUMRET_OK;
  300. }
  301. //================================================================================
  302. // D3DMain_EnumDisplayModes
  303. //================================================================================
  304. BOOL D3DMain_EnumDisplayModes(void)
  305. {
  306. HRESULT LastError;
  307. D3DMain_Log("--- D3DMain_EnumDisplayModes ---\n");
  308. // Get a list of available display modes from DirectDraw
  309. D3DInfo.NumModes = 0;
  310. LastError = D3DInfo.lpDD->EnumDisplayModes(0, NULL, 0, EnumDisplayModesCallback);
  311. if(LastError != DD_OK )
  312. {
  313. D3DMain_Log("EnumDisplayModes failed.\n %s\n", D3DErrorToString(LastError));
  314. D3DInfo.NumModes = 0;
  315. return FALSE;
  316. }
  317. // Sort the list of display modes
  318. qsort((void *)&D3DInfo.Modes[0], (size_t)D3DInfo.NumModes, sizeof(App_Mode), CompareModes);
  319. return TRUE;
  320. }
  321. //================================================================================
  322. // D3DMain_CreateD3D
  323. //================================================================================
  324. static BOOL D3DMain_CreateD3D(void)
  325. {
  326. HRESULT LastError;
  327. assert(D3DInfo.lpDD);
  328. D3DMain_Log("--- D3DMain_CreateD3D ---\n");
  329. LastError = D3DInfo.lpDD->QueryInterface(IID_IDirect3D7, (LPVOID*)&D3DInfo.lpD3D);
  330. if (LastError != DD_OK)
  331. {
  332. D3DMain_Log("Creation of IDirect3D7 failed.\n %s\n", D3DErrorToString(LastError));
  333. goto exit_with_error;
  334. }
  335. return TRUE;
  336. exit_with_error:
  337. return FALSE;
  338. }
  339. /*
  340. #define MUST_BLEND (D3DPBLENDCAPS_BOTHINVSRCALPHA | \
  341. D3DPBLENDCAPS_BOTHSRCALPHA | \
  342. D3DPBLENDCAPS_DESTALPHA | \
  343. D3DPBLENDCAPS_DESTCOLOR | \
  344. D3DPBLENDCAPS_INVDESTALPHA | \
  345. D3DPBLENDCAPS_INVDESTCOLOR | \
  346. D3DPBLENDCAPS_INVSRCALPHA | \
  347. D3DPBLENDCAPS_INVSRCCOLOR | \
  348. D3DPBLENDCAPS_ONE | \
  349. D3DPBLENDCAPS_SRCALPHA | \
  350. D3DPBLENDCAPS_SRCALPHASAT | \
  351. D3DPBLENDCAPS_SRCCOLOR | \
  352. D3DPBLENDCAPS_ZERO)
  353. */
  354. #if 0
  355. #define MUST_BLEND_SRC (D3DPBLENDCAPS_SRCALPHA | \
  356. D3DPBLENDCAPS_INVSRCALPHA | \
  357. D3DPBLENDCAPS_DESTCOLOR | \
  358. D3DPBLENDCAPS_ONE | \
  359. D3DPBLENDCAPS_ZERO)
  360. #define MUST_BLEND_DEST (D3DPBLENDCAPS_SRCALPHA | \
  361. D3DPBLENDCAPS_INVSRCALPHA | \
  362. D3DPBLENDCAPS_SRCCOLOR | \
  363. D3DPBLENDCAPS_ONE | \
  364. D3DPBLENDCAPS_ZERO)
  365. #else
  366. #define MUST_BLEND_SRC (D3DPBLENDCAPS_SRCALPHA | \
  367. D3DPBLENDCAPS_DESTCOLOR | \
  368. D3DPBLENDCAPS_ONE | \
  369. D3DPBLENDCAPS_ZERO)
  370. #define MUST_BLEND_DEST (D3DPBLENDCAPS_INVSRCALPHA | \
  371. D3DPBLENDCAPS_ONE | \
  372. D3DPBLENDCAPS_ZERO)
  373. #endif
  374. //================================================================================
  375. // D3DEnumDevicesCallback7
  376. //================================================================================
  377. static HRESULT CALLBACK D3DEnumDevicesCallback7(
  378. LPSTR lpDeviceDescription,
  379. LPSTR lpDeviceName,
  380. LPD3DDEVICEDESC7 lpD3DDeviceDesc,
  381. LPVOID lpContext)
  382. {
  383. DDMain_D3DDriver *Driver;
  384. BOOL Good;
  385. if (!lpDeviceDescription || !lpDeviceName || !lpD3DDeviceDesc)
  386. return (D3DENUMRET_OK);
  387. if (strlen(lpDeviceDescription) >= MAX_DRIVER_NAME)
  388. return (D3DENUMRET_OK);
  389. if (strlen(lpDeviceName) >= MAX_DRIVER_NAME)
  390. return (D3DENUMRET_OK);
  391. if (D3DInfo.NumDrivers >= DDMAIN_MAX_D3D_DRIVERS)
  392. return (D3DENUMRET_CANCEL);
  393. if (!memcmp(&lpD3DDeviceDesc->deviceGUID, &IID_IDirect3DRGBDevice, sizeof (GUID)))
  394. return D3DENUMRET_OK; // We only want HW devices
  395. lpContext = lpContext;
  396. Good = TRUE;
  397. D3DInfo.CurrentDriver = D3DInfo.NumDrivers;
  398. Driver = &D3DInfo.Drivers[D3DInfo.NumDrivers];
  399. // Record the D3D driver's inforamation
  400. memcpy(&Driver->Guid, &lpD3DDeviceDesc->deviceGUID, sizeof(GUID));
  401. lstrcpy(Driver->About, lpDeviceDescription);
  402. lstrcpy(Driver->Name, lpDeviceName);
  403. memcpy(&Driver->Desc, lpD3DDeviceDesc, sizeof(D3DDEVICEDESC7));
  404. Driver->IsHardware = TRUE;
  405. Driver->MaxTextureBlendStages = lpD3DDeviceDesc->wMaxTextureBlendStages;
  406. Driver->MaxSimultaneousTextures = lpD3DDeviceDesc->wMaxSimultaneousTextures;
  407. if (!(lpD3DDeviceDesc->dwDeviceZBufferBitDepth))
  408. Good = FALSE;
  409. else
  410. Driver->DoesZBuffer = TRUE;
  411. if (!(lpD3DDeviceDesc->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE))
  412. Good = FALSE;
  413. else
  414. Driver->DoesTextures = TRUE;
  415. // Skip if it does not support alpha blending
  416. if (!(lpD3DDeviceDesc->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_ALPHA))
  417. Good = FALSE;
  418. else
  419. Driver->DoesAlpha = TRUE;
  420. if (!(lpD3DDeviceDesc->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_TRANSPARENCY))
  421. Good = FALSE;
  422. else
  423. Driver->DoesTransparency = TRUE;
  424. Driver->DoesClamping = TRUE;
  425. if ((lpD3DDeviceDesc->dpcTriCaps.dwSrcBlendCaps & MUST_BLEND_SRC) != MUST_BLEND_SRC)
  426. Good = FALSE;
  427. else
  428. Driver->DoesSrcBlending = TRUE;
  429. if ((lpD3DDeviceDesc->dpcTriCaps.dwDestBlendCaps & MUST_BLEND_DEST) != MUST_BLEND_DEST)
  430. Good = FALSE;
  431. else
  432. Driver->DoesDestBlending = TRUE;
  433. // Stop as soon as we find a driver that can render into a window
  434. if ((lpD3DDeviceDesc->dwDeviceRenderBitDepth & BPPToDDBD(D3DInfo.OldBpp)) && D3DInfo.IsPrimary && Good)
  435. {
  436. Driver->CanDoWindow = TRUE;
  437. D3DInfo.CanDoWindow = TRUE;
  438. }
  439. else
  440. Driver->CanDoWindow = FALSE;
  441. // Store if we can use this driver
  442. Driver->CanUse = Good;
  443. if (!Good)
  444. return (D3DENUMRET_OK);
  445. // Tell global structure that we found a good device
  446. D3DInfo.FoundGoodDevice = TRUE;
  447. // If all was good, increment the number of drivers
  448. D3DInfo.NumDrivers++;
  449. return (D3DENUMRET_OK);
  450. }
  451. //================================================================================
  452. // EnumDevices
  453. //================================================================================
  454. static BOOL D3DMain_EnumDevices(void)
  455. {
  456. HRESULT LastError;
  457. D3DMain_Log("--- D3DMain_EnumDevices ---\n");
  458. D3DInfo.NumDrivers = 0;
  459. LastError = D3DInfo.lpD3D->EnumDevices(D3DEnumDevicesCallback7, NULL);
  460. if (LastError != DD_OK)
  461. {
  462. D3DMain_Log("Enumeration of drivers failed.\n %s\n", D3DErrorToString(LastError));
  463. return FALSE;
  464. }
  465. D3DInfo.CurrentDriver = 0;
  466. return TRUE;
  467. }
  468. //================================================================================
  469. // CreateSurface
  470. //================================================================================
  471. static HRESULT CreateSurface(LPDDSURFACEDESC2 lpDDSurfDesc, LPDIRECTDRAWSURFACE7 FAR *lpDDSurface)
  472. {
  473. HRESULT Result;
  474. //if (D3DInfo.OnlySystemMemory)
  475. // lpDDSurfDesc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  476. Result = D3DInfo.lpDD->CreateSurface(lpDDSurfDesc, lpDDSurface, NULL);
  477. return Result;
  478. }
  479. //================================================================================
  480. // GetSurfDesc
  481. //================================================================================
  482. static HRESULT GetSurfDesc(LPDDSURFACEDESC2 lpDDSurfDesc, LPDIRECTDRAWSURFACE7 lpDDSurf)
  483. {
  484. HRESULT Result;
  485. memset(lpDDSurfDesc, 0, sizeof(DDSURFACEDESC2));
  486. lpDDSurfDesc->dwSize = sizeof(DDSURFACEDESC2);
  487. Result = lpDDSurf->GetSurfaceDesc(lpDDSurfDesc);
  488. return Result;
  489. }
  490. //================================================================================
  491. // EnumTextureFormatsCallback
  492. // Record information about each texture format the current D3D driver can
  493. // support. Choose one as the default format and return it through lpContext.
  494. //================================================================================
  495. static HRESULT CALLBACK EnumTextureFormatsCallback(LPDDPIXELFORMAT lpddpfPixelFormat, LPVOID lpContext)
  496. {
  497. DDMain_SurfFormat *pTexFormat;
  498. if(!lpddpfPixelFormat)
  499. return DDENUMRET_OK;
  500. if (D3DInfo.NumTextureFormats+1 >= DDMAIN_MAX_TEXTURE_FORMATS )
  501. {
  502. return DDENUMRET_CANCEL;
  503. }
  504. pTexFormat = &D3DInfo.TextureFormats[D3DInfo.NumTextureFormats];
  505. // Clear out this texture format slot
  506. memset(pTexFormat, 0, sizeof(DDMain_SurfFormat));
  507. if(lpddpfPixelFormat->dwFlags & DDPF_ALPHAPIXELS)
  508. {
  509. if(lpddpfPixelFormat->dwRGBAlphaBitMask == 0x8000)
  510. {
  511. if(lpddpfPixelFormat->dwRBitMask != 0x7c00 ||
  512. lpddpfPixelFormat->dwGBitMask != 0x3e0 ||
  513. lpddpfPixelFormat->dwBBitMask != 0x1f)
  514. return DDENUMRET_OK;
  515. pTexFormat->HasOneBitAlpha = TRUE;
  516. pTexFormat->HasFourBitAlpha = FALSE;
  517. }
  518. else if(lpddpfPixelFormat->dwRGBAlphaBitMask == 0xf000)
  519. {
  520. if(lpddpfPixelFormat->dwRBitMask != 0xf00 ||
  521. lpddpfPixelFormat->dwGBitMask != 0xf0 ||
  522. lpddpfPixelFormat->dwBBitMask != 0xf)
  523. return DDENUMRET_OK;
  524. pTexFormat->HasOneBitAlpha = FALSE;
  525. pTexFormat->HasFourBitAlpha = TRUE;
  526. }
  527. else
  528. {
  529. pTexFormat->HasOneBitAlpha = FALSE;
  530. pTexFormat->HasFourBitAlpha = FALSE;
  531. }
  532. }
  533. else
  534. {
  535. if(!(lpddpfPixelFormat->dwFlags & DDPF_RGB))
  536. return DDENUMRET_OK;
  537. #if 0
  538. if(lpddpfPixelFormat->dwRGBBitCount != 16)
  539. return DDENUMRET_OK;
  540. if( (lpddpfPixelFormat->dwRBitMask != 0xf800 && lpddpfPixelFormat->dwRBitMask != 0x7c00) ||
  541. (lpddpfPixelFormat->dwGBitMask != 0x7e0 && lpddpfPixelFormat->dwGBitMask != 0x3e0) ||
  542. (lpddpfPixelFormat->dwBBitMask != 0x1f))
  543. return DDENUMRET_OK;
  544. #endif
  545. pTexFormat->HasOneBitAlpha = FALSE;
  546. pTexFormat->HasFourBitAlpha = FALSE;
  547. }
  548. // Record the PixelFormat of this texture
  549. memcpy(&pTexFormat->ddsd.ddpfPixelFormat, lpddpfPixelFormat, sizeof(DDPIXELFORMAT));
  550. D3DInfo.NumTextureFormats++;
  551. return DDENUMRET_OK;
  552. }
  553. //================================================================================
  554. // Main_EnumTextureFormats
  555. // Get a list of available texture map formats from the Direct3D driver by
  556. // enumeration. Choose a default format.
  557. //================================================================================
  558. BOOL Main_EnumTextureFormats(void)
  559. {
  560. HRESULT LastError;
  561. assert(D3DInfo.lpD3DDevice);
  562. D3DInfo.NumTextureFormats = 0;
  563. LastError = D3DInfo.lpD3DDevice->EnumTextureFormats(EnumTextureFormatsCallback, NULL);
  564. if (LastError != DD_OK)
  565. {
  566. D3DMain_Log("Main_EnumTextureFormats: Enumeration of texture formats failed.\n %s\n",
  567. D3DErrorToString(LastError));
  568. return FALSE;
  569. }
  570. return TRUE;
  571. }
  572. //================================================================================
  573. // EnumSurfaceFormatsCallback
  574. //================================================================================
  575. HRESULT WINAPI EnumSurfaceFormatsCallback(LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext)
  576. {
  577. LPDDPIXELFORMAT lpddpfPixelFormat;
  578. DDMain_SurfFormat *pSurfFormat;
  579. // Don't need this.
  580. RELEASE(lpDDSurface);
  581. lpddpfPixelFormat = &lpDDSurfaceDesc->ddpfPixelFormat;
  582. if(!lpddpfPixelFormat)
  583. return DDENUMRET_OK;
  584. if (D3DInfo.NumSurfFormats+1 >= DDMAIN_MAX_SURFACE_FORMATS )
  585. return DDENUMRET_CANCEL;
  586. pSurfFormat = &D3DInfo.SurfFormats[D3DInfo.NumSurfFormats];
  587. // Clear out this texture format slot
  588. memset(pSurfFormat, 0, sizeof(DDMain_SurfFormat));
  589. if(lpddpfPixelFormat->dwFlags & DDPF_ALPHAPIXELS)
  590. {
  591. if(lpddpfPixelFormat->dwRGBAlphaBitMask == 0x8000)
  592. {
  593. // 1555
  594. if(lpddpfPixelFormat->dwRBitMask != 0x7c00 ||
  595. lpddpfPixelFormat->dwGBitMask != 0x3e0 ||
  596. lpddpfPixelFormat->dwBBitMask != 0x1f)
  597. return DDENUMRET_OK;
  598. pSurfFormat->HasOneBitAlpha = TRUE;
  599. pSurfFormat->HasFourBitAlpha = FALSE;
  600. }
  601. else if(lpddpfPixelFormat->dwRGBAlphaBitMask == 0xf000)
  602. {
  603. // 4444
  604. if(lpddpfPixelFormat->dwRBitMask != 0xf00 ||
  605. lpddpfPixelFormat->dwGBitMask != 0xf0 ||
  606. lpddpfPixelFormat->dwBBitMask != 0xf)
  607. return DDENUMRET_OK;
  608. pSurfFormat->HasOneBitAlpha = FALSE;
  609. pSurfFormat->HasFourBitAlpha = TRUE;
  610. }
  611. else
  612. {
  613. pSurfFormat->HasOneBitAlpha = FALSE;
  614. pSurfFormat->HasFourBitAlpha = FALSE;
  615. }
  616. }
  617. else
  618. {
  619. if(!(lpddpfPixelFormat->dwFlags & DDPF_RGB))
  620. return DDENUMRET_OK;
  621. pSurfFormat->HasOneBitAlpha = FALSE;
  622. pSurfFormat->HasFourBitAlpha = FALSE;
  623. }
  624. // Record the PixelFormat of this texture
  625. memcpy(&pSurfFormat->ddsd.ddpfPixelFormat, lpddpfPixelFormat,sizeof(DDPIXELFORMAT));
  626. D3DInfo.NumSurfFormats++;
  627. return DDENUMRET_OK;
  628. }
  629. //================================================================================
  630. // Main_EnumSurfaceFormats
  631. //================================================================================
  632. BOOL Main_EnumSurfaceFormats(void)
  633. {
  634. HRESULT LastError;
  635. assert(D3DInfo.lpDD);
  636. D3DInfo.NumSurfFormats = 0;
  637. LastError = D3DInfo.lpDD->EnumSurfaces(DDENUMSURFACES_DOESEXIST|DDENUMSURFACES_ALL,
  638. NULL, NULL, EnumSurfaceFormatsCallback);
  639. if (LastError != DD_OK)
  640. {
  641. D3DMain_Log("Main_EnumSurfaceFormats: Enumeration of texture formats failed.\n %s\n",
  642. D3DErrorToString(LastError));
  643. return FALSE;
  644. }
  645. return TRUE;
  646. }
  647. //-----------------------------------------------------------------------------
  648. // Name: EnumZBufferFormatsCallback()
  649. // Desc: Enumeration function to report valid pixel formats for z-buffers.
  650. //-----------------------------------------------------------------------------
  651. static HRESULT WINAPI EnumZBufferFormatsCallback( DDPIXELFORMAT* pddpf,
  652. VOID* pddpfDesired )
  653. {
  654. if( NULL==pddpf || NULL==pddpfDesired )
  655. return D3DENUMRET_CANCEL;
  656. // If the current pixel format's match the desired ones (DDPF_ZBUFFER and
  657. // possibly DDPF_STENCILBUFFER), lets copy it and return. This function is
  658. // not choosy...it accepts the first valid format that comes along.
  659. if( pddpf->dwFlags == ((DDPIXELFORMAT*)pddpfDesired)->dwFlags )
  660. {
  661. memcpy( pddpfDesired, pddpf, sizeof(DDPIXELFORMAT) );
  662. // We're happy with a 16-bit z-buffer. Otherwise, keep looking.
  663. if( pddpf->dwZBufferBitDepth == 16 )
  664. return D3DENUMRET_CANCEL;
  665. }
  666. return D3DENUMRET_OK;
  667. }
  668. //================================================================================
  669. // D3DMain_ClearBuffers
  670. //================================================================================
  671. static BOOL D3DMain_ClearBuffers(void)
  672. {
  673. DDSURFACEDESC2 ddsd;
  674. RECT dst;
  675. DDBLTFX ddbltfx;
  676. HRESULT LastError;
  677. // Find the width and height of the front buffer by getting its
  678. // DDSURFACEDESC2
  679. if (D3DInfo.lpFrontBuffer)
  680. {
  681. LastError = GetSurfDesc(&ddsd, D3DInfo.lpFrontBuffer);
  682. if (LastError != DD_OK)
  683. {
  684. D3DMain_Log("D3DMain_ClearBuffers: Failure getting the surface description of the front buffer before clearing.\n %s\n",
  685. D3DErrorToString(LastError));
  686. return FALSE;
  687. }
  688. // Clear the front buffer to black
  689. memset(&ddbltfx, 0, sizeof(ddbltfx));
  690. ddbltfx.dwSize = sizeof(DDBLTFX);
  691. SetRect(&dst, 0, 0, ddsd.dwWidth, ddsd.dwHeight);
  692. LastError = D3DInfo.lpFrontBuffer->Blt(&dst, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT,
  693. &ddbltfx);
  694. if (LastError != DD_OK)
  695. {
  696. if(LastError==DDERR_SURFACELOST)
  697. {
  698. if (!D3DMain_RestoreAllSurfaces())
  699. {
  700. D3DMain_Log("D3DMain_ClearBuffers: D3DMain_RestoreAllSurfaces failed...\n");
  701. return FALSE;
  702. }
  703. }
  704. else
  705. {
  706. D3DMain_Log("D3DMain_ClearBuffers: Clearing the front buffer failed.\n %s\n",
  707. D3DErrorToString(LastError));
  708. return FALSE;
  709. }
  710. }
  711. }
  712. if (D3DInfo.lpBackBuffer)
  713. {
  714. // Find the width and height of the back buffer by getting its
  715. // DDSURFACEDESC2
  716. LastError = GetSurfDesc(&ddsd, D3DInfo.lpBackBuffer);
  717. if (LastError != DD_OK)
  718. {
  719. D3DMain_Log("D3DMain_ClearBuffers: Failure while getting the surface description of the back buffer before clearing.\n %s\n",
  720. D3DErrorToString(LastError));
  721. return FALSE;
  722. }
  723. // Clear the back buffer to black
  724. memset(&ddbltfx, 0, sizeof(ddbltfx));
  725. ddbltfx.dwSize = sizeof(DDBLTFX);
  726. SetRect(&dst, 0, 0, ddsd.dwWidth, ddsd.dwHeight);
  727. LastError = D3DInfo.lpBackBuffer->Blt(&dst, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT,
  728. &ddbltfx);
  729. if (LastError != DD_OK)
  730. {
  731. if(LastError==DDERR_SURFACELOST)
  732. {
  733. if (!D3DMain_RestoreAllSurfaces())
  734. {
  735. D3DMain_Log("D3DMain_ClearBuffers: D3DMain_RestoreAllSurfaces failed.\n");
  736. return FALSE;
  737. }
  738. }
  739. else
  740. {
  741. D3DMain_Log("D3DMain_ClearBuffers: Clearing the back buffer failed.\n %s\n",
  742. D3DErrorToString(LastError));
  743. return FALSE;
  744. }
  745. }
  746. }
  747. return TRUE;
  748. }
  749. //================================================================================
  750. // Main_ShowBackBuffer
  751. //================================================================================
  752. BOOL Main_ShowBackBuffer(void)
  753. {
  754. HRESULT LastError;
  755. if (!D3DInfo.RenderingIsOK)
  756. return TRUE;
  757. if (D3DInfo.FullScreen)
  758. {
  759. // Flip the back and front buffers
  760. #if 1
  761. LastError = D3DInfo.lpFrontBuffer->Flip(D3DInfo.lpBackBuffer, DDFLIP_WAIT);
  762. #else
  763. LastError = D3DInfo.lpFrontBuffer->Flip(D3DInfo.lpBackBuffer, DDFLIP_NOVSYNC);
  764. #endif
  765. if (LastError == DDERR_SURFACELOST)
  766. {
  767. D3DMain_RestoreAllSurfaces();
  768. //D3DInfo.lpFrontBuffer->Restore();
  769. //D3DInfo.lpBackBuffer->Restore();
  770. D3DMain_ClearBuffers();
  771. }
  772. else if (LastError == DDERR_WASSTILLDRAWING)
  773. {
  774. }
  775. else if (LastError != DD_OK)
  776. {
  777. D3DMain_Log("Flipping complex display surface failed.\n %s\n", D3DErrorToString(LastError));
  778. return FALSE;
  779. }
  780. }
  781. else
  782. {
  783. RECT FRect, BRect;
  784. FRect.left = D3DInfo.WindowXOffset;
  785. FRect.right = FRect.left + D3DInfo.CurrentWidth;
  786. FRect.top = D3DInfo.WindowYOffset;
  787. FRect.bottom = FRect.top + D3DInfo.CurrentHeight;
  788. BRect.left = 0;
  789. BRect.right = D3DInfo.CurrentWidth;
  790. BRect.top = 0;
  791. BRect.bottom = D3DInfo.CurrentHeight;
  792. LastError = D3DInfo.lpFrontBuffer->Blt(&FRect, D3DInfo.lpBackBuffer,
  793. &BRect, DDBLT_WAIT, NULL);
  794. if (LastError != DD_OK)
  795. {
  796. if(LastError==DDERR_SURFACELOST)
  797. {
  798. if (!D3DMain_RestoreAllSurfaces())
  799. {
  800. D3DMain_Log("Main_ShowBackBuffer: D3DMain_RestoreAllSurfaces.\n");
  801. return FALSE;
  802. }
  803. }
  804. else
  805. {
  806. D3DMain_Log("Main_ShowBackBuffer: Blt of back buffer to front buffer failed.\n %s\n", D3DErrorToString(LastError));
  807. return FALSE;
  808. }
  809. }
  810. }
  811. return TRUE;
  812. }
  813. //================================================================================
  814. // Main_ClearBackBuffer
  815. //================================================================================
  816. BOOL Main_ClearBackBuffer(BOOL Clear, BOOL ClearZ)
  817. {
  818. int ClearFlags;
  819. D3DRECT Dummy;
  820. HRESULT LastError;
  821. if (!D3DInfo.RenderingIsOK)
  822. return TRUE;
  823. // Default to clear nothing
  824. ClearFlags = 0;
  825. // Then set in what callers wants to clear
  826. if (Clear)
  827. ClearFlags |= D3DCLEAR_TARGET;
  828. if (ClearZ)
  829. ClearFlags |= D3DCLEAR_ZBUFFER;
  830. Dummy.x1 = Dummy.y1 = 0;
  831. Dummy.x2 = D3DInfo.CurrentWidth;
  832. Dummy.y2 = D3DInfo.CurrentHeight;
  833. LastError = D3DInfo.lpD3DDevice->Clear(1, &Dummy, ClearFlags, 0, 1.0f, 0);
  834. if (LastError != D3D_OK)
  835. {
  836. D3DMain_Log("Main_ClearBackBuffer: Viewport clear failed.\n %s\n",
  837. D3DErrorToString(LastError));
  838. return FALSE;
  839. }
  840. return TRUE;
  841. }
  842. //================================================================================
  843. // Surface manipulation
  844. //================================================================================
  845. typedef struct
  846. {
  847. unsigned char r, g, b;
  848. } MY_D3D_RGB;
  849. typedef struct
  850. {
  851. DWORD R_Shift;
  852. DWORD G_Shift;
  853. DWORD B_Shift;
  854. DWORD A_Shift;
  855. DWORD R_Mask;
  856. DWORD G_Mask;
  857. DWORD B_Mask;
  858. DWORD A_Mask;
  859. DWORD R_Width;
  860. DWORD G_Width;
  861. DWORD B_Width;
  862. DWORD A_Width;
  863. } D3D_PixelMask;
  864. //================================================================================
  865. // GetSurfacePixelMask
  866. //================================================================================
  867. static void GetSurfacePixelMask(DDSURFACEDESC2 *ddsd, D3D_PixelMask *PixelMask)
  868. {
  869. DWORD red_mask, grn_mask, blu_mask, a_mask;
  870. DWORD red_shift, grn_shift, blu_shift, a_shift;
  871. DWORD red_width, grn_width, blu_width, a_width;
  872. red_mask = grn_mask = blu_mask = a_mask =
  873. red_shift = grn_shift = blu_shift = a_shift =
  874. red_width = grn_width = blu_width = a_width = 0;
  875. int i;
  876. red_mask = ddsd->ddpfPixelFormat.dwRBitMask;
  877. grn_mask = ddsd->ddpfPixelFormat.dwGBitMask;
  878. blu_mask = ddsd->ddpfPixelFormat.dwBBitMask;
  879. a_mask = ddsd->ddpfPixelFormat.dwRGBAlphaBitMask;
  880. //
  881. // Derive shift, width values from masks
  882. //
  883. for (i=31; i >= 0; i--)
  884. {
  885. if (red_mask & (1 << i))
  886. red_shift = i;
  887. if (grn_mask & (1 << i))
  888. grn_shift = i;
  889. if (blu_mask & (1 << i))
  890. blu_shift = i;
  891. if (a_mask & (1 << i))
  892. a_shift = i;
  893. }
  894. for (i=0; i <= 31; i++)
  895. {
  896. if (red_mask & (1 << i))
  897. red_width = i - red_shift + 1;
  898. if (grn_mask & (1 << i))
  899. grn_width = i - grn_shift + 1;
  900. if (blu_mask & (1 << i))
  901. blu_width = i - blu_shift + 1;
  902. if (a_mask & (1 << i))
  903. a_width = i - a_shift + 1;
  904. }
  905. //
  906. // Pass all requested values back to the caller
  907. //
  908. PixelMask->R_Shift = red_shift;
  909. PixelMask->G_Shift = grn_shift;
  910. PixelMask->B_Shift = blu_shift;
  911. PixelMask->A_Shift = a_shift;
  912. PixelMask->R_Mask = red_mask;
  913. PixelMask->G_Mask = grn_mask;
  914. PixelMask->B_Mask = blu_mask;
  915. PixelMask->A_Mask = a_mask;
  916. PixelMask->R_Width = red_width;
  917. PixelMask->G_Width = grn_width;
  918. PixelMask->B_Width = blu_width;
  919. PixelMask->A_Width = a_width;
  920. }
  921. //================================================================================
  922. // MyRGB
  923. //================================================================================
  924. static unsigned int MyRGB(DWORD R, DWORD G, DWORD B, D3D_PixelMask *PixelMask)
  925. {
  926. DWORD R_Left, G_Left, B_Left;
  927. DWORD R_Right, G_Right, B_Right;
  928. // Get shift constants for current video mode
  929. R_Left = PixelMask->R_Shift;
  930. G_Left = PixelMask->G_Shift;
  931. B_Left = PixelMask->B_Shift;
  932. R_Right = 8 - PixelMask->R_Width;
  933. G_Right = 8 - PixelMask->G_Width;
  934. B_Right = 8 - PixelMask->B_Width;
  935. // Shift R,G, and B into one value
  936. return(
  937. (((((unsigned int) R) >> R_Right) << R_Left) & PixelMask->R_Mask) |
  938. (((((unsigned int) G) >> G_Right) << G_Left) & PixelMask->G_Mask) |
  939. (((((unsigned int) B) >> B_Right) << B_Left) & PixelMask->B_Mask)
  940. );
  941. }
  942. //==========================================================================================
  943. // D3DMain_GetSurfaceFormats
  944. //==========================================================================================
  945. BOOL D3DMain_GetSurfaceFormats(void)
  946. {
  947. int32 i;
  948. D3DMain_Log("--- D3DMain_GetSurfaceFormats ---\n");
  949. if (!Main_EnumTextureFormats())
  950. {
  951. D3DMain_Log("D3DMain_GetSurfaceFormats: Main_EnumTextureFormats failed.\n");
  952. return FALSE;
  953. }
  954. if (!Main_EnumSurfaceFormats())
  955. {
  956. D3DMain_Log("D3DMain_GetSurfaceFormats: Main_EnumSurfaceFormats failed.\n");
  957. return FALSE;
  958. }
  959. #if 1
  960. for(i = 0; i < D3DInfo.NumSurfFormats; i++)
  961. {
  962. LPDDPIXELFORMAT lpddpfPixelFormat;
  963. lpddpfPixelFormat = &D3DInfo.SurfFormats[i].ddsd.ddpfPixelFormat;
  964. if(lpddpfPixelFormat->dwRGBBitCount != D3DInfo.ddsd.ddpfPixelFormat.dwRGBBitCount)
  965. continue;
  966. if (lpddpfPixelFormat->dwRGBAlphaBitMask != D3DInfo.ddsd.ddpfPixelFormat.dwRGBAlphaBitMask)
  967. continue;
  968. if (lpddpfPixelFormat->dwRBitMask != D3DInfo.ddsd.ddpfPixelFormat.dwRBitMask)
  969. continue;
  970. if (lpddpfPixelFormat->dwGBitMask != D3DInfo.ddsd.ddpfPixelFormat.dwGBitMask)
  971. continue;
  972. if (lpddpfPixelFormat->dwBBitMask != D3DInfo.ddsd.ddpfPixelFormat.dwBBitMask)
  973. continue;
  974. #if 0 // For debugging (This is the surface it is going to use for 2d decals)
  975. D3DMain_Log("Bits: %i, A:%x, R:%x, G:%x, B:%x\n", D3DInfo.ddsd.ddpfPixelFormat.dwRGBBitCount,
  976. D3DInfo.ddsd.ddpfPixelFormat.dwRGBAlphaBitMask,
  977. D3DInfo.ddsd.ddpfPixelFormat.dwRBitMask,
  978. D3DInfo.ddsd.ddpfPixelFormat.dwGBitMask,
  979. D3DInfo.ddsd.ddpfPixelFormat.dwBBitMask);
  980. return FALSE;
  981. #endif
  982. D3DInfo.ddSurfFormat = D3DInfo.SurfFormats[i].ddsd;
  983. break;
  984. }
  985. if(i == D3DInfo.NumSurfFormats)
  986. {
  987. D3DMain_Log("D3DMain_GetSurfaceFormats: Unable to find a 2d surface format that matches current bit depth.\n");
  988. return FALSE;
  989. }
  990. #else
  991. for(i = 0; i < D3DInfo.NumTextureFormats; i++)
  992. {
  993. LPDDPIXELFORMAT lpddpfPixelFormat;
  994. lpddpfPixelFormat = &D3DInfo.TextureFormats[i].ddsd.ddpfPixelFormat;
  995. if(lpddpfPixelFormat->dwRGBBitCount != D3DInfo.ddsd.ddpfPixelFormat.dwRGBBitCount)
  996. continue;
  997. if (lpddpfPixelFormat->dwRGBAlphaBitMask != D3DInfo.ddsd.ddpfPixelFormat.dwRGBAlphaBitMask)
  998. continue;
  999. if (lpddpfPixelFormat->dwRBitMask != D3DInfo.ddsd.ddpfPixelFormat.dwRBitMask)
  1000. continue;
  1001. if (lpddpfPixelFormat->dwGBitMask != D3DInfo.ddsd.ddpfPixelFormat.dwGBitMask)
  1002. continue;
  1003. if (lpddpfPixelFormat->dwBBitMask != D3DInfo.ddsd.ddpfPixelFormat.dwBBitMask)
  1004. continue;
  1005. #if 0 // For debugging (This is the surface it is going to use for 2d decals)
  1006. D3DMain_Log("Bits: %i, A:%x, R:%x, G:%x, B:%x\n", D3DInfo.ddsd.ddpfPixelFormat.dwRGBBitCount,
  1007. D3DInfo.ddsd.ddpfPixelFormat.dwRGBAlphaBitMask,
  1008. D3DInfo.ddsd.ddpfPixelFormat.dwRBitMask,
  1009. D3DInfo.ddsd.ddpfPixelFormat.dwGBitMask,
  1010. D3DInfo.ddsd.ddpfPixelFormat.dwBBitMask);
  1011. return FALSE;
  1012. #endif
  1013. D3DInfo.ddSurfFormat = D3DInfo.TextureFormats[i].ddsd;
  1014. break;
  1015. }
  1016. if(i == D3DInfo.NumTextureFormats)
  1017. {
  1018. D3DMain_Log("D3DMain_GetSurfaceFormats: Unable to find a 2d surface format that matches current bit depth.\n");
  1019. return FALSE;
  1020. }
  1021. #endif
  1022. // Now get the 3d surface formats
  1023. // Get 1555
  1024. for(i = 0; i < D3DInfo.NumTextureFormats; i++)
  1025. {
  1026. if(D3DInfo.TextureFormats[i].HasOneBitAlpha == TRUE)
  1027. {
  1028. D3DInfo.ddOneBitAlphaSurfFormat = D3DInfo.TextureFormats[i].ddsd;
  1029. break;
  1030. }
  1031. }
  1032. if(i == D3DInfo.NumTextureFormats)
  1033. {
  1034. D3DMain_Log("D3DMain_GetSurfaceFormats: Unable to find 1555 texture support.\n");
  1035. return FALSE;
  1036. }
  1037. // Get 4444
  1038. for(i = 0; i < D3DInfo.NumTextureFormats; i++)
  1039. {
  1040. if(D3DInfo.TextureFormats[i].HasFourBitAlpha == TRUE)
  1041. {
  1042. D3DInfo.ddFourBitAlphaSurfFormat = D3DInfo.TextureFormats[i].ddsd;
  1043. break;
  1044. }
  1045. }
  1046. if(i == D3DInfo.NumTextureFormats)
  1047. {
  1048. D3DMain_Log("D3DMain_GetSurfaceFormats: Unable to find 4444 texture support.\n");
  1049. return FALSE;
  1050. }
  1051. // Get either 555, or 565.
  1052. for(i = 0; i < D3DInfo.NumTextureFormats; i++)
  1053. {
  1054. LPDDPIXELFORMAT lpddpfPixelFormat;
  1055. if(D3DInfo.TextureFormats[i].HasOneBitAlpha == TRUE)
  1056. continue;
  1057. if (D3DInfo.TextureFormats[i].HasFourBitAlpha == TRUE)
  1058. continue;
  1059. lpddpfPixelFormat = &D3DInfo.TextureFormats[i].ddsd.ddpfPixelFormat;
  1060. // For now, force 3d textures with RGB only info to be either 565 or 555
  1061. // We could enum all formats and let the caller pick between several different RGB formats...
  1062. if (lpddpfPixelFormat->dwFlags & DDPF_ALPHAPIXELS)
  1063. continue; // We don't want any surface that has alpha, just pure RGB...
  1064. if(lpddpfPixelFormat->dwRGBBitCount != 16)
  1065. continue;
  1066. if( (lpddpfPixelFormat->dwRBitMask != 0xf800 && lpddpfPixelFormat->dwRBitMask != 0x7c00) ||
  1067. (lpddpfPixelFormat->dwGBitMask != 0x7e0 && lpddpfPixelFormat->dwGBitMask != 0x3e0) ||
  1068. (lpddpfPixelFormat->dwBBitMask != 0x1f))
  1069. continue;
  1070. // This is it
  1071. D3DInfo.ddTexFormat = D3DInfo.TextureFormats[i].ddsd;
  1072. break;
  1073. }
  1074. if(i == D3DInfo.NumTextureFormats)
  1075. {
  1076. D3DMain_Log("D3DMain_GetSurfaceFormats: Unable to find 555 or 565 texture support.\n");
  1077. return FALSE;
  1078. }
  1079. Main_BuildRGBGammaTables(1.0f);
  1080. return TRUE;
  1081. }
  1082. //==========================================================================================
  1083. // Main_CheckDD
  1084. // Checks to see if current DD driver has any usable D3D Devices...
  1085. //==========================================================================================
  1086. BOOL Main_CheckDD(void)
  1087. {
  1088. D3DInfo.NumDrivers = 0;
  1089. D3DInfo.CurrentDriver = 0;
  1090. D3DInfo.FoundGoodDevice = FALSE;
  1091. D3DInfo.CanDoWindow = FALSE;
  1092. assert(D3DInfo.lpDD);
  1093. if (!D3DMain_RememberOldMode(GetDesktopWindow()))
  1094. return FALSE;
  1095. memset(D3DInfo.Drivers, 0, sizeof(DDMain_D3DDriver)*DDMAIN_MAX_D3D_DRIVERS);
  1096. if (!D3DMain_CreateD3D())
  1097. return FALSE;
  1098. if (!D3DMain_EnumDevices()) // See if we can enumerate at least one good device for this DD Driver
  1099. return FALSE;
  1100. if (!D3DInfo.FoundGoodDevice) // Return FALSE if not...
  1101. return FALSE;
  1102. return TRUE; // Found at least one!!!
  1103. }
  1104. //==========================================================================================
  1105. // OutputDriverInfo
  1106. //==========================================================================================
  1107. static BOOL OutputDriverInfo(const char *FileName, DDMain_D3DDriver *Driver)
  1108. {
  1109. FILE *f;
  1110. SYSTEMTIME Time;
  1111. char YesNo[2][10];
  1112. f = fopen(FileName, "a+t");
  1113. if (!f)
  1114. return FALSE;
  1115. GetSystemTime(&Time);
  1116. strcpy(YesNo[0], "No\n");
  1117. strcpy(YesNo[1], "Yes\n");
  1118. fprintf(f,"=================================================================\n");
  1119. fprintf(f,"Time: %2i:%2i:%2i\n", Time.wHour, Time.wMinute, Time.wSecond);
  1120. fprintf(f,"Date: %2i-%2i-%4i\n", Time.wMonth, Time.wDay, Time.wYear);
  1121. fprintf(f, "DirectDraw Name: \n");
  1122. fprintf(f, " %s\n", D3DInfo.DDName);
  1123. fprintf(f, "D3D Driver Name: \n");
  1124. fprintf(f, " %s\n", Driver->Name);
  1125. fprintf(f, "D3D Driver Description: \n");
  1126. fprintf(f, " %s\n", Driver->About);
  1127. fprintf(f, "3D Acceleration : %s", YesNo[Driver->IsHardware]);
  1128. fprintf(f, "Texture Support : %s", YesNo[Driver->DoesTextures]);
  1129. fprintf(f, "Transparency Support : %s", YesNo[Driver->DoesTransparency]);
  1130. fprintf(f, "Alpha Support : %s", YesNo[Driver->DoesAlpha]);
  1131. fprintf(f, "UV Clamping Support : %s", YesNo[Driver->DoesClamping]);
  1132. fprintf(f, "Src Blending Support : %s", YesNo[Driver->DoesSrcBlending]);
  1133. fprintf(f, "Dest Blending Support : %s", YesNo[Driver->DoesDestBlending]);
  1134. fprintf(f, "Window Support : %s", YesNo[Driver->CanDoWindow]);
  1135. fprintf(f, "Can Use : %s", YesNo[Driver->CanUse]);
  1136. fclose(f);
  1137. return TRUE;
  1138. }
  1139. //==========================================================================================
  1140. // D3DMain_GetTextureMemory
  1141. //==========================================================================================
  1142. BOOL D3DMain_GetTextureMemory(void)
  1143. {
  1144. DDSCAPS2 ddsCaps;
  1145. DWORD dwTotal;
  1146. DWORD dwFree;
  1147. HRESULT Error;
  1148. D3DMain_Log("--- D3DMain_GetTextureMemory ---\n");
  1149. memset(&ddsCaps, 0, sizeof(ddsCaps));
  1150. //ddsCaps.dwSize = sizeof(DDSCAPS2);
  1151. ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
  1152. Error = D3DInfo.lpDD->GetAvailableVidMem(&ddsCaps, &dwTotal, &dwFree);
  1153. if(Error !=DD_OK)
  1154. {
  1155. D3DMain_Log("Getting DD capabilities failed while checking total video memory.\n %s\n", D3DErrorToString(Error));
  1156. return FALSE;
  1157. }
  1158. D3DInfo.VidMemFree = dwFree;
  1159. D3DMain_Log(" Ram free: %i\n", D3DInfo.VidMemFree);
  1160. return TRUE;
  1161. }
  1162. //==========================================================================================
  1163. //==========================================================================================
  1164. void Main_BuildRGBGammaTables(float Gamma)
  1165. {
  1166. int32 i, Val;
  1167. int32 GammaTable[256];
  1168. D3D_PixelMask PixelMask;
  1169. DWORD R_Left, G_Left, B_Left, A_Left;
  1170. DWORD R_Right, G_Right, B_Right, A_Right;
  1171. D3DInfo.Gamma = Gamma;
  1172. if (Gamma == 1.0)
  1173. {
  1174. #ifdef USE_2X_MODULATION
  1175. if (!(D3DInfo.dwTextureOpCaps & D3DTOP_MODULATE2X))
  1176. {
  1177. for (i=0 ; i<256 ; i++)
  1178. {
  1179. float Ratio = ((float)i+0.5f)/255.5f;
  1180. float RGB = (float)(255.0 * pow((double)Ratio, 1.0/(double)3.0) + 0.5);
  1181. if (RGB < 0.0f)
  1182. RGB = 0.0f;
  1183. if (RGB > 255.0f)
  1184. RGB = 255.0f;
  1185. GammaTable[i] = (int32)RGB;
  1186. //GammaTable[i] = min(255, i<<1);
  1187. }
  1188. }
  1189. else
  1190. #endif
  1191. {
  1192. for (i=0 ; i<256 ; i++)
  1193. GammaTable[i] = i;
  1194. }
  1195. }
  1196. else for (i=0 ; i<256 ; i++)
  1197. {
  1198. float Ratio = (i+0.5f)/255.5f;
  1199. float RGB = (float)(255.0 * pow((double)Ratio, 1.0/(double)Gamma) + 0.5);
  1200. if (RGB < 0.0f)
  1201. RGB = 0.0f;
  1202. if (RGB > 255.0f)
  1203. RGB = 255.0f;
  1204. GammaTable[i] = (int32)RGB;
  1205. }
  1206. GetSurfacePixelMask(&D3DInfo.ddTexFormat, &PixelMask);
  1207. for (i=0; i< 256; i++)
  1208. {
  1209. // Get shift constants for current video mode/pixel format
  1210. R_Left = PixelMask.R_Shift;
  1211. G_Left = PixelMask.G_Shift;
  1212. B_Left = PixelMask.B_Shift;
  1213. A_Left = PixelMask.A_Shift;
  1214. R_Right = 8 - PixelMask.R_Width;
  1215. G_Right = 8 - PixelMask.G_Width;
  1216. B_Right = 8 - PixelMask.B_Width;
  1217. A_Right = 8 - PixelMask.A_Width;
  1218. Val = GammaTable[i];
  1219. D3DInfo.Lut1.R[i] = (((uint32)Val >> R_Right) << R_Left) & PixelMask.R_Mask;
  1220. D3DInfo.Lut1.G[i] = (((uint32)Val >> G_Right) << G_Left) & PixelMask.G_Mask;
  1221. D3DInfo.Lut1.B[i] = (((uint32)Val >> B_Right) << B_Left) & PixelMask.B_Mask;
  1222. D3DInfo.Lut1.A[i] = (((uint32) i >> A_Right) << A_Left) & PixelMask.A_Mask;
  1223. }
  1224. GetSurfacePixelMask(&D3DInfo.ddFourBitAlphaSurfFormat, &PixelMask);
  1225. for (i=0; i< 256; i++)
  1226. {
  1227. // Get shift constants for current video mode/pixel format
  1228. R_Left = PixelMask.R_Shift;
  1229. G_Left = PixelMask.G_Shift;
  1230. B_Left = PixelMask.B_Shift;
  1231. A_Left = PixelMask.A_Shift;
  1232. R_Right = 8 - PixelMask.R_Width;
  1233. G_Right = 8 - PixelMask.G_Width;
  1234. B_Right = 8 - PixelMask.B_Width;
  1235. A_Right = 8 - PixelMask.A_Width;
  1236. Val = GammaTable[i];
  1237. D3DInfo.Lut2.R[i] = (((uint32)Val >> R_Right) << R_Left) & PixelMask.R_Mask;
  1238. D3DInfo.Lut2.G[i] = (((uint32)Val >> G_Right) << G_Left) & PixelMask.G_Mask;
  1239. D3DInfo.Lut2.B[i] = (((uint32)Val >> B_Right) << B_Left) & PixelMask.B_Mask;
  1240. D3DInfo.Lut2.A[i] = (((uint32) i >> A_Right) << A_Left) & PixelMask.A_Mask;
  1241. }
  1242. GetSurfacePixelMask(&D3DInfo.ddOneBitAlphaSurfFormat, &PixelMask);
  1243. for (i=0; i< 256; i++)
  1244. {
  1245. // Get shift constants for current video mode/pixel format
  1246. R_Left = PixelMask.R_Shift;
  1247. G_Left = PixelMask.G_Shift;
  1248. B_Left = PixelMask.B_Shift;
  1249. A_Left = PixelMask.A_Shift;
  1250. R_Right = 8 - PixelMask.R_Width;
  1251. G_Right = 8 - PixelMask.G_Width;
  1252. B_Right = 8 - PixelMask.B_Width;
  1253. A_Right = 8 - PixelMask.A_Width;
  1254. Val = GammaTable[i];
  1255. D3DInfo.Lut3.R[i] = (((uint32)Val >> R_Right) << R_Left) & PixelMask.R_Mask;
  1256. D3DInfo.Lut3.G[i] = (((uint32)Val >> G_Right) << G_Left) & PixelMask.G_Mask;
  1257. D3DInfo.Lut3.B[i] = (((uint32)Val >> B_Right) << B_Left) & PixelMask.B_Mask;
  1258. D3DInfo.Lut3.A[i] = (((uint32) i >> A_Right) << A_Left) & PixelMask.A_Mask;
  1259. }
  1260. }
  1261. //====================================================================================================
  1262. // D3DMain_UpdateWindow
  1263. //====================================================================================================
  1264. jeBoolean DRIVERCC D3DMain_UpdateWindow(void)
  1265. {
  1266. //D3DMain_GetClientWindowOffset(D3DInfo.hWnd);
  1267. if (!D3DInfo.ModeSet)
  1268. return JE_TRUE;
  1269. if (D3DInfo.FullScreen)
  1270. return JE_TRUE;
  1271. //D3DInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE,false);
  1272. // <> Pollard changes from 9/2 :
  1273. RELEASE(D3DInfo.lpClipper);
  1274. RELEASE(D3DInfo.lpZBuffer);
  1275. RELEASE(D3DInfo.lpFrontBuffer);
  1276. RELEASE(D3DInfo.lpBackBuffer);
  1277. RELEASE(D3DInfo.lpD3DDevice);
  1278. D3DMain_RememberOldMode(D3DInfo.hWnd);
  1279. //ATTEMPT(D3DMain_SetDisplayMode(D3DInfo.hWnd, D3DInfo.OldWindowWidth, D3DInfo.OldWindowHeight, D3DInfo.OldBpp, JE_FALSE));
  1280. D3DInfo.CurrentWidth = D3DInfo.OldWindowWidth;
  1281. D3DInfo.CurrentHeight = D3DInfo.OldWindowHeight;
  1282. // Pick a device we will be happy with
  1283. // ATTEMPT(D3DMain_PickDevice());
  1284. // Create front/back buffer
  1285. ATTEMPT(D3DMain_CreateBuffers());
  1286. // For some reason, we have to create the zbuffer BEFORE the device??? Why???
  1287. ATTEMPT(D3DMain_CreateZBuffer());
  1288. // Create the device
  1289. ATTEMPT(D3DMain_CreateDevice());
  1290. ATTEMPT(D3DMain_SetDefaultRenderStates());
  1291. return JE_TRUE;
  1292. // Error
  1293. exit_with_error:
  1294. {
  1295. return JE_FALSE;
  1296. }
  1297. }
  1298. //====================================================================================================
  1299. // D3DMain_SetActive
  1300. //====================================================================================================
  1301. jeBoolean DRIVERCC D3DMain_SetActive(jeBoolean wParam)
  1302. {
  1303. if (D3DInfo.lpFrontBuffer)
  1304. D3DInfo.RenderingIsOK = wParam;
  1305. if(D3DInfo.RenderingIsOK) // Regaining focus
  1306. {
  1307. HRESULT Result;
  1308. if (D3DInfo.lpFrontBuffer)
  1309. {
  1310. OutputDebugString("Regaining Focus\n");
  1311. Result = D3DInfo.lpFrontBuffer->IsLost();
  1312. if(Result != DD_OK)
  1313. {
  1314. if(Result == DDERR_SURFACELOST)
  1315. {
  1316. if(!D3DMain_RestoreAllSurfaces())
  1317. {
  1318. OutputDebugString("Couldn't restore surfaces!\n");
  1319. return JE_FALSE;
  1320. }
  1321. ShowWindow(D3DInfo.hWnd, SW_SHOWNORMAL); // Dx doesn't restore it
  1322. }
  1323. }
  1324. else
  1325. OutputDebugString("Regained focus, no surfaces lost\n");
  1326. }
  1327. }
  1328. return JE_TRUE;
  1329. }
  1330. //================================================================================
  1331. // D3DMain_GetClientWindowOffset
  1332. //================================================================================
  1333. BOOL D3DMain_GetClientWindowOffset(HWND hWnd)
  1334. {
  1335. POINT CPoint;
  1336. CPoint.x = CPoint.y = 0;
  1337. ClientToScreen(hWnd, &CPoint);
  1338. D3DInfo.WindowXOffset = CPoint.x;
  1339. D3DInfo.WindowYOffset = CPoint.y;
  1340. return TRUE;
  1341. }
  1342. //================================================================================
  1343. // D3DMain_RememberOldMode
  1344. //================================================================================
  1345. static BOOL D3DMain_RememberOldMode(HWND hWnd)
  1346. {
  1347. DDSURFACEDESC2 ddsd;
  1348. HRESULT LastError;
  1349. RECT CRect;
  1350. D3DMain_Log("--- D3DMain_RememberOldMode ---\n");
  1351. memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
  1352. ddsd.dwSize = sizeof(DDSURFACEDESC2);
  1353. LastError = D3DInfo.lpDD->GetDisplayMode(&ddsd);
  1354. if (LastError != DD_OK)
  1355. {
  1356. D3DMain_Log("Getting the current display mode failed.\n %s\n", D3DErrorToString(LastError));
  1357. return FALSE;
  1358. }
  1359. GetClientRect(hWnd, &CRect);
  1360. // Get old fulscreen width/height/bpp
  1361. D3DInfo.OldWidth = ddsd.dwWidth;
  1362. D3DInfo.OldHeight = ddsd.dwHeight;
  1363. D3DInfo.OldBpp = ddsd.ddpfPixelFormat.dwRGBBitCount;
  1364. // Get old window width/pos
  1365. D3DInfo.OldWindowWidth = CRect.right;
  1366. D3DInfo.OldWindowHeight = CRect.bottom;
  1367. GetWindowRect(hWnd, &CRect);
  1368. D3DInfo.OldWindowRect = CRect;
  1369. // D3DInfo.OldGWL_STYLE = GetWindowLong(hWnd, GWL_STYLE);
  1370. D3DMain_GetClientWindowOffset(hWnd);
  1371. return TRUE;
  1372. }
  1373. //==========================================================================================
  1374. // D3DMain_SetDisplayMode
  1375. //==========================================================================================
  1376. static BOOL D3DMain_SetDisplayMode(HWND hWnd, int w, int h, int bpp, BOOL FullScreen)
  1377. {
  1378. HRESULT LastError;
  1379. int DWidth, DHeight;
  1380. char YN[2][32];
  1381. strcpy(YN[0], "NO");
  1382. strcpy(YN[1], "YES");
  1383. D3DMain_Log("--- D3DMain_SetDisplayMode ---\n");
  1384. D3DMain_Log(" W: %i, H: %i, Bpp: %i, FullScreen: %s\n", w, h, bpp, YN[FullScreen]);
  1385. if (FullScreen)
  1386. {
  1387. LastError = D3DInfo.lpDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);// | DDSCL_ALLOWREBOOT);
  1388. if(LastError != DD_OK )
  1389. {
  1390. D3DMain_Log("SetCooperativeLevel to fullscreen failed.\n %s\n",
  1391. D3DErrorToString(LastError));
  1392. return FALSE;
  1393. }
  1394. D3DMain_Log(" SetCooperativeLevel: DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN succesfull...\n");
  1395. LastError = D3DInfo.lpDD->SetDisplayMode(w, h, bpp,0,0);
  1396. if(LastError != DD_OK )
  1397. {
  1398. D3DMain_Log("SetFullScreenDisplayMode: Mode %dx%dx%d failed\n %s\n", w, h, bpp, D3DErrorToString(LastError));
  1399. return FALSE;
  1400. }
  1401. D3DMain_Log(" SetDisplayMode: succesfull...\n");
  1402. DWidth = GetSystemMetrics(SM_CXSCREEN);
  1403. DHeight = GetSystemMetrics(SM_CYSCREEN);
  1404. #if 0 //{
  1405. //
  1406. // Set window boundaries to cover entire desktop, and show it
  1407. //
  1408. SetWindowLong(hWnd, GWL_STYLE, D3DInfo.OldGWL_STYLE | WS_POPUP);
  1409. SetWindowLong(hWnd, GWL_STYLE, D3DInfo.OldGWL_STYLE &
  1410. ~(WS_OVERLAPPED |
  1411. WS_CAPTION |
  1412. WS_SYSMENU |
  1413. WS_MINIMIZEBOX |
  1414. WS_MAXIMIZEBOX |
  1415. WS_THICKFRAME));
  1416. SetWindowPos(D3DInfo.hWnd,
  1417. HWND_TOP,
  1418. 0,
  1419. 0,
  1420. DWidth,
  1421. DHeight,
  1422. SWP_NOCOPYBITS | SWP_NOZORDER);
  1423. ShowWindow(D3DInfo.hWnd, SW_SHOWNORMAL);
  1424. #endif //}
  1425. }
  1426. else
  1427. {
  1428. LastError = D3DInfo.lpDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
  1429. if(LastError != DD_OK )
  1430. {
  1431. D3DMain_Log("SetCooperativeLevel to normal failed.\n %s\n",
  1432. D3DErrorToString(LastError));
  1433. return FALSE;
  1434. }
  1435. }
  1436. D3DInfo.hWnd = hWnd;
  1437. D3DInfo.CurrentWidth = w;
  1438. D3DInfo.CurrentHeight = h;
  1439. D3DInfo.CurrentBpp = bpp;
  1440. D3DInfo.FullScreen = FullScreen;
  1441. D3DInfo.WireFrame = FALSE;
  1442. D3DInfo.ModeSet = JE_TRUE;
  1443. return TRUE;
  1444. }
  1445. //================================================================================
  1446. // D3DMain_PickDevice
  1447. //================================================================================
  1448. static BOOL D3DMain_PickDevice(void)
  1449. {
  1450. int32 i;
  1451. DWORD Depths;
  1452. D3DMain_Log("--- D3DMain_PickDevice ---\n");
  1453. // Find a device with the same bpp as the mode set
  1454. Depths = BPPToDDBD(D3DInfo.CurrentBpp);
  1455. for (i = 0; i < D3DInfo.NumDrivers; i++)
  1456. {
  1457. if (!(D3DInfo.Drivers[i].IsHardware)) // ONLY hardware
  1458. continue;
  1459. // Only choose drivers that can support our draw buffer bpp
  1460. if (!(D3DInfo.Drivers[i].Desc.dwDeviceRenderBitDepth & Depths))
  1461. continue;
  1462. // Only choose drivers that can create the zbuffer we need
  1463. if (!(D3DInfo.Drivers[i].Desc.dwDeviceZBufferBitDepth & DDBD_16))
  1464. continue;
  1465. if (!D3DInfo.Drivers[i].CanDoWindow && !D3DInfo.FullScreen)
  1466. continue;
  1467. // Remember the current driver
  1468. D3DInfo.CurrentDriver = i;
  1469. return TRUE;
  1470. }
  1471. return FALSE;
  1472. }
  1473. char * stristr(const char *StrBase,const char *SubBase)
  1474. {
  1475. while ( *StrBase )
  1476. {
  1477. if ( toupper(*StrBase) == toupper(*SubBase) )
  1478. {
  1479. const char * Str,* Sub;
  1480. Str = StrBase + 1;
  1481. Sub = SubBase + 1;
  1482. while ( *Sub && toupper(*Sub) == toupper(*Str) )
  1483. {
  1484. Sub++; Str++;
  1485. }
  1486. if ( ! *Sub) return((char *)StrBase);
  1487. }
  1488. StrBase++;
  1489. }
  1490. return(NULL);
  1491. }
  1492. //================================================================================
  1493. // D3DMain_CreateDevice
  1494. //================================================================================
  1495. static BOOL D3DMain_CreateDevice(void)
  1496. {
  1497. HRESULT Error;
  1498. D3DVIEWPORT7 ViewPort;
  1499. D3DMain_Log("--- D3DMain_CreateDevice ---\n");
  1500. // Release old device
  1501. RELEASE(D3DInfo.lpD3DDevice);
  1502. Error = D3DInfo.lpD3D->CreateDevice(D3DInfo.Drivers[D3DInfo.CurrentDriver].Guid,
  1503. D3DInfo.lpBackBuffer,
  1504. &D3DInfo.lpD3DDevice);
  1505. if (Error != DD_OK)
  1506. {
  1507. D3DMain_Log("D3DMain_CreateDevice: lpD3D->CreateDevice failed:\n %s\n", D3DErrorToString(Error));
  1508. return FALSE;
  1509. }
  1510. {
  1511. // Get some info from the device
  1512. D3DDEVICEDESC7 DeviceDesc;
  1513. D3DInfo.lpD3DDevice->GetCaps(&DeviceDesc);
  1514. D3DInfo.MaxTextureWidth = DeviceDesc.dwMaxTextureWidth;
  1515. D3DInfo.MaxTextureHeight = DeviceDesc.dwMaxTextureHeight;
  1516. D3DInfo.MaxTextureWidth = max(D3DInfo.MaxTextureWidth ,256);
  1517. D3DInfo.MaxTextureHeight = max(D3DInfo.MaxTextureHeight,256);
  1518. // Fog reset
  1519. D3DInfo.Fog.R = D3DInfo.Fog.G = D3DInfo.Fog.B = D3DInfo.Fog.Start = D3DInfo.Fog.End = 0.0f;
  1520. D3DInfo.Fog.Enabled = FALSE;
  1521. #if 1
  1522. char str[1024];
  1523. sprintf(str,"D3DDrv : Max Texture Dimensions = %d x %d\n",
  1524. D3DInfo.MaxTextureWidth,D3DInfo.MaxTextureHeight);
  1525. OutputDebugString(str);
  1526. D3DMain_Log(str);
  1527. #endif
  1528. // <> test this by forcing MaxWidth back to 256 ; seems ok cept for uv's
  1529. #if 0
  1530. D3DInfo.MaxTextureWidth =
  1531. D3DInfo.MaxTextureHeight = 256;
  1532. #endif
  1533. //D3DInfo.dwTextureOpCaps = hw.dwTextureOpCaps;
  1534. //D3DInfo.dwTextureOpCaps = D3DTOP_MODULATE2X;
  1535. D3DInfo.dwTextureOpCaps = 0;
  1536. }
  1537. // <> look in name for a 3dfx and set up a MaxSurfaces variable
  1538. if ( stristr(D3DInfo.DDName,"3dfx") )
  1539. {
  1540. OutputDebugString("D3DDrv : found 3dfx card, using 1024 surfaces\n");
  1541. D3DMain_Log("D3DDrv : found 3dfx card, using 1024 surfaces\n");
  1542. D3DInfo.MaxSurfaceCount = 1024;
  1543. }
  1544. else
  1545. {
  1546. D3DInfo.MaxSurfaceCount = 65536 - 1024;
  1547. }
  1548. #if 0 // <> test it! seems ok
  1549. D3DInfo.MaxSurfaceCount = 128;
  1550. #endif
  1551. // Set ViewPort data for this device
  1552. ViewPort.dwX = 0;
  1553. ViewPort.dwY = 0;
  1554. ViewPort.dwWidth = D3DInfo.CurrentWidth;
  1555. ViewPort.dwHeight = D3DInfo.CurrentHeight;
  1556. ViewPort.dvMinZ = 0.0f;
  1557. ViewPort.dvMaxZ = 1.0f;
  1558. Error = D3DInfo.lpD3DDevice->SetViewport(&ViewPort);
  1559. if (Error != D3D_OK)
  1560. {
  1561. D3DMain_Log("D3DMain_CreateDevice: SetViewport failed.\n %s\n", D3DErrorToString(Error));
  1562. {
  1563. RELEASE(D3DInfo.lpD3DDevice);
  1564. return FALSE;
  1565. }
  1566. }
  1567. return TRUE;
  1568. }
  1569. //================================================================================
  1570. // D3DMain_CreateBuffers
  1571. //================================================================================
  1572. static BOOL D3DMain_CreateBuffers(void)
  1573. {
  1574. DDSURFACEDESC2 ddsd;
  1575. HRESULT LastError;
  1576. D3DMain_Log("--- D3DMain_CreateBuffers ---\n");
  1577. // Release any old objects that might be lying around. This should have
  1578. // already been taken care of, but just in case...
  1579. RELEASE(D3DInfo.lpClipper);
  1580. RELEASE(D3DInfo.lpBackBuffer);
  1581. RELEASE(D3DInfo.lpFrontBuffer);
  1582. if (D3DInfo.FullScreen)
  1583. {
  1584. DDSCAPS2 ddscaps = {DDSCAPS_BACKBUFFER, 0, 0, 0};
  1585. // Create a complex flipping surface for fullscreen mode with one
  1586. // back buffer.
  1587. memset(&ddsd,0,sizeof(DDSURFACEDESC2));
  1588. ddsd.dwSize = sizeof( ddsd );
  1589. ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  1590. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
  1591. DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX;
  1592. ddsd.dwBackBufferCount = 1;
  1593. ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  1594. LastError = CreateSurface(&ddsd, &D3DInfo.lpFrontBuffer);
  1595. if(LastError != DD_OK)
  1596. {
  1597. if (LastError == DDERR_OUTOFMEMORY || LastError == DDERR_OUTOFVIDEOMEMORY)
  1598. {
  1599. D3DMain_Log("CreateBuffers: There was not enough video memory to create the rendering surface.\n Please restart the program and try another fullscreen mode with less resolution or lower bit depth.\n");
  1600. }
  1601. else
  1602. {
  1603. D3DMain_Log("CreateBuffers: CreateSurface for fullscreen flipping surface failed.\n %s\n",
  1604. D3DErrorToString(LastError));
  1605. }
  1606. goto exit_with_error;
  1607. }
  1608. // Obtain a pointer to the back buffer surface created above so we
  1609. // can use it later. For now, just check to see if it ended up in
  1610. // video memory (FYI).
  1611. LastError = D3DInfo.lpFrontBuffer->GetAttachedSurface(&ddscaps, &D3DInfo.lpBackBuffer);
  1612. if(LastError != DD_OK)
  1613. {
  1614. D3DMain_Log("CreateBuffers: GetAttachedSurface failed to get back buffer.\n %s\n",
  1615. D3DErrorToString(LastError));
  1616. goto exit_with_error;
  1617. }
  1618. LastError = GetSurfDesc(&ddsd, D3DInfo.lpBackBuffer);
  1619. if (LastError != DD_OK)
  1620. {
  1621. D3DMain_Log("CreateBuffers: Failed to get surface description of back buffer.\n %s\n",
  1622. D3DErrorToString(LastError));
  1623. goto exit_with_error;
  1624. }
  1625. D3DInfo.BackBufferInVideo =
  1626. (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) ? TRUE : FALSE;
  1627. D3DInfo.ddsd = ddsd; // Save the format of the back buffer
  1628. }
  1629. else
  1630. {
  1631. // In the window case, create a front buffer which is the primary
  1632. // surface and a back buffer which is an offscreen plane surface.
  1633. memset(&ddsd,0,sizeof(DDSURFACEDESC2));
  1634. ddsd.dwSize = sizeof(DDSURFACEDESC2);
  1635. ddsd.dwFlags = DDSD_CAPS;
  1636. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
  1637. LastError = D3DInfo.lpDD->CreateSurface(&ddsd, &D3DInfo.lpFrontBuffer, NULL);
  1638. if(LastError != DD_OK )
  1639. {
  1640. if (LastError == DDERR_OUTOFMEMORY || LastError == DDERR_OUTOFVIDEOMEMORY)
  1641. {
  1642. D3DMain_Log("CreateBuffers: There was not enough video memory to create the rendering surface.\n To run this program in a window of this size, please adjust your display settings for a smaller desktop area or a lower palette size and restart the program.\n");
  1643. }
  1644. else
  1645. {
  1646. D3DMain_Log("CreateBuffers: CreateSurface for window front buffer failed.\n %s\n",
  1647. D3DErrorToString(LastError));
  1648. }
  1649. goto exit_with_error;
  1650. }
  1651. ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
  1652. ddsd.dwWidth = D3DInfo.CurrentWidth;
  1653. ddsd.dwHeight = D3DInfo.CurrentHeight;
  1654. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
  1655. ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  1656. LastError = CreateSurface(&ddsd, &D3DInfo.lpBackBuffer);
  1657. if (LastError != DD_OK)
  1658. {
  1659. if (LastError == DDERR_OUTOFMEMORY || LastError == DDERR_OUTOFVIDEOMEMORY)
  1660. {
  1661. D3DMain_Log("CreateBuffers: There was not enough video memory to create the rendering surface.\n To run this program in a window of this size, please adjust your display settings for a smaller desktop area or a lower palette size and restart the program.\n");
  1662. }
  1663. else
  1664. {
  1665. D3DMain_Log("CreateBuffers: CreateSurface for window back buffer failed.\n %s\n",
  1666. D3DErrorToString(LastError));
  1667. }
  1668. goto exit_with_error;
  1669. }
  1670. // Check to see if the back buffer is in video memory (FYI).
  1671. LastError = GetSurfDesc(&ddsd, D3DInfo.lpBackBuffer);
  1672. if (LastError != DD_OK)
  1673. {
  1674. D3DMain_Log("CreateBuffers: Failed to get surface description for back buffer.\n %s\n",
  1675. D3DErrorToString(LastError));
  1676. goto exit_with_error;
  1677. }
  1678. D3DInfo.BackBufferInVideo = (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) ? TRUE : FALSE;
  1679. // Create the DirectDraw Clipper object and attach it to the window
  1680. // and front buffer.
  1681. LastError = D3DInfo.lpDD->CreateClipper(0, &D3DInfo.lpClipper, NULL);
  1682. if(LastError != DD_OK )
  1683. {
  1684. D3DMain_Log("CreateBuffers: CreateClipper failed.\n %s\n",
  1685. D3DErrorToString(LastError));
  1686. goto exit_with_error;
  1687. }
  1688. LastError = D3DInfo.lpClipper->SetHWnd(0, D3DInfo.hWnd);
  1689. if(LastError != DD_OK )
  1690. {
  1691. D3DMain_Log("CreateBuffers: Attaching clipper to window failed.\n %s\n",
  1692. D3DErrorToString(LastError));
  1693. goto exit_with_error;
  1694. }
  1695. LastError = D3DInfo.lpFrontBuffer->SetClipper(D3DInfo.lpClipper);
  1696. if(LastError != DD_OK )
  1697. {
  1698. D3DMain_Log("CreateBuffers: Attaching clipper to front buffer failed.\n %s\n",
  1699. D3DErrorToString(LastError));
  1700. goto exit_with_error;
  1701. }
  1702. D3DInfo.ddsd = ddsd; // Save the format of the back buffer
  1703. }
  1704. D3DMain_ClearBuffers();
  1705. return TRUE;
  1706. exit_with_error:
  1707. RELEASE(D3DInfo.lpFrontBuffer);
  1708. RELEASE(D3DInfo.lpBackBuffer);
  1709. RELEASE(D3DInfo.lpClipper);
  1710. return FALSE;
  1711. }
  1712. //================================================================================
  1713. // D3DMain_DestroyBuffers
  1714. //================================================================================
  1715. static void D3DMain_DestroyBuffers(void)
  1716. {
  1717. RELEASE(D3DInfo.lpClipper);
  1718. RELEASE(D3DInfo.lpBackBuffer);
  1719. RELEASE(D3DInfo.lpFrontBuffer);
  1720. }
  1721. //================================================================================
  1722. // D3DMain_CreateZBuffer
  1723. // Create a Z-Buffer of the appropriate depth and attach it to the back buffer.
  1724. //================================================================================
  1725. static BOOL D3DMain_CreateZBuffer(void)
  1726. {
  1727. DDSURFACEDESC2 ddsd;
  1728. HRESULT LastError;
  1729. assert(D3DInfo.lpBackBuffer);
  1730. D3DMain_Log("--- D3DMain_CreateZBuffer ---\n");
  1731. // Release any Z-Buffer that might be around just in case.
  1732. RELEASE(D3DInfo.lpZBuffer);
  1733. memset(&ddsd, 0 ,sizeof(DDSURFACEDESC2));
  1734. ddsd.dwSize = sizeof( ddsd );
  1735. ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;//DDSD_ZBUFFERBITDEPTH;
  1736. ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
  1737. ddsd.dwWidth = D3DInfo.CurrentWidth;
  1738. ddsd.dwHeight = D3DInfo.CurrentHeight;
  1739. ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
  1740. // Find a valid zbuffer, from the current device
  1741. D3DInfo.lpD3D->EnumZBufferFormats(D3DInfo.Drivers[D3DInfo.CurrentDriver].Guid, EnumZBufferFormatsCallback,
  1742. (VOID*)&ddsd.ddpfPixelFormat);
  1743. if( sizeof(DDPIXELFORMAT) != ddsd.ddpfPixelFormat.dwSize )
  1744. {
  1745. D3DMain_Log("CreateZBuffer: No zbuffer found for 3d device.\n");
  1746. return FALSE;
  1747. }
  1748. LastError = D3DInfo.lpDD->CreateSurface(&ddsd, &D3DInfo.lpZBuffer, NULL);
  1749. if(LastError != DD_OK)
  1750. {
  1751. if (LastError == DDERR_OUTOFMEMORY || LastError == DDERR_OUTOFVIDEOMEMORY)
  1752. {
  1753. if (D3DInfo.FullScreen)
  1754. {
  1755. D3DMain_Log("CreateZBuffer: There was not enough video memory to create the Z-buffer surface.\n Please try another mode with less resolution.\n");
  1756. }
  1757. else
  1758. {
  1759. D3DMain_Log("CreateZBuffer: There was not enough video memory to create the Z-buffer surface.\n Please try another mode with less resolution.\n");
  1760. }
  1761. }
  1762. else
  1763. {
  1764. D3DMain_Log("CreateZBuffer: CreateSurface for Z-buffer failed.\n %s\n",
  1765. D3DErrorToString(LastError));
  1766. }
  1767. goto exit_with_error;
  1768. }
  1769. // Attach the Z-buffer to the back buffer so D3D will find it
  1770. LastError = D3DInfo.lpBackBuffer->AddAttachedSurface(D3DInfo.lpZBuffer);
  1771. if(LastError != DD_OK)
  1772. {
  1773. D3DMain_Log("CreateZBuffer: AddAttachedBuffer failed for Z-Buffer.\n %s\n",
  1774. D3DErrorToString(LastError));
  1775. goto exit_with_error;
  1776. }
  1777. // Find out if it ended up in video memory.
  1778. LastError = GetSurfDesc(&ddsd, D3DInfo.lpZBuffer);
  1779. if (LastError != DD_OK)
  1780. {
  1781. D3DMain_Log("CreateZBuffer: Failed to get surface description of Z buffer.\n %s\n",
  1782. D3DErrorToString(LastError));
  1783. goto exit_with_error;
  1784. }
  1785. D3DInfo.ZBufferInVideo = (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) ? TRUE : FALSE;
  1786. return TRUE;
  1787. exit_with_error:
  1788. RELEASE(D3DInfo.lpZBuffer);
  1789. return FALSE;
  1790. }
  1791. //================================================================================
  1792. // D3DMain_DestroyZBuffer
  1793. //================================================================================
  1794. static void D3DMain_DestroyZBuffer(void)
  1795. {
  1796. RELEASE(D3DInfo.lpZBuffer)
  1797. }
  1798. //================================================================================
  1799. // D3DMain_SetDefaultRenderStates
  1800. //================================================================================
  1801. static jeBoolean D3DMain_SetDefaultRenderStates(void)
  1802. {
  1803. HRESULT LastError;
  1804. // Set some defaults render states
  1805. LastError = D3DInfo.lpD3DDevice->BeginScene();
  1806. if (LastError != D3D_OK)
  1807. {
  1808. D3DMain_Log("D3DMain_SetDefaultRenderStates: BeginScene failed.\n %s\n",
  1809. D3DErrorToString(LastError));
  1810. goto exit_with_error;
  1811. }
  1812. D3DInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
  1813. //D3DInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_GREATEREQUAL);
  1814. D3DInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE);
  1815. D3DInfo.lpD3DDevice->SetRenderState(D3DREN