Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2136 lines
74 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * **************************
  4. * * DirectDraw SAMPLE CODE *
  5. * **************************
  6. *
  7. * Module Name: dd.c
  8. *
  9. * Content:
  10. *
  11. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #define INITGUID
  15. #include "precomp.h"
  16. #include <mmsystem.h>
  17. #include "directx.h"
  18. #include "dd.h"
  19. #include "d3dhw.h"
  20. #include "d3dtext.h"
  21. #include "heap.h"
  22. //-----------------------------------------------------------------------------
  23. //
  24. // use bits to indicate which ROPs you support.
  25. //
  26. // DWORD 0, bit 0 == ROP 0
  27. // DWORD 8, bit 31 == ROP 255
  28. //
  29. //-----------------------------------------------------------------------------
  30. static BYTE ropList[] =
  31. {
  32. SRCCOPY >> 16,
  33. };
  34. static DWORD rops[DD_ROP_SPACE] = { 0 };
  35. // The FourCC's we support
  36. static DWORD fourCC[] =
  37. {
  38. FOURCC_YUV422
  39. };
  40. //-----------------------------------------------------------------------------
  41. //
  42. // setupRops
  43. //
  44. // build array for supported ROPS
  45. //
  46. //-----------------------------------------------------------------------------
  47. VOID
  48. setupRops( LPBYTE proplist, LPDWORD proptable, int cnt )
  49. {
  50. INT i;
  51. DWORD idx;
  52. DWORD bit;
  53. DWORD rop;
  54. for(i=0; i<cnt; i++)
  55. {
  56. rop = proplist[i];
  57. idx = rop / 32;
  58. bit = 1L << ((DWORD)(rop % 32));
  59. proptable[idx] |= bit;
  60. }
  61. } // setupRops
  62. //-----------------------------------------------------------------------------
  63. //
  64. // P2DisableAllUnits
  65. //
  66. // reset permedia rasterizer to known state
  67. //
  68. //-----------------------------------------------------------------------------
  69. VOID
  70. P2DisableAllUnits(PPDev ppdev)
  71. {
  72. PERMEDIA_DEFS(ppdev);
  73. RESERVEDMAPTR(47);
  74. SEND_PERMEDIA_DATA(RasterizerMode, __PERMEDIA_DISABLE);
  75. SEND_PERMEDIA_DATA(AreaStippleMode, __PERMEDIA_DISABLE);
  76. SEND_PERMEDIA_DATA(ScissorMode, __PERMEDIA_DISABLE);
  77. SEND_PERMEDIA_DATA(ColorDDAMode, __PERMEDIA_DISABLE);
  78. SEND_PERMEDIA_DATA(FogMode, __PERMEDIA_DISABLE);
  79. SEND_PERMEDIA_DATA(LBReadMode, __PERMEDIA_DISABLE);
  80. SEND_PERMEDIA_DATA(Window, __PERMEDIA_DISABLE);
  81. SEND_PERMEDIA_DATA(StencilMode, __PERMEDIA_DISABLE);
  82. SEND_PERMEDIA_DATA(DepthMode, __PERMEDIA_DISABLE);
  83. SEND_PERMEDIA_DATA(LBWriteMode, __PERMEDIA_DISABLE);
  84. SEND_PERMEDIA_DATA(FBReadMode, __PERMEDIA_DISABLE);
  85. SEND_PERMEDIA_DATA(DitherMode, __PERMEDIA_DISABLE);
  86. SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
  87. SEND_PERMEDIA_DATA(FBWriteMode, __PERMEDIA_DISABLE);
  88. SEND_PERMEDIA_DATA(StatisticMode, __PERMEDIA_DISABLE);
  89. SEND_PERMEDIA_DATA(AlphaBlendMode, __PERMEDIA_DISABLE);
  90. SEND_PERMEDIA_DATA(FilterMode, __PERMEDIA_DISABLE);
  91. SEND_PERMEDIA_DATA(FBSourceData, __PERMEDIA_DISABLE);
  92. SEND_PERMEDIA_DATA(LBWriteFormat, __PERMEDIA_DISABLE);
  93. SEND_PERMEDIA_DATA(TextureReadMode, __PERMEDIA_DISABLE);
  94. SEND_PERMEDIA_DATA(TextureMapFormat, __PERMEDIA_DISABLE);
  95. SEND_PERMEDIA_DATA(TextureDataFormat, __PERMEDIA_DISABLE);
  96. SEND_PERMEDIA_DATA(TexelLUTMode, __PERMEDIA_DISABLE);
  97. SEND_PERMEDIA_DATA(TextureColorMode, __PERMEDIA_DISABLE);
  98. SEND_PERMEDIA_DATA(YUVMode, __PERMEDIA_DISABLE);
  99. SEND_PERMEDIA_DATA(AStart, PM_BYTE_COLOR(0xFF));
  100. SEND_PERMEDIA_DATA(TextureBaseAddress, __PERMEDIA_DISABLE);
  101. SEND_PERMEDIA_DATA(TexelLUTIndex, __PERMEDIA_DISABLE);
  102. SEND_PERMEDIA_DATA(TexelLUTTransfer, __PERMEDIA_DISABLE);
  103. SEND_PERMEDIA_DATA(TextureAddressMode, __PERMEDIA_DISABLE);
  104. SEND_PERMEDIA_DATA(AlphaMapUpperBound, 0);
  105. SEND_PERMEDIA_DATA(AlphaMapLowerBound, 0);
  106. SEND_PERMEDIA_DATA(Color, 0);
  107. SEND_PERMEDIA_DATA(FBWriteMode, __PERMEDIA_ENABLE);
  108. SEND_PERMEDIA_DATA(FBPixelOffset, 0x0);
  109. SEND_PERMEDIA_DATA(FBHardwareWriteMask, __PERMEDIA_ALL_WRITEMASKS_SET);
  110. SEND_PERMEDIA_DATA(FBSoftwareWriteMask, __PERMEDIA_ALL_WRITEMASKS_SET);
  111. // We sometimes use the scissor in DDRAW to scissor out unnecessary pixels.
  112. SEND_PERMEDIA_DATA(ScissorMinXY, 0);
  113. SEND_PERMEDIA_DATA(ScissorMaxXY, (ppdev->cyMemory << 16) | (ppdev->cxMemory));
  114. SEND_PERMEDIA_DATA(ScreenSize, (ppdev->cyMemory << 16) | (ppdev->cxMemory));
  115. SEND_PERMEDIA_DATA(WindowOrigin, 0x0);
  116. // DirectDraw might not need to set these up
  117. SEND_PERMEDIA_DATA(dXDom, 0x0);
  118. SEND_PERMEDIA_DATA(dXSub, 0x0);
  119. // set max size, no filtering
  120. SEND_PERMEDIA_DATA(TextureReadMode,
  121. PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) |
  122. PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) |
  123. PM_TEXREADMODE_WIDTH(11) |
  124. PM_TEXREADMODE_HEIGHT(11) );
  125. // 16 bit Z, no other buffers
  126. SEND_PERMEDIA_DATA(LBWriteFormat, __PERMEDIA_DEPTH_WIDTH_16);
  127. // Ensure an extra LBData message doesn't flow through the core.
  128. SEND_PERMEDIA_DATA(Window, PM_WINDOW_DISABLELBUPDATE(__PERMEDIA_ENABLE));
  129. SEND_PERMEDIA_DATA(FBReadPixel, ppdev->bPixShift);
  130. COMMITDMAPTR();
  131. FLUSHDMA();
  132. } // P2DisableAllUnits
  133. //-----------------------------------------------------------------------------
  134. //
  135. // GetDDHALInfo
  136. //
  137. // Takes a pointer to a partially or fully filled in ppdev and a pointer
  138. // to an empty DDHALINFO and fills in the DDHALINFO.
  139. //
  140. //-----------------------------------------------------------------------------
  141. VOID
  142. GetDDHALInfo(PPDev ppdev, DDHALINFO* pHALInfo)
  143. {
  144. DWORD dwResult;
  145. BOOL bRet;
  146. DBG_DD(( 5, "DDraw:GetDDHalInfo"));
  147. // Setup the HAL driver caps.
  148. memset( pHALInfo, 0, sizeof(DDHALINFO));
  149. pHALInfo->dwSize = sizeof(DDHALINFO);
  150. // Setup the ROPS we do.
  151. setupRops( ropList, rops, sizeof(ropList)/sizeof(ropList[0]));
  152. // The most basic DirectDraw functionality
  153. pHALInfo->ddCaps.dwCaps = DDCAPS_BLT |
  154. DDCAPS_BLTQUEUE |
  155. DDCAPS_BLTCOLORFILL |
  156. DDCAPS_READSCANLINE;
  157. pHALInfo->ddCaps.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
  158. DDSCAPS_PRIMARYSURFACE |
  159. DDSCAPS_FLIP;
  160. // add caps for D3D
  161. pHALInfo->ddCaps.dwCaps |= DDCAPS_3D |
  162. DDCAPS_ALPHA |
  163. DDCAPS_BLTDEPTHFILL;
  164. // add surface caps for D3D
  165. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_ALPHA |
  166. DDSCAPS_3DDEVICE |
  167. DDSCAPS_ZBUFFER;
  168. // Permedia can do
  169. // 1. Stretching/Shrinking
  170. // 2. YUV->RGB conversion (only non paletted mode)
  171. // 3. Mirroring in X and Y
  172. // add Permedia caps to global caps
  173. pHALInfo->ddCaps.dwCaps |= DDCAPS_BLTSTRETCH |
  174. DDCAPS_COLORKEY |
  175. DDCAPS_CANBLTSYSMEM;
  176. #if DX7_STEREO
  177. // check if mode supports stereo
  178. DD_STEREOMODE DDStereoMode;
  179. DDStereoMode.dwHeight = ppdev->cyScreen;
  180. DDStereoMode.dwWidth = ppdev->cxScreen;
  181. DDStereoMode.dwBpp = ppdev->cBitsPerPel;
  182. DDStereoMode.dwRefreshRate= 0;
  183. ppdev->bCanDoStereo=bIsStereoMode(ppdev,&DDStereoMode);
  184. // Stereo caps are set if the driver can do stereo in any mode:
  185. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_STEREO;
  186. pHALInfo->ddCaps.dwSVCaps = DDSVCAPS_STEREOSEQUENTIAL;
  187. #endif
  188. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_CANMANAGETEXTURE;
  189. //declare we can handle textures wider than the primary
  190. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_WIDESURFACES;
  191. // Special effects caps
  192. pHALInfo->ddCaps.dwFXCaps = DDFXCAPS_BLTSTRETCHY |
  193. DDFXCAPS_BLTSTRETCHX |
  194. DDFXCAPS_BLTSTRETCHYN |
  195. DDFXCAPS_BLTSTRETCHXN |
  196. DDFXCAPS_BLTSHRINKY |
  197. DDFXCAPS_BLTSHRINKX |
  198. DDFXCAPS_BLTSHRINKYN |
  199. DDFXCAPS_BLTSHRINKXN |
  200. DDFXCAPS_BLTMIRRORUPDOWN |
  201. DDFXCAPS_BLTMIRRORLEFTRIGHT;
  202. // add AlphaBlt and Filter caps
  203. pHALInfo->ddCaps.dwFXCaps |= DDFXCAPS_BLTALPHA |
  204. DDFXCAPS_BLTFILTER;
  205. // colorkey caps, only src color key supported
  206. pHALInfo->ddCaps.dwCKeyCaps = DDCKEYCAPS_SRCBLT |
  207. DDCKEYCAPS_SRCBLTCLRSPACE;
  208. // We can do a texture from sysmem to video mem blt.
  209. pHALInfo->ddCaps.dwSVBCaps = DDCAPS_BLT;
  210. pHALInfo->ddCaps.dwSVBCKeyCaps = 0;
  211. pHALInfo->ddCaps.dwSVBFXCaps = 0;
  212. // Fill in the sysmem->vidmem rops (only can copy);
  213. for(int i=0;i<DD_ROP_SPACE;i++ )
  214. {
  215. pHALInfo->ddCaps.dwSVBRops[i] = rops[i];
  216. }
  217. if (ppdev->iBitmapFormat != BMF_8BPP)
  218. {
  219. pHALInfo->ddCaps.dwCaps |= DDCAPS_BLTFOURCC;
  220. pHALInfo->ddCaps.dwCKeyCaps |= DDCKEYCAPS_SRCBLTCLRSPACEYUV;
  221. }
  222. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
  223. // Z Buffer is only 16 Bits on Permedia
  224. pHALInfo->ddCaps.dwZBufferBitDepths = DDBD_16;
  225. #if D3D_MIPMAPPING
  226. // Mip Mapping
  227. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
  228. #endif
  229. if (DD_P2AGPCAPABLE(ppdev))
  230. {
  231. DBG_DD((1, "GetDDHALInfo: P2 AGP board - supports NONLOCALVIDMEM"));
  232. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_NONLOCALVIDMEM |
  233. DDCAPS2_NONLOCALVIDMEMCAPS;
  234. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM |
  235. DDSCAPS_NONLOCALVIDMEM;
  236. }
  237. else
  238. {
  239. DBG_DD((1,"GetDDHALInfo: P2 Board is NOT AGP"));
  240. }
  241. // Won't do Video-Sys mem Blits.
  242. pHALInfo->ddCaps.dwVSBCaps = 0;
  243. pHALInfo->ddCaps.dwVSBCKeyCaps = 0;
  244. pHALInfo->ddCaps.dwVSBFXCaps = 0;
  245. for( i=0;i<DD_ROP_SPACE;i++ )
  246. {
  247. pHALInfo->ddCaps.dwVSBRops[i] = 0;
  248. }
  249. // Won't do Sys-Sys mem Blits
  250. pHALInfo->ddCaps.dwSSBCaps = 0;
  251. pHALInfo->ddCaps.dwSSBCKeyCaps = 0;
  252. pHALInfo->ddCaps.dwSSBFXCaps = 0;
  253. for( i=0;i<DD_ROP_SPACE;i++ )
  254. {
  255. pHALInfo->ddCaps.dwSSBRops[i] = 0;
  256. }
  257. // bit depths supported for alpha and Z
  258. pHALInfo->ddCaps.dwAlphaBltConstBitDepths = DDBD_2 |
  259. DDBD_4 |
  260. DDBD_8;
  261. pHALInfo->ddCaps.dwAlphaBltPixelBitDepths = DDBD_1 |
  262. DDBD_8;
  263. pHALInfo->ddCaps.dwAlphaBltSurfaceBitDepths = DDBD_1 |
  264. DDBD_2 |
  265. DDBD_4 |
  266. DDBD_8;
  267. pHALInfo->ddCaps.dwAlphaOverlayConstBitDepths = DDBD_2 |
  268. DDBD_4 |
  269. DDBD_8;
  270. pHALInfo->ddCaps.dwAlphaOverlayPixelBitDepths = DDBD_1 |
  271. DDBD_8;
  272. pHALInfo->ddCaps.dwAlphaOverlaySurfaceBitDepths = DDBD_1 |
  273. DDBD_2 |
  274. DDBD_4 |
  275. DDBD_8;
  276. // ROPS supported
  277. for( i=0;i<DD_ROP_SPACE;i++ )
  278. {
  279. pHALInfo->ddCaps.dwRops[i] = rops[i];
  280. }
  281. // For DX5 and beyond we support this new informational callback.
  282. pHALInfo->GetDriverInfo = DdGetDriverInfo;
  283. pHALInfo->dwFlags |= DDHALINFO_GETDRIVERINFOSET;
  284. // now setup D3D callbacks
  285. D3DHALCreateDriver( ppdev,
  286. (LPD3DHAL_GLOBALDRIVERDATA*)
  287. &pHALInfo->lpD3DGlobalDriverData,
  288. (LPD3DHAL_CALLBACKS*)
  289. &pHALInfo->lpD3DHALCallbacks,
  290. (LPDDHAL_D3DBUFCALLBACKS*)
  291. &pHALInfo->lpD3DBufCallbacks);
  292. if(pHALInfo->lpD3DGlobalDriverData == NULL)
  293. {
  294. // no D3D available - kill caps we set before
  295. pHALInfo->ddCaps.dwCaps &=
  296. ~(DDCAPS_3D | DDCAPS_BLTDEPTHFILL);
  297. pHALInfo->ddCaps.ddsCaps.dwCaps &=
  298. ~(DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER);
  299. }
  300. } // GetHALInfo
  301. //-----------------------------------------------------------------------------
  302. //
  303. // Global DirectDraw Callbacks
  304. //
  305. //-----------------------------------------------------------------------------
  306. //-----------------------------------------------------------------------------
  307. //
  308. // DdFlip
  309. //
  310. // This callback is invoked whenever we are about to flip to from
  311. // one surface to another. lpFlipData->lpSurfCurr is the surface we were at,
  312. // lpFlipData->lpSurfTarg is the one we are flipping to.
  313. //
  314. // You should point the hardware registers at the new surface, and
  315. // also keep track of the surface that was flipped away from, so
  316. // that if the user tries to lock it, you can be sure that it is done
  317. // being displayed
  318. //
  319. //-----------------------------------------------------------------------------
  320. DWORD CALLBACK
  321. DdFlip( LPDDHAL_FLIPDATA lpFlipData)
  322. {
  323. PPDev ppdev=(PPDev)lpFlipData->lpDD->dhpdev;
  324. PERMEDIA_DEFS(ppdev);
  325. DWORD dwDDSurfaceOffset;
  326. HRESULT ddrval;
  327. DBG_DD(( 3, "DDraw:Flip"));
  328. // Switch to DirectDraw context
  329. DDCONTEXT;
  330. // is the previous Flip already done?
  331. // check if the current surface is already displayed
  332. ddrval = updateFlipStatus(ppdev);
  333. if( FAILED(ddrval) )
  334. {
  335. lpFlipData->ddRVal = ddrval;
  336. return DDHAL_DRIVER_HANDLED;
  337. }
  338. // everything is OK, do the flip.
  339. // get offset for Permedia ScreenBase register
  340. dwDDSurfaceOffset=(DWORD)lpFlipData->lpSurfTarg->lpGbl->fpVidMem;
  341. #if DX7_STEREO
  342. if (lpFlipData->dwFlags & DDFLIP_STEREO) // will be stereo
  343. {
  344. DBG_DD((4,"DDraw:Flip:Stereo"));
  345. DBG_DD((5,"ScreenBase: %08lx", dwDDSurfaceOffset));
  346. if (lpFlipData->lpSurfTargLeft!=NULL)
  347. {
  348. DWORD dwDDLeftSurfaceOffset;
  349. dwDDLeftSurfaceOffset=(DWORD)
  350. lpFlipData->lpSurfTargLeft->lpGbl->fpVidMem;
  351. LD_PERMEDIA_REG(PREG_SCREENBASERIGHT,dwDDLeftSurfaceOffset>>3);
  352. DBG_DD((5,"ScreenBaseLeft: %08lx", dwDDLeftSurfaceOffset));
  353. }
  354. ULONG ulVControl=READ_PERMEDIA_REG(PREG_VIDEOCONTROL);
  355. if ((ulVControl&PREG_VC_STEREOENABLE)==0 ||
  356. !ppdev->bDdStereoMode)
  357. {
  358. ppdev->bDdStereoMode=TRUE;
  359. LD_PERMEDIA_REG(PREG_VIDEOCONTROL, ulVControl
  360. | PREG_VC_STEREOENABLE);
  361. }
  362. } else
  363. #endif // DX7_STEREO
  364. {
  365. // append flip command to Permedia render pipeline
  366. // that makes sure that all buffers are flushed before
  367. // the flip occurs
  368. #if DX7_STEREO
  369. if (ppdev->bDdStereoMode)
  370. {
  371. ppdev->bDdStereoMode=FALSE;
  372. LD_PERMEDIA_REG(PREG_VIDEOCONTROL,
  373. READ_PERMEDIA_REG(PREG_VIDEOCONTROL)&
  374. ~PREG_VC_STEREOENABLE);
  375. }
  376. #endif
  377. }
  378. // adjust base address according to register spec.
  379. dwDDSurfaceOffset>>=3;
  380. // add new base address to render pipeline
  381. RESERVEDMAPTR(1);
  382. LD_INPUT_FIFO(__Permedia2TagSuspendUntilFrameBlank, dwDDSurfaceOffset);
  383. COMMITDMAPTR();
  384. FLUSHDMA();
  385. // remember new Surface Offset for GetFlipStatus
  386. ppdev->dwNewDDSurfaceOffset=dwDDSurfaceOffset;
  387. lpFlipData->ddRVal = DD_OK;
  388. return DDHAL_DRIVER_HANDLED;
  389. } // DdFlip
  390. //-----------------------------------------------------------------------------
  391. //
  392. // DdWaitForVerticalBlank
  393. //
  394. // This callback is invoked to get information about the vertical blank
  395. // status of the display or to wait until the display is at the begin or
  396. // the end of the vertical blank
  397. //
  398. //-----------------------------------------------------------------------------
  399. DWORD CALLBACK
  400. DdWaitForVerticalBlank(LPDDHAL_WAITFORVERTICALBLANKDATA lpWaitForVerticalBlank)
  401. {
  402. static int bInVBlank = FALSE;
  403. PPDev ppdev=(PPDev)lpWaitForVerticalBlank->lpDD->dhpdev;
  404. DBG_DD(( 2, "DDraw:WaitForVerticalBlank"));
  405. switch(lpWaitForVerticalBlank->dwFlags)
  406. {
  407. case DDWAITVB_I_TESTVB:
  408. // If the monitor is off, we don't always want to report
  409. // the same status or else an app polling this status
  410. // might hang
  411. if( !(READ_PERMEDIA_REG(PREG_VIDEOCONTROL) & PREG_VC_VIDEO_ENABLE))
  412. {
  413. lpWaitForVerticalBlank->bIsInVB = bInVBlank;
  414. bInVBlank = !bInVBlank;
  415. }
  416. else
  417. {
  418. // Just a request for current VBLANK status.
  419. lpWaitForVerticalBlank->bIsInVB = IN_VRETRACE(ppdev);
  420. }
  421. lpWaitForVerticalBlank->ddRVal = DD_OK;
  422. return DDHAL_DRIVER_HANDLED;
  423. case DDWAITVB_BLOCKBEGIN:
  424. // we don't care to wait if the monitor is off
  425. if( READ_PERMEDIA_REG(PREG_VIDEOCONTROL) & PREG_VC_VIDEO_ENABLE)
  426. {
  427. // if blockbegin is requested we wait until the vertical retrace
  428. // is over, and then wait for the display period to end.
  429. while(IN_VRETRACE(ppdev));
  430. while(IN_DISPLAY(ppdev));
  431. }
  432. lpWaitForVerticalBlank->ddRVal = DD_OK;
  433. return DDHAL_DRIVER_HANDLED;
  434. case DDWAITVB_BLOCKEND:
  435. // we don't care to wait if the monitor is off
  436. if( READ_PERMEDIA_REG(PREG_VIDEOCONTROL) & PREG_VC_VIDEO_ENABLE)
  437. {
  438. // if blockend is requested we wait for the vblank interval to end.
  439. if( IN_VRETRACE(ppdev) )
  440. {
  441. while( IN_VRETRACE(ppdev) );
  442. }
  443. else
  444. {
  445. while(IN_DISPLAY(ppdev));
  446. while(IN_VRETRACE(ppdev));
  447. }
  448. }
  449. lpWaitForVerticalBlank->ddRVal = DD_OK;
  450. return DDHAL_DRIVER_HANDLED;
  451. }
  452. return DDHAL_DRIVER_NOTHANDLED;
  453. } // WaitForVerticalBlank
  454. //-----------------------------------------------------------------------------
  455. //
  456. // Lock
  457. //
  458. // This call is invoked to lock a DirectDraw Videomemory surface. To make
  459. // sure there are no pending drawing operations on the surface, flush all
  460. // drawing operations and wait for a flip if it is still pending.
  461. //
  462. //-----------------------------------------------------------------------------
  463. DWORD CALLBACK
  464. DdLock( LPDDHAL_LOCKDATA lpLockData )
  465. {
  466. PPDev ppdev=(PPDev)lpLockData->lpDD->dhpdev;
  467. PERMEDIA_DEFS(ppdev);
  468. HRESULT ddrval;
  469. DWORD pSurf;
  470. DBG_DD(( 2, "DDraw:Lock"));
  471. //
  472. // Switch to DirectDraw context
  473. //
  474. DDCONTEXT;
  475. // check to see if any pending physical flip has occurred
  476. ddrval = updateFlipStatus(ppdev);
  477. if( FAILED(ddrval) )
  478. {
  479. lpLockData->ddRVal = DDERR_WASSTILLDRAWING;
  480. return DDHAL_DRIVER_HANDLED;
  481. }
  482. //
  483. // don't allow a lock if a blt is in progress
  484. //
  485. if(DRAW_ENGINE_BUSY)
  486. {
  487. DBG_DD((2,"DDraw:Lock, DrawEngineBusy"));
  488. FLUSHDMA();
  489. lpLockData->ddRVal = DDERR_WASSTILLDRAWING;
  490. return DDHAL_DRIVER_HANDLED;
  491. }
  492. // send a flush and wait for outstanding operations
  493. // before allowing surfaces to be locked.
  494. SYNC_WITH_PERMEDIA;
  495. // now check if the user wants to lock a texture surface,
  496. // which was loaded as patched! In this case we have to to
  497. // a blit to unpatch before we return it to the user
  498. // This is not expensive, since we leave it unpatched for
  499. // the future when the application decides to use it this way
  500. LPDDRAWI_DDRAWSURFACE_LCL pLcl=lpLockData->lpDDSurface;
  501. LPDDRAWI_DDRAWSURFACE_GBL pGbl=pLcl->lpGbl;
  502. PermediaSurfaceData *pPrivate=
  503. (PermediaSurfaceData*)pGbl->dwReserved1;
  504. //
  505. // If the user attempts to lock a managed surface, mark it as dirty
  506. // and return.
  507. //
  508. if (pLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
  509. {
  510. DBG_DD(( 3, "DDraw:Lock %08lx %08lx",
  511. pLcl->lpSurfMore->dwSurfaceHandle, pGbl->fpVidMem));
  512. if (NULL != pPrivate)
  513. pPrivate->dwFlags |= P2_SURFACE_NEEDUPDATE;
  514. lpLockData->lpSurfData = (LPVOID)(pLcl->lpGbl->fpVidMem +
  515. (pLcl->lpGbl->lPitch * lpLockData->rArea.top) +
  516. (lpLockData->rArea.left << DDSurf_GetPixelShift(pLcl)));
  517. lpLockData->ddRVal = DD_OK;
  518. return DDHAL_DRIVER_HANDLED;
  519. }
  520. DD_CHECK_PRIMARY_SURFACE_DATA(pLcl,pPrivate);
  521. //
  522. // We only need to unswizzle a surface if the
  523. // PrivateData is in a format we know (pPrivate!=NULL)
  524. //
  525. if (pPrivate!=NULL)
  526. {
  527. //
  528. // if the surface is a texture which was loaded in a swizzled
  529. // format, we have to undo the swizzle before succeding the lock.
  530. // In this driver, a texture remains unswizzled when a user
  531. // attempted to lock it once.
  532. //
  533. if (pPrivate->dwFlags & P2_ISPATCHED)
  534. {
  535. //
  536. // The scratchpad must be 32 lines high and should have
  537. // the same width as our original surface.
  538. //
  539. PermediaSurfaceData ScratchData=*pPrivate;
  540. LONG lScratchDelta;
  541. VIDEOMEMORY* pvmHeap;
  542. ULONG ulScratchOffset=
  543. ulVidMemAllocate( ppdev,
  544. DDSurf_Width(pLcl),
  545. DDSurf_Height(pLcl),
  546. DDSurf_GetPixelShift(pLcl),
  547. &lScratchDelta,
  548. &pvmHeap,
  549. &ScratchData.ulPackedPP,
  550. FALSE);
  551. DBG_DD(( 5, " unswizzle surface, scratchpad at: %08lx",
  552. ulScratchOffset));
  553. if (ulScratchOffset!=0)
  554. {
  555. RECTL rSurfRect;
  556. RECTL rScratchRect;
  557. rSurfRect.left=0;
  558. rSurfRect.top=0;
  559. rSurfRect.right=DDSurf_Width(pLcl);
  560. rSurfRect.bottom=32;
  561. rScratchRect=rSurfRect;
  562. // scratchpad should be non patched
  563. ScratchData.dwFlags &= ~(P2_ISPATCHED|P2_CANPATCH);
  564. LONG lSurfOffset;
  565. DWORD dwSurfBase=(DWORD)pGbl->fpVidMem >>
  566. DDSurf_GetPixelShift(pLcl);
  567. DWORD dwScratchBase=ulScratchOffset >>
  568. DDSurf_GetPixelShift(pLcl);
  569. lScratchDelta >>= DDSurf_GetPixelShift(pLcl);
  570. LONG lSurfDelta=DDSurf_Pitch(pLcl)>>
  571. DDSurf_GetPixelShift(pLcl);
  572. for (DWORD i=0; i<DDSurf_Height(pLcl); i+=32)
  573. {
  574. lSurfOffset = dwSurfBase-dwScratchBase;
  575. // first do a patched to unpatched blt to the scratchpad
  576. PermediaPatchedCopyBlt( ppdev,
  577. lScratchDelta,
  578. lSurfDelta,
  579. &ScratchData,
  580. pPrivate,
  581. &rScratchRect,
  582. &rSurfRect,
  583. dwScratchBase,
  584. lSurfOffset);
  585. // then do a fast copyblt back to the original
  586. // Packed blit ignores the ISPATCHED flag
  587. lSurfOffset = dwScratchBase-dwSurfBase;
  588. PermediaPackedCopyBlt( ppdev,
  589. lSurfDelta,
  590. lScratchDelta,
  591. pPrivate,
  592. &ScratchData,
  593. &rSurfRect,
  594. &rScratchRect,
  595. dwSurfBase,
  596. lSurfOffset);
  597. rSurfRect.top += 32;
  598. rSurfRect.bottom += 32;
  599. }
  600. pPrivate->dwFlags &= ~P2_ISPATCHED;
  601. //
  602. // free scratchpad memory
  603. //
  604. VidMemFree( pvmHeap->lpHeap, ulScratchOffset);
  605. SYNC_WITH_PERMEDIA;
  606. } else
  607. {
  608. lpLockData->ddRVal = DDERR_OUTOFMEMORY;
  609. return DDHAL_DRIVER_HANDLED;
  610. }
  611. }
  612. }
  613. // Because we correctly set 'fpVidMem' to be the offset into our frame
  614. // buffer when we created the surface, DirectDraw will automatically take
  615. // care of adding in the user-mode frame buffer address if we return
  616. // DDHAL_DRIVER_NOTHANDLED:
  617. return DDHAL_DRIVER_NOTHANDLED;
  618. } // DdLock
  619. //-----------------------------------------------------------------------------
  620. //
  621. // DdGetScanLine
  622. //
  623. // This callback is invoked to get the current scanline of our video display
  624. //
  625. //-----------------------------------------------------------------------------
  626. DWORD CALLBACK
  627. DdGetScanLine(LPDDHAL_GETSCANLINEDATA lpGetScanLine)
  628. {
  629. PPDev ppdev=(PPDev)lpGetScanLine->lpDD->dhpdev;
  630. DBG_DD(( 2, "DDraw:GetScanLine"));
  631. // If a vertical blank is in progress the scan line is
  632. // indeterminant. If the scan line is indeterminant we return
  633. // the error code DDERR_VERTICALBLANKINPROGRESS.
  634. // Otherwise we return the scan line and a success code
  635. if( IN_VRETRACE(ppdev) )
  636. {
  637. lpGetScanLine->ddRVal = DDERR_VERTICALBLANKINPROGRESS;
  638. lpGetScanLine->dwScanLine = 0;
  639. }
  640. else
  641. {
  642. lpGetScanLine->dwScanLine = CURRENT_VLINE(ppdev);
  643. lpGetScanLine->ddRVal = DD_OK;
  644. }
  645. return DDHAL_DRIVER_HANDLED;
  646. } // DdGetScanLine
  647. //-----------------------------------------------------------------------------
  648. //
  649. // DdGetBltStatus
  650. //
  651. // This callback is invoked to get the current blit status or to ask if the
  652. // user can add the next blit.
  653. //
  654. //-----------------------------------------------------------------------------
  655. DWORD CALLBACK
  656. DdGetBltStatus(LPDDHAL_GETBLTSTATUSDATA lpGetBltStatus )
  657. {
  658. PPDev ppdev=(PPDev)lpGetBltStatus->lpDD->dhpdev;
  659. PERMEDIA_DEFS(ppdev);
  660. DBG_DD(( 2, "DDraw:DdGetBltStatus"));
  661. // CANBLT: can we add a blt?
  662. // On the Permedia we can always add blits
  663. if( lpGetBltStatus->dwFlags == DDGBS_CANBLT )
  664. {
  665. lpGetBltStatus->ddRVal = DD_OK;
  666. }
  667. else
  668. {
  669. if( DRAW_ENGINE_BUSY )
  670. {
  671. //@@BEGIN_DDKSPLIT
  672. #if MULTITHREADED
  673. if(ppdev->ulLockCount)
  674. {
  675. DBG_DD((MT_LOG_LEVEL, "DdGetBltStatus: re-entry! %d", ppdev->ulLockCount));
  676. }
  677. EngAcquireSemaphore(ppdev->hsemLock);
  678. ppdev->ulLockCount++;
  679. #endif
  680. //@@END_DDKSPLIT
  681. // switch to DDraw context if necessary
  682. DDCONTEXT;
  683. FLUSHDMA();
  684. lpGetBltStatus->ddRVal = DDERR_WASSTILLDRAWING;
  685. //@@BEGIN_DDKSPLIT
  686. #if MULTITHREADED
  687. ppdev->ulLockCount--;
  688. EngReleaseSemaphore(ppdev->hsemLock);
  689. #endif
  690. //@@END_DDKSPLIT
  691. }
  692. else
  693. {
  694. lpGetBltStatus->ddRVal = DD_OK;
  695. }
  696. }
  697. return DDHAL_DRIVER_HANDLED;
  698. } // DdGetBltStatus
  699. //-----------------------------------------------------------------------------
  700. //
  701. // DdGetFlipStatus
  702. //
  703. // If the display has went through one refresh cycle since the flip
  704. // occurred we return DD_OK. If it has not went through one refresh
  705. // cycle we return DDERR_WASSTILLDRAWING to indicate that this surface
  706. // is still busy "drawing" the flipped page. We also return
  707. // DDERR_WASSTILLDRAWING if the bltter is busy and the caller wanted
  708. // to know if they could flip yet
  709. //
  710. //-----------------------------------------------------------------------------
  711. DWORD CALLBACK
  712. DdGetFlipStatus(LPDDHAL_GETFLIPSTATUSDATA lpGetFlipStatus )
  713. {
  714. PPDev ppdev=(PPDev)lpGetFlipStatus->lpDD->dhpdev;
  715. PERMEDIA_DEFS(ppdev);
  716. DBG_DD(( 2, "DDraw:GetFlipStatus"));
  717. // switch to DDraw context if necessary
  718. DDCONTEXT;
  719. // we can always flip, since the flip is pipelined
  720. // but we allow only one flip in advance
  721. if( lpGetFlipStatus->dwFlags == DDGFS_CANFLIP )
  722. {
  723. lpGetFlipStatus->ddRVal = updateFlipStatus(ppdev);
  724. return DDHAL_DRIVER_HANDLED;
  725. }
  726. // don't want a flip to work until after the last flip is done,
  727. // so we ask for the general flip status and ignore the vmem
  728. lpGetFlipStatus->ddRVal = updateFlipStatus(ppdev);
  729. return DDHAL_DRIVER_HANDLED;
  730. } // DdGetFlipStatus
  731. //-----------------------------------------------------------------------------
  732. //
  733. // DdMapMemory
  734. //
  735. // This is a new DDI call specific to Windows NT that is used to map
  736. // or unmap all the application modifiable portions of the frame buffer
  737. // into the specified process's address space.
  738. //
  739. //-----------------------------------------------------------------------------
  740. DWORD CALLBACK
  741. DdMapMemory(PDD_MAPMEMORYDATA lpMapMemory)
  742. {
  743. PDev* ppdev;
  744. VIDEO_SHARE_MEMORY ShareMemory;
  745. VIDEO_SHARE_MEMORY_INFORMATION ShareMemoryInformation;
  746. DWORD ReturnedDataLength;
  747. DBG_DD(( 2, "DDraw:MapMemory"));
  748. ppdev = (PDev*) lpMapMemory->lpDD->dhpdev;
  749. if (lpMapMemory->bMap)
  750. {
  751. ShareMemory.ProcessHandle = lpMapMemory->hProcess;
  752. // 'RequestedVirtualAddress' isn't actually used for the SHARE IOCTL:
  753. ShareMemory.RequestedVirtualAddress = 0;
  754. // We map in starting at the top of the frame buffer:
  755. ShareMemory.ViewOffset = 0;
  756. // We map down to the end of the frame buffer.
  757. //
  758. // Note: There is a 64k granularity on the mapping (meaning that
  759. // we have to round up to 64k).
  760. //
  761. // Note: If there is any portion of the frame buffer that must
  762. // not be modified by an application, that portion of memory
  763. // MUST NOT be mapped in by this call. This would include
  764. // any data that, if modified by a malicious application,
  765. // would cause the driver to crash. This could include, for
  766. // example, any DSP code that is kept in off-screen memory.
  767. ShareMemory.ViewSize
  768. = ROUND_UP_TO_64K(ppdev->cyMemory * ppdev->lDelta);
  769. if (EngDeviceIoControl(ppdev->hDriver,
  770. IOCTL_VIDEO_SHARE_VIDEO_MEMORY,
  771. &ShareMemory,
  772. sizeof(VIDEO_SHARE_MEMORY),
  773. &ShareMemoryInformation,
  774. sizeof(VIDEO_SHARE_MEMORY_INFORMATION),
  775. &ReturnedDataLength))
  776. {
  777. DBG_DD((0, "Failed IOCTL_VIDEO_SHARE_MEMORY"));
  778. lpMapMemory->ddRVal = DDERR_GENERIC;
  779. return(DDHAL_DRIVER_HANDLED);
  780. }
  781. lpMapMemory->fpProcess=(FLATPTR)ShareMemoryInformation.VirtualAddress;
  782. }
  783. else
  784. {
  785. ShareMemory.ProcessHandle = lpMapMemory->hProcess;
  786. ShareMemory.ViewOffset = 0;
  787. ShareMemory.ViewSize = 0;
  788. ShareMemory.RequestedVirtualAddress = (VOID*) lpMapMemory->fpProcess;
  789. if (EngDeviceIoControl(ppdev->hDriver,
  790. IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY,
  791. &ShareMemory,
  792. sizeof(VIDEO_SHARE_MEMORY),
  793. NULL,
  794. 0,
  795. &ReturnedDataLength))
  796. {
  797. RIP("Failed IOCTL_VIDEO_UNSHARE_MEMORY");
  798. }
  799. }
  800. lpMapMemory->ddRVal = DD_OK;
  801. return(DDHAL_DRIVER_HANDLED);
  802. }
  803. //-----------------------------------------------------------------------------
  804. //
  805. // DdSetExclusiveMode
  806. //
  807. // This function is called by DirectDraw when we switch from the GDI surface,
  808. // to DirectDraw exclusive mode, e.g. to run a game in fullcreen mode.
  809. // You only need to implement this function when you are using the
  810. // 'HeapVidMemAllocAligned' function and allocate memory for Device Bitmaps
  811. // and DirectDraw surfaces from the same heap.
  812. //
  813. // We use this call to disable GDI DeviceBitMaps when we are running in
  814. // DirectDraw exclusive mode. Otherwise a DD app gets confused if both GDI and
  815. // DirectDraw allocate memory from the same heap.
  816. //
  817. // See also DdFlipToGDISurface.
  818. //
  819. //-----------------------------------------------------------------------------
  820. DWORD CALLBACK
  821. DdSetExclusiveMode(PDD_SETEXCLUSIVEMODEDATA lpSetExclusiveMode)
  822. {
  823. PDev* ppdev=(PDev*)lpSetExclusiveMode->lpDD->dhpdev;
  824. DBG_DD((6, "DDraw::DdSetExclusiveMode called"));
  825. // remember setting of exclusive mode in ppdev,
  826. // so GDI can stop to promote DeviceBitmaps into
  827. // video memory
  828. ppdev->bDdExclusiveMode = lpSetExclusiveMode->dwEnterExcl;
  829. if (ppdev->bDdExclusiveMode)
  830. {
  831. // remove all GDI device bitmaps from video memory here
  832. // and make sure they will not be promoted to videomemory
  833. // until we leave exclusive mode.
  834. bDemoteAll(ppdev);
  835. }
  836. lpSetExclusiveMode->ddRVal=DD_OK;
  837. return (DDHAL_DRIVER_HANDLED);
  838. }
  839. //-----------------------------------------------------------------------------
  840. //
  841. // DWORD DdFlipToGDISurface
  842. //
  843. // This function is called by DirectDraw when it flips to the surface on which
  844. // GDI can write to.
  845. //
  846. //-----------------------------------------------------------------------------
  847. DWORD CALLBACK
  848. DdFlipToGDISurface(PDD_FLIPTOGDISURFACEDATA lpFlipToGDISurface)
  849. {
  850. PDev* ppdev=(PDev*)lpFlipToGDISurface->lpDD->dhpdev;
  851. DBG_DD((6, "DDraw::DdFlipToGDISurface called"));
  852. ppdev->dwNewDDSurfaceOffset=0xffffffff;
  853. #if DX7_STEREO
  854. if (ppdev->bDdStereoMode)
  855. {
  856. ppdev->bDdStereoMode=FALSE;
  857. LD_PERMEDIA_REG(PREG_VIDEOCONTROL,
  858. READ_PERMEDIA_REG(PREG_VIDEOCONTROL) &
  859. ~PREG_VC_STEREOENABLE);
  860. }
  861. #endif
  862. lpFlipToGDISurface->ddRVal=DD_OK;
  863. //
  864. // we return NOTHANDLED, then the ddraw runtime takes
  865. // care that we flip back to the primary...
  866. //
  867. return (DDHAL_DRIVER_NOTHANDLED);
  868. }
  869. //-----------------------------------------------------------------------------
  870. //
  871. // DWORD DdFreeDriverMemory
  872. //
  873. // This function called by DirectDraw when it's running low on memory in
  874. // our heap. You only need to implement this function if you use the
  875. // DirectDraw 'HeapVidMemAllocAligned' function in your driver, and you
  876. // can boot those allocations out of memory to make room for DirectDraw.
  877. //
  878. // We implement this function in the P2 driver because we have DirectDraw
  879. // entirely manage our off-screen heap, and we use HeapVidMemAllocAligned
  880. // to put GDI device-bitmaps in off-screen memory. DirectDraw applications
  881. // have a higher priority for getting stuff into video memory, though, and
  882. // so this function is used to boot those GDI surfaces out of memory in
  883. // order to make room for DirectDraw.
  884. //
  885. //-----------------------------------------------------------------------------
  886. DWORD CALLBACK
  887. DdFreeDriverMemory(PDD_FREEDRIVERMEMORYDATA lpFreeDriverMemory)
  888. {
  889. PDev* ppdev;
  890. DBG_DD((6, "DDraw::DdFreeDriverMemory called"));
  891. ppdev = (PDev*)lpFreeDriverMemory->lpDD->dhpdev;
  892. lpFreeDriverMemory->ddRVal = DDERR_OUTOFMEMORY;
  893. //@@BEGIN_DDKSPLIT
  894. #if MULTITHREADED
  895. if(ppdev->ulLockCount)
  896. {
  897. DBG_DD((MT_LOG_LEVEL, "DdFreeDriverMemory: re-entry! %d", ppdev->ulLockCount));
  898. }
  899. EngAcquireSemaphore(ppdev->hsemLock);
  900. ppdev->ulLockCount++;
  901. #endif
  902. //@@END_DDKSPLIT
  903. //
  904. // If we successfully freed up some memory, set the return value to
  905. // 'DD_OK'. DirectDraw will try again to do its allocation, and
  906. // will call us again if there's still not enough room. (It will
  907. // call us until either there's enough room for its alocation to
  908. // succeed, or until we return something other than DD_OK.)
  909. //
  910. if ( bMoveOldestBMPOut(ppdev) )
  911. {
  912. lpFreeDriverMemory->ddRVal = DD_OK;
  913. }
  914. //@@BEGIN_DDKSPLIT
  915. #if MULTITHREADED
  916. ppdev->ulLockCount--;
  917. EngReleaseSemaphore(ppdev->hsemLock);
  918. #endif
  919. //@@END_DDKSPLIT
  920. return (DDHAL_DRIVER_HANDLED);
  921. }// DdFreeDriverMemory()
  922. //-----------------------------------------------------------------------------
  923. //
  924. // BOOL DrvGetDirectDrawInfo
  925. //
  926. // Function called by DirectDraw to returns the capabilities of the graphics
  927. // hardware
  928. //
  929. // Parameters:
  930. //
  931. // dhpdev-------Is a handle to the PDEV returned by the driver's DrvEnablePDEV
  932. // routine.
  933. // pHalInfo-----Points to a DD_HALINFO structure in which the driver should
  934. // return the hardware capabilities that it supports.
  935. // pdwNumHeaps--Points to the location in which the driver should return the
  936. // number of VIDEOMEMORY structures pointed to by pvmList.
  937. // pvmList------Points to an array of VIDEOMEMORY structures in which the
  938. // driver should return information about each video memory chunk
  939. // that it controls. The driver should ignore this parameter when
  940. // it is NULL.
  941. // pdwNumFourCC-Points to the location in which the driver should return the
  942. // number of DWORDs pointed to by pdwFourCC.
  943. // pdwFourCC----Points to an array of DWORDs in which the driver should return
  944. // information about each FOURCC that it supports. The driver
  945. // should ignore this parameter when it is NULL.
  946. //
  947. // Return:
  948. // Returns TRUE if it succeeds; otherwise, it returns FALSE
  949. //
  950. // Note:
  951. // This function will be called twice before DrvEnableDirectDraw is called.
  952. //
  953. // Comments
  954. // The driver's DrvGetDirectDrawInfo routine should do the following:
  955. // 1)When pvmList and pdwFourCC are NULL:
  956. // Reserve off-screen video memory for DirectDraw use. Write the number of
  957. // driver video memory heaps and supported FOURCCs in pdwNumHeaps and
  958. // pdwNumFourCC, respectively.
  959. //
  960. // 2)When pvmList and pdwFourCC are not NULL:
  961. // Write the number of driver video memory heaps and supported FOURCCs in
  962. // pdwNumHeaps and pdwNumFourCC, respectively.
  963. // Get ptr to reserved offscreen mem?
  964. // For each VIDEOMEMORY structure in the list to which pvmList points, fill in
  965. // the appropriate members to describe a particular chunk of display memory.
  966. // The list of structures provides DirectDraw with a complete description of
  967. // the driver's off-screen memory.
  968. //
  969. // 3)Initialize the members of the DD_HALINFO structure with driver-specific
  970. // information as follows:
  971. // Initialize the appropriate members of the VIDEOMEMORYINFO structure to
  972. // describe the general characteristics of the display's memory.
  973. // Initialize the appropriate members of the DDNTCORECAPS structure to
  974. // describe the capabilities of the hardware.
  975. // If the driver implements a DdGetDriverInfo function, set GetDriverInfo to
  976. // point to it and set dwFlags to DDHALINFO_GETDRIVERINFOSET
  977. //
  978. //-----------------------------------------------------------------------------
  979. BOOL
  980. DrvGetDirectDrawInfo(DHPDEV dhpdev,
  981. DD_HALINFO* pHalInfo,
  982. DWORD* pdwNumHeaps,
  983. VIDEOMEMORY* pvmList, // Will be NULL on first call
  984. DWORD* pdwNumFourCC,
  985. DWORD* pdwFourCC) // Will be NULL on first call
  986. {
  987. BOOL bCanFlip;
  988. BOOL bDefineAGPHeap = FALSE,bDefineDDrawHeap = FALSE;
  989. LONGLONG li;
  990. VIDEOMEMORY* pVm;
  991. DWORD cHeaps;
  992. DWORD dwRegistryValue;
  993. DBG_DD((3, "DrvGetDirectDrawInfo Called"));
  994. PDev *ppdev=(PDev*) dhpdev;
  995. *pdwNumFourCC = 0;
  996. *pdwNumHeaps = 0;
  997. //On the first call, setup the chip info
  998. if(!(pvmList && pdwFourCC)) {
  999. //
  1000. // Fill in the DDHAL Informational caps
  1001. //
  1002. GetDDHALInfo(ppdev, pHalInfo);
  1003. //
  1004. // Current primary surface attributes:
  1005. //
  1006. pHalInfo->vmiData.pvPrimary = ppdev->pjScreen;
  1007. pHalInfo->vmiData.fpPrimary = 0;
  1008. pHalInfo->vmiData.dwDisplayWidth = ppdev->cxScreen;
  1009. pHalInfo->vmiData.dwDisplayHeight = ppdev->cyScreen;
  1010. pHalInfo->vmiData.lDisplayPitch = ppdev->lDelta;
  1011. pHalInfo->vmiData.ddpfDisplay.dwSize = sizeof(DDPIXELFORMAT);
  1012. pHalInfo->vmiData.ddpfDisplay.dwFlags = DDPF_RGB;
  1013. pHalInfo->vmiData.ddpfDisplay.dwRGBBitCount = ppdev->cjPelSize * 8;
  1014. if ( ppdev->iBitmapFormat == BMF_8BPP ) {
  1015. //
  1016. // Tell DDRAW that the surface is 8-bit color indexed
  1017. //
  1018. pHalInfo->vmiData.ddpfDisplay.dwFlags |= DDPF_PALETTEINDEXED8;
  1019. }
  1020. //
  1021. // These masks will be zero at 8bpp:
  1022. //
  1023. pHalInfo->vmiData.ddpfDisplay.dwRBitMask = ppdev->flRed;
  1024. pHalInfo->vmiData.ddpfDisplay.dwGBitMask = ppdev->flGreen;
  1025. pHalInfo->vmiData.ddpfDisplay.dwBBitMask = ppdev->flBlue;
  1026. //
  1027. // We have to tell DirectDraw our preferred off-screen alignment
  1028. //
  1029. pHalInfo->vmiData.dwOffscreenAlign = 4;
  1030. pHalInfo->vmiData.dwZBufferAlign = 4;
  1031. pHalInfo->vmiData.dwTextureAlign = 4;
  1032. pHalInfo->ddCaps.dwVidMemTotal =
  1033. (ppdev->lVidMemHeight - ppdev->cyScreen) * ppdev->lDelta;
  1034. }
  1035. cHeaps = 0;
  1036. //
  1037. // Determine the YUV modes for Video playback acceleration. We can do YUV
  1038. // conversions at any depth except 8 bits...
  1039. //
  1040. if (ppdev->iBitmapFormat != BMF_8BPP) {
  1041. *pdwNumFourCC = sizeof( fourCC ) / sizeof( fourCC[0] );
  1042. }
  1043. if(DD_P2AGPCAPABLE(ppdev)) {
  1044. bDefineAGPHeap = TRUE;
  1045. cHeaps++;
  1046. }
  1047. // Do we have sufficient videomemory to create an off-screen heap for
  1048. // DDraw? Test how much video memory is left after we subtract
  1049. // that which is being used for the screen.
  1050. if ( (ppdev->cxScreen < ppdev->lVidMemWidth)
  1051. ||(ppdev->cyScreen < ppdev->lVidMemHeight))
  1052. {
  1053. bDefineDDrawHeap = TRUE;
  1054. cHeaps++;
  1055. }
  1056. ppdev->cHeaps = cHeaps;
  1057. *pdwNumHeaps = cHeaps;
  1058. // Define the fourCC's that we support
  1059. if (pdwFourCC) {
  1060. memcpy(pdwFourCC, fourCC, sizeof(fourCC));
  1061. }
  1062. // If pvmList is not NULL then we can go ahead and fill out the VIDEOMEMORY
  1063. // structures which define our requested heaps.
  1064. if(pvmList) {
  1065. pVm=pvmList;
  1066. //
  1067. // Snag a pointer to the video-memory list so that we can use it to
  1068. // call back to DirectDraw to allocate video memory:
  1069. //
  1070. ppdev->pvmList = pVm;
  1071. //
  1072. // Create one heap to describe the unused portion of video memory for
  1073. // DirectDraw use
  1074. //
  1075. // Note: here lVidMemWidth is in "pixel" unit. So we should multiply it
  1076. // by cjPelSize to get actually BYTES of video memory
  1077. //
  1078. // fpStart---Points to the starting address of a memory range in the
  1079. // heap.
  1080. // fpEnd-----Points to the ending address of a memory range if the heap
  1081. // is linear. This address is inclusive, that is, it specifies the last
  1082. // valid address in the range. Thus, the number of bytes specified by
  1083. // fpStart and fpEnd is (fpEnd-fpStart+1).
  1084. //
  1085. // Define the heap for DirectDraw
  1086. //
  1087. if ( bDefineDDrawHeap )
  1088. {
  1089. pVm->dwFlags = VIDMEM_ISLINEAR ;
  1090. pVm->fpStart = ppdev->cyScreen * ppdev->lDelta;
  1091. pVm->fpEnd = ppdev->lVidMemHeight * ppdev->lDelta - 1;
  1092. //
  1093. // DWORD align the size, the hardware should guarantee this
  1094. //
  1095. ASSERTDD(((pVm->fpEnd - pVm->fpStart + 1) & 3) == 0,
  1096. "The off-screen heap size should be DWORD aligned");
  1097. pVm->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  1098. DBG_DD((7, "fpStart %ld fpEnd %ld", pVm->fpStart, pVm->fpEnd));
  1099. DBG_DD((7, "DrvGetDirectDrawInfo Creates 1 heap for DDRAW"));
  1100. pVm++;
  1101. }
  1102. //Define the AGP heap
  1103. if(bDefineAGPHeap) {
  1104. DWORD dwAGPMemBytes;
  1105. BOOL bSuccess;
  1106. // Request 32Mb of AGP Memory, DDRAW will allocate less
  1107. // if this amount is not available
  1108. dwAGPMemBytes = P2_AGP_HEAPSIZE*1024*1024;
  1109. DBG_DD((7, "Initialised AGP Heap for P2"));
  1110. // The start address of the heap,
  1111. // just set to zero as DDRAW handles the allocation
  1112. pVm->fpStart = 0;
  1113. // Fetch the last byte of AGP memory
  1114. pVm->fpEnd = dwAGPMemBytes - 1;
  1115. // drivers can set VIDMEM_ISWC here,
  1116. // then memory will be write combined.
  1117. // but memory on AGP buses is always uncached
  1118. pVm->dwFlags = VIDMEM_ISNONLOCAL | VIDMEM_ISLINEAR | VIDMEM_ISWC;
  1119. // Only use AGP memory for textures and OFFSCREENPLAIN
  1120. pVm->ddsCaps.dwCaps = DDSCAPS_OVERLAY |
  1121. DDSCAPS_FRONTBUFFER |
  1122. DDSCAPS_BACKBUFFER |
  1123. DDSCAPS_ZBUFFER |
  1124. DDSCAPS_3DDEVICE
  1125. ;
  1126. pVm->ddsCapsAlt.dwCaps =DDSCAPS_OVERLAY |
  1127. DDSCAPS_FRONTBUFFER |
  1128. DDSCAPS_BACKBUFFER |
  1129. DDSCAPS_ZBUFFER |
  1130. DDSCAPS_3DDEVICE
  1131. ;
  1132. ++pVm;
  1133. }
  1134. }
  1135. DBG_DD((6, "DrvGetDirectDrawInfo return TRUE"));
  1136. return(TRUE);
  1137. }// DrvGetDirectDrawInfo()
  1138. //-----------------------------------------------------------------------------
  1139. //
  1140. // InitDDHAL
  1141. //
  1142. // do the final initialisation of the HAL:
  1143. // setup DDraw specific variables for the ppdev and fill in all callbacks
  1144. // for DirectDraw
  1145. //
  1146. // No Chip register setup is done here - it is all handled in the mode
  1147. // change code which this function calls
  1148. //
  1149. //-----------------------------------------------------------------------------
  1150. BOOL
  1151. InitDDHAL(PPDev ppdev)
  1152. {
  1153. PERMEDIA_DEFS(ppdev);
  1154. DBG_DD((1, "DDraw:InitDDHAL*************************************" ));
  1155. DBG_DD((1, " ScreenStart =%08lx", ppdev->dwScreenStart));
  1156. DBG_DD((1, " ScreenWidth=%08lx", ppdev->cxScreen ));
  1157. DBG_DD((1, " ScreenHeight=%08lx", ppdev->cyScreen));
  1158. DBG_DD((1, " dwRGBBitCount=%ld", ppdev->ddpfDisplay.dwRGBBitCount ));
  1159. DBG_DD((1, " RMask: 0x%x", ppdev->ddpfDisplay.dwRBitMask ));
  1160. DBG_DD((1, " GMask: 0x%x", ppdev->ddpfDisplay.dwGBitMask ));
  1161. DBG_DD((1, " BMask: 0x%x", ppdev->ddpfDisplay.dwBBitMask ));
  1162. DBG_DD((1, "*****************************************************" ));
  1163. // Fill in the HAL Callback pointers
  1164. memset(&ppdev->DDHALCallbacks, 0, sizeof(DDHAL_DDCALLBACKS));
  1165. ppdev->DDHALCallbacks.dwSize = sizeof(DDHAL_DDCALLBACKS);
  1166. ppdev->DDHALCallbacks.WaitForVerticalBlank = DdWaitForVerticalBlank;
  1167. ppdev->DDHALCallbacks.CanCreateSurface = DdCanCreateSurface;
  1168. ppdev->DDHALCallbacks.GetScanLine = DdGetScanLine;
  1169. ppdev->DDHALCallbacks.MapMemory = DdMapMemory;
  1170. //@@BEGIN_DDKSPLIT
  1171. #if MULTITHREADED
  1172. ppdev->DDHALCallbacks.CreateSurface = MtDdCreateSurface;
  1173. #else
  1174. //@@END_DDKSPLIT
  1175. ppdev->DDHALCallbacks.CreateSurface = DdCreateSurface;
  1176. //@@BEGIN_DDKSPLIT
  1177. #endif MULTITHREADED
  1178. //@@END_DDKSPLIT
  1179. // Fill in the HAL Callback flags
  1180. ppdev->DDHALCallbacks.dwFlags = DDHAL_CB32_WAITFORVERTICALBLANK |
  1181. DDHAL_CB32_MAPMEMORY |
  1182. DDHAL_CB32_GETSCANLINE |
  1183. DDHAL_CB32_CANCREATESURFACE |
  1184. DDHAL_CB32_CREATESURFACE;
  1185. // Fill in the Surface Callback pointers
  1186. memset(&ppdev->DDSurfCallbacks, 0, sizeof(DDHAL_DDSURFACECALLBACKS));
  1187. ppdev->DDSurfCallbacks.dwSize = sizeof(DDHAL_DDSURFACECALLBACKS);
  1188. //@@BEGIN_DDKSPLIT
  1189. #if MULTITHREADED
  1190. ppdev->DDSurfCallbacks.DestroySurface = MtDdDestroySurface;
  1191. ppdev->DDSurfCallbacks.Flip = MtDdFlip;
  1192. ppdev->DDSurfCallbacks.Lock = MtDdLock;
  1193. ppdev->DDSurfCallbacks.GetBltStatus = DdGetBltStatus; // Internally protected
  1194. ppdev->DDSurfCallbacks.GetFlipStatus = MtDdGetFlipStatus;
  1195. ppdev->DDSurfCallbacks.Blt = MtDdBlt;
  1196. #else
  1197. //@@END_DDKSPLIT
  1198. ppdev->DDSurfCallbacks.DestroySurface = DdDestroySurface;
  1199. ppdev->DDSurfCallbacks.Flip = DdFlip;
  1200. ppdev->DDSurfCallbacks.Lock = DdLock;
  1201. ppdev->DDSurfCallbacks.GetBltStatus = DdGetBltStatus;
  1202. ppdev->DDSurfCallbacks.GetFlipStatus = DdGetFlipStatus;
  1203. ppdev->DDSurfCallbacks.Blt = DdBlt;
  1204. //@@BEGIN_DDKSPLIT
  1205. #endif MULTITHREADED
  1206. //@@END_DDKSPLIT
  1207. ppdev->DDSurfCallbacks.dwFlags = DDHAL_SURFCB32_DESTROYSURFACE |
  1208. DDHAL_SURFCB32_FLIP |
  1209. DDHAL_SURFCB32_LOCK |
  1210. DDHAL_SURFCB32_BLT |
  1211. DDHAL_SURFCB32_GETBLTSTATUS |
  1212. DDHAL_SURFCB32_GETFLIPSTATUS;
  1213. //@@BEGIN_DDKSPLIT
  1214. #if MULTITHREADED
  1215. ppdev->DDSurfCallbacks.SetColorKey = MtDdSetColorKey;
  1216. #else
  1217. //@@END_DDKSPLIT
  1218. ppdev->DDSurfCallbacks.SetColorKey = DdSetColorKey;
  1219. //@@BEGIN_DDKSPLIT
  1220. #endif MULTITHREADED
  1221. //@@END_DDKSPLIT
  1222. ppdev->DDSurfCallbacks.dwFlags |= DDHAL_SURFCB32_SETCOLORKEY;
  1223. // Fill in the DDHAL Informational caps
  1224. GetDDHALInfo(ppdev, &ppdev->ddhi32);
  1225. return (TRUE);
  1226. }// InitDDHAL()
  1227. //-----------------------------------------------------------------------------
  1228. //
  1229. // bIsStereoMode
  1230. //
  1231. // Decide if mode can be displayed as stereo mode. Here we limit stereo
  1232. // modes so that two front and two backbuffers can be created for rendering.
  1233. //
  1234. //-----------------------------------------------------------------------------
  1235. BOOL bIsStereoMode(PDev *ppdev, PDD_STEREOMODE pDDStereoMode)
  1236. {
  1237. pDDStereoMode->bSupported = FALSE;
  1238. // we need to check dwBpp for a valid value as PDD_STEREOMODE.dwBpp is a
  1239. // parameter passed on from the user mode API call
  1240. if ((pDDStereoMode->dwWidth >= 320) &&
  1241. (pDDStereoMode->dwHeight >= 240) &&
  1242. (pDDStereoMode->dwBpp >= 8) &&
  1243. (pDDStereoMode->dwBpp <= 32)
  1244. )
  1245. {
  1246. DWORD dwLines=ppdev->FrameBufferLength/
  1247. (pDDStereoMode->dwWidth*pDDStereoMode->dwBpp/8);
  1248. if (dwLines > (pDDStereoMode->dwHeight*4))
  1249. {
  1250. pDDStereoMode->bSupported = TRUE;
  1251. }
  1252. }
  1253. return pDDStereoMode->bSupported;
  1254. }
  1255. //-----------------------------------------------------------------------------
  1256. //
  1257. // DdGetDriverInfo
  1258. //
  1259. // callback for various new HAL features, post DX3.
  1260. //
  1261. //-----------------------------------------------------------------------------
  1262. DWORD CALLBACK
  1263. DdGetDriverInfo(LPDDHAL_GETDRIVERINFODATA lpData)
  1264. {
  1265. PPDev ppdev=(PPDev)lpData->dhpdev;
  1266. PERMEDIA_DEFS(ppdev);
  1267. DWORD dwSize;
  1268. DBG_DD(( 2, "DDraw:GetDriverInfo"));
  1269. // Get a pointer to the chip we are on.
  1270. // Default to 'not supported'
  1271. lpData->ddRVal = DDERR_CURRENTLYNOTAVAIL;
  1272. ppdev = (PDev*) lpData->dhpdev;
  1273. // fill in supported stuff
  1274. if (IsEqualIID(&lpData->guidInfo, &GUID_D3DCallbacks3))
  1275. {
  1276. D3DHAL_CALLBACKS3 D3DCB3;
  1277. DBG_DD((3," GUID_D3DCallbacks3"));
  1278. memset(&D3DCB3, 0, sizeof(D3DHAL_CALLBACKS3));
  1279. D3DCB3.dwSize = sizeof(D3DHAL_CALLBACKS3);
  1280. D3DCB3.lpvReserved = NULL;
  1281. D3DCB3.ValidateTextureStageState = D3DValidateTextureStageState;
  1282. //@@BEGIN_DDKSPLIT
  1283. #if MULTITHREADED
  1284. D3DCB3.DrawPrimitives2 = MtD3DDrawPrimitives2;
  1285. #else
  1286. //@@END_DDKSPLIT
  1287. D3DCB3.DrawPrimitives2 = D3DDrawPrimitives2;
  1288. //@@BEGIN_DDKSPLIT
  1289. #endif MULTITHREADED
  1290. //@@END_DDKSPLIT
  1291. D3DCB3.dwFlags |= D3DHAL3_CB32_DRAWPRIMITIVES2 |
  1292. D3DHAL3_CB32_VALIDATETEXTURESTAGESTATE |
  1293. 0;
  1294. lpData->dwActualSize = sizeof(D3DHAL_CALLBACKS3);
  1295. dwSize=min(lpData->dwExpectedSize,sizeof(D3DHAL_CALLBACKS3));
  1296. memcpy(lpData->lpvData, &D3DCB3, dwSize);
  1297. lpData->ddRVal = DD_OK;
  1298. }
  1299. else if (IsEqualIID(&lpData->guidInfo, &GUID_D3DExtendedCaps))
  1300. {
  1301. D3DNTHAL_D3DEXTENDEDCAPS D3DExtendedCaps;
  1302. DBG_DD((3," GUID_D3DExtendedCaps"));
  1303. memset(&D3DExtendedCaps, 0, sizeof(D3DExtendedCaps));
  1304. dwSize=min(lpData->dwExpectedSize, sizeof(D3DExtendedCaps));
  1305. lpData->dwActualSize = dwSize;
  1306. D3DExtendedCaps.dwSize = dwSize;
  1307. // number of (multi)textures we support simultaneusly for DX6
  1308. D3DExtendedCaps.dwFVFCaps = 1;
  1309. D3DExtendedCaps.dwMinTextureWidth = 1;
  1310. D3DExtendedCaps.dwMinTextureHeight = 1;
  1311. D3DExtendedCaps.dwMaxTextureWidth = 2048;
  1312. D3DExtendedCaps.dwMaxTextureHeight = 2048;
  1313. D3DExtendedCaps.dwMinStippleWidth = 8;
  1314. D3DExtendedCaps.dwMaxStippleWidth = 8;
  1315. D3DExtendedCaps.dwMinStippleHeight = 8;
  1316. D3DExtendedCaps.dwMaxStippleHeight = 8;
  1317. D3DExtendedCaps.dwTextureOpCaps =
  1318. D3DTEXOPCAPS_DISABLE |
  1319. D3DTEXOPCAPS_SELECTARG1 |
  1320. D3DTEXOPCAPS_SELECTARG2 |
  1321. D3DTEXOPCAPS_MODULATE |
  1322. D3DTEXOPCAPS_ADD |
  1323. D3DTEXOPCAPS_BLENDTEXTUREALPHA |
  1324. 0;
  1325. D3DExtendedCaps.wMaxTextureBlendStages = 1;
  1326. D3DExtendedCaps.wMaxSimultaneousTextures = 1;
  1327. // Full range of the integer (non-fractional) bits of the
  1328. // post-normalized texture indices. If the
  1329. // D3DDEVCAPS_TEXREPEATNOTSCALEDBYSIZE bit is set, the
  1330. // device defers scaling by the texture size until after
  1331. // the texture address mode is applied. If it isn't set,
  1332. // the device scales the texture indices by the texture size
  1333. // (largest level-of-detail) prior to interpolation.
  1334. D3DExtendedCaps.dwMaxTextureRepeat = 2048;
  1335. // In order to support stencil buffers in DX6 we need besides
  1336. // setting these caps and handling the proper renderstates to
  1337. // declare the appropriate z buffer pixel formats here in
  1338. // response to the GUID_ZPixelFormats and implement the
  1339. // Clear2 callback. Also , we need to be able to create the
  1340. // appropriate ddraw surfaces.
  1341. #if D3D_STENCIL
  1342. D3DExtendedCaps.dwStencilCaps = 0 |
  1343. D3DSTENCILCAPS_KEEP |
  1344. D3DSTENCILCAPS_ZERO |
  1345. D3DSTENCILCAPS_REPLACE |
  1346. D3DSTENCILCAPS_INCRSAT |
  1347. D3DSTENCILCAPS_DECRSAT |
  1348. D3DSTENCILCAPS_INVERT;
  1349. #endif
  1350. #if D3DDX7_TL
  1351. // In order to use hw accelerated T&L we must declare
  1352. // how many simultaneously active lights we can handle.
  1353. D3DExtendedCaps.dwMaxActiveLights = 0;
  1354. #endif //D3DDX7_TL
  1355. //@@BEGIN_DDKSPLIT
  1356. #if D3D_POINTSPRITES
  1357. // Parameter for point sprites
  1358. D3DExtendedCaps.dvMaxPointSize = 10.0;
  1359. #endif // D3D_POINTSPRITES
  1360. //@@END_DDKSPLIT
  1361. memcpy(lpData->lpvData, &D3DExtendedCaps, dwSize);
  1362. lpData->ddRVal = DD_OK;
  1363. }
  1364. else if (IsEqualIID(&lpData->guidInfo, &GUID_ZPixelFormats))
  1365. {
  1366. DDPIXELFORMAT ddZBufPixelFormat[2];
  1367. DWORD dwNumZPixelFormats;
  1368. DBG_DD((3," GUID_ZPixelFormats"));
  1369. memset(ddZBufPixelFormat, 0, sizeof(ddZBufPixelFormat));
  1370. #if D3D_STENCIL
  1371. dwSize = (DWORD)min(lpData->dwExpectedSize, 2*sizeof(DDPIXELFORMAT));
  1372. lpData->dwActualSize = 2*sizeof(DDPIXELFORMAT) + sizeof(DWORD);
  1373. #else
  1374. dwSize = (DWORD)min(lpData->dwExpectedSize, 1*sizeof(DDPIXELFORMAT));
  1375. lpData->dwActualSize = 1*sizeof(DDPIXELFORMAT) + sizeof(DWORD);
  1376. #endif
  1377. // If we didn't support stencils, we would only fill one 16-bit
  1378. // Z Buffer format since that is all what the Permedia supports.
  1379. // Drivers that implement stencil buffer support (like this one)
  1380. // have to report here all Z Buffer formats supported since they
  1381. // have to support the Clear2 callback (or the D3DDP2OP_CLEAR
  1382. // token)
  1383. #if D3D_STENCIL
  1384. dwNumZPixelFormats = 2;
  1385. #else
  1386. dwNumZPixelFormats = 1;
  1387. #endif
  1388. ddZBufPixelFormat[0].dwSize = sizeof(DDPIXELFORMAT);
  1389. ddZBufPixelFormat[0].dwFlags = DDPF_ZBUFFER;
  1390. ddZBufPixelFormat[0].dwFourCC = 0;
  1391. ddZBufPixelFormat[0].dwZBufferBitDepth = 16;
  1392. ddZBufPixelFormat[0].dwStencilBitDepth = 0;
  1393. ddZBufPixelFormat[0].dwZBitMask = 0xFFFF;
  1394. ddZBufPixelFormat[0].dwStencilBitMask = 0x0000;
  1395. ddZBufPixelFormat[0].dwRGBZBitMask = 0;
  1396. #if D3D_STENCIL
  1397. ddZBufPixelFormat[1].dwSize = sizeof(DDPIXELFORMAT);
  1398. ddZBufPixelFormat[1].dwFlags = DDPF_ZBUFFER | DDPF_STENCILBUFFER;
  1399. ddZBufPixelFormat[1].dwFourCC = 0;
  1400. // The sum of the z buffer bit depth AND the stencil depth
  1401. // should be included here
  1402. ddZBufPixelFormat[1].dwZBufferBitDepth = 16;
  1403. ddZBufPixelFormat[1].dwStencilBitDepth = 1;
  1404. ddZBufPixelFormat[1].dwZBitMask = 0x7FFF;
  1405. ddZBufPixelFormat[1].dwStencilBitMask = 0x8000;
  1406. ddZBufPixelFormat[1].dwRGBZBitMask = 0;
  1407. #endif
  1408. memcpy(lpData->lpvData, &dwNumZPixelFormats, sizeof(DWORD));
  1409. memcpy((LPVOID)((LPBYTE)(lpData->lpvData) + sizeof(DWORD)),
  1410. ddZBufPixelFormat, dwSize);
  1411. lpData->ddRVal = DD_OK;
  1412. }
  1413. else if (IsEqualIID(&(lpData->guidInfo),
  1414. &GUID_D3DParseUnknownCommandCallback))
  1415. {
  1416. DBG_DD((3," GUID_D3DParseUnknownCommandCallback"));
  1417. ppdev->pD3DParseUnknownCommand =
  1418. (PFND3DNTPARSEUNKNOWNCOMMAND)(lpData->lpvData);
  1419. lpData->ddRVal = DD_OK;
  1420. }
  1421. //@@BEGIN_DDKSPLIT
  1422. #if DX7_ALPHABLT
  1423. else if (IsEqualIID(&(lpData->guidInfo), &GUID_DDMoreCaps))
  1424. {
  1425. DD_MORECAPS DDMoreCaps;
  1426. DBG_DD((3," GUID_DDMoreCaps"));
  1427. // here we set all the caps for the new
  1428. // DirectDraw 7 AlphaBlt callback
  1429. memset(&DDMoreCaps, 0, sizeof(DD_MORECAPS));
  1430. DDMoreCaps.dwSize=sizeof(DD_MORECAPS);
  1431. // alpha caps for Vmem->Vmem blts
  1432. // claim to do lots of stuff, we can still fail in callback
  1433. DDMoreCaps.dwAlphaCaps = DDALPHACAPS_BLTALPHAPIXELS |
  1434. DDALPHACAPS_BLTSATURATE |
  1435. DDALPHACAPS_BLTPREMULT |
  1436. DDALPHACAPS_BLTNONPREMULT |
  1437. DDALPHACAPS_BLTALPHAFILL |
  1438. DDALPHACAPS_BLTARGBSCALE1F |
  1439. DDALPHACAPS_BLTARGBSCALE2F |
  1440. DDALPHACAPS_BLTARGBSCALE4F |
  1441. DDALPHACAPS_BLTALPHAANDARGBSCALING;
  1442. DDMoreCaps.dwSVBAlphaCaps = 0;
  1443. // alpha capabilities for System->Vmem blts
  1444. DDMoreCaps.dwVSBAlphaCaps = 0;
  1445. // alpha capabilities for Vmem->System blts
  1446. DDMoreCaps.dwSSBAlphaCaps = 0;
  1447. // alpha capabilities for System->System blts
  1448. // filter caps for Vmem->Vmem blts
  1449. DDMoreCaps.dwFilterCaps = DDFILTCAPS_BLTQUALITYFILTER |
  1450. DDFILTCAPS_BLTCANDISABLEFILTER;
  1451. DDMoreCaps.dwSVBFilterCaps= 0;
  1452. // filter capabilities for System->Vmem blts
  1453. DDMoreCaps.dwVSBFilterCaps= 0;
  1454. // filter capabilities for Vmem->System blts
  1455. DDMoreCaps.dwSSBFilterCaps= 0;
  1456. // filter capabilities for System->System blts
  1457. lpData->dwActualSize = sizeof(DDMoreCaps);
  1458. dwSize=min( sizeof(DDMoreCaps), lpData->dwExpectedSize);
  1459. memcpy(lpData->lpvData, &DDMoreCaps, dwSize);
  1460. lpData->ddRVal = DD_OK;
  1461. }
  1462. #endif
  1463. //@@END_DDKSPLIT
  1464. else if (IsEqualIID(&(lpData->guidInfo), &GUID_Miscellaneous2Callbacks) )
  1465. {
  1466. BOOL bRet;
  1467. DWORD dwResult;
  1468. DDHAL_DDMISCELLANEOUS2CALLBACKS MISC2_CB;
  1469. DBG_DD((3," GUID_Miscellaneous2Callbacks2"));
  1470. memset(&MISC2_CB, 0, sizeof(DDHAL_DDMISCELLANEOUS2CALLBACKS));
  1471. MISC2_CB.dwSize = sizeof(DDHAL_DDMISCELLANEOUS2CALLBACKS);
  1472. MISC2_CB.dwFlags = 0
  1473. //@@BEGIN_DDKSPLIT
  1474. #if DX7_ALPHABLT
  1475. | DDHAL_MISC2CB32_ALPHABLT
  1476. #endif
  1477. //@@END_DDKSPLIT
  1478. | DDHAL_MISC2CB32_CREATESURFACEEX
  1479. | DDHAL_MISC2CB32_GETDRIVERSTATE
  1480. | DDHAL_MISC2CB32_DESTROYDDLOCAL;
  1481. MISC2_CB.GetDriverState = D3DGetDriverState;
  1482. MISC2_CB.CreateSurfaceEx = D3DCreateSurfaceEx;
  1483. MISC2_CB.DestroyDDLocal = D3DDestroyDDLocal;
  1484. //@@BEGIN_DDKSPLIT
  1485. #if DX7_ALPHABLT
  1486. MISC2_CB.AlphaBlt = DdAlphaBlt;
  1487. #endif
  1488. //@@END_DDKSPLIT
  1489. lpData->dwActualSize = sizeof(MISC2_CB);
  1490. dwSize = min(sizeof(MISC2_CB),lpData->dwExpectedSize);
  1491. memcpy(lpData->lpvData, &MISC2_CB, dwSize);
  1492. lpData->ddRVal = DD_OK;
  1493. }
  1494. else if (IsEqualIID(&(lpData->guidInfo), &GUID_UpdateNonLocalHeap))
  1495. {
  1496. LPDDHAL_UPDATENONLOCALHEAPDATA pDDNonLocalHeap;
  1497. DBG_DD((3," GUID_UpdateNonLocalHeap"));
  1498. pDDNonLocalHeap = (LPDDHAL_UPDATENONLOCALHEAPDATA)lpData->lpvData;
  1499. ppdev->dwGARTLinBase = pDDNonLocalHeap->fpGARTLin;
  1500. ppdev->dwGARTDevBase = pDDNonLocalHeap->fpGARTDev;
  1501. // These values are used to specify the base address of the
  1502. // visible 8Mb window of AGP memory
  1503. ppdev->dwGARTLin = pDDNonLocalHeap->fpGARTLin;
  1504. ppdev->dwGARTDev = pDDNonLocalHeap->fpGARTDev;
  1505. DDCONTEXT;
  1506. SYNC_WITH_PERMEDIA;
  1507. LD_PERMEDIA_REG (PREG_AGPTEXBASEADDRESS,(ULONG)ppdev->dwGARTDev);
  1508. DBG_DD((3,"GartLin: 0x%x, GartDev: 0x%x",
  1509. (ULONG)ppdev->dwGARTLin, ppdev->dwGARTDev));
  1510. lpData->ddRVal = DD_OK;
  1511. }
  1512. else if (IsEqualIID(&(lpData->guidInfo), &GUID_GetHeapAlignment) )
  1513. {
  1514. LPDDHAL_GETHEAPALIGNMENTDATA lpFData=
  1515. (LPDDHAL_GETHEAPALIGNMENTDATA) lpData->lpvData;
  1516. DBG_DD((3," GUID_GetHeapAlignment"));
  1517. lpData->ddRVal = DD_OK;
  1518. }
  1519. else if (IsEqualIID(&(lpData->guidInfo), &GUID_NTPrivateDriverCaps) )
  1520. {
  1521. DD_NTPRIVATEDRIVERCAPS DDPrivateDriverCaps;
  1522. DBG_DD((3," GUID_NTPrivateDriverCaps"));
  1523. memset(&DDPrivateDriverCaps, 0, sizeof(DDPrivateDriverCaps));
  1524. DDPrivateDriverCaps.dwSize=sizeof(DDPrivateDriverCaps);
  1525. // we want the kernel to call us when a primary surface is created
  1526. // so that we can store some private information in the
  1527. // lpGbl->dwReserved1 field
  1528. DDPrivateDriverCaps.dwPrivateCaps=DDHAL_PRIVATECAP_NOTIFYPRIMARYCREATION;
  1529. lpData->dwActualSize =sizeof(DDPrivateDriverCaps);
  1530. dwSize = min(sizeof(DDPrivateDriverCaps),lpData->dwExpectedSize);
  1531. memcpy(lpData->lpvData, &DDPrivateDriverCaps, dwSize);
  1532. lpData->ddRVal = DD_OK;
  1533. }
  1534. #if DX7_STEREO
  1535. else if (IsEqualIID(&(lpData->guidInfo), &GUID_DDMoreSurfaceCaps) )
  1536. {
  1537. DD_MORESURFACECAPS DDMoreSurfaceCaps;
  1538. DDSCAPSEX ddsCapsEx, ddsCapsExAlt;
  1539. ULONG ulCopyPointer;
  1540. DBG_DD((3," GUID_DDMoreSurfaceCaps"));
  1541. // fill in everything until expectedsize...
  1542. memset(&DDMoreSurfaceCaps, 0, sizeof(DDMoreSurfaceCaps));
  1543. // Caps for heaps 2..n
  1544. memset(&ddsCapsEx, 0, sizeof(ddsCapsEx));
  1545. memset(&ddsCapsExAlt, 0, sizeof(ddsCapsEx));
  1546. DDMoreSurfaceCaps.dwSize=lpData->dwExpectedSize;
  1547. DBG_DD((3," stereo support: %ld", ppdev->bCanDoStereo));
  1548. if (ppdev->bCanDoStereo)
  1549. {
  1550. DDMoreSurfaceCaps.ddsCapsMore.dwCaps2 =
  1551. DDSCAPS2_STEREOSURFACELEFT;
  1552. }
  1553. lpData->dwActualSize = lpData->dwExpectedSize;
  1554. dwSize = min(sizeof(DDMoreSurfaceCaps),lpData->dwExpectedSize);
  1555. memcpy(lpData->lpvData, &DDMoreSurfaceCaps, dwSize);
  1556. // now fill in other heaps...
  1557. while (dwSize < lpData->dwExpectedSize)
  1558. {
  1559. memcpy( (PBYTE)lpData->lpvData+dwSize,
  1560. &ddsCapsEx,
  1561. sizeof(DDSCAPSEX));
  1562. dwSize += sizeof(DDSCAPSEX);
  1563. memcpy( (PBYTE)lpData->lpvData+dwSize,
  1564. &ddsCapsExAlt,
  1565. sizeof(DDSCAPSEX));
  1566. dwSize += sizeof(DDSCAPSEX);
  1567. }
  1568. lpData->ddRVal = DD_OK;
  1569. }
  1570. else if (IsEqualIID(&(lpData->guidInfo), &GUID_DDStereoMode) ) {
  1571. PDD_STEREOMODE pDDStereoMode;
  1572. // Permedia supports all modes as stereo modes.
  1573. // for test purposes, we restrict them to something
  1574. // larger than 320x240
  1575. //
  1576. // note: this GUID_DDStereoMode is only used on NT to
  1577. // report stereo modes. There is no need to implement
  1578. // it in win9x drivers. Win9x drivers report stereo
  1579. // modes by setting the DDMODEINFO_STEREO bit in the
  1580. // dwFlags member of the DDHALMODEINFO structure.
  1581. // It is also recommended to report DDMODEINFO_MAXREFRESH
  1582. // for stereo modes when running under a runtime >= DX7 to
  1583. // allow applications to select higher refresh rates for
  1584. // stereo modes.
  1585. //
  1586. if (lpData->dwExpectedSize >= sizeof(PDD_STEREOMODE))
  1587. {
  1588. pDDStereoMode = (PDD_STEREOMODE) lpData->lpvData;
  1589. bIsStereoMode( ppdev, pDDStereoMode);
  1590. DBG_DD((3," GUID_DDStereoMode(%d,%d,%d,%d=%d)",
  1591. pDDStereoMode->dwWidth,
  1592. pDDStereoMode->dwHeight,
  1593. pDDStereoMode->dwBpp,
  1594. pDDStereoMode->dwRefreshRate,
  1595. pDDStereoMode->bSupported));
  1596. lpData->dwActualSize = sizeof(DD_STEREOMODE);
  1597. lpData->ddRVal = DD_OK;
  1598. }
  1599. }
  1600. #endif
  1601. else if (IsEqualIID(&(lpData->guidInfo), &GUID_NonLocalVidMemCaps) )
  1602. {
  1603. DD_NONLOCALVIDMEMCAPS DDNonLocalVidMemCaps;
  1604. DBG_DD((3," GUID_DDNonLocalVidMemCaps"));
  1605. memset(&DDNonLocalVidMemCaps, 0, sizeof(DDNonLocalVidMemCaps));
  1606. DDNonLocalVidMemCaps.dwSize=sizeof(DDNonLocalVidMemCaps);
  1607. //fill in all supported nonlocal to videomemory blts
  1608. //
  1609. DDNonLocalVidMemCaps.dwNLVBCaps = DDCAPS_BLT |
  1610. DDCAPS_BLTSTRETCH |
  1611. DDCAPS_BLTQUEUE |
  1612. DDCAPS_COLORKEY |
  1613. DDCAPS_ALPHA |
  1614. DDCAPS_CANBLTSYSMEM;
  1615. DDNonLocalVidMemCaps.dwNLVBCaps2 = 0;
  1616. DDNonLocalVidMemCaps.dwNLVBCKeyCaps=DDCKEYCAPS_SRCBLT |
  1617. DDCKEYCAPS_SRCBLTCLRSPACE;
  1618. DDNonLocalVidMemCaps.dwNLVBFXCaps = DDFXCAPS_BLTALPHA |
  1619. DDFXCAPS_BLTFILTER |
  1620. DDFXCAPS_BLTSTRETCHY |
  1621. DDFXCAPS_BLTSTRETCHX |
  1622. DDFXCAPS_BLTSTRETCHYN |
  1623. DDFXCAPS_BLTSTRETCHXN |
  1624. DDFXCAPS_BLTSHRINKY |
  1625. DDFXCAPS_BLTSHRINKX |
  1626. DDFXCAPS_BLTSHRINKYN |
  1627. DDFXCAPS_BLTSHRINKXN |
  1628. DDFXCAPS_BLTMIRRORUPDOWN |
  1629. DDFXCAPS_BLTMIRRORLEFTRIGHT;
  1630. if (ppdev->iBitmapFormat != BMF_8BPP)
  1631. {
  1632. DDNonLocalVidMemCaps.dwNLVBCaps |= DDCAPS_BLTFOURCC;
  1633. DDNonLocalVidMemCaps.dwNLVBCKeyCaps|=DDCKEYCAPS_SRCBLTCLRSPACEYUV;
  1634. }
  1635. for(INT i = 0; i < DD_ROP_SPACE; i++ )
  1636. DDNonLocalVidMemCaps.dwNLVBRops[i] = rops[i];
  1637. lpData->dwActualSize =sizeof(DDNonLocalVidMemCaps);
  1638. dwSize = min(sizeof(DDNonLocalVidMemCaps),lpData->dwExpectedSize);
  1639. memcpy(lpData->lpvData, &DDNonLocalVidMemCaps, dwSize);
  1640. lpData->ddRVal = DD_OK;
  1641. } else if (IsEqualIID(&lpData->guidInfo, &GUID_NTCallbacks))
  1642. {
  1643. DD_NTCALLBACKS NtCallbacks;
  1644. memset(&NtCallbacks, 0, sizeof(NtCallbacks));
  1645. dwSize = min(lpData->dwExpectedSize, sizeof(DD_NTCALLBACKS));
  1646. NtCallbacks.dwSize = dwSize;
  1647. NtCallbacks.dwFlags = DDHAL_NTCB32_FREEDRIVERMEMORY
  1648. | DDHAL_NTCB32_SETEXCLUSIVEMODE
  1649. | DDHAL_NTCB32_FLIPTOGDISURFACE
  1650. ;
  1651. //@@BEGIN_DDKSPLIT
  1652. #if MULTITHREADED
  1653. NtCallbacks.FreeDriverMemory = DdFreeDriverMemory; // Internally protected
  1654. NtCallbacks.SetExclusiveMode = MtDdSetExclusiveMode;
  1655. NtCallbacks.FlipToGDISurface = MtDdFlipToGDISurface;
  1656. #else
  1657. //@@END_DDKSPLIT
  1658. NtCallbacks.FreeDriverMemory = DdFreeDriverMemory;
  1659. NtCallbacks.SetExclusiveMode = DdSetExclusiveMode;
  1660. NtCallbacks.FlipToGDISurface = DdFlipToGDISurface;
  1661. //@@BEGIN_DDKSPLIT
  1662. #endif MULTITHREADED
  1663. //@@END_DDKSPLIT
  1664. memcpy(lpData->lpvData, &NtCallbacks, dwSize);
  1665. lpData->ddRVal = DD_OK;
  1666. }
  1667. // We always handled it.
  1668. return DDHAL_DRIVER_HANDLED;
  1669. } // GetDriverInfo
  1670. //-----------------------------------------------------------------------------
  1671. //
  1672. // updateFlipStatus
  1673. //
  1674. // return DD_OK when last flip has occured.
  1675. //
  1676. //-----------------------------------------------------------------------------
  1677. HRESULT
  1678. updateFlipStatus( PPDev ppdev )
  1679. {
  1680. PERMEDIA_DEFS(ppdev);
  1681. DBG_DD((6, "DDraw:updateFlipStatus"));
  1682. // we assume that we are already in the DDraw/D3D context.
  1683. // read Permedia register which tells us if there is a flip pending
  1684. if (ppdev->dwNewDDSurfaceOffset!=0xffffffff)
  1685. {
  1686. ULONG ulScreenBase=READ_PERMEDIA_REG(PREG_SCREENBASE);
  1687. if (ulScreenBase!=
  1688. ppdev->dwNewDDSurfaceOffset)
  1689. {
  1690. DBG_DD((7," SurfaceOffset %08lx instead of %08lx",
  1691. ulScreenBase,
  1692. ppdev->dwNewDDSurfaceOffset));
  1693. //
  1694. // make sure all pending data was flushed!
  1695. //
  1696. FLUSHDMA();
  1697. //
  1698. // if we are busy, return
  1699. // otherwise the pipeline is empty and we can
  1700. // fall through and to check if the chip already flipped.
  1701. //
  1702. if (DRAW_ENGINE_BUSY)
  1703. return DDERR_WASSTILLDRAWING;
  1704. }
  1705. }
  1706. DWORD dwVideoControl=READ_PERMEDIA_REG(PREG_VIDEOCONTROL);
  1707. if (dwVideoControl & PREG_VC_SCREENBASEPENDING)
  1708. {
  1709. DBG_DD((7," VideoControl still pending (%08lx)",dwVideoControl));
  1710. return DDERR_WASSTILLDRAWING;
  1711. }
  1712. return DD_OK;
  1713. } // updateFlipStatus
  1714. //@@BEGIN_DDKSPLIT
  1715. #if MULTITHREADED
  1716. //-----------------------------------------------------------------------------
  1717. //
  1718. // Multithread support wrappers for Dx callback functions
  1719. //
  1720. //-----------------------------------------------------------------------------
  1721. //DWORD CALLBACK MtDdBlt( LPDDHAL_BLTDATA lpBlt );
  1722. WRAPMTDXCALLBACK(DD, DdBlt, LPDDHAL_BLTDATA, lpBlt,
  1723. lpBlt->lpDD->dhpdev);
  1724. //DWORD CALLBACK MtDdCreateSurface( LPDDHAL_CREATESURFACEDATA pcsd);
  1725. WRAPMTDXCALLBACK(DD, DdCreateSurface, LPDDHAL_CREATESURFACEDATA, pcsd,
  1726. pcsd->lpDD->dhpdev);
  1727. //DWORD CALLBACK MtDdDestroySurface( LPDDHAL_DESTROYSURFACEDATA psdd);
  1728. WRAPMTDXCALLBACK(DD, DdDestroySurface, LPDDHAL_DESTROYSURFACEDATA, psdd,
  1729. psdd->lpDD->dhpdev);
  1730. //DWORD CALLBACK MtDdFlip( LPDDHAL_FLIPDATA lpFlipData);
  1731. WRAPMTDXCALLBACK(DD, DdFlip, LPDDHAL_FLIPDATA, lpFlipData,
  1732. lpFlipData->lpDD->dhpdev);
  1733. //DWORD CALLBACK MtDdFlipToGDISurface(PDD_FLIPTOGDISURFACEDATA lpFlipToGDISurface);
  1734. WRAPMTDXCALLBACK(DD, DdFlipToGDISurface, PDD_FLIPTOGDISURFACEDATA, lpFlipToGDISurface,
  1735. lpFlipToGDISurface->lpDD->dhpdev);
  1736. //DWORD CALLBACK MtDdGetFlipStatus(LPDDHAL_GETFLIPSTATUSDATA lpGetFlipStatus);
  1737. WRAPMTDXCALLBACK(DD, DdGetFlipStatus, LPDDHAL_GETFLIPSTATUSDATA, lpGetFlipStatus,
  1738. lpGetFlipStatus->lpDD->dhpdev);
  1739. //DWORD CALLBACK MtDdLock( LPDDHAL_LOCKDATA lpLockData );
  1740. WRAPMTDXCALLBACK(DD, DdLock, LPDDHAL_LOCKDATA, lpLockData,
  1741. lpLockData->lpDD->dhpdev);
  1742. //DWORD CALLBACK MtDdSetExclusiveMode(PDD_SETEXCLUSIVEMODEDATA lpSetExclusiveMode);
  1743. WRAPMTDXCALLBACK(DD, DdSetExclusiveMode, PDD_SETEXCLUSIVEMODEDATA, lpSetExclusiveMode,
  1744. lpSetExclusiveMode->lpDD->dhpdev);
  1745. #endif MULTITHREADED
  1746. //@@END_DDKSPLIT