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.

3790 lines
144 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * **************************
  4. * * DirectDraw SAMPLE CODE *
  5. * **************************
  6. *
  7. * Module Name: dd.c
  8. *
  9. * Content: Main DirectDraw callbacks
  10. *
  11. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #define INITGUID
  15. #include "glint.h"
  16. #if W95_DDRAW
  17. #include "ddkmmini.h"
  18. #include <mmsystem.h>
  19. #endif
  20. #include "dma.h"
  21. #include "tag.h"
  22. void __GetDDHALInfo(P3_THUNKEDDATA* pThisDisplay, DDHALINFO* pHALInfo);
  23. #if W95_DDRAW
  24. // These variables MUST be initialised, therby forcing them into DATA.
  25. // This segment is shared.
  26. P3_THUNKEDDATA* g_pDriverData = NULL;
  27. //-----------------------------------------------------------------------------
  28. //
  29. // ***************************WIN9x ONLY**********************************
  30. //
  31. // DllMain
  32. //
  33. // DLL Entry point.
  34. //
  35. //-----------------------------------------------------------------------------
  36. BOOL WINAPI
  37. DllMain(
  38. HINSTANCE hModule,
  39. DWORD dwReason,
  40. LPVOID lpvReserved)
  41. {
  42. // The 16 bit side requires an HINSTANCE
  43. g_DXGlobals.hInstance = hModule;
  44. switch( dwReason )
  45. {
  46. case DLL_PROCESS_ATTACH:
  47. // We don't care about thread attach messages.
  48. DisableThreadLibraryCalls( hModule );
  49. break;
  50. case DLL_PROCESS_DETACH:
  51. break;
  52. case DLL_THREAD_ATTACH:
  53. case DLL_THREAD_DETACH:
  54. default:
  55. break;
  56. }
  57. return TRUE;
  58. } // DllMain
  59. //-----------------------------Public Routine----------------------------------
  60. //
  61. // ***************************WIN9x ONLY**********************************
  62. //
  63. // DdDestroyDriver
  64. //
  65. // Destroys a DirectDraw driver.
  66. //
  67. // Parameters
  68. // pddd
  69. // Address of a DDHAL_DESTROYDRIVERDATA structure that contains
  70. // information necessary to destroy the driver.
  71. // Members
  72. //
  73. // LPDDRAWI_DIRECTDRAW_GBL
  74. // lpDD
  75. // Address of the DirectDraw structure representing
  76. // the DirectDraw object.
  77. // HRESULT
  78. // ddRVal
  79. // Passes the DirectDraw return values.
  80. // LPDDHAL_DESTROYDRIVER
  81. // DestroyDriver
  82. // This member is used by the DirectDraw API and should
  83. // not be filled in by the driver.
  84. //
  85. // Return Value
  86. // Returns one of the following values:
  87. //
  88. // DDHAL_DRIVER_HANDLED
  89. // DDHAL_DRIVER_NOTHANDLED
  90. //-----------------------------------------------------------------------------
  91. //
  92. // (!!!) Temp patch, move to Win9x header later, this CB is currently not used.
  93. //
  94. #define DIRECTX_DESTROYDRIVER_ESCAPE 0xbadbadee
  95. DWORD CALLBACK
  96. DdDestroyDriver(
  97. LPDDHAL_DESTROYDRIVERDATA pddd)
  98. {
  99. HDC hDC;
  100. P3_THUNKEDDATA* pThisDisplay;
  101. LPGLINTINFO pGLInfo;
  102. DISPDBG((DBGLVL,"*** In DdDestroyDriver"));
  103. GET_THUNKEDDATA(pThisDisplay, pddd->lpDD);
  104. pGLInfo = pThisDisplay->pGLInfo;
  105. // Destroy the hash table
  106. HT_DestroyHashTable(pThisDisplay->pDirectDrawLocalsHashTable, pThisDisplay);
  107. DISPDBG((DBGLVL,"Calling Display Driver's DestroyDriver16"));
  108. hDC = CREATE_DRIVER_DC ( pThisDisplay->pGLInfo );
  109. if ( hDC != NULL )
  110. {
  111. DISPDBG((DBGLVL,"HDC: 0x%x", hDC));
  112. ExtEscape ( hDC,
  113. DIRECTX_DESTROYDRIVER_ESCAPE,
  114. sizeof(DDHAL_DESTROYDRIVERDATA),
  115. (LPCSTR)pddd,
  116. 0,
  117. NULL );
  118. DELETE_DRIVER_DC ( hDC );
  119. }
  120. pddd->ddRVal = DD_OK;
  121. return DDHAL_DRIVER_HANDLED;
  122. } // DdDestroyDriver
  123. //-----------------------------Public Routine----------------------------------
  124. //
  125. // ***************************WIN9x ONLY**********************************
  126. //
  127. // DriverInit
  128. //
  129. // The entry point called by DirectDraw to initialize the 32-bit driver.
  130. //
  131. // DriverInit is called after the control function receives QUERYESCAPESUPPORT
  132. // with DDGET32BITDRIVERNAME escapes and returns the entry point (szEntryPoint).
  133. // DriverInit is only called once during driver initialization; it is not
  134. // called on mode changes.
  135. //
  136. // The dwDriverData parameter points to a region of shared data between the
  137. // 16- and 32-bit address space. It must be aliased through MapSLFix (a
  138. // standard Windows driver routine), which converts it to a 32-bit pointer,
  139. // g_pDriverData. MapSLFix creates a 16-bit selector for a 32-bit pointer, so
  140. // you can use what it returns from the 16-bit side. A 16:16 pointer is created
  141. // to point to the needed 32-bit objects, so a 64K piece of memory is shared
  142. // between 16- and 32-bit sides. Since only 64K of linear address space is
  143. // accessible with a 16:16 pointer, any objects larger than 64K will require
  144. // two 16:16 pointers tiled together (most objects should be smaller than 64K).
  145. // The pointer is used to set the fReset flag to TRUE because the display
  146. // parameters are being reset. The buildDDHALInfo32 function is called from
  147. // this function to fill out all of the 32-bit function names and driver
  148. // information.
  149. //
  150. // Returns 1.
  151. //
  152. // Parameters
  153. // DWORD
  154. // dwDriverData
  155. // Doubleword pointer that points to a shared memory region
  156. // between 16- and 32-bit address space.
  157. //-----------------------------------------------------------------------------
  158. DWORD CALLBACK
  159. DriverInit(
  160. DWORD dwDriverData )
  161. {
  162. P3_THUNKEDDATA* pThisDisplay;
  163. DWORD DataPointer = 0;
  164. HANDLE hDevice = NULL;
  165. DWORD InPtr = dwDriverData;
  166. DWORD dwSizeRet;
  167. DWORD bResult;
  168. // The g_pThisTemp may have been hosed, so we must reset
  169. // it to continue
  170. #if DBG
  171. g_pThisTemp = NULL;
  172. #endif
  173. //extern LPVOID _stdcall MapSL( DWORD ); // 16:16 -> 0:32
  174. //DataPointer = (DWORD)MapSL(dwDriverData);
  175. //!! Don't laugh at this... I tried calling the MapSL function
  176. //to fix up the pointer, but couldn't get it to work all of the time
  177. //(When the display was running the second instance of itself).
  178. hDevice = CreateFile("\\\\.\\perm3mvd",
  179. GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  180. (LPSECURITY_ATTRIBUTES) NULL,
  181. OPEN_EXISTING,
  182. FILE_ATTRIBUTE_NORMAL,
  183. (HANDLE) NULL);
  184. if (hDevice == (HANDLE) INVALID_HANDLE_VALUE)
  185. {
  186. DISPDBG((ERRLVL, "ERROR: Invalid Handle"));
  187. return 0;
  188. }
  189. else
  190. {
  191. DISPDBG((DBGLVL, "Got handle"));
  192. bResult = DeviceIoControl(hDevice,
  193. GLINT_16TO32_POINTER,
  194. &InPtr,
  195. sizeof(DWORD),
  196. &DataPointer,
  197. sizeof(DWORD),
  198. &dwSizeRet,
  199. 0);
  200. if (!bResult || (DataPointer == 0))
  201. {
  202. DISPDBG((ERRLVL,"ERROR: Pointer conversion failed!"));
  203. CloseHandle(hDevice);
  204. return 0;
  205. }
  206. }
  207. CloseHandle(hDevice);
  208. #if DBG
  209. g_pThisTemp = (P3_THUNKEDDATA*)DataPointer;
  210. #endif
  211. //
  212. // Sanity check
  213. //
  214. if (! (((P3_THUNKEDDATA*)DataPointer)->pGLInfo)) {
  215. return 0;
  216. }
  217. if (((P3_THUNKEDDATA*)DataPointer)->pGLInfo->dwDeviceHandle == 1)
  218. {
  219. g_pDriverData = (P3_THUNKEDDATA*)DataPointer;
  220. DISPDBG((ERRLVL, "Device is the Primary, Setting sData: 0x%x",
  221. g_pDriverData));
  222. }
  223. else
  224. {
  225. DISPDBG((ERRLVL, "Device NOT Primary Display, "
  226. "Setting dwReturn: 0x%x",
  227. DataPointer));
  228. }
  229. pThisDisplay = (P3_THUNKEDDATA*)DataPointer;
  230. if (pThisDisplay->dwSetupThisDisplay == 0)
  231. {
  232. // Pass the current pointer to the init function
  233. if (! _DD_InitDDHAL32Bit((P3_THUNKEDDATA*)DataPointer))
  234. {
  235. DISPDBG((ERRLVL,"ERROR: DriverInit Failed!"));
  236. return 0;
  237. }
  238. else
  239. {
  240. //
  241. // Initialize the heap manager data structure
  242. //
  243. _DX_LIN_UnInitialiseHeapManager(&pThisDisplay->LocalVideoHeap0Info);
  244. if (!_DX_LIN_InitialiseHeapManager(
  245. &pThisDisplay->LocalVideoHeap0Info,
  246. pThisDisplay->LocalVideoHeap0Info.dwMemStart,
  247. pThisDisplay->LocalVideoHeap0Info.dwMemEnd))
  248. {
  249. DISPDBG((ERRLVL, "ERROR: Heap0 initialization failed!"));
  250. }
  251. DISPDBG((ERRLVL,"Returned g_pDriverData"));
  252. }
  253. }
  254. // Increase the reference count on the display object.
  255. pThisDisplay->dwSetupThisDisplay++;
  256. // Set up the size of the ddCaps
  257. pThisDisplay->ddhi32.ddCaps.dwSize = sizeof(DDCORECAPS);
  258. // Set the flag that says we have to handle a mode change.
  259. // This will cause the chip to be initialised properly at the
  260. // right time (whilst in a Win16Lock)
  261. ((P3_THUNKEDDATA*)DataPointer)->bResetMode = TRUE;
  262. ((P3_THUNKEDDATA*)DataPointer)->bStartOfDay = TRUE;
  263. ((P3_THUNKEDDATA*)DataPointer)->pGLInfo->dwDirectXState =
  264. DIRECTX_LASTOP_UNKNOWN;
  265. return (DWORD)DataPointer;
  266. } // DriverInit
  267. //-----------------------------Public Routine----------------------------------
  268. //
  269. // ***************************WIN9x ONLY**********************************
  270. //
  271. // DdControlColor
  272. //
  273. // Controls the luminance and brightness controls of an overlay surface
  274. // or a primary surface. This callback is optional.
  275. //
  276. // Parameters
  277. // lpColorControl
  278. // Points to a DD_COLORCONTROLDATA structure that contains
  279. // the color control information for a specified overlay
  280. // surface.
  281. //
  282. // Members
  283. //
  284. // PDD_DIRECTDRAW_GLOBAL
  285. // lpDD
  286. // Points to a DD_DIRECTDRAW_GLOBAL structure that
  287. // describes the driver.
  288. // PDD_SURFACE_LOCAL
  289. // lpDDSurface
  290. // Points to the DD_SURFACE_LOCAL structure
  291. // representing the overlay surface.
  292. // DDCOLORCONTROL
  293. // ColorData
  294. // Is a DDCOLORCONTROL structure. See dwFlags to
  295. // determine how to use this member. The
  296. // DDCOLORCONTROL structure is defined in ddraw.h.
  297. // DWORD
  298. // dwFlags
  299. // Is the color control flags. This member can be
  300. // one of the following values:
  301. //
  302. // DDRAWI_GETCOLOR The driver should return the color
  303. // controls it supports for the
  304. // specified overlay in ColorData.
  305. // The driver should set the appropriate
  306. // flags in the dwFlags member of the
  307. // DDCOLORCONTROL structure to indicate
  308. // which other members the driver has
  309. // returned valid data in.
  310. // DDRAWI_SETCOLOR
  311. // The driver should set the current color
  312. // controls for the specified overlay
  313. // using the values specified in ColorData.
  314. // HRESULT
  315. // ddRVal
  316. // Is the location in which the driver writes the
  317. // return value of the DdControlColor callback. A
  318. // return code of DD_OK indicates success.
  319. // VOID*
  320. // ColorControl
  321. // Is unused on Windows 2000.
  322. //
  323. // Return Value
  324. // DdControlColor returns one of the following callback codes:
  325. //
  326. // DDHAL_DRIVER_HANDLED
  327. // DDHAL_DRIVER_NOTHANDLED
  328. // Comments
  329. //
  330. // DdControlColor can be optionally implemented in a DirectDraw driver.
  331. //-----------------------------------------------------------------------------
  332. // Set this to 1 to support gamma correction, or zero to disable.
  333. #define COLCON_SUPPORTS_GAMMA 1
  334. DWORD CALLBACK
  335. DdControlColor(
  336. LPDDHAL_COLORCONTROLDATA lpColConData )
  337. {
  338. P3_THUNKEDDATA* pThisDisplay;
  339. P3_SURF_FORMAT* pFormatSurface;
  340. GET_THUNKEDDATA(pThisDisplay, lpColConData->lpDD);
  341. DISPDBG((DBGLVL,"DdControlColor"));
  342. //
  343. // What the DDCOLORCONTROL structure looks like:
  344. // {
  345. // DWORD dwSize;
  346. // DWORD dwFlags;
  347. // LONG lBrightness;
  348. // LONG lContrast;
  349. // LONG lHue;
  350. // LONG lSaturation;
  351. // LONG lSharpness;
  352. // LONG lGamma;
  353. // LONG lColorEnable;
  354. // DWORD dwReserved1;
  355. // } DDCOLORCONTROL;
  356. //
  357. pFormatSurface = _DD_SUR_GetSurfaceFormat(lpColConData->lpDDSurface);
  358. if ( pFormatSurface->dwBitsPerPixel <= 8 )
  359. {
  360. // Can't do colour control on this format screen.
  361. // Only works on true-colour screens (and we don't
  362. // support 332 as a primary).
  363. lpColConData->lpColorData->dwFlags = 0;
  364. lpColConData->ddRVal = DD_OK;
  365. return ( DDHAL_DRIVER_HANDLED );
  366. }
  367. // See what they want.
  368. if ( lpColConData->dwFlags == DDRAWI_GETCOLOR )
  369. {
  370. // Get the colour info.
  371. lpColConData->lpColorData->lBrightness =
  372. pThisDisplay->ColConBrightness;
  373. lpColConData->lpColorData->lContrast =
  374. pThisDisplay->ColConContrast;
  375. #if COLCON_SUPPORTS_GAMMA
  376. lpColConData->lpColorData->lGamma =
  377. pThisDisplay->ColConGamma;
  378. lpColConData->lpColorData->dwFlags =
  379. DDCOLOR_BRIGHTNESS |
  380. DDCOLOR_CONTRAST |
  381. DDCOLOR_GAMMA;
  382. #else
  383. // We don't support gamma values.
  384. lpColConData->lpColorData->lGamma = 0;
  385. lpColConData->lpColorData->dwFlags =
  386. DDCOLOR_BRIGHTNESS |
  387. DDCOLOR_CONTRAST;
  388. #endif
  389. }
  390. else if ( lpColConData->dwFlags == DDRAWI_SETCOLOR )
  391. {
  392. WORD wRamp[256*3];
  393. WORD *pwRampR, *pwRampG, *pwRampB;
  394. BOOL bRes;
  395. HDC hDC;
  396. float fCol1, fCol2, fCol3, fCol4;
  397. float fBrightGrad, fBrightBase;
  398. float fContGrad1, fContBase1;
  399. float fContGrad2, fContBase2;
  400. float fContGrad3, fContBase3;
  401. float fContCutoff12, fContCutoff23;
  402. float fGammaGrad1, fGammaBase1;
  403. float fGammaGrad2, fGammaBase2;
  404. float fGammaCutoff12;
  405. float fTemp;
  406. int iTemp, iCount;
  407. // Set some new colour info.
  408. if ( ( lpColConData->lpColorData->dwFlags & DDCOLOR_BRIGHTNESS ) != 0 )
  409. {
  410. pThisDisplay->ColConBrightness =
  411. lpColConData->lpColorData->lBrightness;
  412. }
  413. if ( ( lpColConData->lpColorData->dwFlags & DDCOLOR_CONTRAST ) != 0 )
  414. {
  415. pThisDisplay->ColConContrast =
  416. lpColConData->lpColorData->lContrast;
  417. }
  418. #if COLCON_SUPPORTS_GAMMA
  419. if ( ( lpColConData->lpColorData->dwFlags & DDCOLOR_GAMMA ) != 0 )
  420. {
  421. pThisDisplay->ColConGamma =
  422. lpColConData->lpColorData->lGamma;
  423. }
  424. #endif
  425. // Set up the constants.
  426. // Brightness.
  427. // 0->10000 maps to 0.0->1.0. Default is 0
  428. fCol1 = (float)(pThisDisplay->ColConBrightness) / 10000.0f;
  429. fBrightGrad = 1.0f - fCol1;
  430. fBrightBase = fCol1;
  431. // Contrast
  432. // 0->20000 maps to 0.0->1.0. Default 10000 maps to 0.5
  433. fCol1 = (float)(pThisDisplay->ColConContrast) / 20000.0f;
  434. fContCutoff12 = fCol1 / 2.0f;
  435. fContCutoff23 = 1.0f - ( fCol1 / 2.0f );
  436. fContGrad1 = ( 1.0f - fCol1 ) / fCol1;
  437. fContBase1 = 0.0f;
  438. fContGrad2 = fCol1 / ( 1.0f - fCol1 );
  439. fContBase2 = ( 0.5f - fCol1 ) / ( 1.0f - fCol1 );
  440. fContGrad3 = ( 1.0f - fCol1 ) / fCol1;
  441. fContBase3 = ( ( 2.0f * fCol1 ) - 1.0f ) / fCol1;
  442. // Gamma
  443. // 1->500 maps to 0.01->5.0, default of 100 maps to 1.0
  444. // But then map to 0.0->0.5->1.0 non-linearly.
  445. if ( pThisDisplay->ColConGamma <= 2 )
  446. {
  447. // App is probably using the old docs that forgot to point
  448. // out the *100
  449. ASSERTDD ( FALSE, "** Colorcontrol32: App set gamma value of 2"
  450. " or less - probably using old DX docs" );
  451. fTemp = (float)(pThisDisplay->ColConGamma);
  452. }
  453. else
  454. {
  455. fTemp = (float)(pThisDisplay->ColConGamma) / 100.0f;
  456. }
  457. fTemp = 1.0f - ( 1.0f / ( 1.0f + fTemp ) );
  458. fGammaCutoff12 = 1.0f - fTemp;
  459. fGammaGrad1 = fTemp / ( 1.0f - fTemp );
  460. fGammaBase1 = 0.0f;
  461. fGammaGrad2 = ( 1.0f - fTemp ) / fTemp;
  462. fGammaBase2 = ( 2.0f * fTemp - 1.0f ) / fTemp;
  463. // Now set up the table.
  464. fCol1 = 0.0f;
  465. pwRampR = &(wRamp[0]);
  466. pwRampG = &(wRamp[256]);
  467. pwRampB = &(wRamp[512]);
  468. for ( iCount = 256; iCount > 0; iCount-- )
  469. {
  470. fCol1 += 1.0f / 256.0f;
  471. // Apply linear approximation gamma.
  472. if ( fCol1 < fGammaCutoff12 )
  473. {
  474. fCol2 = fGammaBase1 + fGammaGrad1 * fCol1;
  475. }
  476. else
  477. {
  478. fCol2 = fGammaBase2 + fGammaGrad2 * fCol1;
  479. }
  480. // Apply contrast
  481. if ( fCol2 < fContCutoff12 )
  482. {
  483. fCol3 = fContBase1 + fContGrad1 * fCol2;
  484. }
  485. else if ( fCol2 < fContCutoff23 )
  486. {
  487. fCol3 = fContBase2 + fContGrad2 * fCol2;
  488. }
  489. else
  490. {
  491. fCol3 = fContBase3 + fContGrad3 * fCol2;
  492. }
  493. // Apply brightness
  494. fCol4 = fBrightBase + fBrightGrad * fCol3;
  495. // Convert 0.0->1.0 to 0->65535
  496. fTemp = ( fCol4 * 65536.0f );
  497. myFtoi ( &iTemp, fTemp );
  498. if ( iTemp < 0 )
  499. {
  500. iTemp = 0;
  501. }
  502. else if ( iTemp > 65535 )
  503. {
  504. iTemp = 65535;
  505. }
  506. *pwRampR = (WORD)iTemp;
  507. *pwRampG = (WORD)iTemp;
  508. *pwRampB = (WORD)iTemp;
  509. pwRampR++;
  510. pwRampG++;
  511. pwRampB++;
  512. }
  513. // And do the hardware itself.
  514. hDC = CREATE_DRIVER_DC ( pThisDisplay->pGLInfo );
  515. if ( hDC != NULL )
  516. {
  517. bRes = SetDeviceGammaRamp ( hDC, wRamp );
  518. DELETE_DRIVER_DC ( hDC );
  519. ASSERTDD ( bRes, "DdControlColor - SetDeviceGammaRamp failed" );
  520. }
  521. else
  522. {
  523. ASSERTDD ( FALSE, "DdControlColor - CREATE_DRIVER_DC failed" );
  524. }
  525. }
  526. else
  527. {
  528. // Don't know what they want to do. Panic.
  529. ASSERTDD ( FALSE, "DdControlColor - don't know what to do." );
  530. lpColConData->ddRVal = DDERR_INVALIDPARAMS;
  531. return ( DDHAL_DRIVER_HANDLED );
  532. }
  533. lpColConData->ddRVal = DD_OK;
  534. return ( DDHAL_DRIVER_HANDLED );
  535. } // DdControlColor
  536. #endif // W95_DDRAW
  537. DirectXGlobals g_DXGlobals = { 0 };
  538. #if WNT_DDRAW
  539. //-----------------------------Public Routine----------------------------------
  540. //
  541. // ***************************WIN NT ONLY**********************************
  542. //
  543. // DdMapMemory
  544. //
  545. // Maps application-modifiable portions of the frame buffer into the
  546. // user-mode address space of the specified process, or unmaps memory.
  547. //
  548. // DdMapMemory is called to perform memory mapping before the first call to
  549. // DdLock. The handle returned by the driver in fpProcess will be passed to
  550. // every DdLock call made on the driver.
  551. //
  552. // DdMapMemory is also called to unmap memory after the last DdUnLock call is
  553. // made.
  554. //
  555. // To prevent driver crashes, the driver must not map any portion of the frame
  556. // buffer that must not be modified by an application.
  557. //
  558. // Parameters
  559. // lpMapMemory
  560. // Points to a DD_MAPMEMORYDATA structure that contains details for
  561. // the memory mapping or unmapping operation.
  562. //
  563. // .lpDD
  564. // Points to a DD_DIRECTDRAW_GLOBAL structure that represents
  565. // the driver.
  566. // .bMap
  567. // Specifies the memory operation that the driver should perform.
  568. // A value of TRUE indicates that the driver should map memory;
  569. // FALSE means that the driver should unmap memory.
  570. // .hProcess
  571. // Specifies a handle to the process whose address space is
  572. // affected.
  573. // .fpProcess
  574. // Specifies the location in which the driver should return the
  575. // base address of the process's memory mapped space when bMap
  576. // is TRUE. When bMap is FALSE, fpProcess contains the base
  577. // address of the memory to be unmapped by the driver.
  578. // .ddRVal
  579. // Specifies the location in which the driver writes the return
  580. // value of the DdMapMemory callback. A return code of DD_OK
  581. // indicates success.
  582. //
  583. //-----------------------------------------------------------------------------
  584. DWORD CALLBACK
  585. DdMapMemory(
  586. PDD_MAPMEMORYDATA lpMapMemory)
  587. {
  588. PDEV* ppdev;
  589. VIDEO_SHARE_MEMORY ShareMemory;
  590. VIDEO_SHARE_MEMORY_INFORMATION ShareMemoryInformation;
  591. DWORD ReturnedDataLength;
  592. DBG_CB_ENTRY(DdMapMemory);
  593. ppdev = (PDEV*) lpMapMemory->lpDD->dhpdev;
  594. if (lpMapMemory->bMap)
  595. {
  596. ShareMemory.ProcessHandle = lpMapMemory->hProcess;
  597. // 'RequestedVirtualAddress' isn't actually used for the SHARE IOCTL:
  598. ShareMemory.RequestedVirtualAddress = 0;
  599. // We map in starting at the top of the frame buffer:
  600. ShareMemory.ViewOffset = 0;
  601. // We map down to the end of the frame buffer.
  602. //
  603. // Note: There is a 64k granularity on the mapping (meaning that
  604. // we have to round up to 64k).
  605. //
  606. // Note: If there is any portion of the frame buffer that must
  607. // not be modified by an application, that portion of memory
  608. // MUST NOT be mapped in by this call. This would include
  609. // any data that, if modified by a malicious application,
  610. // would cause the driver to crash. This could include, for
  611. // example, any DSP code that is kept in off-screen memory.
  612. ShareMemory.ViewSize
  613. = ROUND_UP_TO_64K(ppdev->cyMemory * ppdev->lDelta);
  614. if (EngDeviceIoControl(ppdev->hDriver,
  615. IOCTL_VIDEO_SHARE_VIDEO_MEMORY,
  616. &ShareMemory,
  617. sizeof(VIDEO_SHARE_MEMORY),
  618. &ShareMemoryInformation,
  619. sizeof(VIDEO_SHARE_MEMORY_INFORMATION),
  620. &ReturnedDataLength))
  621. {
  622. DISPDBG((ERRLVL, "Failed IOCTL_VIDEO_SHARE_MEMORY"));
  623. lpMapMemory->ddRVal = DDERR_GENERIC;
  624. DISPDBG((ERRLVL, "DdMapMemory: Exit GEN, DDHAL_DRIVER_HANDLED"));
  625. DBG_CB_EXIT(DdMapMemory, DDERR_GENERIC);
  626. return(DDHAL_DRIVER_HANDLED);
  627. }
  628. lpMapMemory->fpProcess =
  629. (FLATPTR) ShareMemoryInformation.VirtualAddress;
  630. }
  631. else
  632. {
  633. ShareMemory.ProcessHandle = lpMapMemory->hProcess;
  634. ShareMemory.ViewOffset = 0;
  635. ShareMemory.ViewSize = 0;
  636. ShareMemory.RequestedVirtualAddress = (VOID*) lpMapMemory->fpProcess;
  637. if (EngDeviceIoControl(ppdev->hDriver,
  638. IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY,
  639. &ShareMemory,
  640. sizeof(VIDEO_SHARE_MEMORY),
  641. NULL,
  642. 0,
  643. &ReturnedDataLength))
  644. {
  645. RIP("Failed IOCTL_VIDEO_UNSHARE_MEMORY");
  646. }
  647. }
  648. lpMapMemory->ddRVal = DD_OK;
  649. DBG_CB_EXIT(DdMapMemory, DD_OK);
  650. return(DDHAL_DRIVER_HANDLED);
  651. } // DdMapMemory
  652. //-----------------------------Public Routine----------------------------------
  653. //
  654. // ***************************WIN NT ONLY**********************************
  655. //
  656. // BOOL DrvGetDirectDrawInfo
  657. //
  658. // Function called by DirectDraw to returns the capabilities of the graphics
  659. // hardware
  660. //
  661. // Parameters:
  662. //
  663. // dhpdev-------Is a handle to the PDEV returned by the driver's DrvEnablePDEV
  664. // routine.
  665. // pHalInfo-----Points to a DD_HALINFO structure in which the driver should
  666. // return the hardware capabilities that it supports.
  667. // pdwNumHeaps--Points to the location in which the driver should return the
  668. // number of VIDEOMEMORY structures pointed to by pvmList.
  669. // pvmList------Points to an array of VIDEOMEMORY structures in which the
  670. // driver should return information about each video memory chunk
  671. // that it controls. The driver should ignore this parameter when
  672. // it is NULL.
  673. // pdwNumFourCC-Points to the location in which the driver should return the
  674. // number of DWORDs pointed to by pdwFourCC.
  675. // pdwFourCC----Points to an array of DWORDs in which the driver should return
  676. // information about each FOURCC that it supports. The driver
  677. // should ignore this parameter when it is NULL.
  678. //
  679. // Return:
  680. // Returns TRUE if it succeeds; otherwise, it returns FALSE
  681. //
  682. // Note:
  683. // This function will be called twice before DrvEnableDirectDraw is called.
  684. //
  685. // Comments
  686. // The driver's DrvGetDirectDrawInfo routine should do the following:
  687. // 1)When pvmList and pdwFourCC are NULL:
  688. // Reserve off-screen video memory for DirectDraw use. Write the number of
  689. // driver video memory heaps and supported FOURCCs in pdwNumHeaps and
  690. // pdwNumFourCC, respectively.
  691. //
  692. // 2)When pvmList and pdwFourCC are not NULL:
  693. // Write the number of driver video memory heaps and supported FOURCCs in
  694. // pdwNumHeaps and pdwNumFourCC, respectively.
  695. // Get ptr to reserved offscreen mem?
  696. // For each VIDEOMEMORY structure in the list to which pvmList points, fill in
  697. // the appropriate members to describe a particular chunk of display memory.
  698. // The list of structures provides DirectDraw with a complete description of
  699. // the driver's off-screen memory.
  700. //
  701. // 3)Initialize the members of the DD_HALINFO structure with driver-specific
  702. // information as follows:
  703. // Initialize the appropriate members of the VIDEOMEMORYINFO structure to
  704. // describe the general characteristics of the display's memory.
  705. // Initialize the appropriate members of the DDNTCORECAPS structure to
  706. // describe the capabilities of the hardware.
  707. // If the driver implements a DdGetDriverInfo function, set GetDriverInfo to
  708. // point to it and set dwFlags to DDHALINFO_GETDRIVERINFOSET
  709. //
  710. //-----------------------------------------------------------------------------
  711. BOOL
  712. DrvGetDirectDrawInfo(
  713. DHPDEV dhpdev,
  714. DD_HALINFO* pHalInfo,
  715. DWORD* pdwNumHeaps,
  716. VIDEOMEMORY* pvmList, // Will be NULL on first call
  717. DWORD* pdwNumFourCC,
  718. DWORD* pdwFourCC) // Will be NULL on first call
  719. {
  720. BOOL bCanFlip;
  721. PDEV* ppdev;
  722. LONGLONG li;
  723. DWORD Unused = 0;
  724. P3_THUNKEDDATA* pThisDisplay;
  725. DWORD dwChipConfig;
  726. DWORD cHeaps;
  727. static DWORD fourCC[] = { FOURCC_YUV422 }; // The FourCC's we support
  728. ppdev = (PDEV*) dhpdev;
  729. pThisDisplay = (P3_THUNKEDDATA*) ppdev->thunkData;
  730. DBG_CB_ENTRY(DrvGetDirectDrawInfo);
  731. *pdwNumFourCC = 0;
  732. // We may not support DirectDraw on this card:
  733. if (!(ppdev->flStatus & STAT_DIRECTDRAW))
  734. {
  735. DISPDBG((ERRLVL, "DrvGetDirectDrawInfo: exit, not enabled"));
  736. DBG_CB_EXIT(DrvGetDirectDrawInfo,FALSE);
  737. return(FALSE);
  738. }
  739. // Need a pointer to the registers to read config info
  740. pThisDisplay->pGLInfo->pRegs = (ULONG_PTR) ppdev->pulCtrlBase[0];
  741. //@@BEGIN_DDKSPLIT
  742. //azn - loss of bits 64->32
  743. //@@END_DDKSPLIT
  744. pThisDisplay->control = (FLATPTR)pThisDisplay->pGLInfo->pRegs;
  745. pThisDisplay->pGlint = (FPGLREG)pThisDisplay->control;
  746. #if DBG
  747. // We can only initialise g_pThisTemp after
  748. // the registers have been mapped in.
  749. g_pThisTemp = pThisDisplay;
  750. #endif
  751. // Decide if we can use AGP or not
  752. dwChipConfig =
  753. (DWORD)((PREGISTERS)pThisDisplay->pGLInfo->pRegs)->Glint.ChipConfig;
  754. // Make the AGP decision (NT Only!)
  755. if ( ((dwChipConfig & PM_CHIPCONFIG_AGP1XCAPABLE) ||
  756. (dwChipConfig & PM_CHIPCONFIG_AGP2XCAPABLE) ||
  757. (dwChipConfig & PM_CHIPCONFIG_AGP4XCAPABLE)) )
  758. {
  759. DISPDBG((WRNLVL,"AGP Permedia3 Board detected!"));
  760. pThisDisplay->bCanAGP = TRUE;
  761. }
  762. else
  763. {
  764. DISPDBG((WRNLVL,"Permedia3 Board is NOT AGP"));
  765. pThisDisplay->bCanAGP = FALSE;
  766. }
  767. // Fill in the DDHAL Informational caps that Win95 has setup.
  768. __GetDDHALInfo(pThisDisplay, pHalInfo);
  769. // On Win2K we need to return the D3D callbacks
  770. DISPDBG((DBGLVL ,"Creating Direct3D info"));
  771. _D3DHALCreateDriver(pThisDisplay);
  772. // Record the pointers that were created. Note that the above call
  773. // may not have recreated a previous set of data.
  774. pHalInfo->lpD3DGlobalDriverData = (void*)pThisDisplay->lpD3DGlobalDriverData;
  775. pHalInfo->lpD3DHALCallbacks = (void*)pThisDisplay->lpD3DHALCallbacks;
  776. pHalInfo->lpD3DBufCallbacks = (void *)pThisDisplay->lpD3DBufCallbacks;
  777. if ( (pHalInfo->lpD3DBufCallbacks) &&
  778. (pHalInfo->lpD3DBufCallbacks->dwSize != 0))
  779. {
  780. pHalInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_EXECUTEBUFFER;
  781. }
  782. // Fill in any DDHAL caps that are specific to Windows NT.
  783. // Current primary surface attributes:
  784. pHalInfo->vmiData.pvPrimary = ppdev->pjScreen;
  785. pHalInfo->vmiData.fpPrimary = 0;
  786. pHalInfo->vmiData.dwDisplayWidth = ppdev->cxScreen;
  787. pHalInfo->vmiData.dwDisplayHeight = ppdev->cyScreen;
  788. pHalInfo->vmiData.lDisplayPitch = ppdev->lDelta;
  789. pHalInfo->vmiData.ddpfDisplay.dwSize = sizeof(DDPIXELFORMAT);
  790. pHalInfo->vmiData.ddpfDisplay.dwFlags = DDPF_RGB;
  791. pHalInfo->vmiData.ddpfDisplay.dwRGBBitCount = ppdev->cjPelSize * 8;
  792. if (ppdev->iBitmapFormat == BMF_8BPP)
  793. {
  794. pHalInfo->vmiData.ddpfDisplay.dwFlags |= DDPF_PALETTEINDEXED8;
  795. }
  796. // These masks will be zero at 8bpp:
  797. pHalInfo->vmiData.ddpfDisplay.dwRBitMask = ppdev->flRed;
  798. pHalInfo->vmiData.ddpfDisplay.dwGBitMask = ppdev->flGreen;
  799. pHalInfo->vmiData.ddpfDisplay.dwBBitMask = ppdev->flBlue;
  800. //@@BEGIN_DDKSPLIT
  801. // Free up as much off-screen memory as possible:
  802. //TMM ?? bMoveAllDfbsFromOffscreenToDibs(ppdev);
  803. //@@END_DDKSPLIT
  804. // We have to tell DirectDraw our preferred off-screen alignment, even
  805. // if we're doing our own off-screen memory management:
  806. pHalInfo->vmiData.dwOffscreenAlign = 4;
  807. pHalInfo->vmiData.dwZBufferAlign = 4;
  808. pHalInfo->vmiData.dwTextureAlign = 4;
  809. pHalInfo->vmiData.dwOverlayAlign = 4;
  810. // Since we do our own memory allocation, we have to set dwVidMemTotal
  811. // ourselves. Note that this represents the amount of available off-
  812. // screen memory, not all of video memory:
  813. pHalInfo->ddCaps.dwVidMemTotal =
  814. ppdev->heap.cxMax * ppdev->heap.cyMax * ppdev->cjPelSize;
  815. // If we are on Permedia, then setup the YUV modes for Video playback
  816. // acceleration. We can do YUV conversions at any depth except 8 bits...
  817. // On Win95 this information is setup in the Mini Display Driver.
  818. if (ppdev->iBitmapFormat != BMF_8BPP)
  819. {
  820. *pdwNumFourCC = sizeof( fourCC ) / sizeof( fourCC[0] );
  821. if (pdwFourCC)
  822. {
  823. memcpy(pdwFourCC, fourCC, sizeof(fourCC));
  824. }
  825. }
  826. cHeaps = 0;
  827. if(pThisDisplay->bCanAGP)
  828. {
  829. ++cHeaps; // agp memory heap
  830. }
  831. // Report the heaps we want DD to manage.
  832. // Currently this is needed in this sample for the AGP heap.
  833. if(pvmList)
  834. {
  835. VIDEOMEMORY *pVm = pvmList;
  836. // If we support AGP , then define the AGP heap
  837. if(pThisDisplay->bCanAGP)
  838. {
  839. DWORD dwAGPMemBytes;
  840. //@@BEGIN_DDKSPLIT
  841. // azn This business of hard-allocating 32MB is not right.
  842. // We need to fix it and verify with JeffN what's the best
  843. // policy to show in the sample
  844. // Request a suitably sized AGP heap, don't ask for a heap
  845. // larger than the available memory
  846. // This is taken care of by the W2000 runtime policy, so I don't
  847. // think we need to do this for W2k. CTM.
  848. //@@END_DDKSPLIT
  849. // Default to 32Mb of AGP memory
  850. dwAGPMemBytes = 32*1024*1024;
  851. // Report the AGP heap
  852. // fpStart---Points to the starting address of a memory range in the
  853. // heap.
  854. // fpEnd-----Points to the ending address of a memory range if the heap
  855. // is linear. This address is inclusive, that is, it specifies the last
  856. // valid address in the range. Thus, the number of bytes specified by
  857. // fpStart and fpEnd is (fpEnd-fpStart+1).
  858. // DDraw ignores our start address so just set to zero
  859. pVm->fpStart = 0;
  860. // Fetch the last byte of AGP memory
  861. pVm->fpEnd = dwAGPMemBytes - 1;
  862. pVm->dwFlags = VIDMEM_ISNONLOCAL |
  863. VIDMEM_ISLINEAR |
  864. VIDMEM_ISWC;
  865. // Only use AGP memory for texture surfaces
  866. pVm->ddsCaps.dwCaps = DDSCAPS_OVERLAY |
  867. DDSCAPS_OFFSCREENPLAIN |
  868. DDSCAPS_FRONTBUFFER |
  869. DDSCAPS_BACKBUFFER |
  870. DDSCAPS_ZBUFFER |
  871. DDSCAPS_3DDEVICE;
  872. pVm->ddsCapsAlt.dwCaps = DDSCAPS_OVERLAY |
  873. DDSCAPS_OFFSCREENPLAIN |
  874. DDSCAPS_FRONTBUFFER |
  875. DDSCAPS_BACKBUFFER |
  876. DDSCAPS_ZBUFFER |
  877. DDSCAPS_3DDEVICE;
  878. DISPDBG((DBGLVL, "Initialised AGP Heap for P2, Start:0x%x, End:0x%x",
  879. pVm->fpStart, pVm->fpEnd));
  880. ++pVm;
  881. }
  882. else
  883. {
  884. DISPDBG((WRNLVL, "NOT reporting AGP heap"));
  885. }
  886. }
  887. else
  888. {
  889. DISPDBG((DBGLVL, "Heap info NOT requested"));
  890. }
  891. // Report the number of heaps we support
  892. if (pdwNumHeaps)
  893. {
  894. *pdwNumHeaps = cHeaps;
  895. }
  896. DBG_CB_EXIT(DrvGetDirectDrawInfo,TRUE);
  897. return(TRUE);
  898. } // DrvGetDirectDrawInfo
  899. #endif // WNT_DDRAW
  900. #if USE_FLIP_BACKOFF
  901. //-----------------------------------------------------------------------------
  902. //
  903. // __WaitTimeDelay
  904. //
  905. //-----------------------------------------------------------------------------
  906. #define WAIT_TIME_DELAY 2
  907. void __WaitTimeDelay(void)
  908. {
  909. static DWORD dwLastTime; // Doesn't matter what the
  910. // start value is (honest!)
  911. DWORD dwCurTime, iTimeDiff;
  912. // Make sure that we don't start hammering on the chip.
  913. // If someone uses the WAIT flag, or they do a loop
  914. // themselves, we will constantly be reading the chip,
  915. // which will disrupt the DMA stream. Therefore,
  916. // make sure we don't start reading it too often.
  917. // This #define will need tweaking, of course.
  918. do
  919. {
  920. dwCurTime = timeGetTime();
  921. // Be careful about wraparound conditions.
  922. iTimeDiff = (signed int)( dwCurTime - dwLastTime );
  923. } while ( ( iTimeDiff > 0 ) && ( iTimeDiff < WAIT_TIME_DELAY ) );
  924. // And store the new "last" time.
  925. dwLastTime = dwCurTime;
  926. } // __WaitTimeDelay
  927. #endif //#if USE_FLIP_BACKOFF
  928. //-----------------------------------------------------------------------------
  929. //
  930. // __QueryRenderIDStatus
  931. //
  932. // Checks to see if the given two RenderIDs have been finished yet.
  933. //
  934. // If there is a problem, the pipeline will be flushed and the
  935. // RenderIDs set to the newest ID.
  936. //
  937. // If bAllowDMAFlush is TRUE, then if either RenderID is still in the
  938. // pipe, the current DMA buffer is flushed. Otherwise there is a
  939. // fairly good chance that the command with that RenderID may simply
  940. // sit in the DMA buffer and never be executed. To disable this,
  941. // pass in FALSE. This may be needed because the routine has already
  942. // grabbed the DMA buffer, etc. and in that case it needs to do the flush
  943. // itself when it gets DDERR_WASSTILLDRAWING.
  944. //
  945. // The return value is either DD_OK (both RenderIDs have been finished),
  946. // or DDERR_WASSTILLDRAWING.
  947. //
  948. //-----------------------------------------------------------------------------
  949. HRESULT
  950. __QueryRenderIDStatus(
  951. P3_THUNKEDDATA* pThisDisplay,
  952. BOOL bAllowDMAFlush )
  953. {
  954. P3_DMA_DEFS();
  955. ASSERTDD ( CHIP_RENDER_ID_IS_VALID(),
  956. "** __QueryRenderIDStatus:Chip RenderID was invalid - fix it!");
  957. if ( RENDER_ID_HAS_COMPLETED ( pThisDisplay->dwLastFlipRenderID ))
  958. {
  959. // OK, the RenderID has cleared the pipe, so we can carry on.
  960. return ( DD_OK );
  961. }
  962. else
  963. {
  964. // Can't flip yet - one surface is still pending.
  965. if (!NEED_TO_RESYNC_CHIP_AND_SURFACE (pThisDisplay->dwLastFlipRenderID))
  966. {
  967. // No error - we just need to wait. We'll flush the buffer and
  968. // return DDERR_WASSTILLDRAWING
  969. if ( bAllowDMAFlush )
  970. {
  971. DDRAW_OPERATION(pContext, pThisDisplay);
  972. P3_DMA_GET_BUFFER();
  973. P3_DMA_FLUSH_BUFFER();
  974. }
  975. #if USE_FLIP_BACKOFF
  976. __WaitTimeDelay();
  977. #endif
  978. return ( DDERR_WASSTILLDRAWING );
  979. }
  980. else
  981. {
  982. // Something went wrong - need to do a safety-net resync.
  983. DISPDBG((ERRLVL,"__QueryRenderIDStatus: "
  984. "RenderID failure - need a resync"));
  985. SYNC_WITH_GLINT;
  986. pThisDisplay->dwLastFlipRenderID = GET_HOST_RENDER_ID();
  987. // And continue with the operation.
  988. return ( DD_OK );
  989. }
  990. }
  991. } // __QueryRenderIDStatus
  992. //-----------------------------------------------------------------------------
  993. //
  994. // _DX_QueryFlipStatus
  995. //
  996. // Checks and sees if the most recent flip has occurred. If so returns DD_OK.
  997. //
  998. //-----------------------------------------------------------------------------
  999. HRESULT
  1000. _DX_QueryFlipStatus(
  1001. P3_THUNKEDDATA* pThisDisplay,
  1002. FLATPTR fpVidMem,
  1003. BOOL bAllowDMAFlush )
  1004. {
  1005. // If fpVidMem == 0, the Query is asking for the 'general flip status'.
  1006. // The question is "Am I safe to add another flip, independent of surfaces".
  1007. // If fpVidmem != 0, the Query is asking if it is safe to 'use' the current
  1008. // fpvidmem surface. It will only be safe to use unconditionally if that
  1009. // surface has been succesfully flipped away from, OR it was not the last
  1010. // surface flipped away from.
  1011. // The answers will be yes, iff the RenderID of the flip travelling down
  1012. // the core has been sent to the MemoryController and put in the scratch ID,
  1013. // and iff the bypass pending bit has been cleared. These two checks
  1014. // effectively guarantee that the previously queue'd flip has taken place.
  1015. // The fpFlipFrom is a record of the last surface that was flipped away from
  1016. if((fpVidMem == 0) || (fpVidMem == pThisDisplay->flipRecord.fpFlipFrom))
  1017. {
  1018. DWORD dwVidControl;
  1019. HRESULT hres;
  1020. // Check if the pThisDisplay->dwLastFlipRenderID has completed
  1021. hres = __QueryRenderIDStatus ( pThisDisplay, bAllowDMAFlush );
  1022. if ( SUCCEEDED(hres) )
  1023. {
  1024. BOOL bFlipHasFinished;
  1025. // OK, the previous flip has got to the end of the pipe,
  1026. // but it may not actually have happened yet.
  1027. // Read the Bypass pending bit. If it's clear then
  1028. // we proceed.
  1029. #if W95_DDRAW
  1030. if ( ( ( pThisDisplay->pGLInfo->dwFlags & GMVF_DFP_DISPLAY ) != 0 ) &&
  1031. ( ( pThisDisplay->pGLInfo->dwScreenWidth !=
  1032. pThisDisplay->pGLInfo->dwVideoWidth ) ||
  1033. ( pThisDisplay->pGLInfo->dwScreenHeight !=
  1034. pThisDisplay->pGLInfo->dwVideoHeight ) ) )
  1035. {
  1036. // Display driver is using the overlay on a DFP, so we need to
  1037. // check the overlay pending bit, not the screen pending bit.
  1038. if ( ( ( READ_GLINT_CTRL_REG(VideoOverlayUpdate) ) & 0x1 ) == 0 )
  1039. {
  1040. bFlipHasFinished = TRUE;
  1041. }
  1042. else
  1043. {
  1044. bFlipHasFinished = FALSE;
  1045. }
  1046. }
  1047. else
  1048. #endif // W95_DDRAW
  1049. {
  1050. dwVidControl = READ_GLINT_CTRL_REG(VideoControl);
  1051. if (dwVidControl & (0x1 << 7))
  1052. {
  1053. bFlipHasFinished = FALSE;
  1054. }
  1055. else
  1056. {
  1057. bFlipHasFinished = TRUE;
  1058. }
  1059. }
  1060. if ( bFlipHasFinished )
  1061. {
  1062. // This flip has actually completed.
  1063. return ( DD_OK );
  1064. }
  1065. else
  1066. {
  1067. #if USE_FLIP_BACKOFF
  1068. __WaitTimeDelay();
  1069. #endif //#if USE_FLIP_BACKOFF
  1070. return ( DDERR_WASSTILLDRAWING );
  1071. }
  1072. }
  1073. else
  1074. {
  1075. // No, still waiting for the flip command to exit the pipe.
  1076. return ( DDERR_WASSTILLDRAWING );
  1077. }
  1078. }
  1079. else
  1080. {
  1081. return ( DD_OK );
  1082. }
  1083. } // _DX_QueryFlipStatus
  1084. //-----------------------------Public Routine----------------------------------
  1085. //
  1086. // DdFlip
  1087. //
  1088. // Causes the surface memory associated with the target surface to become
  1089. // the primary surface, and the current surface to become the nonprimary
  1090. // surface.
  1091. //
  1092. // DdFlip allows a display driver to perform multi-buffering. DirectDraw drivers
  1093. // must implement this function.
  1094. //
  1095. // The driver should update its surface pointers so that the next frame will be
  1096. // written to the surface to which lpSurfTarg points. If a previous flip request
  1097. // is still pending, the driver should fail the call and return
  1098. // DDERR_WASSTILLDRAWING. The driver should ensure that the scan line is not in
  1099. // the vertical blank before performing the flip. DdFlip does not affect the
  1100. // actual display of the video data.
  1101. //
  1102. // If the driver's hardware supports overlays or textures, DdFlip should make
  1103. // any necessary checks based on the surface type before performing the flip.
  1104. //
  1105. // Parameters
  1106. //
  1107. // lpFlipData
  1108. // Points to a DD_FLIPDATA structure that contains the information
  1109. // required to perform the flip.
  1110. //
  1111. // .lpDD
  1112. // Points to the DD_DIRECTDRAW_GLOBAL structure that describes
  1113. // the driver.
  1114. // .lpSurfCurr
  1115. // Points to the DD_SURFACE_LOCAL structure describing the
  1116. // current surface.
  1117. // .lpSurfTarg
  1118. // Points to the DD_SURFACE_LOCAL structure describing the
  1119. // target surface; that is, the surface to which the driver
  1120. // should flip.
  1121. // .dwFlags
  1122. // This is a set of flags that provide the driver with details
  1123. // for the flip. This member can be a bit-wise OR of the
  1124. // following flags:
  1125. //
  1126. // DDFLIP_EVEN
  1127. // The surface to which lpSurfTarg points contains only
  1128. // the even field of video data. This flag is valid only when
  1129. // the surface is an overlay, and is mutually exclusive of
  1130. // DDFLIP_ODD.
  1131. // DDFLIP_ODD
  1132. // The surface to which lpSurfTarg points contains only the
  1133. // odd field of video data. This flag is valid only when the
  1134. // surface is an overlay, and is mutually exclusive of
  1135. // DDFLIP_EVEN.
  1136. // DDFLIP_NOVSYNC
  1137. // The driver should perform the flip and return immediately.
  1138. // Typically, the now current back buffer (which used to be
  1139. // the front buffer) is still visible until the next vertical
  1140. // retrace. Subsequent operations involving the surfaces
  1141. // to which lpSurfCurr and lpSurfTarg point will not check
  1142. // to see if the physical flip has finished. This allows an
  1143. // application to perform flips at a higher frequency than
  1144. // the monitor refresh rate, although it might introduce
  1145. // visible artifacts.
  1146. // DDFLIP_INTERVAL2
  1147. // The driver should perform the flip on every other vertical
  1148. // sync. It should return DDERR_WASSTILLDRAWING until the
  1149. // second vertical retrace has occurred. This flag is mutually
  1150. // exclusive of DDFLIP_INTERVAL3 and DDFLIP_INTERVAL4.
  1151. // DDFLIP_INTERVAL3
  1152. // The driver should perform the flip on every third vertical
  1153. // sync. It should return DDERR_WASSTILLDRAWING until the
  1154. // third vertical retrace has occurred. This flag is mutually
  1155. // exclusive of DDFLIP_INTERVAL2 and DDFLIP_INTERVAL4.
  1156. // DDFLIP_INTERVAL4
  1157. // The driver should perform the flip on every fourth vertical
  1158. // sync. It should return DDERR_WASSTILLDRAWING until the
  1159. // fourth vertical retrace has occurred. This flag is mutually
  1160. // exclusive of DDFLIP_INTERVAL2 and DDFLIP_INTERVAL3.
  1161. //
  1162. // .ddRVal
  1163. // Specifies the location in which the driver writes the return
  1164. // value of the DdFlip callback. A return code of DD_OK indicates
  1165. // success.
  1166. // .Flip
  1167. // This is unused on Windows 2000.
  1168. // .lpSurfCurrLeft
  1169. // Points to the DD_SURFACE_LOCAL structure describing the current
  1170. // left surface.
  1171. // .lpSurfTargLeft
  1172. // Points to the DD_SURFACE_LOCAL structure describing the left
  1173. // target surface to flip to.
  1174. //
  1175. //-----------------------------------------------------------------------------
  1176. DWORD CALLBACK
  1177. DdFlip(
  1178. LPDDHAL_FLIPDATA lpFlipData)
  1179. {
  1180. DWORD dwDDSurfaceOffset;
  1181. P3_THUNKEDDATA* pThisDisplay;
  1182. HRESULT ddrval;
  1183. GET_THUNKEDDATA(pThisDisplay, lpFlipData->lpDD);
  1184. DBG_CB_ENTRY(DdFlip);
  1185. VALIDATE_MODE_AND_STATE(pThisDisplay);
  1186. STOP_SOFTWARE_CURSOR(pThisDisplay);
  1187. // Is the previous Flip already done? Check if the current surface is
  1188. // already displayed and don't allow a new flip (unless the DDFLIP_NOVSYNC
  1189. // is set) to queue if the old one isn't finished.
  1190. ddrval = _DX_QueryFlipStatus(pThisDisplay, 0, TRUE);
  1191. if((FAILED(ddrval)) &&
  1192. !(lpFlipData->dwFlags & DDFLIP_NOVSYNC))
  1193. {
  1194. lpFlipData->ddRVal = DDERR_WASSTILLDRAWING;
  1195. START_SOFTWARE_CURSOR(pThisDisplay);
  1196. DBG_CB_EXIT(DdFlip,DDERR_WASSTILLDRAWING);
  1197. return DDHAL_DRIVER_HANDLED;
  1198. }
  1199. // Set the flipped flag so that the D3D side does any necessary
  1200. // setup updates before starting to render the next frame
  1201. pThisDisplay->bFlippedSurface = TRUE;
  1202. // Do the flip
  1203. {
  1204. P3_DMA_DEFS();
  1205. DWORD dwNewRenderID;
  1206. DDRAW_OPERATION(pContext, pThisDisplay);
  1207. P3_DMA_GET_BUFFER_ENTRIES(12);
  1208. // Make sure all the rendering is finished
  1209. SYNC_WITH_GLINT;
  1210. // Check the surface type (overlay or not overlay)
  1211. // Update the overlay
  1212. if ((((pThisDisplay->pGLInfo->dwFlags & GMVF_DFP_DISPLAY) != 0) &&
  1213. ((pThisDisplay->pGLInfo->dwScreenWidth !=
  1214. pThisDisplay->pGLInfo->dwVideoWidth) ||
  1215. (pThisDisplay->pGLInfo->dwScreenHeight !=
  1216. pThisDisplay->pGLInfo->dwVideoHeight))) ||
  1217. (lpFlipData->lpSurfTarg->ddsCaps.dwCaps & DDSCAPS_OVERLAY))
  1218. {
  1219. DWORD dwVideoOverlayUpdate;
  1220. do
  1221. {
  1222. dwVideoOverlayUpdate = READ_GLINT_CTRL_REG(VideoOverlayUpdate);
  1223. } while ((dwVideoOverlayUpdate & 0x1) != 0);
  1224. // Just let the overlay routine do the hard work.
  1225. // Tell it that this is a screen emulation.
  1226. _DD_OV_UpdateSource(pThisDisplay,
  1227. lpFlipData->lpSurfTarg);
  1228. UPDATE_OVERLAY(pThisDisplay,
  1229. !(lpFlipData->dwFlags & DDFLIP_NOVSYNC),
  1230. FALSE);
  1231. }
  1232. else // Normal mode - flip the screen address.
  1233. {
  1234. ULONG ulVControl;
  1235. #if W95_DDRAW
  1236. // Apps should use the DDFLIP_NOVSYNC to take advantage of
  1237. // the new capability of the Perm3
  1238. if (! (lpFlipData->dwFlags & DDFLIP_NOVSYNC))
  1239. {
  1240. if (READ_GLINT_CTRL_REG(VideoControl) & __GP_VIDEO_ENABLE)
  1241. {
  1242. LOAD_GLINT_CTRL_REG(IntFlags, INTR_VBLANK_SET);
  1243. while (((READ_GLINT_CTRL_REG(IntFlags)) & INTR_VBLANK_SET) == 0);
  1244. }
  1245. }
  1246. #endif
  1247. #if DX7_STEREO
  1248. if (lpFlipData->dwFlags & DDFLIP_STEREO ) // will be stereo
  1249. {
  1250. if (lpFlipData->lpSurfTargLeft)
  1251. {
  1252. dwDDSurfaceOffset =
  1253. (DWORD)(lpFlipData->lpSurfTargLeft->lpGbl->fpVidMem -
  1254. pThisDisplay->dwScreenFlatAddr);
  1255. // Update the screenbase address using the DownloadAddress
  1256. // & Data mechanism (therefore through the core)
  1257. SEND_P3_DATA(VTGAddress,
  1258. VTG_VIDEO_ADDRESS(VID_SCREENBASERIGHT));
  1259. SEND_P3_DATA(VTGData, (dwDDSurfaceOffset >> 4) );
  1260. }
  1261. ulVControl = READ_GLINT_CTRL_REG(VideoControl);
  1262. LOAD_GLINT_CTRL_REG(VideoControl,
  1263. ulVControl | __VIDEO_STEREOENABLE);
  1264. }
  1265. else
  1266. {
  1267. ulVControl = READ_GLINT_CTRL_REG(VideoControl);
  1268. LOAD_GLINT_CTRL_REG(VideoControl,
  1269. ulVControl & (~__VIDEO_STEREOENABLE));
  1270. }
  1271. #endif
  1272. // Get the surface offset from the start of memory
  1273. dwDDSurfaceOffset =
  1274. (DWORD)(lpFlipData->lpSurfTarg->lpGbl->fpVidMem -
  1275. pThisDisplay->dwScreenFlatAddr);
  1276. // Update the screenbase address using the DownloadAddress/data
  1277. // mechanism (therefore through the core)
  1278. // Setup so that DownloadData will update the ScreenBase Address.
  1279. SEND_P3_DATA(VTGAddress, VTG_VIDEO_ADDRESS(VID_SCREENBASE));
  1280. SEND_P3_DATA(VTGData, (dwDDSurfaceOffset >> 4) );
  1281. }
  1282. // Send a new RenderID to the chip.
  1283. dwNewRenderID = GET_NEW_HOST_RENDER_ID();
  1284. SEND_HOST_RENDER_ID ( dwNewRenderID );
  1285. pThisDisplay->dwLastFlipRenderID = dwNewRenderID;
  1286. // Flush the P3 Data
  1287. P3_DMA_COMMIT_BUFFER();
  1288. P3_DMA_FLUSH_BUFFER();
  1289. }
  1290. // Remember where we flipped from
  1291. pThisDisplay->flipRecord.fpFlipFrom =
  1292. lpFlipData->lpSurfCurr->lpGbl->fpVidMem;
  1293. lpFlipData->ddRVal = DD_OK;
  1294. START_SOFTWARE_CURSOR(pThisDisplay);
  1295. DBG_CB_EXIT(DdFlip,DD_OK);
  1296. return DDHAL_DRIVER_HANDLED;
  1297. } // DdFlip
  1298. //-----------------------------Public Routine----------------------------------
  1299. //
  1300. // DdWaitForVerticalBlank
  1301. //
  1302. // Returns the vertical blank status of the device.
  1303. //
  1304. // Parameters
  1305. //
  1306. // lpWaitForVerticalBlank
  1307. // Points to a DD_WAITFORVERTICALBLANKDATA structure that
  1308. // contains the information required to obtain the vertical
  1309. // blank status.
  1310. //
  1311. // PDD_DIRECTDRAW_GLOBAL
  1312. // lpDD
  1313. // Points to the DirectDraw structure representing
  1314. // the DirectDraw object.
  1315. // DWORD
  1316. // dwFlags
  1317. // Specifies how the driver should wait for the vertical blank.
  1318. // This member can be one of the following values:
  1319. //
  1320. // DDWAITVB_I_TESTVB The driver should determine whether
  1321. // a vertical blank is currently
  1322. // occurring and return the status in
  1323. // bIsInVB.
  1324. // DDWAITVB_BLOCKBEGIN The driver should return when it
  1325. // detects the beginning of the vertical
  1326. // blank interval.
  1327. // DDWAITVB_BLOCKBEGINEVENT Is currently unsupported on Windows
  1328. // 2000 and should be ignored by the
  1329. // driver.
  1330. // DDWAITVB_BLOCKEND The driver should return when it
  1331. // detects the end of the vertical
  1332. // blank interval and display begins.
  1333. // DWORD
  1334. // bIsInVB
  1335. // Indicates the status of the vertical blank. A value of
  1336. // TRUE indicates that the device is in a vertical blank;
  1337. // FALSE means that it is not. The driver should return the
  1338. // current vertical blanking status in this member when
  1339. // dwFlags is DDWAITVB_I_TESTVB.
  1340. // DWORD
  1341. // hEvent
  1342. // Is currently unsupported on Windows 2000 and should be ignored
  1343. // by the driver.
  1344. // HRESULT
  1345. // ddRVal
  1346. // Is the location in which the driver writes the return value of
  1347. // the DdWaitForVerticalBlank callback. A return code of DD_OK
  1348. // indicates success.
  1349. // VOID*
  1350. // WaitForVerticalBlank
  1351. // Is unused on Windows 2000.
  1352. //
  1353. // Return Value
  1354. // DdWaitForVerticalBlank returns one of the following callback codes:
  1355. //
  1356. // DDHAL_DRIVER_HANDLED
  1357. // DDHAL_DRIVER_NOTHANDLED
  1358. //
  1359. // Comments
  1360. // Depending on the value of dwFlags, the driver should do the following:
  1361. //
  1362. // If dwFlags is DDWAITVB_I_TESTVB, the driver should query the current
  1363. // vertical blanking status. The driver should set bIsInVB to TRUE if the
  1364. // monitor is currently in a vertical blank; otherwise it should set it
  1365. // to FALSE.
  1366. //
  1367. // If dwFlags is DDWAITVB_BLOCKBEGIN, the driver should block and wait
  1368. // until a vertical blank begins. If a vertical blank is in progress when
  1369. // the driver begins the block, the driver should wait until the next
  1370. // vertical blank begins before returning.
  1371. //
  1372. // If dwFlags is DDWAITVB_BLOCKEND, the driver should block and wait
  1373. // until a vertical blank ends.
  1374. //
  1375. // When the driver successfully handles the action specified in dwFlags,
  1376. // it should set DD_OK in ddRVal and return DDHAL_DRIVER_HANDLED. The
  1377. // driver should return DDHAL_DRIVER_NOTHANDLED for those flags that it
  1378. // is incapable of handling.
  1379. //
  1380. // DdWaitForVerticalBlank allows an application to synchronize itself
  1381. // with the vertical blanking interval (VBI).
  1382. //
  1383. //-----------------------------------------------------------------------------
  1384. // bit in VideoControl Register
  1385. #define __GP_VIDEO_ENABLE 0x0001
  1386. DWORD CALLBACK
  1387. DdWaitForVerticalBlank(
  1388. LPDDHAL_WAITFORVERTICALBLANKDATA lpWaitForVerticalBlank)
  1389. {
  1390. static BOOL bBlankReturn = TRUE;
  1391. P3_THUNKEDDATA* pThisDisplay;
  1392. GET_THUNKEDDATA(pThisDisplay, lpWaitForVerticalBlank->lpDD);
  1393. DBG_CB_ENTRY(DdWaitForVerticalBlank);
  1394. switch(lpWaitForVerticalBlank->dwFlags)
  1395. {
  1396. case DDWAITVB_I_TESTVB:
  1397. //
  1398. // just toggle the return bit when monitor is powered off
  1399. //
  1400. if( ! ( READ_GLINT_CTRL_REG(VideoControl) & __GP_VIDEO_ENABLE ) )
  1401. {
  1402. lpWaitForVerticalBlank->bIsInVB = bBlankReturn;
  1403. bBlankReturn = !bBlankReturn;
  1404. }
  1405. else
  1406. {
  1407. // Just a request for current VBLANK status
  1408. lpWaitForVerticalBlank->bIsInVB = IN_VBLANK;
  1409. }
  1410. lpWaitForVerticalBlank->ddRVal = DD_OK;
  1411. DBG_CB_EXIT(DdWaitForVerticalBlank,DD_OK);
  1412. return DDHAL_DRIVER_HANDLED;
  1413. case DDWAITVB_BLOCKBEGIN:
  1414. //
  1415. // only wait when the monitor is on
  1416. //
  1417. if( READ_GLINT_CTRL_REG(VideoControl) & __GP_VIDEO_ENABLE )
  1418. {
  1419. // if blockbegin is requested we wait until the vertical
  1420. // retrace is over, and then wait for the display period to end.
  1421. while(IN_VBLANK)
  1422. NULL;
  1423. while(!IN_VBLANK)
  1424. NULL;
  1425. }
  1426. lpWaitForVerticalBlank->ddRVal = DD_OK;
  1427. DBG_CB_EXIT(DdWaitForVerticalBlank,DD_OK);
  1428. return DDHAL_DRIVER_HANDLED;
  1429. case DDWAITVB_BLOCKEND:
  1430. //
  1431. // only wait when the monitor is on
  1432. //
  1433. if( READ_GLINT_CTRL_REG(VideoControl) & __GP_VIDEO_ENABLE )
  1434. {
  1435. // if blockend is requested we wait for the vblank interval to end.
  1436. if( IN_VBLANK )
  1437. {
  1438. while( IN_VBLANK )
  1439. NULL;
  1440. }
  1441. else
  1442. {
  1443. while(IN_DISPLAY)
  1444. NULL;
  1445. while(IN_VBLANK)
  1446. NULL;
  1447. }
  1448. }
  1449. lpWaitForVerticalBlank->ddRVal = DD_OK;
  1450. DBG_CB_EXIT(DdWaitForVerticalBlank,DD_OK);
  1451. return DDHAL_DRIVER_HANDLED;
  1452. }
  1453. DBG_CB_EXIT(DdWaitForVerticalBlank,0);
  1454. return DDHAL_DRIVER_NOTHANDLED;
  1455. } // DdWaitForVerticalBlank
  1456. //-----------------------------Public Routine----------------------------------
  1457. //
  1458. // DdLock
  1459. //
  1460. // Locks a specified area of surface memory and provides a valid pointer to a
  1461. // block of memory associated with a surface.
  1462. //
  1463. // Parameters
  1464. // lpLock
  1465. // Points to a DD_LOCKDATA structure that contains the information
  1466. // required to perform the lockdown.
  1467. //
  1468. // Members
  1469. //
  1470. // PDD_DIRECTDRAW_GLOBAL
  1471. // lpDD
  1472. // Points to a DD_DIRECTDRAW_GLOBAL structure that
  1473. // describes the driver.
  1474. // PDD_SURFACE_LOCAL
  1475. // lpDDSurface
  1476. // Points to a DD_SURFACE_LOCAL structure that describes the
  1477. // surface associated with the memory region to be locked down.
  1478. // DWORD
  1479. // bHasRect
  1480. // Specifies whether the area in rArea is valid.
  1481. // RECTL
  1482. // rArea
  1483. // Is a RECTL structure that defines the area on the
  1484. // surface to lock down.
  1485. // LPVOID
  1486. // lpSurfData
  1487. // Is the location in which the driver can return a pointer
  1488. // to the memory region that it locked down.
  1489. // HRESULT
  1490. // ddRVal
  1491. // Is the location in which the driver writes the return value
  1492. // of the DdLock callback. A return code of DD_OK
  1493. // indicates success.
  1494. // VOID*
  1495. // Lock
  1496. // Is unused on Windows 2000.
  1497. // DWORD
  1498. // dwFlags
  1499. // Is a bitmask that tells the driver how to perform the
  1500. // memory lockdown. This member is a bitwise-OR of any
  1501. // of the following values:
  1502. //
  1503. // DDLOCK_SURFACEMEMORYPTR The driver should return a valid
  1504. // memory pointer to the top of the
  1505. // rectangle specified in rArea. If
  1506. // no rectangle is specified, the
  1507. // driver should return a pointer to
  1508. // the top of the surface.
  1509. // DDLOCK_WAIT This flag is reserved for system
  1510. // use and should be ignored by the
  1511. // driver. Otherwise performance may
  1512. // be adversely hurt.
  1513. // DDLOCK_READONLY The surface being locked will only
  1514. // be read from. On Windows 2000,
  1515. // this flag is currently never set.
  1516. // DDLOCK_WRITEONLY The surface being locked will only
  1517. // be written to. On Windows 2000,
  1518. // this flag is currently never set.
  1519. // DDLOCK_EVENT This flag is reserved for system
  1520. // use and should be ignored by the
  1521. // driver.
  1522. // FLATPTR
  1523. // fpProcess
  1524. // Is a pointer to a user-mode mapping of the driver's memory.
  1525. // The driver performs this mapping in DdMapMemory.
  1526. // Return Value
  1527. // DdLock returns one of the following callback codes:
  1528. //
  1529. // DDHAL_DRIVER_HANDLED
  1530. // DDHAL_DRIVER_NOTHANDLED
  1531. // Comments
  1532. //
  1533. // DdLock should set ddRVal to DDERR_WASSTILLDRAWING and return
  1534. // DDHAL_DRIVER_HANDLED if a blt or flip is in progress.
  1535. //
  1536. // Unless otherwise specified by dwFlags, the driver can return a memory
  1537. // pointer to the top of the surface in lpSurfData. If the driver needs
  1538. // to calculate its own address for the surface, it can rely on the
  1539. // pointer passed in fpProcess as being a per-process pointer to the
  1540. // user-mode mapping of its DirectDraw-accessible frame buffer.
  1541. //
  1542. // A lock does not provide exclusive access to the requested memory block;
  1543. // that is, multiple threads can lock the same surface at the same time.
  1544. // It is the application's responsibility to synchronize access to the
  1545. // memory block whose pointer is being obtained.
  1546. //
  1547. //-----------------------------------------------------------------------------
  1548. DWORD CALLBACK
  1549. DdLock(
  1550. LPDDHAL_LOCKDATA lpLockData )
  1551. {
  1552. HRESULT ddrval;
  1553. P3_THUNKEDDATA* pThisDisplay;
  1554. GET_THUNKEDDATA(pThisDisplay, lpLockData->lpDD);
  1555. DBG_CB_ENTRY(DdLock);
  1556. VALIDATE_MODE_AND_STATE(pThisDisplay);
  1557. DBGDUMP_DDRAWSURFACE_LCL(DBGLVL, lpLockData->lpDDSurface);
  1558. // This call is invoked to lock a DirectDraw Videomemory surface. To make
  1559. // sure there are no pending drawing operations on the surface, flush all
  1560. // drawing operations and wait for a flip if it is still pending.
  1561. STOP_SOFTWARE_CURSOR(pThisDisplay);
  1562. // Check to see if any pending physical flip has occurred.
  1563. ddrval = _DX_QueryFlipStatus(pThisDisplay,
  1564. lpLockData->lpDDSurface->lpGbl->fpVidMem,
  1565. TRUE);
  1566. if( FAILED(ddrval) )
  1567. {
  1568. lpLockData->ddRVal = DDERR_WASSTILLDRAWING;
  1569. START_SOFTWARE_CURSOR(pThisDisplay);
  1570. DBG_CB_EXIT(DdLock,DDERR_WASSTILLDRAWING);
  1571. return DDHAL_DRIVER_HANDLED;
  1572. }
  1573. // don't allow a lock if a blt is in progress
  1574. if(DRAW_ENGINE_BUSY(pThisDisplay))
  1575. {
  1576. lpLockData->ddRVal = DDERR_WASSTILLDRAWING;
  1577. START_SOFTWARE_CURSOR(pThisDisplay);
  1578. DBG_CB_EXIT(DdLock, lpLockData->ddRVal);
  1579. return DDHAL_DRIVER_HANDLED;
  1580. }
  1581. #if DX7_TEXMANAGEMENT
  1582. //
  1583. // If the user attempts to lock a driver managed surface,
  1584. // mark it as dirty and return. This way next time we attempt
  1585. // to use the surface we will reload it from the sysmem copy
  1586. //
  1587. if (lpLockData->lpDDSurface->lpSurfMore->ddsCapsEx.dwCaps2 &
  1588. DDSCAPS2_TEXTUREMANAGE)
  1589. {
  1590. DISPDBG((DBGLVL, "DDraw:Lock %08lx %08lx",
  1591. lpLockData->lpDDSurface->lpSurfMore->dwSurfaceHandle,
  1592. lpLockData->lpDDSurface->lpGbl->fpVidMem));
  1593. _D3D_TM_MarkDDSurfaceAsDirty(pThisDisplay,
  1594. lpLockData->lpDDSurface,
  1595. TRUE);
  1596. if (lpLockData->bHasRect)
  1597. {
  1598. #if DX8_3DTEXTURES
  1599. if (lpLockData->dwFlags & DDLOCK_HASVOLUMETEXTUREBOXRECT)
  1600. {
  1601. DWORD left, right, front, back;
  1602. // Sub Volume Lock suppport (DX8.1 feature)
  1603. // Check if we are able to lock just a subvolume instead of
  1604. // the whole volume texture and therefore potentially increase
  1605. // performance.
  1606. // left and .right subfields of the rArea field have to be
  1607. // reinterpreted as also containing respectively the Front and
  1608. // Back coordinates of the locked volume in their higher 16 bits
  1609. front = lpLockData->rArea.left >> 16;
  1610. back = lpLockData->rArea.right >> 16;
  1611. left = lpLockData->rArea.left && 0xFFFF;
  1612. right = lpLockData->rArea.right && 0xFFFF;
  1613. lpLockData->lpSurfData = (LPVOID)
  1614. (lpLockData->lpDDSurface->lpGbl->fpVidMem +
  1615. (front * lpLockData->lpDDSurface->lpGbl->dwBlockSizeY ) +
  1616. (lpLockData->lpDDSurface->lpGbl->lPitch *
  1617. lpLockData->rArea.top) +
  1618. (lpLockData->rArea.left <<
  1619. DDSurf_GetPixelShift(lpLockData->lpDDSurface)));
  1620. }
  1621. else
  1622. #endif // DX8_3DTEXTURES
  1623. {
  1624. lpLockData->lpSurfData = (LPVOID)
  1625. (lpLockData->lpDDSurface->lpGbl->fpVidMem +
  1626. (lpLockData->lpDDSurface->lpGbl->lPitch *
  1627. lpLockData->rArea.top) +
  1628. (lpLockData->rArea.left <<
  1629. DDSurf_GetPixelShift(lpLockData->lpDDSurface)));
  1630. }
  1631. }
  1632. else
  1633. {
  1634. lpLockData->lpSurfData = (LPVOID)
  1635. (lpLockData->lpDDSurface->lpGbl->fpVidMem);
  1636. }
  1637. lpLockData->ddRVal = DD_OK;
  1638. START_SOFTWARE_CURSOR(pThisDisplay);
  1639. DBG_CB_EXIT(DdLock, lpLockData->ddRVal);
  1640. return DDHAL_DRIVER_HANDLED;
  1641. }
  1642. #endif // DX7_TEXMANAGEMENT
  1643. // Switch to DirectDraw context
  1644. DDRAW_OPERATION(pContext, pThisDisplay);
  1645. // send a flush and wait for outstanding operations
  1646. // before allowing surfaces to be locked.
  1647. {P3_DMA_DEFS();
  1648. P3_DMA_GET_BUFFER();
  1649. P3_DMA_FLUSH_BUFFER();
  1650. }
  1651. // Wait for outstanding operations before allowing surfaces to be locked
  1652. SYNC_WITH_GLINT;
  1653. // Since all our surfaces are linear we don't need to do
  1654. // a patch->unpatch conversion here.
  1655. START_SOFTWARE_CURSOR(pThisDisplay);
  1656. lpLockData->ddRVal = DD_OK;
  1657. DBG_CB_EXIT(DdLock,lpLockData->ddRVal);
  1658. // Because we correctly set fpVidMem to be the offset into our frame
  1659. // buffer when we created the surface, DirectDraw will automatically take
  1660. // care of adding in the user-mode frame buffer address if we return
  1661. // DDHAL_DRIVER_NOTHANDLED
  1662. return(DDHAL_DRIVER_NOTHANDLED);
  1663. } // DdLock
  1664. //-----------------------------Public Routine----------------------------------
  1665. //
  1666. // DdUnlock
  1667. //
  1668. // Releases the lock held on the specified surface.
  1669. //
  1670. // Parameters
  1671. //
  1672. // lpUnlock
  1673. // Points to a DD_UNLOCKDATA structure that contains the
  1674. // information required to perform the lock release.
  1675. //
  1676. // Members
  1677. //
  1678. // PDD_DIRECTDRAW_GLOBAL
  1679. // lpDD
  1680. // Points to a DD_DIRECTDRAW_GLOBAL structure that
  1681. // describes the driver.
  1682. // PDD_SURFACE_LOCAL
  1683. // lpDDSurface
  1684. // Points to a DD_SURFACE_LOCAL structure that describes the
  1685. // surface to be unlocked.
  1686. // HRESULT
  1687. // ddRVal
  1688. // Is the location in which the driver writes the return value
  1689. // of the DdUnlock callback. A return code of DD_OK indicates
  1690. // success.
  1691. // VOID*
  1692. // Unlock
  1693. // Is unused on Windows 2000.
  1694. //
  1695. // Return Value
  1696. // DdUnlock returns one of the following callback codes:
  1697. //
  1698. // DDHAL_DRIVER_HANDLED
  1699. // DDHAL_DRIVER_NOTHANDLED
  1700. //
  1701. // Comments
  1702. // The driver does not need to verify that the memory was previously
  1703. // locked down by DdLock, because DirectDraw does parameter validation
  1704. // before calling this routine.
  1705. //-----------------------------------------------------------------------------
  1706. DWORD CALLBACK
  1707. DdUnlock(
  1708. LPDDHAL_UNLOCKDATA lpUnlockData )
  1709. {
  1710. P3_THUNKEDDATA* pThisDisplay;
  1711. DBG_CB_ENTRY(DdUnlock);
  1712. lpUnlockData->ddRVal = DD_OK;
  1713. DBG_CB_EXIT(DdUnlock,lpUnlockData->ddRVal);
  1714. return ( DDHAL_DRIVER_HANDLED );
  1715. } // DdUnlock
  1716. //-----------------------------Public Routine----------------------------------
  1717. // DdGetScanLine
  1718. //
  1719. // Returns the number of the current physical scan line.
  1720. //
  1721. // Parameters
  1722. // pGetScanLine
  1723. // Points to a DD_GETSCANLINEDATA structure in which the
  1724. // driver returns the number of the current scan line.
  1725. // Members
  1726. //
  1727. // PDD_DIRECTDRAW_GLOBAL
  1728. // lpDD
  1729. // Points to a DD_DIRECTDRAW_GLOBAL structure that
  1730. // represents the driver.
  1731. // DWORD
  1732. // dwScanLine
  1733. // Is the location in which the driver returns the number
  1734. // of the current scan line.
  1735. // HRESULT
  1736. // ddRVal
  1737. // Is the location in which the driver writes the return
  1738. // value of the DdGetScanLine callback. A return code of
  1739. // DD_OK indicates success.
  1740. // VOID *
  1741. // GetScanLine
  1742. // Is unused on Windows 2000.
  1743. // Return Value
  1744. // DdGetScanLine returns one of the following callback codes:
  1745. //
  1746. // DDHAL_DRIVER_HANDLED
  1747. // DDHAL_DRIVER_NOTHANDLED
  1748. //
  1749. // Comments
  1750. // If the monitor is not in vertical blank, the driver should write
  1751. // the scan line value in dwScanLine. The number must be between zero
  1752. // and n, where scan line 0 is the first visible scan line and n is
  1753. // the last visible scan line on the screen. The driver should then
  1754. // set DD_OK in ddRVal and return DDHAL_DRIVER_HANDLED.
  1755. //
  1756. // The scan line is indeterminate if a vertical blank is in progress.
  1757. // In this situation, the driver should set ddRVal to
  1758. // DDERR_VERTICALBLANKINPROGRESS and return DDHAL_DRIVER_HANDLED.
  1759. //
  1760. //-----------------------------------------------------------------------------
  1761. DWORD CALLBACK
  1762. DdGetScanLine(
  1763. LPDDHAL_GETSCANLINEDATA lpGetScanLine)
  1764. {
  1765. P3_THUNKEDDATA* pThisDisplay;
  1766. GET_THUNKEDDATA(pThisDisplay, lpGetScanLine->lpDD);
  1767. DBG_CB_ENTRY(DdGetScanLine);
  1768. VALIDATE_MODE_AND_STATE(pThisDisplay);
  1769. //
  1770. // If a vertical blank is in progress the scan line is in
  1771. // indeterminant. If the scan line is indeterminant we return
  1772. // the error code DDERR_VERTICALBLANKINPROGRESS.
  1773. // Otherwise we return the scan line and a success code
  1774. //
  1775. if( IN_VBLANK )
  1776. {
  1777. lpGetScanLine->ddRVal = DDERR_VERTICALBLANKINPROGRESS;
  1778. lpGetScanLine->dwScanLine = 0;
  1779. }
  1780. else
  1781. {
  1782. LONG lVBEnd = READ_GLINT_CTRL_REG(VbEnd);
  1783. LONG lScanline = READ_GLINT_CTRL_REG(LineCount);
  1784. // Need to return a number from 0 -> (ScreenHeight + VBlank Size)
  1785. lScanline = lScanline - lVBEnd;
  1786. if (lScanline < 0)
  1787. {
  1788. lScanline = pThisDisplay->dwScreenHeight + (lVBEnd + lScanline);
  1789. }
  1790. // Modes less than 400 high are line-doubled.
  1791. if (pThisDisplay->dwScreenHeight < 400)
  1792. {
  1793. lScanline >>= 1;
  1794. }
  1795. DISPDBG((DBGLVL,"Scanline: %d", lScanline));
  1796. lpGetScanLine->dwScanLine = (DWORD)lScanline;
  1797. lpGetScanLine->ddRVal = DD_OK;
  1798. }
  1799. DBG_CB_EXIT(DdGetScanLine,lpGetScanLine->ddRVal);
  1800. return DDHAL_DRIVER_HANDLED;
  1801. } // DdGetScanLine
  1802. //-----------------------------Public Routine----------------------------------
  1803. // DdGetBltStatus
  1804. //
  1805. // Queries the blt status of the specified surface.
  1806. //
  1807. // Parameters
  1808. // lpGetBltStatus
  1809. // Points to a DD_GETBLTSTATUSDATA structure that contains the
  1810. // information required to perform the blt status query.
  1811. //
  1812. // Members
  1813. //
  1814. // PDD_DIRECTDRAW_GLOBAL
  1815. // lpDD
  1816. // Points to a DD_DIRECTDRAW_GLOBAL structure that
  1817. // describes the driver.
  1818. // PDD_SURFACE_LOCAL
  1819. // lpDDSurface
  1820. // Points to a DD_SURFACE_LOCAL structure
  1821. // representing the surface whose blt status is
  1822. // being queried.
  1823. // DWORD
  1824. // dwFlags
  1825. // Specifies the blt status being requested. This
  1826. // member can be one of the following values which
  1827. // are defined in ddraw.h:
  1828. //
  1829. // DDGBS_CANBLT Queries whether the driver
  1830. // can currently perform a blit.
  1831. // DDGBS_ISBLTDONE Queries whether the driver
  1832. // has completed the last blit.
  1833. // HRESULT
  1834. // ddRVal
  1835. // Is the location in which the driver writes the
  1836. // return value of the DdGetBltStatus callback.
  1837. // A return code of DD_OK indicates success.
  1838. // VOID*
  1839. // GetBltStatus
  1840. // Is unused on Windows 2000.
  1841. // Return Value
  1842. // DdGetBltStatus returns one of the following callback codes:
  1843. //
  1844. // DDHAL_DRIVER_HANDLED
  1845. // DDHAL_DRIVER_NOTHANDLED
  1846. //
  1847. // Comments
  1848. // The blt status that the driver returns is based on the dwFlags
  1849. // member of the structure that lpGetBltStatus points to as follows:
  1850. //
  1851. // If the flag is DDGBS_CANBLT, the driver should determine whether
  1852. // the surface is currently involved in a flip. If a flip is not in
  1853. // progress and if the hardware is otherwise capable of currently
  1854. // accepting a blt request, the driver should return DD_OK in ddRVal.
  1855. // If a flip is in progress or if the hardware cannot currently
  1856. // accept another blt request, the driver should set ddRVal to
  1857. // DDERR_WASSTILLDRAWING.
  1858. //
  1859. // If the flag is DDGBS_ISBLTDONE, the driver should set ddRVal to
  1860. // DDERR_WASSTILLDRAWING if a blt is currently in progress; otherwise
  1861. // it should return DD_OK.
  1862. //
  1863. //
  1864. //-----------------------------------------------------------------------------
  1865. DWORD CALLBACK DdGetBltStatus(
  1866. LPDDHAL_GETBLTSTATUSDATA lpGetBltStatus )
  1867. {
  1868. P3_THUNKEDDATA* pThisDisplay;
  1869. GET_THUNKEDDATA(pThisDisplay, lpGetBltStatus->lpDD);
  1870. DBG_CB_ENTRY(DdGetBltStatus);
  1871. STOP_SOFTWARE_CURSOR(pThisDisplay);
  1872. // Notice that your implementation could be optimized to check for the
  1873. // particular surface specified. Here we are just querying the general
  1874. // blt status of the engine.
  1875. // Driver is being queried whether it can add a blt
  1876. if( lpGetBltStatus->dwFlags == DDGBS_CANBLT )
  1877. {
  1878. // Must explicitely wait for the flip
  1879. lpGetBltStatus->ddRVal =
  1880. _DX_QueryFlipStatus(pThisDisplay,
  1881. lpGetBltStatus->lpDDSurface->lpGbl->fpVidMem,
  1882. TRUE);
  1883. if( SUCCEEDED( lpGetBltStatus->ddRVal ) )
  1884. {
  1885. // so there was no flip going on, is the engine idle to add a blt?
  1886. if( DRAW_ENGINE_BUSY(pThisDisplay) )
  1887. {
  1888. lpGetBltStatus->ddRVal = DDERR_WASSTILLDRAWING;
  1889. }
  1890. else
  1891. {
  1892. lpGetBltStatus->ddRVal = DD_OK;
  1893. }
  1894. }
  1895. }
  1896. else if ( lpGetBltStatus->dwFlags == DDGBS_ISBLTDONE )
  1897. {
  1898. if ( DRAW_ENGINE_BUSY(pThisDisplay) )
  1899. {
  1900. lpGetBltStatus->ddRVal = DDERR_WASSTILLDRAWING;
  1901. }
  1902. else
  1903. {
  1904. lpGetBltStatus->ddRVal = DD_OK;
  1905. }
  1906. }
  1907. START_SOFTWARE_CURSOR(pThisDisplay);
  1908. DBG_CB_EXIT(DdGetBltStatus, lpGetBltStatus->ddRVal);
  1909. return DDHAL_DRIVER_HANDLED;
  1910. } // DdGetBltStatus
  1911. //-----------------------------Public Routine----------------------------------
  1912. //
  1913. // DdGetFlipStatus
  1914. //
  1915. // Determines whether the most recently requested flip
  1916. // on a surface has occurred.
  1917. //
  1918. // Parameters
  1919. // lpGetFlipStatus
  1920. // Points to a DD_GETFLIPSTATUSDATA structure that contains
  1921. // the information required to perform the flip status query.
  1922. //
  1923. // Members
  1924. //
  1925. // PDD_DIRECTDRAW_GLOBAL
  1926. // lpDD
  1927. // Points to a DD_DIRECTDRAW_GLOBAL structure
  1928. // representing the driver.
  1929. // PDD_SURFACE_LOCAL
  1930. // lpDDSurface
  1931. // Points to a DD_SURFACE_LOCAL structure that
  1932. // describes the surface whose flip status is
  1933. // being queried.
  1934. // DWORD
  1935. // dwFlags
  1936. // Specifies the flip status being requested. This
  1937. // member can be one of the following values which
  1938. // are defined in ddraw.h:
  1939. //
  1940. // DDGFS_CANFLIP Queries whether the driver can
  1941. // currently perform a flip.
  1942. // DDGFS_ISFLIPDONE Queries whether the driver has
  1943. // finished the last flip.
  1944. // HRESULT
  1945. // ddRVal
  1946. // Is the location in which the driver writes the
  1947. // return value of the DdGetFlipStatus callback.
  1948. // A return code of DD_OK indicates success.
  1949. // VOID*
  1950. // GetFlipStatus
  1951. // Is unused on Windows 2000.
  1952. //
  1953. // Return Value
  1954. // DdGetFlipStatus returns one of the following callback codes:
  1955. //
  1956. // DDHAL_DRIVER_HANDLED
  1957. // DDHAL_DRIVER_NOTHANDLED
  1958. //
  1959. // Comments
  1960. //
  1961. // The driver should report its flip status based on the flag set in
  1962. // the dwFlags member of the structure that lpGetFlipStatus points
  1963. // to as follows:
  1964. //
  1965. // If the flag is DDGFS_CANFLIP, the driver should determine whether
  1966. // the surface is currently involved in a flip. If a flip or a blt is
  1967. // not in progress and if the hardware is otherwise capable of
  1968. // currently accepting a flip request, the driver should return DD_OK
  1969. // in ddRVal. If a flip is in progress or if the hardware cannot
  1970. // currently accept a flip request, the driver should set ddRVal to
  1971. // DDERR_WASSTILLDRAWING.
  1972. //
  1973. // If the flag is DDGFS_ISFLIPDONE, the driver should set ddRVal to
  1974. // DDERR_WASSTILLDRAWING if a flip is currently in progress; otherwise
  1975. // it should return DD_OK.
  1976. //
  1977. // Notes:
  1978. //
  1979. // If the display has went through one refresh cycle since the flip
  1980. // occurred we return DD_OK. If it has not went through one refresh
  1981. // cycle we return DDERR_WASSTILLDRAWING to indicate that this surface
  1982. // is still busy "drawing" the flipped page. We also return
  1983. // DDERR_WASSTILLDRAWING if the bltter is busy and the caller wanted
  1984. // to know if they could flip yet
  1985. //
  1986. // On the Permedia, flips are done using SuspendUntilFrameBlank,
  1987. // so no syncs ever need to be done in software, so this always
  1988. // returns DD_OK.
  1989. //
  1990. //-----------------------------------------------------------------------------
  1991. DWORD CALLBACK
  1992. DdGetFlipStatus(
  1993. LPDDHAL_GETFLIPSTATUSDATA lpGetFlipStatus )
  1994. {
  1995. P3_THUNKEDDATA* pThisDisplay;
  1996. GET_THUNKEDDATA(pThisDisplay, lpGetFlipStatus->lpDD);
  1997. DBG_CB_ENTRY(DdGetFlipStatus);
  1998. STOP_SOFTWARE_CURSOR(pThisDisplay);
  1999. //
  2000. // don't want a flip to work until after the last flip is done,
  2001. // so we ask for the general flip status and ignore the vmem
  2002. //
  2003. lpGetFlipStatus->ddRVal = _DX_QueryFlipStatus(pThisDisplay, 0, TRUE);
  2004. //
  2005. // check if the bltter busy if someone wants to know if they can flip
  2006. //
  2007. if( lpGetFlipStatus->dwFlags == DDGFS_CANFLIP )
  2008. {
  2009. if( ( SUCCEEDED( lpGetFlipStatus->ddRVal ) ) &&
  2010. ( DRAW_ENGINE_BUSY(pThisDisplay) ) )
  2011. {
  2012. lpGetFlipStatus->ddRVal = DDERR_WASSTILLDRAWING;
  2013. }
  2014. }
  2015. START_SOFTWARE_CURSOR(pThisDisplay);
  2016. DBG_CB_EXIT(DdGetFlipStatus,lpGetFlipStatus->ddRVal);
  2017. return DDHAL_DRIVER_HANDLED;
  2018. } // DdGetFlipStatus
  2019. //-----------------------------------------------------------------------------
  2020. // __SetupRops
  2021. //
  2022. // Build array for supported ROPS
  2023. //-----------------------------------------------------------------------------
  2024. static void
  2025. __SetupRops(
  2026. LPBYTE proplist,
  2027. LPDWORD proptable,
  2028. int cnt )
  2029. {
  2030. int i;
  2031. DWORD idx;
  2032. DWORD bit;
  2033. DWORD rop;
  2034. for(i=0; i<cnt; i++)
  2035. {
  2036. rop = proplist[i];
  2037. idx = rop / 32;
  2038. bit = 1L << ((DWORD)(rop % 32));
  2039. proptable[idx] |= bit;
  2040. }
  2041. } // __SetupRops
  2042. //-----------------------------------------------------------------------------
  2043. //
  2044. // ChangeDDHAL32Mode
  2045. //
  2046. // CALLED PER MODE CHANGE - NEVER AT START OF DAY (NO LOCK)
  2047. // Sets up Chip registers for this mode.
  2048. //
  2049. //-----------------------------------------------------------------------------
  2050. void
  2051. ChangeDDHAL32Mode(
  2052. P3_THUNKEDDATA* pThisDisplay)
  2053. {
  2054. DISPDBG((DBGLVL,"New Screen Width: %d",pThisDisplay->dwScreenWidth));
  2055. //@@BEGIN_DDKSPLIT
  2056. #if AZN
  2057. // If the driver has just started, reset the DMA Buffers to a known state.
  2058. if (pThisDisplay->bStartOfDay)
  2059. {
  2060. #if 0
  2061. unsigned long i;
  2062. for (i = 0; i < pThisDisplay->pGLInfo->NumberOfSubBuffers; i++)
  2063. {
  2064. pThisDisplay->pGLInfo->DMAPartition[i].bStampedDMA = TRUE;
  2065. pThisDisplay->pGLInfo->DMAPartition[i].Locked = FALSE;
  2066. //azn - this is hard to say in 64 bits!
  2067. memset((void*)pThisDisplay->pGLInfo->DMAPartition[i].VirtAddr,
  2068. 0x4D,
  2069. (pThisDisplay->pGLInfo->DMAPartition[i].MaxAddress -
  2070. pThisDisplay->pGLInfo->DMAPartition[i].VirtAddr));
  2071. }
  2072. #endif
  2073. // We don't need start of day setup anymore
  2074. pThisDisplay->bStartOfDay = FALSE;
  2075. }
  2076. #endif
  2077. //@@END_DDKSPLIT
  2078. STOP_SOFTWARE_CURSOR(pThisDisplay);
  2079. // Switch to DirectDraw context
  2080. DDRAW_OPERATION(pContext, pThisDisplay);
  2081. // Set up video Control
  2082. #if WNT_DDRAW
  2083. {
  2084. ULONG vidCon;
  2085. vidCon = READ_GLINT_CTRL_REG(VideoControl);
  2086. vidCon &= ~(3 << 9);
  2087. vidCon |= (0 << 9); // P3/P2 Limit to frame rate
  2088. LOAD_GLINT_CTRL_REG(VideoControl, vidCon);
  2089. }
  2090. #endif // WNT_DDRAW
  2091. // We have handled the display mode change
  2092. pThisDisplay->bResetMode = 0;
  2093. pThisDisplay->ModeChangeCount++;
  2094. START_SOFTWARE_CURSOR(pThisDisplay);
  2095. } // ChangeDDHAL32Mode
  2096. //-----------------------------------------------------------------------------
  2097. //
  2098. // Function: __GetDDHALInfo
  2099. //
  2100. // Returns: void
  2101. //
  2102. // Description:
  2103. //
  2104. // Takes a pointer to a partially or fully filled in pThisDisplay and a pointer
  2105. // to an empty DDHALINFO and fills in the DDHALINFO. This eases porting to NT
  2106. // and means that caps changes are done in only one place. The pThisDisplay
  2107. // may not be fully constructed here, so you should only:
  2108. // a) Query the registry
  2109. // b) DISPDBG
  2110. // If you need to add anything to pThisDisplay for NT, you should fill it in
  2111. // during the DrvGetDirectDraw call.
  2112. //
  2113. // The problem here is when the code is run on NT. If there was any other way...
  2114. //
  2115. // The following caps have been found to cause NT to bail....
  2116. // DDCAPS_GDI, DDFXCAPS_BLTMIRRORUPDOWN, DDFXCAPS_BLTMIRRORLEFTRIGHT
  2117. //
  2118. //
  2119. //-----------------------------------------------------------------------------
  2120. //
  2121. // use bits to indicate which ROPs you support.
  2122. //
  2123. // DWORD 0, bit 0 == ROP 0
  2124. // DWORD 8, bit 31 == ROP 255
  2125. //
  2126. static DWORD ropsAGP[DD_ROP_SPACE] = { 0 };
  2127. void
  2128. __GetDDHALInfo(
  2129. P3_THUNKEDDATA* pThisDisplay,
  2130. DDHALINFO* pHALInfo)
  2131. {
  2132. DWORD dwResult;
  2133. BOOL bRet;
  2134. int i;
  2135. static BYTE ropList95[] =
  2136. {
  2137. SRCCOPY >> 16,
  2138. WHITENESS >> 16,
  2139. BLACKNESS >> 16
  2140. };
  2141. static BYTE ropListNT[] =
  2142. {
  2143. SRCCOPY >> 16
  2144. };
  2145. static BYTE ropListAGP[] =
  2146. {
  2147. SRCCOPY >> 16,
  2148. WHITENESS >> 16,
  2149. BLACKNESS >> 16
  2150. };
  2151. static DWORD rops[DD_ROP_SPACE] = { 0 };
  2152. // Setup the HAL driver caps.
  2153. memset( pHALInfo, 0, sizeof(DDHALINFO) );
  2154. pHALInfo->dwSize = sizeof(DDHALINFO);
  2155. // Setup the ROPS we do.
  2156. #ifdef WNT_DDRAW
  2157. __SetupRops( ropListNT,
  2158. rops,
  2159. sizeof(ropListNT)/sizeof(ropListNT[0]));
  2160. #else
  2161. __SetupRops( ropList95,
  2162. rops,
  2163. sizeof(ropList95)/sizeof(ropList95[0]));
  2164. #endif
  2165. __SetupRops( ropListAGP,
  2166. ropsAGP,
  2167. sizeof(ropListAGP)/sizeof(ropListAGP[0]));
  2168. // The most basic DirectDraw functionality
  2169. pHALInfo->ddCaps.dwCaps = DDCAPS_BLT |
  2170. DDCAPS_BLTQUEUE |
  2171. DDCAPS_BLTCOLORFILL |
  2172. DDCAPS_READSCANLINE;
  2173. pHALInfo->ddCaps.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
  2174. DDSCAPS_PRIMARYSURFACE |
  2175. DDSCAPS_FLIP;
  2176. // More caps on Win95 than on NT (mainly for D3D)
  2177. #ifdef WNT_DDRAW
  2178. pHALInfo->ddCaps.dwCaps |= DDCAPS_3D |
  2179. DDCAPS_BLTDEPTHFILL;
  2180. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE |
  2181. DDSCAPS_ZBUFFER |
  2182. DDSCAPS_ALPHA;
  2183. pHALInfo->ddCaps.dwCaps2 = 0;
  2184. #else
  2185. pHALInfo->ddCaps.dwCaps |= DDCAPS_3D |
  2186. DDCAPS_GDI |
  2187. DDCAPS_ALPHA |
  2188. DDCAPS_BLTDEPTHFILL;
  2189. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_ALPHA |
  2190. DDSCAPS_3DDEVICE |
  2191. DDSCAPS_ZBUFFER;
  2192. pHALInfo->ddCaps.dwCaps2 = DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_FLIPNOVSYNC;
  2193. #endif // WNT_DDRAW
  2194. #if DX7_TEXMANAGEMENT
  2195. // We need to set this bit up in order to be able to do
  2196. // out own texture management
  2197. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_CANMANAGETEXTURE;
  2198. #if DX8_DDI
  2199. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_CANMANAGERESOURCE;
  2200. #endif
  2201. #endif
  2202. #if DX8_DDI
  2203. // We need to flag we can run in windowed mode, otherwise we
  2204. // might get restricted by apps to run in fullscreen only
  2205. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_CANRENDERWINDOWED;
  2206. #endif
  2207. pHALInfo->ddCaps.dwFXCaps = 0;
  2208. // P3RX can do:
  2209. // 1. Stretching/Shrinking
  2210. // 2. YUV->RGB conversion
  2211. // 3. Mirroring in X and Y
  2212. // 4. ColorKeying from a source color and a source color space
  2213. pHALInfo->ddCaps.dwCaps |= DDCAPS_BLTSTRETCH |
  2214. DDCAPS_BLTFOURCC |
  2215. DDCAPS_COLORKEY |
  2216. DDCAPS_CANBLTSYSMEM;
  2217. // Special effects caps
  2218. pHALInfo->ddCaps.dwFXCaps = DDFXCAPS_BLTSTRETCHY |
  2219. DDFXCAPS_BLTSTRETCHX |
  2220. DDFXCAPS_BLTSTRETCHYN |
  2221. DDFXCAPS_BLTSTRETCHXN |
  2222. DDFXCAPS_BLTSHRINKY |
  2223. DDFXCAPS_BLTSHRINKX |
  2224. DDFXCAPS_BLTSHRINKYN |
  2225. DDFXCAPS_BLTSHRINKXN;
  2226. // ColorKey caps
  2227. pHALInfo->ddCaps.dwCKeyCaps = DDCKEYCAPS_SRCBLT |
  2228. DDCKEYCAPS_SRCBLTCLRSPACE |
  2229. DDCKEYCAPS_DESTBLT |
  2230. DDCKEYCAPS_DESTBLTCLRSPACE;
  2231. pHALInfo->ddCaps.dwSVBCaps = DDCAPS_BLT;
  2232. // We can do a texture from sysmem to video mem.
  2233. pHALInfo->ddCaps.dwSVBCKeyCaps = DDCKEYCAPS_DESTBLT |
  2234. DDCKEYCAPS_DESTBLTCLRSPACE;
  2235. pHALInfo->ddCaps.dwSVBFXCaps = 0;
  2236. // Fill in the sysmem->vidmem rops (only can copy);
  2237. for( i=0;i<DD_ROP_SPACE;i++ )
  2238. {
  2239. pHALInfo->ddCaps.dwSVBRops[i] = rops[i];
  2240. }
  2241. pHALInfo->ddCaps.dwFXCaps |= DDFXCAPS_BLTMIRRORUPDOWN |
  2242. DDFXCAPS_BLTMIRRORLEFTRIGHT;
  2243. pHALInfo->ddCaps.dwCKeyCaps |= DDCKEYCAPS_SRCBLTCLRSPACEYUV;
  2244. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
  2245. #if DX7_STEREO
  2246. // Report the stereo capability back to runtime
  2247. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_STEREO;
  2248. pHALInfo->ddCaps.dwSVCaps = DDSVCAPS_STEREOSEQUENTIAL;
  2249. #endif
  2250. // Z Buffer is only 16 Bits
  2251. pHALInfo->ddCaps.dwZBufferBitDepths = DDBD_16;
  2252. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
  2253. if (pThisDisplay->bCanAGP && (pThisDisplay->dwDXVersion > DX5_RUNTIME))
  2254. {
  2255. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_NONLOCALVIDMEM;
  2256. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM |
  2257. DDSCAPS_NONLOCALVIDMEM;
  2258. // We support the hybrid AGP model. This means we have
  2259. // specific things we can do from AGP->Video memory, but
  2260. // we can also texture directly from AGP memory
  2261. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_NONLOCALVIDMEMCAPS;
  2262. }
  2263. else
  2264. {
  2265. DISPDBG((WRNLVL,"P3 Board is NOT AGP"));
  2266. }
  2267. // If we are a P3 we can do videoports
  2268. if (RENDERCHIP_PERMEDIAP3)
  2269. {
  2270. #ifdef SUPPORT_VIDEOPORT
  2271. // We support 1 video port. Must set CurrVideoPorts to 0
  2272. // We can't do interleaved bobbing yet - maybe in the future.
  2273. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_VIDEOPORT |
  2274. DDCAPS2_CANBOBNONINTERLEAVED;
  2275. pHALInfo->ddCaps.dwMaxVideoPorts = 1;
  2276. pHALInfo->ddCaps.dwCurrVideoPorts = 0;
  2277. #if W95_DDRAW
  2278. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_VIDEOPORT;
  2279. #endif // W95_DDRAW
  2280. #endif // SUPPORT_VIDEOPORT
  2281. if ( ( ( pThisDisplay->pGLInfo->dwFlags & GMVF_DFP_DISPLAY ) != 0 ) &&
  2282. ( ( pThisDisplay->pGLInfo->dwScreenWidth !=
  2283. pThisDisplay->pGLInfo->dwVideoWidth ) ||
  2284. ( pThisDisplay->pGLInfo->dwScreenHeight !=
  2285. pThisDisplay->pGLInfo->dwVideoHeight ) ) )
  2286. {
  2287. // Display driver is using the overlay to show the
  2288. // picture - disable the overlay.
  2289. pHALInfo->ddCaps.dwMaxVisibleOverlays = 0;
  2290. pHALInfo->ddCaps.dwCurrVisibleOverlays = 0;
  2291. }
  2292. #if WNT_DDRAW
  2293. else if (pThisDisplay->ppdev->flCaps & CAPS_DISABLE_OVERLAY)
  2294. #else
  2295. else if (pThisDisplay->pGLInfo->dwFlags & GMVF_DISABLE_OVERLAY)
  2296. #endif
  2297. {
  2298. // Overlays not supported in hw
  2299. pHALInfo->ddCaps.dwMaxVisibleOverlays = 0;
  2300. pHALInfo->ddCaps.dwCurrVisibleOverlays = 0;
  2301. }
  2302. else
  2303. {
  2304. // Overlay is free to use.
  2305. pHALInfo->ddCaps.dwMaxVisibleOverlays = 1;
  2306. pHALInfo->ddCaps.dwCurrVisibleOverlays = 0;
  2307. pHALInfo->ddCaps.dwCaps |= DDCAPS_OVERLAY |
  2308. DDCAPS_OVERLAYFOURCC |
  2309. DDCAPS_OVERLAYSTRETCH |
  2310. DDCAPS_COLORKEYHWASSIST |
  2311. DDCAPS_OVERLAYCANTCLIP;
  2312. pHALInfo->ddCaps.dwCKeyCaps |= DDCKEYCAPS_SRCOVERLAY |
  2313. DDCKEYCAPS_SRCOVERLAYONEACTIVE |
  2314. DDCKEYCAPS_SRCOVERLAYYUV |
  2315. DDCKEYCAPS_DESTOVERLAY |
  2316. DDCKEYCAPS_DESTOVERLAYONEACTIVE |
  2317. DDCKEYCAPS_DESTOVERLAYYUV;
  2318. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_OVERLAY;
  2319. pHALInfo->ddCaps.dwFXCaps |= DDFXCAPS_OVERLAYSHRINKX |
  2320. DDFXCAPS_OVERLAYSHRINKXN |
  2321. DDFXCAPS_OVERLAYSHRINKY |
  2322. DDFXCAPS_OVERLAYSHRINKYN |
  2323. DDFXCAPS_OVERLAYSTRETCHX |
  2324. DDFXCAPS_OVERLAYSTRETCHXN |
  2325. DDFXCAPS_OVERLAYSTRETCHY |
  2326. DDFXCAPS_OVERLAYSTRETCHYN;
  2327. // Indicates that Perm3 has no stretch ratio limitation
  2328. pHALInfo->ddCaps.dwMinOverlayStretch = 1;
  2329. pHALInfo->ddCaps.dwMaxOverlayStretch = 32000;
  2330. }
  2331. }
  2332. #ifdef W95_DDRAW
  2333. // Enable colour control asc brightness, contrast, gamma.
  2334. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_COLORCONTROLPRIMARY;
  2335. #endif
  2336. // Also permit surfaces wider than the display buffer.
  2337. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_WIDESURFACES;
  2338. // Enable copy blts betweemn Four CC formats for DShow acceleration
  2339. pHALInfo->ddCaps.dwCaps2 |= DDCAPS2_COPYFOURCC;
  2340. // Won't do Video-Sys mem Blits.
  2341. pHALInfo->ddCaps.dwVSBCaps = 0;
  2342. pHALInfo->ddCaps.dwVSBCKeyCaps = 0;
  2343. pHALInfo->ddCaps.dwVSBFXCaps = 0;
  2344. for( i=0;i<DD_ROP_SPACE;i++ )
  2345. {
  2346. pHALInfo->ddCaps.dwVSBRops[i] = 0;
  2347. }
  2348. // Won't do Sys-Sys mem Blits
  2349. pHALInfo->ddCaps.dwSSBCaps = 0;
  2350. pHALInfo->ddCaps.dwSSBCKeyCaps = 0;
  2351. pHALInfo->ddCaps.dwSSBFXCaps = 0;
  2352. for( i=0;i<DD_ROP_SPACE;i++ )
  2353. {
  2354. pHALInfo->ddCaps.dwSSBRops[i] = 0;
  2355. }
  2356. //
  2357. // bit depths supported for alpha and Z
  2358. //
  2359. pHALInfo->ddCaps.dwAlphaBltConstBitDepths = DDBD_2 |
  2360. DDBD_4 |
  2361. DDBD_8;
  2362. pHALInfo->ddCaps.dwAlphaBltPixelBitDepths = DDBD_1 |
  2363. DDBD_8;
  2364. pHALInfo->ddCaps.dwAlphaBltSurfaceBitDepths = DDBD_1 |
  2365. DDBD_2 |
  2366. DDBD_4 |
  2367. DDBD_8;
  2368. // No alpha blending for overlays, so I'm not sure what these should be.
  2369. // Because we support 32bpp overlays, it's just that you can't use the
  2370. // alpha bits for blending. Pass.
  2371. pHALInfo->ddCaps.dwAlphaBltConstBitDepths = DDBD_2 |
  2372. DDBD_4 |
  2373. DDBD_8;
  2374. pHALInfo->ddCaps.dwAlphaBltPixelBitDepths = DDBD_1 |
  2375. DDBD_8;
  2376. pHALInfo->ddCaps.dwAlphaBltSurfaceBitDepths = DDBD_1 |
  2377. DDBD_2 |
  2378. DDBD_4 |
  2379. DDBD_8;
  2380. //
  2381. // ROPS supported
  2382. //
  2383. for( i=0;i<DD_ROP_SPACE;i++ )
  2384. {
  2385. pHALInfo->ddCaps.dwRops[i] = rops[i];
  2386. }
  2387. #if W95_DDRAW
  2388. // Reset to NULL for debugging
  2389. pThisDisplay->lpD3DGlobalDriverData = 0;
  2390. ZeroMemory(&pThisDisplay->DDExeBufCallbacks,
  2391. sizeof(DDHAL_DDEXEBUFCALLBACKS));
  2392. // Note that the NT code does this elsewhere
  2393. _D3DHALCreateDriver(
  2394. pThisDisplay);
  2395. // (LPD3DHAL_GLOBALDRIVERDATA*)&pThisDisplay->lpD3DGlobalDriverData,
  2396. // (LPD3DHAL_CALLBACKS*) &pThisDisplay->lpD3DHALCallbacks,
  2397. // &pThisDisplay->DDExeBufCallbacks);
  2398. // If we filled in the execute buffer callbacks, set the cap bit
  2399. if (pThisDisplay->DDExeBufCallbacks.dwSize != 0)
  2400. {
  2401. pHALInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_EXECUTEBUFFER;
  2402. }
  2403. #endif
  2404. // For DX5 and beyond we support this new informational callback.
  2405. pHALInfo->GetDriverInfo = DdGetDriverInfo;
  2406. pHALInfo->dwFlags |= DDHALINFO_GETDRIVERINFOSET;
  2407. #if DX8_DDI
  2408. // Flag our support for a new class of GUIDs that may come through
  2409. // GetDriverInfo for DX8 drivers. (This support will be compulsory)
  2410. pHALInfo->dwFlags |= DDHALINFO_GETDRIVERINFO2;
  2411. #endif DX8_DDI
  2412. } // __GetDDHALInfo
  2413. static HashTable* g_pDirectDrawLocalsHashTable = NULL; // azn
  2414. //-----------------------------------------------------------------------------
  2415. //
  2416. // _DD_InitDDHAL32Bit
  2417. //
  2418. // CALLED ONCE AT START OF DAY
  2419. // No Chip register setup is done here - it is all handled in the mode
  2420. // change code. DO NOT DO IT HERE - THERE IS NO WIN16LOCK AT THIS TIME!!!
  2421. //
  2422. //-----------------------------------------------------------------------------
  2423. BOOL
  2424. _DD_InitDDHAL32Bit(
  2425. P3_THUNKEDDATA* pThisDisplay)
  2426. {
  2427. BOOL bRet;
  2428. DWORD Result;
  2429. LPGLINTINFO pGLInfo = pThisDisplay->pGLInfo;
  2430. ASSERTDD(pGLInfo != NULL, "ERROR: pGLInfo not valid!");
  2431. // Note: Can't use P3_DMA_DEFS macro here, as pGlint isn't initialised yet.
  2432. DISPDBG((DBGLVL, "** In _DD_InitDDHAL32Bit, pGlint 0x%x",
  2433. pThisDisplay->control));
  2434. DISPDBG((DBGLVL, "Sizeof DDHALINFO: %d", (int) sizeof(DDHALINFO)));
  2435. // Force D3D to setup surface offsets as if a flip had happened
  2436. pThisDisplay->bFlippedSurface = TRUE;
  2437. // A flag to say that the driver is essentially at the start of day. This
  2438. // is set to let later calls in the driver know that they have work to do.
  2439. pThisDisplay->bStartOfDay = TRUE;
  2440. #if W95_DDRAW
  2441. // At start of day the videoport is dead to the world
  2442. pThisDisplay->VidPort.bActive = FALSE;
  2443. #endif // W95_DDRAW
  2444. // Reset the GART copies.
  2445. pThisDisplay->dwGARTLin = 0;
  2446. pThisDisplay->dwGARTDev = 0;
  2447. pThisDisplay->dwGARTLinBase = 0;
  2448. pThisDisplay->dwGARTDevBase = 0;
  2449. pThisDisplay->pGlint = (FPGLREG)pThisDisplay->control;
  2450. // Set up the global overlay data
  2451. pThisDisplay->bOverlayVisible = (DWORD)FALSE;
  2452. pThisDisplay->OverlayDstRectL = 0;
  2453. pThisDisplay->OverlayDstRectR = 0;
  2454. pThisDisplay->OverlayDstRectT = 0;
  2455. pThisDisplay->OverlayDstRectB = 0;
  2456. pThisDisplay->OverlaySrcRectL = 0;
  2457. pThisDisplay->OverlaySrcRectR = 0;
  2458. pThisDisplay->OverlaySrcRectT = 0;
  2459. pThisDisplay->OverlaySrcRectB = 0;
  2460. pThisDisplay->OverlayDstSurfLcl = (ULONG_PTR)NULL;
  2461. pThisDisplay->OverlaySrcSurfLcl = (ULONG_PTR)NULL;
  2462. pThisDisplay->OverlayDstColourKey = CLR_INVALID;
  2463. pThisDisplay->OverlaySrcColourKey = CLR_INVALID;
  2464. pThisDisplay->OverlayClipRgnMem = (ULONG_PTR)NULL;
  2465. pThisDisplay->OverlayClipRgnMemSize = 0;
  2466. pThisDisplay->OverlayUpdateCountdown = 0;
  2467. pThisDisplay->bOverlayFlippedThisVbl = (DWORD)FALSE;
  2468. pThisDisplay->bOverlayUpdatedThisVbl = (DWORD)FALSE;
  2469. pThisDisplay->OverlayTempSurf.VidMem = (ULONG_PTR)NULL;
  2470. pThisDisplay->OverlayTempSurf.Pitch = (DWORD)0;
  2471. #if W95_DDRAW
  2472. // Set up colour control data.
  2473. pThisDisplay->ColConBrightness = 0;
  2474. pThisDisplay->ColConContrast = 10000;
  2475. pThisDisplay->ColConGamma = 100;
  2476. #endif // W95_DDRAW
  2477. #if DX7_VIDMEM_VB
  2478. // Set up DrawPrim temporary index buffer.
  2479. pThisDisplay->DrawPrimIndexBufferMem = (ULONG_PTR)NULL;
  2480. pThisDisplay->DrawPrimIndexBufferMemSize = 0;
  2481. pThisDisplay->DrawPrimVertexBufferMem = (ULONG_PTR)NULL;
  2482. pThisDisplay->DrawPrimVertexBufferMemSize = 0;
  2483. #endif // DX7_VIDMEM_VB
  2484. // Set up current RenderID to be as far away from a "sensible"
  2485. // value as possible. Hopefully, if the context switch fails and
  2486. // someone starts using it for something else, these values and
  2487. // the ones they use will be very different, and various asserts
  2488. // will scream immediately.
  2489. // Also, say that the RenderID is invalid, because we have not actually
  2490. // set up the chip. The context switch should set up & flush the
  2491. // chip, and then it will set bRenderIDValid to TRUE.
  2492. // Loads of asserts throughout the code will scream if something
  2493. // doesn't do the setup & flush for some reason.
  2494. pThisDisplay->dwRenderID = 0x8eaddead | RENDER_ID_KNACKERED_BITS;
  2495. pThisDisplay->dwLastFlipRenderID = 0x8eaddead | RENDER_ID_KNACKERED_BITS;
  2496. pThisDisplay->bRenderIDValid = (DWORD)FALSE;
  2497. #if W95_DDRAW
  2498. // Create a shared heap
  2499. if (g_DXGlobals.hHeap32 == 0)
  2500. g_DXGlobals.hHeap32 = (DWORD)HeapCreate( HEAP_SHARED, 2500, 0);
  2501. #endif // W95_DDRAW
  2502. // Make sure we're running the right chip. If not, STOP.
  2503. ASSERTDD((RENDERCHIP_P3RXFAMILY),"ERROR: Invalid RENDERFAMILY!!");
  2504. // Dump some debugging information
  2505. DISPDBG((DBGLVL, "************* _DD_InitDDHAL32Bit *************************************" ));
  2506. DISPDBG((DBGLVL, " dwScreenFlatAddr=%08lx", pThisDisplay->dwScreenFlatAddr ));
  2507. DISPDBG((DBGLVL, " dwScreenStart =%08lx", pThisDisplay->dwScreenStart));
  2508. DISPDBG((DBGLVL, " dwLocalBuffer=%08lx", pThisDisplay->dwLocalBuffer ));
  2509. DISPDBG((DBGLVL, " dwScreenWidth=%08lx", pThisDisplay->dwScreenWidth ));
  2510. DISPDBG((DBGLVL, " dwScreenHeight=%08lx", pThisDisplay->dwScreenHeight ));
  2511. DISPDBG((DBGLVL, " bReset=%08lx", pThisDisplay->bResetMode ));
  2512. DISPDBG((DBGLVL, " dwRGBBitCount=%ld", pThisDisplay->ddpfDisplay.dwRGBBitCount ));
  2513. DISPDBG((DBGLVL, " pGLInfo=%08lp", pGLInfo ));
  2514. DISPDBG((DBGLVL, " Render: 0x%x, Rev:0x%x", pGLInfo->dwRenderChipID, pGLInfo->dwRenderChipRev));
  2515. #if W95_DDRAW
  2516. DISPDBG((DBGLVL, " Support: 0x%x, Rev:0x%x", pGLInfo->dwSupportChipID, pGLInfo->dwSupportChipRev));
  2517. DISPDBG((DBGLVL, " Board: 0x%x, Rev:0x%x", pGLInfo->dwBoardID, pGLInfo->dwBoardRev));
  2518. // DISPDBG((DBGLVL, " BF Size: 0x%x, LB Depth:0x%x", pGLInfo->cBlockFillSize, pGLInfo->cLBDepth));
  2519. #endif // W95_DDRAW
  2520. DISPDBG((DBGLVL, " FB Size: 0x%x", pGLInfo->ddFBSize));
  2521. DISPDBG((DBGLVL, " RMask: 0x%x", pThisDisplay->ddpfDisplay.dwRBitMask ));
  2522. DISPDBG((DBGLVL, " GMask: 0x%x", pThisDisplay->ddpfDisplay.dwGBitMask ));
  2523. DISPDBG((DBGLVL, " BMask: 0x%x", pThisDisplay->ddpfDisplay.dwBBitMask ));
  2524. DISPDBG((DBGLVL, "******************************************************************" ));
  2525. // Allocate a DMA buffer for the DX driver
  2526. HWC_AllocDMABuffer(pThisDisplay);
  2527. #define SURFCB pThisDisplay->DDSurfCallbacks
  2528. #define HALCB pThisDisplay->DDHALCallbacks
  2529. // Fill in the HAL Callback pointers
  2530. memset(&HALCB, 0, sizeof(DDHAL_DDCALLBACKS));
  2531. HALCB.dwSize = sizeof(DDHAL_DDCALLBACKS);
  2532. // Field the HAL DDraw callbacks we support
  2533. HALCB.CanCreateSurface = DdCanCreateSurface;
  2534. HALCB.CreateSurface = DdCreateSurface;
  2535. HALCB.WaitForVerticalBlank = DdWaitForVerticalBlank;
  2536. HALCB.GetScanLine = DdGetScanLine;
  2537. #if WNT_DDRAW
  2538. HALCB.MapMemory = DdMapMemory;
  2539. #else
  2540. HALCB.DestroyDriver = DdDestroyDriver; // Only on Win95.
  2541. #endif // WNT_DDRAW
  2542. HALCB.dwFlags = DDHAL_CB32_WAITFORVERTICALBLANK |
  2543. #if WNT_DDRAW
  2544. DDHAL_CB32_MAPMEMORY |
  2545. #else // WNT_DDRAW
  2546. DDHAL_CB32_DESTROYDRIVER |
  2547. #endif
  2548. DDHAL_CB32_GETSCANLINE |
  2549. DDHAL_CB32_CANCREATESURFACE |
  2550. DDHAL_CB32_CREATESURFACE;
  2551. // Fill in the Surface Callback pointers
  2552. memset(&SURFCB, 0, sizeof(DDHAL_DDSURFACECALLBACKS));
  2553. SURFCB.dwSize = sizeof(DDHAL_DDSURFACECALLBACKS);
  2554. // Field the Ddraw Surface callbacks we support
  2555. SURFCB.DestroySurface = DdDestroySurface;
  2556. SURFCB.Lock = DdLock;
  2557. SURFCB.Unlock = DdUnlock;
  2558. SURFCB.GetBltStatus = DdGetBltStatus;
  2559. SURFCB.GetFlipStatus = DdGetFlipStatus;
  2560. SURFCB.SetColorKey = DdSetColorKey;
  2561. SURFCB.Flip = DdFlip;
  2562. SURFCB.Blt = DdBlt;
  2563. SURFCB.dwFlags = DDHAL_SURFCB32_DESTROYSURFACE |
  2564. DDHAL_SURFCB32_FLIP |
  2565. DDHAL_SURFCB32_LOCK |
  2566. DDHAL_SURFCB32_BLT |
  2567. DDHAL_SURFCB32_GETBLTSTATUS |
  2568. DDHAL_SURFCB32_GETFLIPSTATUS |
  2569. DDHAL_SURFCB32_SETCOLORKEY |
  2570. DDHAL_SURFCB32_UNLOCK;
  2571. pThisDisplay->hInstance = g_DXGlobals.hInstance;
  2572. #if WNT_DDRAW
  2573. if (0 == (pThisDisplay->ppdev->flCaps & CAPS_DISABLE_OVERLAY))
  2574. #else
  2575. if (0 == (pThisDisplay->pGLInfo->dwFlags & GMVF_DISABLE_OVERLAY))
  2576. #endif
  2577. {
  2578. SURFCB.UpdateOverlay = DdUpdateOverlay; // Now supporting overlays.
  2579. SURFCB.SetOverlayPosition = DdSetOverlayPosition;
  2580. SURFCB.dwFlags |=
  2581. DDHAL_SURFCB32_UPDATEOVERLAY | // Now supporting
  2582. DDHAL_SURFCB32_SETOVERLAYPOSITION ; // overlays.
  2583. }
  2584. // Fill in the DDHAL Informational caps
  2585. __GetDDHALInfo(pThisDisplay, &pThisDisplay->ddhi32);
  2586. // Create/get DD locals hash table to store our DX surface handles
  2587. //@@BEGIN_DDKSPLIT
  2588. // azn
  2589. // We need to move this creation/destruction of g_pDirectDrawLocalsHashTable
  2590. // into DrvEnableDriver and DrvDisableDriver and maybe maintain a Ref count
  2591. // as we might be running on a multi-Perm3 machine.
  2592. //@@END_DDKSPLIT
  2593. if (g_pDirectDrawLocalsHashTable == NULL)
  2594. {
  2595. DISPDBG((DBGLVL,"pDirectDrawLocalsHashTable CREATED"));
  2596. g_pDirectDrawLocalsHashTable =
  2597. pThisDisplay->pDirectDrawLocalsHashTable = HT_CreateHashTable();
  2598. }
  2599. else
  2600. {
  2601. DISPDBG((DBGLVL,"Hash table for DirectDraw locals already exists"));
  2602. pThisDisplay->pDirectDrawLocalsHashTable =
  2603. g_pDirectDrawLocalsHashTable;
  2604. }
  2605. if (pThisDisplay->pDirectDrawLocalsHashTable == NULL)
  2606. {
  2607. return (FALSE);
  2608. }
  2609. HT_SetDataDestroyCallback(pThisDisplay->pDirectDrawLocalsHashTable,
  2610. _D3D_SU_DirectDrawLocalDestroyCallback);
  2611. #if W95_DDRAW
  2612. if ( g_DXGlobals.hHeap32 == 0 )
  2613. {
  2614. return ( FALSE );
  2615. }
  2616. else
  2617. {
  2618. return ( TRUE );
  2619. }
  2620. #endif
  2621. return (TRUE);
  2622. } // _DD_InitDDHAL32Bit
  2623. #if DX7_STEREO
  2624. //-----------------------------------------------------------------------------
  2625. //
  2626. // _DD_bIsStereoMode
  2627. //
  2628. // Decide if mode can be displayed as stereo mode. Here we limit stereo
  2629. // modes so that two front and two backbuffers can be created for rendering.
  2630. //
  2631. //-----------------------------------------------------------------------------
  2632. BOOL
  2633. _DD_bIsStereoMode(
  2634. P3_THUNKEDDATA* pThisDisplay,
  2635. DWORD dwWidth,
  2636. DWORD dwHeight,
  2637. DWORD dwBpp)
  2638. {
  2639. DWORD dwLines;
  2640. // we need to check dwBpp for a valid value as PDD_STEREOMODE.dwBpp is a
  2641. // parameter passed on from the user mode API call and which is expected
  2642. // to have the values 8,16,24,32 (though we don't really support 24bpp)
  2643. if ((dwWidth >= 320) && (dwHeight >= 240) &&
  2644. ((dwBpp == 8) || (dwBpp == 16) || (dwBpp == 24) || (dwBpp ==32) ) )
  2645. {
  2646. // This the total number of "lines" that fit in our available vidmem
  2647. // at the given width and pixel format
  2648. dwLines = pThisDisplay->pGLInfo->ddFBSize / (dwWidth*dwBpp/8);
  2649. // Here we limit stereo modes so that two front and two backbuffers
  2650. // can be created for rendering.
  2651. if (dwLines > (dwHeight*4))
  2652. {
  2653. return TRUE;
  2654. }
  2655. }
  2656. return FALSE;
  2657. }
  2658. #endif // DX7_STEREO
  2659. #ifdef WNT_DDRAW
  2660. typedef DD_NONLOCALVIDMEMCAPS DDNONLOCALVIDMEMCAPS;
  2661. #else
  2662. #define DD_MISCELLANEOUSCALLBACKS DDHAL_DDMISCELLANEOUSCALLBACKS
  2663. #endif
  2664. //-----------------------------Public Routine----------------------------------
  2665. //
  2666. // DdGetDriverInfo
  2667. //
  2668. // Queries the driver for additional information about itself.
  2669. //
  2670. // Parameters
  2671. // lpGetDriverInfo
  2672. // Points to a DD_GETDRIVERINFODATA structure that contains the
  2673. // information required to perform the query.
  2674. //
  2675. // Members
  2676. //
  2677. // VOID *
  2678. // dphdev
  2679. // Is a handle to the driver's PDEV.
  2680. // DWORD
  2681. // dwSize
  2682. // Specifies the size in bytes of this
  2683. // DD_GETDRIVERINFODATA structure.
  2684. // DWORD
  2685. // dwFlags
  2686. // Is currently unused and is set to zero.
  2687. // GUID
  2688. // guidInfo
  2689. // Specifies the GUID of the DirectX support for which the
  2690. // driver is being queried. In a Windows 2000 DirectDraw
  2691. // driver, this member can be one of the following values
  2692. // (in alphabetic order):
  2693. //
  2694. // GUID_ColorControlCallbacks Queries whether the driver supports
  2695. // DdControlColor. If the driver does
  2696. // support it, the driver should
  2697. // initialize and return a
  2698. // DD_COLORCONTROLCALLBACKS structure
  2699. // in the buffer to which lpvData
  2700. // points.
  2701. // GUID_D3DCallbacks Queries whether the driver supports
  2702. // any of the functionality specified
  2703. // through the D3DNTHAL_CALLBACKS
  2704. // structure. If the driver does not
  2705. // provide any of this support, it
  2706. // should initialize and return a
  2707. // D3DNTHAL_CALLBACKS structure in
  2708. // the buffer to which lpvData points
  2709. // GUID_D3DCallbacks2 Obsolete.
  2710. // GUID_D3DCallbacks3 Queries whether the driver supports
  2711. // any of the functionality specified
  2712. // through the D3DNTHAL_CALLBACKS3
  2713. // structure. If the driver does provide
  2714. // any of this support, it should
  2715. // initialize and return a
  2716. // D3DNTHAL_CALLBACKS3 structure in
  2717. // the buffer to which lpvData points.
  2718. // GUID_D3DCaps Obsolete.
  2719. // GUID_D3DExtendedCaps Queries whether the driver supports
  2720. // any of the Direct3D functionality
  2721. // specified through the
  2722. // D3DNTHAL_D3DEXTENDEDCAPS structure.
  2723. // If the driver does provide any of
  2724. // this support, it should initialize
  2725. // and return a
  2726. // D3DNTHAL_D3DEXTENDEDCAPS structure
  2727. // in the buffer to which lpvData
  2728. // points.
  2729. // GUID_D3DParseUnknownCommandCallback Provides the Direct3D
  2730. // portion of the driver with the
  2731. // Direct3D runtime's
  2732. // D3dParseUnknownCommandCallback.
  2733. // The driver's D3dDrawPrimitives2
  2734. // callback calls
  2735. // D3dParseUnknownCommandCallback
  2736. // to parse commands from the
  2737. // command buffer that the driver
  2738. // doesn't understand.
  2739. // DirectDraw passes a pointer to this
  2740. // function in the buffer to which
  2741. // lpvData points. If the driver
  2742. // supports this aspect of Direct3D,
  2743. // it should store the pointer.
  2744. // GUID_GetHeapAlignment Queries whether the driver supports
  2745. // surface alignment requirements on a
  2746. // per-heap basis. If the driver does
  2747. // provide this support, it should
  2748. // initialize and return a
  2749. // DD_GETHEAPALIGNMENTDATA structure
  2750. // in the buffer to which lpvData
  2751. // points.
  2752. // GUID_KernelCallbacks Queries whether the driver supports
  2753. // any of the functionality specified
  2754. // through the DD_KERNELCALLBACKS
  2755. // structure. If the driver does
  2756. // provide any of this support, it
  2757. // should initialize and return a
  2758. // DD_KERNELCALLBACKS structure in the
  2759. // buffer to which lpvData points.
  2760. // GUID_KernelCaps Queries whether the driver supports
  2761. // any of the kernel-mode capabilities
  2762. // specified through the DDKERNELCAPS
  2763. // structure. If the driver does
  2764. // provide any of this support, it
  2765. // should initialize and return a
  2766. // DDKERNELCAPS structure in the buffer
  2767. // to which lpvData points.
  2768. // GUID_MiscellaneousCallbacks Queries whether the driver supports
  2769. // DdGetAvailDriverMemory. If the
  2770. // driver does support it, the driver
  2771. // should initialize and return a
  2772. // DD_MISCELLANEOUSCALLBACKS structure
  2773. // in the buffer to which lpvData
  2774. // points.
  2775. // GUID_Miscellaneous2Callbacks Queries whether the driver
  2776. // supports the additional miscellaneous
  2777. // functionality specified in the
  2778. // DD_MISCELLANEOUS2CALLBACKS structure.
  2779. // If the driver does support any of
  2780. // this support, the driver should
  2781. // initialize and return a
  2782. // DD_MISCELLANEOUS2CALLBACKS structure
  2783. // in the buffer to which lpvData
  2784. // points.
  2785. // GUID_MotionCompCallbacks Queries whether the driver supports
  2786. // the motion compensation
  2787. // functionality specified through the
  2788. // DD_MOTIONCOMPCALLBACKS structure.
  2789. // If the driver does provide any of
  2790. // this support, is should initialize
  2791. // and return a DD_MOTIONCOMPCALLBACKS
  2792. // structure in the buffer to which
  2793. // lpvData points.
  2794. // GUID_NonLocalVidMemCaps Queries whether the driver supports
  2795. // any of the nonlocal display memory
  2796. // capabilities specified through the
  2797. // DD_NONLOCALVIDMEMCAPS structure.
  2798. // If the driver does provide any of
  2799. // this support, it should initialize
  2800. // and return a DD_NONLOCALVIDMEMCAPS
  2801. // structure in the buffer to which
  2802. // lpvData points.
  2803. // GUID_NTCallbacks Queries whether the driver supports
  2804. // any of the functionality specified
  2805. // through the DD_NTCALLBACKS structure.
  2806. // If the driver does provide any of
  2807. // this support, it should initialize
  2808. // and return a DD_NTCALLBACKS
  2809. // structure in the buffer to which
  2810. // lpvData points.
  2811. // GUID_NTPrivateDriverCaps Queries whether the driver supports
  2812. // the Windows 95/ Windows 98-style
  2813. // surface creation techniques
  2814. // specified through the
  2815. // DD_NTPRIVATEDRIVERCAPS structure.
  2816. // If the driver does provide any of
  2817. // this support, it should initialize
  2818. // and return a DD_NTPRIVATEDRIVERCAPS
  2819. // structure in the buffer to which
  2820. // lpvData points.
  2821. // GUID_UpdateNonLocalHeap Queries whether the driver supports
  2822. // retrieval of the base addresses of
  2823. // each nonlocal heap in turn. If the
  2824. // driver does provide this support,
  2825. // it should initialize and return a
  2826. // DD_UPDATENONLOCALHEAPDATA structure
  2827. // in the buffer to which lpvData
  2828. // points.
  2829. // GUID_VideoPortCallbacks Queries whether the driver supports
  2830. // the video port extensions (VPE). If
  2831. // the driver does support VPE, it
  2832. // should initialize and return a
  2833. // DD_VIDEOPORTCALLBACKS structure in
  2834. // the buffer to which lpvData points.
  2835. // GUID_VideoPortCaps Queries whether the driver supports
  2836. // any of the VPE object capabilities
  2837. // specified through the DDVIDEOPORTCAPS
  2838. // structure. If the driver does provide
  2839. // any of this support, it should
  2840. // initialize and return a
  2841. // DDVIDEOPORTCAPS structure in the
  2842. // buffer to which lpvData points.
  2843. // GUID_ZPixelFormats Queries the pixel formats supported
  2844. // by the depth buffer. If the driver
  2845. // supports Direct3D, it should allocate
  2846. // and initialize the appropriate
  2847. // members of a DDPIXELFORMAT structure
  2848. // for every z-buffer format that it
  2849. // supports and return these in the
  2850. // buffer to which lpvData points.
  2851. //
  2852. // DWORD
  2853. // dwExpectedSize
  2854. // Specifies the number of bytes of data that DirectDraw
  2855. // expects the driver to pass back in the buffer to which
  2856. // lpvData points.
  2857. // PVOID
  2858. // lpvData
  2859. // Points to a DirectDraw-allocated buffer into which the
  2860. // driver copies the requested data. This buffer is
  2861. // typically dwExpectedSize bytes in size. The driver must
  2862. // not write more than dwExpectedSize bytes of data in it.
  2863. // DWORD
  2864. // dwActualSize
  2865. // Is the location in which the driver returns the number
  2866. // of bytes of data it writes in lpvData.
  2867. // HRESULT
  2868. // ddRVal
  2869. // Specifies the driver's return value.
  2870. //
  2871. // Return Value
  2872. // DdGetDriverInfo must return DDHAL_DRIVER_HANDLED.
  2873. //
  2874. // Comments
  2875. //
  2876. // Drivers must implement DdGetDriverInfo to expose driver-supported
  2877. // DirectDraw functionality that is not returnable through
  2878. // DrvEnableDirectDraw.
  2879. //
  2880. // The driver's DrvGetDirectDrawInfo function returns a pointer to
  2881. // DdGetDriverInfo in the GetDriverInfo member of the DD_HALINFO structure.
  2882. //
  2883. // To inform DirectDraw that the DdGetDriverInfo member has been set
  2884. // correctly, the driver must also set the DDHALINFO_GETDRIVERINFOSET bit
  2885. // of dwFlags in the DD_HALINFO structure.
  2886. //
  2887. // DdGetDriverInfo should determine whether the driver and its hardware
  2888. // support the callbacks or capabilities requested by the specified GUID.
  2889. // For all GUIDs except GUID_D3DParseUnknownCommandCallback, if the driver
  2890. // does provide the requested support, it should set the following members
  2891. // of the DD_GETDRIVERINFODATA structure:
  2892. //
  2893. // Set dwActualSize to be the size in bytes of the callback or capability
  2894. // structure being returned by the driver.
  2895. //
  2896. // In the memory that lpvData points to, initialize the members of the
  2897. // callback or capability structure that corresponds with the requested
  2898. // feature as follows:
  2899. //
  2900. // Set the dwSize member to be the size in bytes of the structure.
  2901. //
  2902. // For callbacks, set the function pointers to point to those callbacks
  2903. // implemented by the driver, and set the bits in the dwFlags member to
  2904. // indicate which functions the driver supports.
  2905. //
  2906. // For capabilities, set the appropriate members of the capability
  2907. // structure with values supported by the driver/device.
  2908. //
  2909. // Return DD_OK in ddRVal.
  2910. // If the driver does not support the feature, it should set ddRVal
  2911. // to DDERR_CURRENTLYNOTAVAIL and return.
  2912. //
  2913. // DirectDraw informs the driver of the expected amount of data in the
  2914. // dwExpectedSize member of the DD_GETDRIVERINFODATA structure. The
  2915. // driver must not fill in more data than dwExpectedSize bytes.
  2916. //
  2917. // To avoid problems using DdGetDriverInfo:
  2918. //
  2919. // Do not implement dependencies based on the order in which DdGetDriverInfo
  2920. // is called. For example, avoid hooking driver initialization steps into
  2921. // DdGetDriverInfo.
  2922. //
  2923. // Do not try to ascertain the DirectDraw version based on the calls to
  2924. // DdGetDriverInfo.
  2925. //
  2926. // Do not assume anything about the number of times DirectDraw will call the
  2927. // driver, or the number of times DirectDraw will query a given GUID. It is
  2928. // possible that DirectDraw will probe the driver repeatedly with the same
  2929. // GUID. Implementing assumptions about this in the driver hampers its
  2930. // compatibility with future runtimes.
  2931. //
  2932. //-----------------------------------------------------------------------------
  2933. DWORD CALLBACK
  2934. DdGetDriverInfo(
  2935. LPDDHAL_GETDRIVERINFODATA lpData)
  2936. {
  2937. DWORD dwSize;
  2938. P3_THUNKEDDATA* pThisDisplay;
  2939. #if WNT_DDRAW
  2940. pThisDisplay = (P3_THUNKEDDATA*)(((PPDEV)(lpData->dhpdev))->thunkData);
  2941. #else
  2942. pThisDisplay = (P3_THUNKEDDATA*)lpData->dwContext;
  2943. if (! pThisDisplay)
  2944. {
  2945. pThisDisplay = g_pDriverData;
  2946. }
  2947. #endif
  2948. DBG_CB_ENTRY(DdGetDriverInfo);
  2949. // Default to 'not supported'
  2950. lpData->ddRVal = DDERR_CURRENTLYNOTAVAIL;
  2951. //------------------------------------
  2952. // Process any D3D related GUIDs here
  2953. //------------------------------------
  2954. _D3DGetDriverInfo(lpData);
  2955. //------------------------------------
  2956. // any other GUIDS are handled here
  2957. //------------------------------------
  2958. if (MATCH_GUID((lpData->guidInfo), GUID_MiscellaneousCallbacks) )
  2959. {
  2960. DD_MISCELLANEOUSCALLBACKS MISC_CB;
  2961. DISPDBG((DBGLVL," GUID_MiscellaneousCallbacks"));
  2962. memset(&MISC_CB, 0, sizeof(DD_MISCELLANEOUSCALLBACKS));
  2963. MISC_CB.dwSize = sizeof(DD_MISCELLANEOUSCALLBACKS);
  2964. #if W95_DDRAW
  2965. MISC_CB.GetHeapAlignment = DdGetHeapAlignment;
  2966. MISC_CB.dwFlags = DDHAL_MISCCB32_GETHEAPALIGNMENT;
  2967. // Setup the AGP callback if running on an AGP board.
  2968. if ((pThisDisplay->dwDXVersion > DX5_RUNTIME) &&
  2969. pThisDisplay->bCanAGP)
  2970. {
  2971. MISC_CB.dwFlags |= DDHAL_MISCCB32_UPDATENONLOCALHEAP;
  2972. MISC_CB.UpdateNonLocalHeap = DdUpdateNonLocalHeap;
  2973. }
  2974. #endif // W95_DDRAW
  2975. MISC_CB.dwFlags |= DDHAL_MISCCB32_GETAVAILDRIVERMEMORY;
  2976. MISC_CB.GetAvailDriverMemory = DdGetAvailDriverMemory;
  2977. // Copy the filled in structure into the passed data area
  2978. dwSize = min(lpData->dwExpectedSize , sizeof(MISC_CB));
  2979. lpData->dwActualSize = sizeof(MISC_CB);
  2980. memcpy(lpData->lpvData, &MISC_CB, dwSize );
  2981. lpData->ddRVal = DD_OK;
  2982. }
  2983. #if WNT_DDRAW
  2984. if (MATCH_GUID((lpData->guidInfo), GUID_UpdateNonLocalHeap))
  2985. {
  2986. // On NT kernels the AGP heap details are passed into the driver
  2987. // here, rather than through a seperate callback.
  2988. if (pThisDisplay->bCanAGP)
  2989. {
  2990. DDHAL_UPDATENONLOCALHEAPDATA* plhd;
  2991. DISPDBG((DBGLVL, " GUID_UpdateNonLocalHeap"));
  2992. plhd = (DDHAL_UPDATENONLOCALHEAPDATA*)lpData->lpvData;
  2993. // Fill in the base pointers
  2994. pThisDisplay->dwGARTDevBase = (DWORD)plhd->fpGARTDev;
  2995. pThisDisplay->dwGARTLinBase = (DWORD)plhd->fpGARTLin;
  2996. // Fill in the changeable base pointers.
  2997. pThisDisplay->dwGARTDev = pThisDisplay->dwGARTDevBase;
  2998. pThisDisplay->dwGARTLin = pThisDisplay->dwGARTLinBase;
  2999. lpData->ddRVal = DD_OK;
  3000. }
  3001. }
  3002. #endif // WNT_DDRAW
  3003. if (MATCH_GUID((lpData->guidInfo), GUID_NonLocalVidMemCaps) &&
  3004. (pThisDisplay->bCanAGP))
  3005. {
  3006. int i;
  3007. DDNONLOCALVIDMEMCAPS NLVCAPS;
  3008. DISPDBG((DBGLVL," GUID_NonLocalVidMemCaps"));
  3009. if (lpData->dwExpectedSize != sizeof(DDNONLOCALVIDMEMCAPS) )
  3010. {
  3011. DISPDBG((ERRLVL,"ERROR: NON-Local vidmem caps size incorrect!"));
  3012. DBG_CB_EXIT(DdGetDriverInfo, lpData->ddRVal );
  3013. return DDHAL_DRIVER_HANDLED;
  3014. }
  3015. // The flag D3DDEVCAPS_TEXTURENONLOCALVIDMEM in the D3D caps
  3016. // indicates that although we are exposing DMA-Model AGP, we
  3017. // can still texture directly from AGP memory.
  3018. memset(&NLVCAPS, 0, sizeof(DDNONLOCALVIDMEMCAPS));
  3019. NLVCAPS.dwSize = sizeof(DDNONLOCALVIDMEMCAPS);
  3020. NLVCAPS.dwNLVBCaps = DDCAPS_BLT |
  3021. DDCAPS_ALPHA |
  3022. DDCAPS_BLTSTRETCH |
  3023. DDCAPS_BLTQUEUE |
  3024. DDCAPS_BLTFOURCC |
  3025. DDCAPS_COLORKEY |
  3026. DDCAPS_CANBLTSYSMEM;
  3027. NLVCAPS.dwNLVBCaps2 = DDCAPS2_WIDESURFACES;
  3028. NLVCAPS.dwNLVBCKeyCaps = DDCKEYCAPS_SRCBLT |
  3029. DDCKEYCAPS_SRCBLTCLRSPACE |
  3030. DDCKEYCAPS_DESTBLT |
  3031. DDCKEYCAPS_DESTBLTCLRSPACE;
  3032. NLVCAPS.dwNLVBFXCaps = DDFXCAPS_BLTSTRETCHY |
  3033. DDFXCAPS_BLTSTRETCHX |
  3034. DDFXCAPS_BLTSTRETCHYN |
  3035. DDFXCAPS_BLTSTRETCHXN |
  3036. DDFXCAPS_BLTSHRINKY |
  3037. DDFXCAPS_BLTSHRINKX |
  3038. DDFXCAPS_BLTSHRINKYN |
  3039. DDFXCAPS_BLTSHRINKXN;
  3040. for( i=0;i<DD_ROP_SPACE;i++ )
  3041. {
  3042. NLVCAPS.dwNLVBRops[i] = ropsAGP[i];
  3043. }
  3044. // Copy the filled in structure into the passed data area
  3045. dwSize = min( lpData->dwExpectedSize, sizeof(DDNONLOCALVIDMEMCAPS));
  3046. lpData->dwActualSize = sizeof(DDNONLOCALVIDMEMCAPS);
  3047. memcpy(lpData->lpvData, &NLVCAPS, dwSize );
  3048. lpData->ddRVal = DD_OK;
  3049. }
  3050. //@@BEGIN_DDKSPLIT
  3051. #ifdef SUPPORT_VIDEOPORT
  3052. #if W95_DDRAW
  3053. // Fill in the VideoPort callbacks
  3054. if (MATCH_GUID((lpData->guidInfo), GUID_VideoPortCallbacks) )
  3055. {
  3056. DDHAL_DDVIDEOPORTCALLBACKS VIDCB;
  3057. DISPDBG((DBGLVL," GUID_VideoPortCallbacks"));
  3058. memset(&VIDCB, 0, sizeof(DDHAL_DDVIDEOPORTCALLBACKS));
  3059. VIDCB.dwSize = sizeof(DDHAL_DDVIDEOPORTCALLBACKS);
  3060. VIDCB.CanCreateVideoPort = DdCanCreateVideoPort;
  3061. VIDCB.CreateVideoPort = DdCreateVideoPort;
  3062. VIDCB.FlipVideoPort = DdFlipVideoPort;
  3063. VIDCB.GetVideoPortBandwidth = DdGetVideoPortBandwidth;
  3064. VIDCB.GetVideoPortInputFormats = DdGetVideoPortInputFormats;
  3065. VIDCB.GetVideoPortOutputFormats = DdGetVideoPortOutputFormats;
  3066. VIDCB.GetVideoPortField = DdGetVideoPortField;
  3067. VIDCB.GetVideoPortLine = DdGetVideoPortLine;
  3068. VIDCB.GetVideoPortConnectInfo = DDGetVideoPortConnectInfo;
  3069. VIDCB.DestroyVideoPort = DdDestroyVideoPort;
  3070. VIDCB.GetVideoPortFlipStatus = DdGetVideoPortFlipStatus;
  3071. VIDCB.UpdateVideoPort = DdUpdateVideoPort;
  3072. VIDCB.WaitForVideoPortSync = DdWaitForVideoPortSync;
  3073. VIDCB.GetVideoSignalStatus = DdGetVideoSignalStatus;
  3074. VIDCB.dwFlags = DDHAL_VPORT32_CANCREATEVIDEOPORT |
  3075. DDHAL_VPORT32_CREATEVIDEOPORT |
  3076. DDHAL_VPORT32_DESTROY |
  3077. DDHAL_VPORT32_FLIP |
  3078. DDHAL_VPORT32_GETBANDWIDTH |
  3079. DDHAL_VPORT32_GETINPUTFORMATS |
  3080. DDHAL_VPORT32_GETOUTPUTFORMATS |
  3081. DDHAL_VPORT32_GETFIELD |
  3082. DDHAL_VPORT32_GETLINE |
  3083. DDHAL_VPORT32_GETFLIPSTATUS |
  3084. DDHAL_VPORT32_UPDATE |
  3085. DDHAL_VPORT32_WAITFORSYNC |
  3086. DDHAL_VPORT32_GETCONNECT |
  3087. DDHAL_VPORT32_GETSIGNALSTATUS;
  3088. // Copy the filled in structure into the
  3089. // passed data area
  3090. dwSize = lpData->dwExpectedSize;
  3091. if ( sizeof(VIDCB) < dwSize )
  3092. {
  3093. dwSize = sizeof(VIDCB);
  3094. }
  3095. lpData->dwActualSize = sizeof(VIDCB);
  3096. memcpy(lpData->lpvData, &VIDCB, dwSize );
  3097. lpData->ddRVal = DD_OK;
  3098. }
  3099. // Fill in the VideoPortCaps
  3100. if (MATCH_GUID((lpData->guidInfo), GUID_VideoPortCaps) )
  3101. {
  3102. DDVIDEOPORTCAPS VIDCAPS;
  3103. DISPDBG((DBGLVL," GUID_VideoPortCaps"));
  3104. if (lpData->dwExpectedSize != sizeof(VIDCAPS) )
  3105. {
  3106. DISPDBG((ERRLVL,"ERROR: VIDCAPS size incorrect"));
  3107. DBG_CB_EXIT(DdGetDriverInfo, lpData->ddRVal );
  3108. return DDHAL_DRIVER_HANDLED;
  3109. }
  3110. // Now fill in the videoport description (it's easier if it's on
  3111. // the 32 bit side..)
  3112. VIDCAPS.dwSize = sizeof(DDVIDEOPORTCAPS);
  3113. VIDCAPS.dwFlags = DDVPD_ALIGN |
  3114. DDVPD_AUTOFLIP |
  3115. DDVPD_WIDTH |
  3116. DDVPD_HEIGHT |
  3117. DDVPD_FX |
  3118. DDVPD_CAPS;
  3119. VIDCAPS.dwMaxWidth = 2048;
  3120. VIDCAPS.dwMaxVBIWidth = 2048;
  3121. VIDCAPS.dwMaxHeight = 2048;
  3122. VIDCAPS.dwVideoPortID = 0;
  3123. VIDCAPS.dwCaps = DDVPCAPS_AUTOFLIP |
  3124. DDVPCAPS_NONINTERLACED |
  3125. DDVPCAPS_INTERLACED |
  3126. DDVPCAPS_READBACKFIELD |
  3127. DDVPCAPS_READBACKLINE |
  3128. DDVPCAPS_SKIPEVENFIELDS |
  3129. DDVPCAPS_SKIPODDFIELDS |
  3130. DDVPCAPS_VBISURFACE |
  3131. DDVPCAPS_OVERSAMPLEDVBI;
  3132. VIDCAPS.dwFX = DDVPFX_CROPX |
  3133. DDVPFX_CROPY |
  3134. DDVPFX_INTERLEAVE |
  3135. DDVPFX_MIRRORLEFTRIGHT |
  3136. DDVPFX_MIRRORUPDOWN |
  3137. DDVPFX_PRESHRINKXB |
  3138. DDVPFX_VBICONVERT |
  3139. DDVPFX_VBINOSCALE |
  3140. DDVPFX_PRESHRINKYB |
  3141. DDVPFX_IGNOREVBIXCROP;
  3142. VIDCAPS.dwNumAutoFlipSurfaces = 2;
  3143. VIDCAPS.dwAlignVideoPortBoundary = 4;
  3144. VIDCAPS.dwAlignVideoPortPrescaleWidth = 4;
  3145. VIDCAPS.dwAlignVideoPortCropBoundary = 4;
  3146. VIDCAPS.dwAlignVideoPortCropWidth = 4;
  3147. VIDCAPS.dwPreshrinkXStep = 1;
  3148. VIDCAPS.dwPreshrinkYStep = 1;
  3149. lpData->dwActualSize = sizeof(VIDCAPS);
  3150. memcpy(lpData->lpvData, &VIDCAPS, sizeof(VIDCAPS) );
  3151. lpData->ddRVal = DD_OK;
  3152. }
  3153. // Fill in the kernel Callbacks
  3154. if (MATCH_GUID((lpData->guidInfo), GUID_KernelCallbacks) )
  3155. {
  3156. DDHAL_DDKERNELCALLBACKS KERNCB;
  3157. DISPDBG((DBGLVL," GUID_KernelCallbacks"));
  3158. memset(&KERNCB, 0, sizeof(DDHAL_DDKERNELCALLBACKS));
  3159. KERNCB.dwSize = sizeof(KERNCB);
  3160. KERNCB.SyncSurfaceData = DdSyncSurfaceData;
  3161. KERNCB.SyncVideoPortData = DdSyncVideoPortData;
  3162. KERNCB.dwFlags = DDHAL_KERNEL_SYNCSURFACEDATA |
  3163. DDHAL_KERNEL_SYNCVIDEOPORTDATA;
  3164. dwSize = lpData->dwExpectedSize;
  3165. if ( sizeof(KERNCB) < dwSize )
  3166. {
  3167. dwSize = sizeof(KERNCB);
  3168. }
  3169. lpData->dwActualSize = sizeof(KERNCB);
  3170. memcpy(lpData->lpvData, &KERNCB, dwSize );
  3171. lpData->ddRVal = DD_OK;
  3172. }
  3173. // Fill in the kernel caps
  3174. if (MATCH_GUID((lpData->guidInfo), GUID_KernelCaps) )
  3175. {
  3176. DDKERNELCAPS KERNCAPS;
  3177. DISPDBG((DBGLVL," GUID_KernelCaps"));
  3178. if (lpData->dwExpectedSize != sizeof(DDKERNELCAPS) )
  3179. {
  3180. DISPDBG((ERRLVL,"ERROR: Kernel caps structure invalid size!"));
  3181. return DDHAL_DRIVER_HANDLED;
  3182. }
  3183. ZeroMemory(&KERNCAPS, sizeof(KERNCAPS));
  3184. KERNCAPS.dwSize = sizeof(KERNCAPS);
  3185. KERNCAPS.dwCaps = DDKERNELCAPS_LOCK |
  3186. DDKERNELCAPS_FLIPOVERLAY |
  3187. DDKERNELCAPS_SETSTATE;
  3188. if (!(pThisDisplay->pGLInfo->dwFlags & GMVF_NOIRQ))
  3189. {
  3190. KERNCAPS.dwCaps |= DDKERNELCAPS_CAPTURE_SYSMEM |
  3191. DDKERNELCAPS_FIELDPOLARITY |
  3192. DDKERNELCAPS_SKIPFIELDS |
  3193. DDKERNELCAPS_FLIPVIDEOPORT |
  3194. DDKERNELCAPS_AUTOFLIP;
  3195. KERNCAPS.dwIRQCaps = DDIRQ_VPORT0_VSYNC |
  3196. DDIRQ_DISPLAY_VSYNC |
  3197. DDIRQ_BUSMASTER;
  3198. }
  3199. lpData->dwActualSize = sizeof(DDKERNELCAPS);
  3200. memcpy(lpData->lpvData, &KERNCAPS, sizeof(DDKERNELCAPS) );
  3201. lpData->ddRVal = DD_OK;
  3202. }
  3203. #endif // W95_DDRAW
  3204. #endif // SUPPORT_VIDEOPORT
  3205. //@@END_DDKSPLIT
  3206. #ifdef W95_DDRAW
  3207. #ifdef USE_DD_CONTROL_COLOR
  3208. // Fill in the colour control callbacks.
  3209. if (MATCH_GUID((lpData->guidInfo), GUID_ColorControlCallbacks) )
  3210. {
  3211. DDHAL_DDCOLORCONTROLCALLBACKS ColConCB;
  3212. DISPDBG((DBGLVL," GUID_ColorControlCallbacks"));
  3213. memset(&ColConCB, 0, sizeof(ColConCB));
  3214. ColConCB.dwSize = sizeof(ColConCB);
  3215. ColConCB.dwFlags = DDHAL_COLOR_COLORCONTROL;
  3216. ColConCB.ColorControl = DdControlColor;
  3217. dwSize = min( lpData->dwExpectedSize, sizeof(ColConCB));
  3218. lpData->dwActualSize = sizeof(ColConCB);
  3219. memcpy(lpData->lpvData, &ColConCB, dwSize);
  3220. lpData->ddRVal = DD_OK;
  3221. }
  3222. #endif
  3223. #endif
  3224. #if !defined(_WIN64) && WNT_DDRAW
  3225. // Fill in the NT specific callbacks
  3226. if (MATCH_GUID((lpData->guidInfo), GUID_NTCallbacks) )
  3227. {
  3228. DD_NTCALLBACKS NtCallbacks;
  3229. memset(&NtCallbacks, 0, sizeof(NtCallbacks));
  3230. dwSize = min(lpData->dwExpectedSize, sizeof(DD_NTCALLBACKS));
  3231. NtCallbacks.dwSize = dwSize;
  3232. NtCallbacks.dwFlags = DDHAL_NTCB32_FREEDRIVERMEMORY |
  3233. DDHAL_NTCB32_SETEXCLUSIVEMODE |
  3234. DDHAL_NTCB32_FLIPTOGDISURFACE;
  3235. NtCallbacks.FreeDriverMemory = DdFreeDriverMemory;
  3236. NtCallbacks.SetExclusiveMode = DdSetExclusiveMode;
  3237. NtCallbacks.FlipToGDISurface = DdFlipToGDISurface;
  3238. memcpy(lpData->lpvData, &NtCallbacks, dwSize);
  3239. lpData->ddRVal = DD_OK;
  3240. }
  3241. #endif
  3242. #if DX7_STEREO
  3243. if (MATCH_GUID((lpData->guidInfo), GUID_DDMoreSurfaceCaps) )
  3244. {
  3245. #if WNT_DDRAW
  3246. DD_MORESURFACECAPS DDMoreSurfaceCaps;
  3247. #else
  3248. DDMORESURFACECAPS DDMoreSurfaceCaps;
  3249. #endif
  3250. DDSCAPSEX ddsCapsEx, ddsCapsExAlt;
  3251. ULONG ulCopyPointer;
  3252. DISPDBG((DBGLVL," GUID_DDMoreSurfaceCaps"));
  3253. // fill in everything until expectedsize...
  3254. memset(&DDMoreSurfaceCaps, 0, sizeof(DDMoreSurfaceCaps));
  3255. // Caps for heaps 2..n
  3256. memset(&ddsCapsEx, 0, sizeof(ddsCapsEx));
  3257. memset(&ddsCapsExAlt, 0, sizeof(ddsCapsEx));
  3258. DDMoreSurfaceCaps.dwSize=lpData->dwExpectedSize;
  3259. if (_DD_bIsStereoMode(pThisDisplay,
  3260. pThisDisplay->dwScreenWidth,
  3261. pThisDisplay->dwScreenHeight,
  3262. pThisDisplay->ddpfDisplay.dwRGBBitCount))
  3263. {
  3264. DDMoreSurfaceCaps.ddsCapsMore.dwCaps2 =
  3265. DDSCAPS2_STEREOSURFACELEFT;
  3266. }
  3267. lpData->dwActualSize = lpData->dwExpectedSize;
  3268. dwSize = min(sizeof(DDMoreSurfaceCaps),lpData->dwExpectedSize);
  3269. memcpy(lpData->lpvData, &DDMoreSurfaceCaps, dwSize);
  3270. // Now fill in ddsCapsEx and ddsCapsExAlt heaps
  3271. // Hardware with different restrictions for different heaps
  3272. // should prepare ddsCapsEx and ddsCapsExAlt carefully and
  3273. // fill them into lpvData in proper order
  3274. while (dwSize < lpData->dwExpectedSize)
  3275. {
  3276. memcpy( (PBYTE)lpData->lpvData+dwSize,
  3277. &ddsCapsEx,
  3278. sizeof(DDSCAPSEX));
  3279. dwSize += sizeof(DDSCAPSEX);
  3280. memcpy( (PBYTE)lpData->lpvData+dwSize,
  3281. &ddsCapsExAlt,
  3282. sizeof(DDSCAPSEX));
  3283. dwSize += sizeof(DDSCAPSEX);
  3284. }
  3285. lpData->ddRVal = DD_OK;
  3286. }
  3287. #endif // DX7_STEREO
  3288. // We always handled it.
  3289. DBG_CB_EXIT(DdGetDriverInfo, lpData->ddRVal );
  3290. return DDHAL_DRIVER_HANDLED;
  3291. } // DdGetDriverInfo