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.

2158 lines
74 KiB

  1. /******************************Module*Header***********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: enable.c
  8. *
  9. * This module contains the functions that enable and disable the
  10. * driver, the pdev, and the surface.
  11. *
  12. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  13. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  14. \******************************************************************************/
  15. #include "precomp.h"
  16. #include "directx.h"
  17. #include "gdi.h"
  18. #include "text.h"
  19. #include "heap.h"
  20. #include "dd.h"
  21. #define ALLOC_TAG ALLOC_TAG_NE2P
  22. PVOID pCounterBlock; // some macros need this
  23. #define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\
  24. CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\
  25. VARIABLE_PITCH | FF_DONTCARE,L"System"}
  26. #define HELVE_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\
  27. CLIP_STROKE_PRECIS,PROOF_QUALITY,\
  28. VARIABLE_PITCH | FF_DONTCARE,L"MS Sans Serif"}
  29. #define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\
  30. CLIP_STROKE_PRECIS,PROOF_QUALITY,\
  31. FIXED_PITCH | FF_DONTCARE, L"Courier"}
  32. //----------------------------Public*Structure---------------------------------
  33. //
  34. // GDIINFO ggdiDefault
  35. //
  36. // This contains the default GDIINFO fields that are passed back to GDI
  37. // during DrvEnablePDEV.
  38. //
  39. // NOTE: This structure defaults to values for an 8bpp palette device.
  40. // Some fields are overwritten for different colour depths.
  41. //
  42. //-----------------------------------------------------------------------------
  43. GDIINFO ggdiDefault =
  44. {
  45. 0x5000, // Major OS Ver 5, Minor Ver 0, Driver Ver 0
  46. DT_RASDISPLAY, // ulTechnology
  47. 0, // ulHorzSize (filled in later)
  48. 0, // ulVertSize (filled in later)
  49. 0, // ulHorzRes (filled in later)
  50. 0, // ulVertRes (filled in later)
  51. 0, // cBitsPixel (filled in later)
  52. 0, // cPlanes (filled in later)
  53. 20, // ulNumColors (palette managed)
  54. 0, // flRaster (DDI reserved field)
  55. 0, // ulLogPixelsX (filled in later)
  56. 0, // ulLogPixelsY (filled in later)
  57. TC_RA_ABLE, // flTextCaps
  58. 0, // ulDACRed (filled in later)
  59. 0, // ulDACGreen (filled in later)
  60. 0, // ulDACBlue (filled in later)
  61. 0x0024, // ulAspectX
  62. 0x0024, // ulAspectY
  63. 0x0033, // ulAspectXY (one-to-one aspect ratio)
  64. 1, // xStyleStep
  65. 1, // yStyleSte;
  66. 3, // denStyleStep -- Styles have a one-to-one aspect
  67. // ratio, and every 'dot' is 3 pixels long
  68. { 0, 0 }, // ptlPhysOffset
  69. { 0, 0 }, // szlPhysSize
  70. 256, // ulNumPalReg
  71. // These fields are for halftone initialization. The actual values are
  72. // a bit magic, but seem to work well on our display.
  73. { // ciDevice
  74. { 6700, 3300, 0 }, // Red
  75. { 2100, 7100, 0 }, // Green
  76. { 1400, 800, 0 }, // Blue
  77. { 1750, 3950, 0 }, // Cyan
  78. { 4050, 2050, 0 }, // Magenta
  79. { 4400, 5200, 0 }, // Yellow
  80. { 3127, 3290, 0 }, // AlignmentWhite
  81. 20000, // RedGamma
  82. 20000, // GreenGamma
  83. 20000, // BlueGamma
  84. 0, 0, 0, 0, 0, 0 // No dye correction for raster displays
  85. },
  86. 0, // ulDevicePelsDPI (for printers only)
  87. PRIMARY_ORDER_CBA, // ulPrimaryOrder
  88. HT_PATSIZE_4x4_M, // ulHTPatternSize
  89. HT_FORMAT_8BPP, // ulHTOutputFormat
  90. HT_FLAG_ADDITIVE_PRIMS, // flHTFlags
  91. 0, // ulVRefresh
  92. 0, // ulPanningHorzRes
  93. 0, // ulPanningVertRes
  94. 0, // ulBltAlignment
  95. };// GDIINFO ggdiDefault
  96. //-----------------------------Public*Structure--------------------------------
  97. //
  98. // DEVINFO gdevinfoDefault
  99. //
  100. // This contains the default DEVINFO fields that are passed back to GDI
  101. // during DrvEnablePDEV.
  102. //
  103. // NOTE: This structure defaults to values for an 8bpp palette device.
  104. // Some fields are overwritten for different colour depths.
  105. //
  106. //-----------------------------------------------------------------------------
  107. DEVINFO gdevinfoDefault =
  108. {
  109. (GCAPS_OPAQUERECT |
  110. GCAPS_DITHERONREALIZE |
  111. GCAPS_PALMANAGED |
  112. GCAPS_ALTERNATEFILL |
  113. GCAPS_WINDINGFILL |
  114. GCAPS_MONO_DITHER |
  115. GCAPS_DIRECTDRAW |
  116. GCAPS_GRAY16 | // we handle anti-aliased text
  117. GCAPS_COLOR_DITHER),
  118. // flGraphicsFlags
  119. SYSTM_LOGFONT, // lfDefaultFont
  120. HELVE_LOGFONT, // lfAnsiVarFont
  121. COURI_LOGFONT, // lfAnsiFixFont
  122. 0, // cFonts
  123. BMF_8BPP, // iDitherFormat
  124. 8, // cxDither
  125. 8, // cyDither
  126. 0, // hpalDefault (filled in later)
  127. GCAPS2_SYNCTIMER |
  128. GCAPS2_SYNCFLUSH
  129. }; // DEVINFO gdevinfoDefault
  130. //-----------------------------Public*Structure--------------------------------
  131. //
  132. // DFVFN gadrvfn[]
  133. //
  134. // Build the driver function table gadrvfn with function index/address
  135. // pairs. This table tells GDI which DDI calls we support, and their
  136. // location (GDI does an indirect call through this table to call us).
  137. //
  138. // Why haven't we implemented DrvSaveScreenBits? To save code.
  139. //
  140. // When the driver doesn't hook DrvSaveScreenBits, USER simulates on-
  141. // the-fly by creating a temporary device-format-bitmap, and explicitly
  142. // calling DrvCopyBits to save/restore the bits. Since we already hook
  143. // DrvCreateDeviceBitmap, we'll end up using off-screen memory to store
  144. // the bits anyway (which would have been the main reason for implementing
  145. // DrvSaveScreenBits). So we may as well save some working set.
  146. //
  147. //-----------------------------------------------------------------------------
  148. DRVFN gadrvfnOne[] =
  149. {
  150. { INDEX_DrvAssertMode, (PFN) DrvAssertMode },
  151. { INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
  152. { INDEX_DrvCreateDeviceBitmap, (PFN) DrvCreateDeviceBitmap },
  153. { INDEX_DrvDeleteDeviceBitmap, (PFN) DrvDeleteDeviceBitmap },
  154. { INDEX_DrvDeriveSurface, (PFN) DrvDeriveSurface },
  155. { INDEX_DrvDestroyFont, (PFN) DrvDestroyFont },
  156. { INDEX_DrvDisableDirectDraw, (PFN) DrvDisableDirectDraw },
  157. { INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
  158. { INDEX_DrvDisableDriver, (PFN) DrvDisableDriver },
  159. { INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
  160. { INDEX_DrvEnableDirectDraw, (PFN) DrvEnableDirectDraw },
  161. { INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
  162. { INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
  163. { INDEX_DrvEscape, (PFN) DrvEscape },
  164. { INDEX_DrvGetDirectDrawInfo, (PFN) DrvGetDirectDrawInfo },
  165. { INDEX_DrvGetModes, (PFN) DrvGetModes },
  166. { INDEX_DrvIcmSetDeviceGammaRamp, (PFN) DrvIcmSetDeviceGammaRamp },
  167. { INDEX_DrvMovePointer, (PFN) DrvMovePointer },
  168. { INDEX_DrvNotify, (PFN) DrvNotify },
  169. { INDEX_DrvRealizeBrush, (PFN) DrvRealizeBrush },
  170. { INDEX_DrvResetPDEV, (PFN) DrvResetPDEV },
  171. { INDEX_DrvSetPalette, (PFN) DrvSetPalette },
  172. { INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape },
  173. { INDEX_DrvStretchBlt, (PFN) DrvStretchBlt },
  174. { INDEX_DrvSynchronizeSurface, (PFN) DrvSynchronizeSurface },
  175. #if THUNK_LAYER
  176. { INDEX_DrvAlphaBlend, (PFN) xDrvAlphaBlend },
  177. { INDEX_DrvBitBlt, (PFN) xDrvBitBlt },
  178. { INDEX_DrvCopyBits, (PFN) xDrvCopyBits },
  179. { INDEX_DrvFillPath, (PFN) xDrvFillPath },
  180. { INDEX_DrvGradientFill, (PFN) xDrvGradientFill },
  181. { INDEX_DrvLineTo, (PFN) xDrvLineTo },
  182. { INDEX_DrvStrokePath, (PFN) xDrvStrokePath },
  183. { INDEX_DrvTextOut, (PFN) xDrvTextOut },
  184. { INDEX_DrvTransparentBlt, (PFN) xDrvTransparentBlt },
  185. #else
  186. { INDEX_DrvAlphaBlend, (PFN) DrvAlphaBlend },
  187. { INDEX_DrvBitBlt, (PFN) DrvBitBlt },
  188. { INDEX_DrvCopyBits, (PFN) DrvCopyBits },
  189. { INDEX_DrvFillPath, (PFN) DrvFillPath },
  190. { INDEX_DrvGradientFill, (PFN) DrvGradientFill },
  191. { INDEX_DrvLineTo, (PFN) DrvLineTo },
  192. { INDEX_DrvStrokePath, (PFN) DrvStrokePath },
  193. { INDEX_DrvTextOut, (PFN) DrvTextOut },
  194. { INDEX_DrvTransparentBlt, (PFN) DrvTransparentBlt },
  195. #endif
  196. { INDEX_DrvResetDevice, (PFN) DrvResetDevice },
  197. };// DRVFN gadrvfnOne[]
  198. // Number of driver callbacks for after NT5.
  199. #define NON_NT5_FUNCTIONS 1
  200. //
  201. // Driver Function array we use when running on NT40. Notice the INDEX_Drv
  202. // calls which we have commneted out implying we dont support these
  203. // calls on NT4.0
  204. DRVFN gadrvfnOne40[] =
  205. {
  206. { INDEX_DrvAssertMode, (PFN) DrvAssertMode },
  207. { INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
  208. { INDEX_DrvCreateDeviceBitmap, (PFN) DrvCreateDeviceBitmap },
  209. { INDEX_DrvDeleteDeviceBitmap, (PFN) DrvDeleteDeviceBitmap },
  210. // { INDEX_DrvDeriveSurface, (PFN) DrvDeriveSurface },
  211. { INDEX_DrvDisableDirectDraw, (PFN) DrvDisableDirectDraw },
  212. { INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
  213. { INDEX_DrvDisableDriver, (PFN) DrvDisableDriver },
  214. { INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
  215. { INDEX_DrvEnableDirectDraw, (PFN) DrvEnableDirectDraw },
  216. { INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
  217. { INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
  218. { INDEX_DrvEscape, (PFN) DrvEscape },
  219. { INDEX_DrvGetDirectDrawInfo, (PFN) DrvGetDirectDrawInfo },
  220. { INDEX_DrvGetModes, (PFN) DrvGetModes },
  221. { INDEX_DrvMovePointer, (PFN) DrvMovePointer },
  222. { INDEX_DrvRealizeBrush, (PFN) DrvRealizeBrush },
  223. { INDEX_DrvSetPalette, (PFN) DrvSetPalette },
  224. { INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape },
  225. // { INDEX_DrvIcmSetDeviceGammaRamp, (PFN) DrvIcmSetDeviceGammaRamp },
  226. // { INDEX_DrvNotify, (PFN) DrvNotify },
  227. // { INDEX_DrvSynchronizeSurface, (PFN) DrvSynchronizeSurface },
  228. #if THUNK_LAYER
  229. { INDEX_DrvBitBlt, (PFN) xDrvBitBlt },
  230. { INDEX_DrvCopyBits, (PFN) xDrvCopyBits },
  231. { INDEX_DrvTextOut, (PFN) xDrvTextOut },
  232. // { INDEX_DrvAlphaBlend, (PFN) xDrvAlphaBlend },
  233. // { INDEX_DrvGradientFill, (PFN) xDrvGradientFill },
  234. // { INDEX_DrvTransparentBlt, (PFN) xDrvTransparentBlt },
  235. { INDEX_DrvLineTo, (PFN) xDrvLineTo },
  236. { INDEX_DrvFillPath, (PFN) xDrvFillPath },
  237. { INDEX_DrvStrokePath, (PFN) xDrvStrokePath },
  238. #else
  239. { INDEX_DrvBitBlt, (PFN) DrvBitBlt },
  240. { INDEX_DrvCopyBits, (PFN) DrvCopyBits },
  241. { INDEX_DrvTextOut, (PFN) DrvTextOut },
  242. // { INDEX_DrvAlphaBlend, (PFN) DrvAlphaBlend },
  243. // { INDEX_DrvGradientFill, (PFN) DrvGradientFill },
  244. // { INDEX_DrvTransparentBlt, (PFN) DrvTransparentBlt },
  245. { INDEX_DrvLineTo, (PFN) DrvLineTo },
  246. { INDEX_DrvFillPath, (PFN) DrvFillPath },
  247. { INDEX_DrvStrokePath, (PFN) DrvStrokePath },
  248. #endif
  249. };// DRVFN gadrvfnOne40[]
  250. ULONG gcdrvfnOne = sizeof(gadrvfnOne) / sizeof(DRVFN);
  251. //
  252. // Special setup for NT4.0 runtime behaviour
  253. //
  254. ULONG gcdrvfnOne40 = sizeof(gadrvfnOne40) / sizeof(DRVFN);
  255. //
  256. // We initialize this to TRUE and set it to FALSE in
  257. // DrvEnablePDEV when on NT5.0. We do this using the iEngineVersion passed on
  258. // to us in that call.
  259. //
  260. BOOL g_bOnNT40 = TRUE;
  261. //@@BEGIN_DDKSPLIT
  262. #if MULTITHREADED
  263. HSEMAPHORE gLock = NULL;
  264. ULONG gLockCount = 0;
  265. #endif
  266. //@@END_DDKSPLIT
  267. //
  268. // Local prototypes
  269. //
  270. BOOL bAssertModeHardware(PDev* ppdev, BOOL bEnable);
  271. BOOL bEnableHardware(PDev* ppdev);
  272. BOOL bInitializeModeFields(PDev* ppdev, GDIINFO* pgdi,
  273. DEVINFO* pdi, DEVMODEW* pdm);
  274. DWORD getAvailableModes(HANDLE hDriver,
  275. PVIDEO_MODE_INFORMATION* modeInformation,
  276. DWORD* cbModeSize);
  277. VOID vDisableHardware(PDev* ppdev);
  278. #define SETUP_LOG_LEVEL 2
  279. //-------------------------------Public*Routine--------------------------------
  280. //
  281. // BOOL DrvEnableDriver
  282. //
  283. // DrvEnableDriver is the initial driver entry point exported by the driver
  284. // DLL. It fills a DRVENABLEDATA structure with the driver version number and
  285. // calling addresses of functions supported by the driver
  286. //
  287. // Parameters:
  288. // iEngineVersion--Identifies the version of GDI that is currently running.
  289. // cj--------------Specifies the size in bytes of the DRVENABLEDATA structure.
  290. // If the structure is larger than expected, extra members
  291. // should be left unmodified.
  292. // pded------------Points to a DRVENABLEDATA structure. GDI zero-initializes
  293. // cj bytes before the call. The driver fills in its own data.
  294. //
  295. // Return Value
  296. // The return value is TRUE if the specified driver is enabled. Otherwise, it
  297. // is FALSE, and an error code is logged.
  298. //
  299. //-----------------------------------------------------------------------------
  300. BOOL
  301. DrvEnableDriver(ULONG iEngineVersion,
  302. ULONG cj,
  303. DRVENABLEDATA* pded)
  304. {
  305. ULONG gcdrvfn;
  306. DRVFN* gadrvfn;
  307. ULONG DriverVersion;
  308. DBG_GDI((SETUP_LOG_LEVEL, "DrvEnableDriver: iEngineVersion = 0x%lx\n",
  309. iEngineVersion, cj, pded));
  310. // Set up g_bOnNT40 based on the value in iEngineVersion
  311. if(iEngineVersion >= DDI_DRIVER_VERSION_NT5)
  312. g_bOnNT40 = FALSE;
  313. if(g_bOnNT40 == FALSE)
  314. {
  315. // Since this driver is backwards compatible,
  316. // report highest driver version this was built
  317. // against that the Engine will also recognize.
  318. // Ordered list of supported DDI versions
  319. ULONG SupportedVersions[] = {
  320. DDI_DRIVER_VERSION_NT5,
  321. DDI_DRIVER_VERSION_NT5_01,
  322. };
  323. LONG i = sizeof(SupportedVersions)/sizeof(SupportedVersions[0]);
  324. // Look for highest version also supported by engine
  325. while (--i >= 0)
  326. {
  327. if (SupportedVersions[i] <= iEngineVersion) break;
  328. }
  329. // Fail if there isn't common support
  330. if (i < 0) return FALSE;
  331. DriverVersion = SupportedVersions[i];
  332. gadrvfn = gadrvfnOne;
  333. gcdrvfn = gcdrvfnOne;
  334. if (iEngineVersion < DDI_DRIVER_VERSION_NT5_01)
  335. {
  336. // Trim new DDI hooks since NT5.0
  337. gcdrvfn -= NON_NT5_FUNCTIONS;
  338. }
  339. if(!bEnableThunks())
  340. {
  341. ASSERTDD(0,"DrvEnableDriver: bEnableThunks Failed\n");
  342. return FALSE;
  343. }
  344. }
  345. else
  346. {
  347. DriverVersion = DDI_DRIVER_VERSION_NT4;
  348. gadrvfn = gadrvfnOne40;
  349. gcdrvfn = gcdrvfnOne40;
  350. }
  351. //
  352. // Engine Version is passed down so future drivers can support previous
  353. // engine versions. A next generation driver can support both the old
  354. // and new engine conventions if told what version of engine it is
  355. // working with. For the first version the driver does nothing with it.
  356. // Fill in as much as we can.
  357. //
  358. if ( cj >= (sizeof(ULONG) * 3) )
  359. {
  360. pded->pdrvfn = gadrvfn;
  361. }
  362. //
  363. // Tell GDI what are the functions this driver can do
  364. //
  365. if ( cj >= (sizeof(ULONG) * 2) )
  366. {
  367. pded->c = gcdrvfn;
  368. }
  369. //
  370. // DDI version this driver was targeted for is passed back to engine.
  371. // Future graphic's engine may break calls down to old driver format.
  372. //
  373. if ( cj >= sizeof(ULONG) )
  374. {
  375. DBG_GDI((SETUP_LOG_LEVEL, "DrvEnableDriver: iDriverVersion = 0x%lx",
  376. DriverVersion));
  377. pded->iDriverVersion = DriverVersion;
  378. }
  379. //
  380. // add instance to memory tracker if enabled
  381. //
  382. MEMTRACKERADDINSTANCE();
  383. return(TRUE);
  384. }// DrvEnableDriver()
  385. //-------------------------------Public*Routine--------------------------------
  386. //
  387. // VOID DrvDisableDriver
  388. //
  389. // This function is used by GDI to notify a driver that it no longer requires
  390. // the driver and is ready to unload it.
  391. //
  392. // Comments
  393. // The driver should free all allocated resources and return the device to the
  394. // state it was in before the driver loaded.
  395. //
  396. // DrvDisableDriver is required for graphics drivers.
  397. //
  398. //-----------------------------------------------------------------------------
  399. VOID
  400. DrvDisableDriver(VOID)
  401. {
  402. //
  403. // Do nothing
  404. //
  405. //
  406. // except cleanup memory tracker, if enabled.
  407. // also show memory usage
  408. //
  409. MEMTRACKERDEBUGCHK();
  410. MEMTRACKERREMINSTANCE();
  411. return;
  412. }// DrvDisableDriver()
  413. //-------------------------------Public*Routine--------------------------------
  414. //
  415. // DHPDEV DrvEnablePDEV
  416. //
  417. // This function returns a description of the physical device's characteristics
  418. // to GDI.
  419. //
  420. // It initializes a bunch of fields for GDI, based on the mode we've been asked
  421. // to do. This is the first thing called after DrvEnableDriver, when GDI wants
  422. // to get some information about the driver.
  423. //
  424. // Parameters
  425. //
  426. // pdm-------------Points to a DEVMODEW structure that contains driver data.
  427. //
  428. // pwszLogAddress--Will always be null and can be ignored
  429. //
  430. // cPat------------No longer used by GDI and can be ignored
  431. //
  432. // phsurfPatterns--No longer used by GDI and can be ignored
  433. //
  434. // cjCaps----------Specifies the size of the buffer pointed to by pdevcaps.
  435. // The driver must not access memory beyond the end of the
  436. // buffer.
  437. //
  438. // pdevcaps--------Points to a GDIINFO structure that will be used to describe
  439. // device capabilities. GDI zero-initializes this structure
  440. // calling DrvEnablePDEV.
  441. //
  442. // cjDevInfo-------Specifies the number of bytes in the DEVINFO structure
  443. // pointed to by pdi. The driver should modify no more than
  444. // this number of bytes in the DEVINFO.
  445. //
  446. // pdi-------------Points to the DEVINFO structure, which describes the driver
  447. // and the physical device. The driver should only alter the
  448. // members it understands. GDI fills this structure with zeros
  449. // before a call to DrvEnablePDEV.
  450. //
  451. // hdev------------Is a GDI-supplied handle to the display driver device that
  452. // is being enabled. The device is in the process of being
  453. // created and thus can not be used for Eng calls thus making
  454. // this paramter practially useless. The one exception to this
  455. // rule is the use of hdev for calls to EngGetDriverName. No
  456. // other Eng calls are gaurenteed to work.
  457. //
  458. // pwszDeviceName--Device driver file name stored as a zero terminated ASCII
  459. // string
  460. //
  461. // hDriver---------Identifies the kernel-mode driver that supports the device.
  462. // We will use this to make EngDeviceIoControl calls to our
  463. // corresponding mini-port driver.
  464. //
  465. // Returns upon success a handle to the driver-defined device instance
  466. // information upon success. Otherwise it returns NULL.
  467. //
  468. //-----------------------------------------------------------------------------
  469. DHPDEV
  470. DrvEnablePDEV(DEVMODEW* pdm,
  471. PWSTR pwszLogAddr,
  472. ULONG cPat,
  473. HSURF* phsurfPatterns,
  474. ULONG cjCaps,
  475. ULONG* pdevcaps,
  476. ULONG cjDevInfo,
  477. DEVINFO* pdi,
  478. HDEV hdev,
  479. PWSTR pwszDeviceName,
  480. HANDLE hDriver)
  481. {
  482. PDev* ppdev = NULL;
  483. GDIINFO gdiinfo;
  484. DEVINFO devinfo;
  485. DBG_GDI((SETUP_LOG_LEVEL, "DrvEnablePDEV(...)"));
  486. //
  487. // Invalidate input parameters
  488. // Note: here we use "<" to check the size of the structure is to ensure
  489. // that the driver can be used in the future version of NT, in which case
  490. // that the structure size might go larger
  491. //
  492. // GDIINFO and DEVINFO are larger on NT50. On NT40 they are smaller.
  493. // To make NT50 built driver binary work on NT40, we use temporary copies of
  494. // GDIINFO and DEVINFO and only copy what cjCaps and cjDevInfo indicate
  495. // into these structures.
  496. RtlZeroMemory(&gdiinfo, sizeof(GDIINFO));
  497. RtlCopyMemory(&gdiinfo, pdevcaps, __min(cjCaps, sizeof(GDIINFO)));
  498. RtlZeroMemory(&devinfo, sizeof(DEVINFO));
  499. RtlCopyMemory(&devinfo, pdi, __min(cjDevInfo, sizeof(DEVINFO)));
  500. //
  501. // Allocate a physical device structure. Note that we definitely
  502. // rely on the zero initialization:
  503. //
  504. ppdev = (PDev*)ENGALLOCMEM(FL_ZERO_MEMORY, sizeof(PDev), ALLOC_TAG);
  505. if ( ppdev == NULL )
  506. {
  507. DBG_GDI((0, "DrvEnablePDEV: failed memory allocation"));
  508. goto errExit;
  509. }
  510. ppdev->hDriver = hDriver;
  511. //
  512. // Initialize status field.
  513. //
  514. ppdev->flStatus = ENABLE_BRUSH_CACHE;
  515. // NT50 -> NT40 compat:
  516. // We dont do Device Bitamps on NT40.
  517. //
  518. if(!g_bOnNT40)
  519. ppdev->flStatus |= STAT_DEV_BITMAPS;
  520. //@@BEGIN_DDKSPLIT
  521. #if MULTITHREADED
  522. ppdev->hsemLock = EngCreateSemaphore();
  523. if(ppdev->hsemLock == NULL)
  524. {
  525. DBG_GDI((0, "DrvEnablePDEV: failed to create semaphore"));
  526. goto errExit;
  527. }
  528. #endif
  529. //@@END_DDKSPLIT
  530. //
  531. // We haven't initialized the pointer yet
  532. //
  533. ppdev->bPointerInitialized = FALSE;
  534. //
  535. // Get the current screen mode information. Set up device caps and devinfo
  536. //
  537. if ( !bInitializeModeFields(ppdev, &gdiinfo, &devinfo, pdm) )
  538. {
  539. goto errExit;
  540. }
  541. RtlCopyMemory(pdevcaps, &gdiinfo, cjCaps);
  542. RtlCopyMemory(pdi, &devinfo, cjDevInfo);
  543. //
  544. // Initialize palette information.
  545. //
  546. if ( !bInitializePalette(ppdev, pdi) )
  547. {
  548. goto errExit;
  549. }
  550. DBG_GDI((SETUP_LOG_LEVEL, "DrvEnablePDEV(...) returning %lx", ppdev));
  551. return((DHPDEV)ppdev);
  552. errExit:
  553. if( ppdev != NULL )
  554. {
  555. DrvDisablePDEV((DHPDEV)ppdev);
  556. }
  557. DBG_GDI((0, "Failed DrvEnablePDEV"));
  558. return(0);
  559. }// DrvEnablePDEV()
  560. //-------------------------------Public*Routine--------------------------------
  561. //
  562. // DrvDisablePDEV
  563. //
  564. // This function is used by GDI to notify a driver that the specified PDEV is
  565. // no longer needed
  566. //
  567. // Parameters
  568. // dhpdev------Pointer to the PDEV that describes the physical device to be
  569. // disabled. This value is the handle returned by DrvEnablePDEV.
  570. //
  571. // Comments
  572. // If the physical device has an enabled surface, GDI calls DrvDisablePDEV
  573. // after calling DrvDisableSurface. The driver should free any memory and
  574. // resources used by the PDEV.
  575. //
  576. // DrvDisablePDEV is required for graphics drivers.
  577. //
  578. // Note: In an error, we may call this before DrvEnablePDEV is done.
  579. //
  580. //-----------------------------------------------------------------------------
  581. VOID
  582. DrvDisablePDEV(DHPDEV dhpdev)
  583. {
  584. PDev* ppdev = (PDev*)dhpdev;
  585. DBG_GDI((SETUP_LOG_LEVEL, "DrvDisablePDEV(%lx)", ppdev));
  586. vUninitializePalette(ppdev);
  587. //@@BEGIN_DDKSPLIT
  588. #if MULTITHREADED
  589. if( ppdev->hsemLock != NULL)
  590. {
  591. EngDeleteSemaphore(ppdev->hsemLock);
  592. ppdev->hsemLock = NULL;
  593. }
  594. #endif
  595. //@@END_DDKSPLIT
  596. ENGFREEMEM(ppdev);
  597. }// DrvDisablePDEV()
  598. //-------------------------------Public*Routine--------------------------------
  599. //
  600. // DrvResetPDEV
  601. //
  602. // This function is used by GDI to allow a driver to pass state information
  603. // from one driver instance to the next.
  604. //
  605. // Parameters
  606. // dhpdevOld---Pointer to the PDEV that describes the physical device to be
  607. // disabled. This value is the handle returned by DrvEnablePDEV.
  608. // dhpdevNew---Pointer to the PDEV that describes the physical device to be
  609. // enabled. This value is the handle returned by DrvEnablePDEV.
  610. //
  611. //
  612. // Return Value
  613. // TRUE if successful, FALSE otherwise.
  614. //
  615. //-----------------------------------------------------------------------------
  616. BOOL
  617. DrvResetPDEV(DHPDEV dhpdevOld,
  618. DHPDEV dhpdevNew)
  619. {
  620. PDev* ppdevOld = (PDev*)dhpdevOld;
  621. PDev* ppdevNew = (PDev*)dhpdevNew;
  622. BOOL bResult = TRUE;
  623. DBG_GDI((SETUP_LOG_LEVEL, "DrvResetPDEV(%lx,%lx)", ppdevOld, ppdevNew));
  624. // pass state information here:
  625. // sometimes the new ppdev has already some DeviceBitmaps assigned...
  626. if (ppdevOld->bDdExclusiveMode)
  627. {
  628. bResult = bDemoteAll(ppdevNew);
  629. }
  630. // pass information if DirectDraw is in exclusive mode
  631. // to next active PDEV
  632. if(bResult)
  633. {
  634. ppdevNew->bDdExclusiveMode=ppdevOld->bDdExclusiveMode;
  635. }
  636. return bResult;
  637. }// DrvResetPDEV()
  638. //-------------------------------Public*Routine--------------------------------
  639. //
  640. // VOID DrvCompletePDEV
  641. //
  642. // This function stores the GDI handle (hdev) of the physical device in dhpdev.
  643. // The driver should retain this handle for use when calling GDI services.
  644. //
  645. // Parameters
  646. // dhpdev------Identifies the physical device by its handle, which was
  647. // returned to GDI when it called DrvEnablePDEV.
  648. // hdev--------Identifies the physical device that has been installed. This is
  649. // the GDI handle for the physical device being created. The
  650. // driver should use this handle when calling GDI functions.
  651. //
  652. // Comments
  653. // DrvCompletePDEV is called by GDI when its installation of the physical
  654. // device is complete. It also provides the driver with a handle to the PDEV
  655. // to be used when requesting GDI services for the device. This function is
  656. // required for graphics drivers; when GDI calls DrvCompletePDEV, it cannot
  657. // fail.
  658. //
  659. //-----------------------------------------------------------------------------
  660. VOID
  661. DrvCompletePDEV(DHPDEV dhpdev,
  662. HDEV hdev)
  663. {
  664. PDev* ppdev = (PDev*)dhpdev;
  665. DBG_GDI((SETUP_LOG_LEVEL, "DrvCompletePDEV(%lx, %lx)", dhpdev, hdev));
  666. ppdev->hdevEng = hdev;
  667. if(!g_bOnNT40)
  668. {
  669. //
  670. // Retrieve acceleration level before the surface is enabled.
  671. //
  672. EngQueryDeviceAttribute(hdev,
  673. QDA_ACCELERATION_LEVEL,
  674. NULL,
  675. 0,
  676. (PVOID)&ppdev->dwAccelLevel,
  677. sizeof(ppdev->dwAccelLevel));
  678. }
  679. DBG_GDI((6, "acceleration level %d", ppdev->dwAccelLevel));
  680. }// DrvCompletePDEV()
  681. //-------------------------------Public*Routine--------------------------------
  682. //
  683. // HSURF DrvEnableSurface
  684. //
  685. // This function sets up a surface to be drawn on and associates it with a
  686. // given PDEV and initializes the hardware. This is called after DrvEnablePDEV
  687. // and performs the final device initialization.
  688. //
  689. // Parameters
  690. // dhpdev------Identifies a handle to a PDEV. This value is the return value
  691. // of DrvEnablePDEV. The PDEV describes the physical device for
  692. // which a surface is to be created.
  693. //
  694. // Return Value
  695. // The return value is a handle that identifies the newly created surface.
  696. // Otherwise, it is zero, and an error code is logged.
  697. //
  698. // Comments
  699. // Depending on the device and circumstances, the driver can do any of the
  700. // following to enable the surface:
  701. //
  702. // If the driver manages its own surface, the driver can call
  703. // EngCreateDeviceSurface to get a handle for the surface.
  704. // GDI can manage the surface completely if the device has a surface that
  705. // resembles a standard-format bitmap. The driver can obtain a bitmap handle
  706. // for the surface by calling EngCreateBitmap with a pointer to the buffer for
  707. // the bitmap.
  708. // GDI can collect the graphics directly onto a GDI bitmap. The driver should
  709. // call EngCreateBitmap, allowing GDI to allocate memory for the bitmap. This
  710. // function is generally used only by printer devices.
  711. // Any existing GDI bitmap handle is a valid surface handle.
  712. //
  713. // Before defining and returning a surface, a graphics driver must associate
  714. // the surface with the physical device using EngAssociateSurface. This GDI
  715. // function allows the driver to specify which graphics output routines are
  716. // supported for standard-format bitmaps. A call to this function can only be
  717. // made when no surface exists for the given physical device.
  718. //
  719. //-----------------------------------------------------------------------------
  720. HSURF
  721. DrvEnableSurface(DHPDEV dhpdev)
  722. {
  723. PDev* ppdev;
  724. HSURF hsurf;
  725. SIZEL sizl;
  726. Surf* psurf;
  727. VOID* pvTmpBuffer;
  728. BYTE* pjScreen;
  729. LONG lDelta;
  730. FLONG flHooks;
  731. ULONG DIBHooks;
  732. DBG_GDI((SETUP_LOG_LEVEL, "DrvEnableSurface(%lx)", dhpdev));
  733. ppdev = (PDev*)dhpdev;
  734. //@@BEGIN_DDKSPLIT
  735. #if MULTITHREADED
  736. if(ppdev->ulLockCount)
  737. {
  738. DBG_GDI((MT_LOG_LEVEL, "DrvEnableSurface: re-entry! %d", ppdev->ulLockCount));
  739. }
  740. EngAcquireSemaphore(ppdev->hsemLock);
  741. ppdev->ulLockCount++;
  742. #endif
  743. //@@END_DDKSPLIT
  744. if ( !bEnableHardware(ppdev) )
  745. {
  746. goto errExit;
  747. }
  748. //
  749. // Initializes the off-screen heap
  750. //
  751. if ( !bEnableOffscreenHeap(ppdev) )
  752. {
  753. goto errExit;
  754. }
  755. //
  756. // The DSURF for the screen is special.
  757. //
  758. // It is custom built here as opposed to being allocated via the
  759. // heap management calls.
  760. //
  761. // NOTE: The video memory for the screen is reserved up front starting
  762. // at zero and thus we do not need to allocate this memory from the
  763. // video memory heap.
  764. //
  765. // NOTE: The DSURF will not be among the list of all of the other DSURFs
  766. // which are allocated dynamically.
  767. //
  768. // NIT: remove the dynamic allocation of the DSURF. Instead, just
  769. // declare pdsurfScreen as a DSURF instead of a DSURF*.
  770. //
  771. psurf = (Surf*)ENGALLOCMEM(FL_ZERO_MEMORY, sizeof(Surf), ALLOC_TAG);
  772. if ( psurf == NULL )
  773. {
  774. DBG_GDI((0, "DrvEnableSurface: failed pdsurf memory allocation"));
  775. goto errExit;
  776. }
  777. ppdev->pdsurfScreen = psurf;
  778. psurf->flags = SF_VM;
  779. psurf->ppdev = ppdev;
  780. psurf->ulByteOffset= 0;
  781. psurf->ulPixOffset = 0;
  782. psurf->lDelta = ppdev->lDelta;
  783. psurf->ulPixDelta = ppdev->lDelta >> ppdev->cPelSize;
  784. vCalcPackedPP(ppdev->lDelta >> ppdev->cPelSize, NULL, &psurf->ulPackedPP);
  785. //
  786. // Create screen SURFOBJ.
  787. //
  788. sizl.cx = ppdev->cxScreen;
  789. sizl.cy = ppdev->cyScreen;
  790. //
  791. // On NT4.0 we create a GDI managed bitmap as the primay surface. But
  792. // on NT5.0 we create a device managed primary.
  793. //
  794. // On NT4.0 we still use our driver's accleration capabilities by
  795. // doing a trick with EngLockSurface on the GDI managed primary.
  796. //
  797. if(g_bOnNT40)
  798. {
  799. hsurf = (HSURF) EngCreateBitmap(sizl,
  800. ppdev->lDelta,
  801. ppdev->iBitmapFormat,
  802. (ppdev->lDelta > 0) ? BMF_TOPDOWN : 0,
  803. (PVOID)(ppdev->pjScreen));
  804. }
  805. else
  806. {
  807. hsurf = (HSURF)EngCreateDeviceSurface((DHSURF)psurf, sizl,
  808. ppdev->iBitmapFormat);
  809. }
  810. if ( hsurf == 0 )
  811. {
  812. DBG_GDI((0, "DrvEnableSurface: failed EngCreateDeviceBitmap"));
  813. goto errExit;
  814. }
  815. //
  816. // On NT5.0 we call EngModifSurface to expose our device surface to
  817. // GDI. We cant do this on NT4.0 hence we call EngAssociateSurface.
  818. //
  819. if(g_bOnNT40)
  820. {
  821. //
  822. // We have to associate the surface we just created with our physical
  823. // device so that GDI can get information related to the PDEV when
  824. // it's drawing to the surface (such as, for example, the length of
  825. // styles on the device when simulating styled lines).
  826. //
  827. //
  828. // On NT4.0 we dont want to be called to Synchronize Access
  829. //
  830. SURFOBJ *psoScreen;
  831. LONG myflHooks = ppdev->flHooks;
  832. myflHooks &= ~HOOK_SYNCHRONIZE;
  833. if (!EngAssociateSurface(hsurf, ppdev->hdevEng, myflHooks))
  834. {
  835. DBG_GDI((0, "DrvEnableSurface: failed EngAssociateSurface"));
  836. goto errExit;
  837. }
  838. //
  839. // Jam in the value of dhsurf into screen SURFOBJ. We do this to
  840. // make sure the driver acclerates Drv calls we hook and not
  841. // punt them back to GDI as the SURFOBJ's dhsurf = 0.
  842. //
  843. ppdev->psoScreen = EngLockSurface(hsurf);
  844. if(ppdev->psoScreen == 0)
  845. {
  846. DBG_GDI((0, "DrvEnableSurface: failed EngLockSurface"));
  847. goto errExit;
  848. }
  849. ppdev->psoScreen->dhsurf = (DHSURF)psurf;
  850. }
  851. else
  852. {
  853. //
  854. // Tell GDI about the screen surface. This will enable GDI to render
  855. // directly to the screen.
  856. //
  857. if ( !EngModifySurface(hsurf,
  858. ppdev->hdevEng,
  859. ppdev->flHooks,
  860. MS_NOTSYSTEMMEMORY,
  861. (DHSURF)psurf,
  862. ppdev->pjScreen,
  863. ppdev->lDelta,
  864. NULL))
  865. {
  866. DBG_GDI((0, "DrvEnableSurface: failed EngModifySurface"));
  867. goto errExit;
  868. }
  869. }
  870. if(MAKE_BITMAPS_OPAQUE)
  871. {
  872. SURFOBJ* surfobj = EngLockSurface(hsurf);
  873. ASSERTDD(surfobj->iType == STYPE_BITMAP,
  874. "expected STYPE_BITMAP");
  875. surfobj->iType = STYPE_DEVBITMAP;
  876. EngUnlockSurface(surfobj);
  877. }
  878. ppdev->hsurfScreen = hsurf; // Remember it for clean-up
  879. ppdev->bEnabled = TRUE; // We'll soon be in graphics mode
  880. //
  881. // Allocate some pageable memory for temp space. This will save
  882. // us from having to allocate and free the temp space inside high
  883. // frequency calls.
  884. //
  885. pvTmpBuffer = ENGALLOCMEM(0, TMP_BUFFER_SIZE, ALLOC_TAG);
  886. if ( pvTmpBuffer == NULL )
  887. {
  888. DBG_GDI((0, "DrvEnableSurface: failed TmpBuffer allocation"));
  889. goto errExit;
  890. }
  891. ppdev->pvTmpBuffer = pvTmpBuffer;
  892. //
  893. // Now enable all the subcomponents.
  894. //
  895. // Note that the order in which these 'Enable' functions are called
  896. // may be significant in low off-screen memory conditions, because
  897. // the off-screen heap manager may fail some of the later
  898. // allocations...
  899. //
  900. if ( !bInitializeHW(ppdev) )
  901. {
  902. goto errExit;
  903. }
  904. //
  905. // On NT5.0 bEnablePointer call is made in DrvNotify. On NT4.0 we wont
  906. // get called with DrvNotify and hence we have to call bInitializePointer
  907. // now.
  908. //
  909. if(g_bOnNT40)
  910. {
  911. if ( !bEnablePointer(ppdev) )
  912. {
  913. goto errExit;
  914. }
  915. }
  916. if ( !bEnablePalette(ppdev) )
  917. {
  918. goto errExit;
  919. }
  920. if (!bEnableText(ppdev))
  921. {
  922. goto errExit;
  923. }
  924. //@@BEGIN_DDKSPLIT
  925. #if MULTITHREADED
  926. ppdev->ulLockCount--;
  927. EngReleaseSemaphore(ppdev->hsemLock);
  928. #endif
  929. //@@END_DDKSPLIT
  930. DBG_GDI((7, "DrvEnableSurface: done with hsurf=%x", hsurf));
  931. DBG_GDI((6, "DrvEnableSurface: done with dhpdev = %lx", dhpdev));
  932. DBG_GDI((SETUP_LOG_LEVEL, "DrvEnableSurface(..) return hsurf = %lx", hsurf));
  933. return(hsurf);
  934. errExit:
  935. //@@BEGIN_DDKSPLIT
  936. #if MULTITHREADED
  937. ppdev->ulLockCount--;
  938. EngReleaseSemaphore(ppdev->hsemLock);
  939. #endif
  940. //@@END_DDKSPLIT
  941. DrvDisableSurface((DHPDEV) ppdev);
  942. DBG_GDI((0, "DrvEnableSurface: failed"));
  943. return(0);
  944. }// DrvEnableSurface()
  945. //-------------------------------Public*Routine--------------------------------
  946. //
  947. // VOID DrvDisableSurface
  948. //
  949. // This function is used by GDI to notify a driver that the surface created
  950. // by DrvEnableSurface for the current device is no longer needed
  951. //
  952. // Parameters
  953. // dhpdev------Handle to the PDEV that describes the physical device whose
  954. // surface is to be released.
  955. //
  956. // Comments
  957. // The driver should free any memory and resources used by the surface
  958. // associated with the PDEV as soon as the physical device is disabled.
  959. //
  960. // If the driver has been disabled by a call to DrvAssertMode, the driver
  961. // cannot access the hardware during DrvDisablePDEV because another active
  962. // PDEV might be in use. Any necessary hardware changes should have been
  963. // performed during the call to DrvAssertMode. A driver should keep track of
  964. // whether or not it has been disabled by DrvAssertMode so that it can perform
  965. // proper cleanup operations in DrvDisablePDEV.
  966. //
  967. // If the physical device has an enabled surface, GDI calls DrvDisableSurface
  968. // before calling DrvDisablePDEV.
  969. //
  970. // DrvDisableSurface is required for graphics drivers
  971. //
  972. // Note: In an error case, we may call this before DrvEnableSurface is
  973. // completely done.
  974. //
  975. //-----------------------------------------------------------------------------
  976. VOID
  977. DrvDisableSurface(DHPDEV dhpdev)
  978. {
  979. PDev* ppdev = (PDev*)dhpdev;
  980. Surf* psurf = ppdev->pdsurfScreen;
  981. DBG_GDI((SETUP_LOG_LEVEL, "DrvDisableSurface(%lx)", ppdev));
  982. //
  983. // Note: In an error case, some of the following relies on the
  984. // fact that the PDEV is zero-initialized, so fields like
  985. // 'hsurfScreen' will be zero unless the surface has been
  986. // sucessfully initialized, and makes the assumption that
  987. // EngDeleteSurface can take '0' as a parameter.
  988. //
  989. vDisableText(ppdev);
  990. vDisableHW(ppdev);
  991. vDisableOffscreenHeap(ppdev);
  992. vDisableHardware(ppdev);
  993. ENGFREEMEM(ppdev->pvTmpBuffer);
  994. if(g_bOnNT40)
  995. EngUnlockSurface(ppdev->psoScreen);
  996. EngDeleteSurface(ppdev->hsurfScreen);
  997. ppdev->hsurfScreen = NULL;
  998. ENGFREEMEM(psurf);
  999. }// DrvDisableSurface()
  1000. //-------------------------------Public*Routine--------------------------------
  1001. //
  1002. // BOOL DrvAssertMode
  1003. //
  1004. // This function sets the mode of the specified physical device to either the
  1005. // mode specified when the PDEV was initialized or to the default mode of the
  1006. // hardware.
  1007. //
  1008. // Parameters
  1009. //
  1010. // dhpdev------Identifies the PDEV describing the hardware mode that should be
  1011. // set.
  1012. // bEnable-----Specifies the mode to which the hardware is to be set. If this
  1013. // parameter is TRUE, then the hardware is set to the original
  1014. // mode specified by the initialized PDEV. Otherwise, the hardware
  1015. // is set to its default mode so the video miniport driver can
  1016. // assume control.
  1017. //
  1018. // Comments
  1019. // GDI calls DrvAssertMode when it is required to switch among multiple
  1020. // desktops on a single display surface. To switch from one PDEV to another,
  1021. // GDI calls DrvAssertMode with the bEnable parameter set to FALSE for one
  1022. // PDEV, and TRUE for the other. To revert to the original PDEV, DrvAssertMode
  1023. // is called with bEnable set to FALSE, followed by another call to
  1024. // DrvAssertMode, with bEnable set to TRUE and dhpdev set to the original PDEV
  1025. //
  1026. // If the physical device is palette-managed, GDI should call DrvSetPalette to
  1027. // reset the device's palette. The driver does not then need to keep track of
  1028. // the current pointer state because the Window Manager selects the correct
  1029. // pointer shape and moves it to the current position. The Console Manager
  1030. // ensures that desktops are properly redrawn.
  1031. //
  1032. // DrvAssertMode is required for display drivers
  1033. //
  1034. //-----------------------------------------------------------------------------
  1035. BOOL
  1036. DrvAssertMode(DHPDEV dhpdev,
  1037. BOOL bEnable)
  1038. {
  1039. PDev* ppdev = (PDev*)dhpdev;
  1040. BOOL bRet = FALSE;
  1041. DBG_GDI((SETUP_LOG_LEVEL, "DrvAssertMode(%lx, %lx)", dhpdev, bEnable));
  1042. //@@BEGIN_DDKSPLIT
  1043. #if MULTITHREADED
  1044. if(ppdev->ulLockCount)
  1045. {
  1046. DBG_GDI((MT_LOG_LEVEL, "DrvAssertMode: re-entered! %d", ppdev->ulLockCount));
  1047. }
  1048. EngAcquireSemaphore(ppdev->hsemLock);
  1049. ppdev->ulLockCount++;
  1050. #endif
  1051. //@@END_DDKSPLIT
  1052. if ( !bEnable )
  1053. {
  1054. //
  1055. // bEnable == FALSE. The hardware is set to its default mode so the
  1056. // video miniport driver can assume control.
  1057. //
  1058. vAssertModeBrushCache(ppdev, FALSE);
  1059. vAssertModePointer(ppdev, FALSE);
  1060. vAssertModeText(ppdev, FALSE);
  1061. if ( bAssertModeOffscreenHeap(ppdev, FALSE) )
  1062. {
  1063. vAssertModeHW(ppdev, FALSE);
  1064. if ( bAssertModeHardware(ppdev, FALSE) )
  1065. {
  1066. ppdev->bEnabled = FALSE;
  1067. bRet = TRUE;
  1068. goto done;
  1069. }
  1070. //
  1071. // We failed to switch to full-screen. So undo everything:
  1072. //
  1073. vAssertModeHW(ppdev, TRUE);
  1074. } // return code with TRUE
  1075. bEnablePointer(ppdev);
  1076. vAssertModeText(ppdev, TRUE);
  1077. vAssertModeBrushCache(ppdev, TRUE);
  1078. }// if ( !bEnable )
  1079. else
  1080. {
  1081. //
  1082. // bEnable == TRUE means the hardware is set to the original mode
  1083. // specified by the initialized PDEV
  1084. //
  1085. // Switch back to graphics mode
  1086. //
  1087. // We have to enable every subcomponent in the reverse order
  1088. // in which it was disabled:
  1089. //
  1090. // NOTE: We defer the enabling of the brush and pointer cache
  1091. // to DrvNotify. The direct draw heap is not valid
  1092. // at this point.
  1093. //
  1094. if ( bAssertModeHardware(ppdev, TRUE) )
  1095. {
  1096. vAssertModeHW(ppdev, TRUE);
  1097. vAssertModeText(ppdev, TRUE);
  1098. ppdev->bEnabled = TRUE;
  1099. bRet = TRUE;
  1100. }
  1101. }// bEnable == TRUE
  1102. done:
  1103. //@@BEGIN_DDKSPLIT
  1104. #if MULTITHREADED
  1105. ppdev->ulLockCount--;
  1106. EngReleaseSemaphore(ppdev->hsemLock);
  1107. #endif
  1108. //@@END_DDKSPLIT
  1109. return(bRet);
  1110. }// DrvAssertMode()
  1111. //-------------------------------Public*Routine--------------------------------
  1112. //
  1113. // ULONG DrvGetModes
  1114. //
  1115. // This function lists the modes supported by the device.
  1116. //
  1117. // Parameters:
  1118. //
  1119. // hDriver-----Specifies the handle to the kernel driver for which the modes
  1120. // must be enumerated. This is the handle that is passed in the
  1121. // hDriver parameter of the DrvEnablePDEV function.
  1122. // cjSize------Specifies the size, in bytes, of the buffer pointed to by pdm.
  1123. // pdm---------Points to the buffer in which DEVMODEW structures will be
  1124. // written.
  1125. //
  1126. // Return Value
  1127. // The return value is the count of bytes written to the buffer, or, if pdm is
  1128. // null, the number of bytes required to hold all mode data. If an error
  1129. // occurs, the return value is zero, and an error code is logged
  1130. //
  1131. //-----------------------------------------------------------------------------
  1132. ULONG
  1133. DrvGetModes(HANDLE hDriver,
  1134. ULONG cjSize,
  1135. DEVMODEW* pdm)
  1136. {
  1137. DWORD cModes;
  1138. DWORD cbOutputSize;
  1139. PVIDEO_MODE_INFORMATION pVideoModeInformation;
  1140. PVIDEO_MODE_INFORMATION pVideoTemp;
  1141. //
  1142. // How many MODEs the caller wants us to fill
  1143. //
  1144. DWORD cOutputModes = cjSize
  1145. / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  1146. DWORD cbModeSize;
  1147. DBG_GDI((7, "DrvGetModes"));
  1148. cModes = getAvailableModes(hDriver,
  1149. (PVIDEO_MODE_INFORMATION*)&pVideoModeInformation,
  1150. &cbModeSize);
  1151. if ( cModes == 0 )
  1152. {
  1153. DBG_GDI((0, "DrvGetModes: failed to get mode information"));
  1154. return(0);
  1155. }
  1156. if ( pdm == NULL )
  1157. {
  1158. //
  1159. // GDI only wants to know the number of bytes required to hold all
  1160. // mode data at this moment
  1161. //
  1162. cbOutputSize = cModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  1163. }
  1164. else
  1165. {
  1166. //
  1167. // Now copy the information for the supported modes back into the
  1168. // output buffer
  1169. //
  1170. cbOutputSize = 0;
  1171. pVideoTemp = pVideoModeInformation;
  1172. do
  1173. {
  1174. if ( pVideoTemp->Length != 0 )
  1175. {
  1176. //
  1177. // If the caller's buffer is filled up, we should quit now
  1178. //
  1179. if ( cOutputModes == 0 )
  1180. {
  1181. break;
  1182. }
  1183. //
  1184. // Zero the entire structure to start off with.
  1185. //
  1186. memset(pdm, 0, sizeof(DEVMODEW));
  1187. //
  1188. // Set the name of the device to the name of the DLL.
  1189. //
  1190. memcpy(pdm->dmDeviceName, DLL_NAME, sizeof(DLL_NAME));
  1191. pdm->dmSpecVersion = DM_SPECVERSION;
  1192. pdm->dmDriverVersion = DM_SPECVERSION;
  1193. //
  1194. // We currently do not support Extra information in the driver
  1195. //
  1196. pdm->dmDriverExtra = DRIVER_EXTRA_SIZE;
  1197. pdm->dmSize = sizeof(DEVMODEW);
  1198. pdm->dmBitsPerPel = pVideoTemp->NumberOfPlanes
  1199. * pVideoTemp->BitsPerPlane;
  1200. pdm->dmPelsWidth = pVideoTemp->VisScreenWidth;
  1201. pdm->dmPelsHeight = pVideoTemp->VisScreenHeight;
  1202. pdm->dmDisplayFrequency = pVideoTemp->Frequency;
  1203. pdm->dmDisplayFlags = 0;
  1204. pdm->dmPanningWidth = pdm->dmPelsWidth;
  1205. pdm->dmPanningHeight = pdm->dmPelsHeight;
  1206. pdm->dmFields = DM_BITSPERPEL
  1207. | DM_PELSWIDTH
  1208. | DM_PELSHEIGHT
  1209. | DM_DISPLAYFREQUENCY
  1210. | DM_DISPLAYFLAGS;
  1211. //
  1212. // Go to the next DEVMODE entry in the buffer.
  1213. //
  1214. cOutputModes--;
  1215. pdm = (LPDEVMODEW)(((UINT_PTR)pdm) + sizeof(DEVMODEW)
  1216. + DRIVER_EXTRA_SIZE);
  1217. cbOutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  1218. }// if ( pVideoTemp->Length != 0 )
  1219. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  1220. (((PUCHAR)pVideoTemp) + cbModeSize);
  1221. } while (--cModes);
  1222. }// pbm != NULL
  1223. ENGFREEMEM(pVideoModeInformation);
  1224. return(cbOutputSize);
  1225. }// DrvGetModes()
  1226. //-----------------------------------------------------------------------------
  1227. //
  1228. // BOOL bAssertModeHardware
  1229. //
  1230. // Sets the appropriate hardware state for graphics mode or full-screen.
  1231. //
  1232. //-----------------------------------------------------------------------------
  1233. BOOL
  1234. bAssertModeHardware(PDev* ppdev, BOOL bEnable)
  1235. {
  1236. DWORD dLength;
  1237. ULONG ulReturn;
  1238. VIDEO_MODE_INFORMATION VideoModeInfo;
  1239. PERMEDIA_DECL;
  1240. DBG_GDI((6, "bAssertModeHardware: bEnable = %d", bEnable));
  1241. if ( bEnable )
  1242. {
  1243. //
  1244. // Call the miniport via an IOCTL to set the graphics mode.
  1245. //
  1246. if ( EngDeviceIoControl(ppdev->hDriver,
  1247. IOCTL_VIDEO_SET_CURRENT_MODE,
  1248. &ppdev->ulMode, // input buffer
  1249. sizeof(DWORD),
  1250. NULL,
  1251. 0,
  1252. &dLength) )
  1253. {
  1254. DBG_GDI((0, "bAssertModeHardware: failed VIDEO_SET_CURRENT_MODE"));
  1255. goto errExit;
  1256. }
  1257. if ( EngDeviceIoControl(ppdev->hDriver,
  1258. IOCTL_VIDEO_QUERY_CURRENT_MODE,
  1259. NULL,
  1260. 0,
  1261. &VideoModeInfo,
  1262. sizeof(VideoModeInfo),
  1263. &dLength) )
  1264. {
  1265. DBG_GDI((0,"bAssertModeHardware: failed VIDEO_QUERY_CURRENT_MODE"));
  1266. goto errExit;
  1267. }
  1268. //
  1269. // The following variables are determined only after the initial
  1270. // modeset
  1271. // Note: here lVidMemWidth and lVidMemHeight are in "pixel" unit, not
  1272. // bytes
  1273. //
  1274. ppdev->cxMemory = VideoModeInfo.VideoMemoryBitmapWidth;
  1275. ppdev->cyMemory = VideoModeInfo.VideoMemoryBitmapHeight;
  1276. ppdev->lVidMemWidth = VideoModeInfo.VideoMemoryBitmapWidth;
  1277. ppdev->lVidMemHeight = VideoModeInfo.VideoMemoryBitmapHeight;
  1278. ppdev->lDelta = VideoModeInfo.ScreenStride;
  1279. ppdev->flCaps = VideoModeInfo.DriverSpecificAttributeFlags;
  1280. DBG_GDI((7, "bAssertModeHardware: Got flCaps 0x%x", ppdev->flCaps));
  1281. DBG_GDI((7, "bAssertModeHardware: using %s pointer",
  1282. (ppdev->flCaps & CAPS_SW_POINTER) ?
  1283. "GDI Software Cursor":
  1284. (ppdev->flCaps & CAPS_TVP4020_POINTER) ?
  1285. "TI TVP4020" :
  1286. (ppdev->flCaps & CAPS_P2RD_POINTER) ?
  1287. "3Dlabs P2RD" : "unknown"));
  1288. }
  1289. else
  1290. {
  1291. //
  1292. // Call the kernel driver to reset the device to a known state.
  1293. // NTVDM will take things from there:
  1294. //
  1295. if ( EngDeviceIoControl(ppdev->hDriver,
  1296. IOCTL_VIDEO_RESET_DEVICE,
  1297. NULL,
  1298. 0,
  1299. NULL,
  1300. 0,
  1301. &ulReturn) )
  1302. {
  1303. DBG_GDI((0, "bAssertModeHardware: failed reset IOCTL"));
  1304. goto errExit;
  1305. }
  1306. }
  1307. return(TRUE);
  1308. errExit:
  1309. DBG_GDI((0, "bAssertModeHardware: failed"));
  1310. return(FALSE);
  1311. }// bAssertModeHardware()
  1312. //-----------------------------------------------------------------------------
  1313. //
  1314. // BOOL bEnableHardware
  1315. //
  1316. // Puts the hardware in the requested mode and initializes it.
  1317. //
  1318. // Note: This function Should be called before any access is done to the
  1319. // hardware from the display driver
  1320. //
  1321. //-----------------------------------------------------------------------------
  1322. BOOL
  1323. bEnableHardware(PDev* ppdev)
  1324. {
  1325. VIDEO_MEMORY VideoMemory;
  1326. VIDEO_MEMORY_INFORMATION VideoMemoryInfo;
  1327. DWORD dLength;
  1328. VIDEO_PUBLIC_ACCESS_RANGES VideoAccessRange[3];
  1329. DBG_GDI((7, "bEnableHardware"));
  1330. //
  1331. // Map control registers into virtual memory:
  1332. //
  1333. VideoMemory.RequestedVirtualAddress = NULL;
  1334. if ( EngDeviceIoControl(ppdev->hDriver,
  1335. IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES,
  1336. &VideoMemory, // input buffer
  1337. sizeof(VIDEO_MEMORY),
  1338. &VideoAccessRange[0], // output buffer
  1339. sizeof (VideoAccessRange),
  1340. &dLength) )
  1341. {
  1342. DBG_GDI((0,"bEnableHardware: query failed"));
  1343. goto errExit;
  1344. }
  1345. ppdev->pulCtrlBase[0] = (ULONG*)VideoAccessRange[0].VirtualAddress;
  1346. ppdev->pulCtrlBase[1] = (ULONG*)VideoAccessRange[1].VirtualAddress;
  1347. ppdev->pulDenseCtrlBase = (ULONG*)VideoAccessRange[2].VirtualAddress;
  1348. ppdev->pulInputDmaCount = ppdev->pulCtrlBase[0] + (PREG_INDMACOUNT>>2);
  1349. ppdev->pulInputDmaAddress = ppdev->pulCtrlBase[0] + (PREG_INDMAADDRESS>>2);
  1350. ppdev->pulFifo = ppdev->pulCtrlBase[0] + (PREG_FIFOINTERFACE>>2);
  1351. ppdev->pulOutputFifoCount = ppdev->pulCtrlBase[0] + (PREG_OUTFIFOWORDS>>2);
  1352. ppdev->pulInputFifoCount = ppdev->pulCtrlBase[0] + (PREG_INFIFOSPACE>>2);
  1353. DBG_GDI((7, "bEnableHardware: mapped control registers[0] at 0x%x",
  1354. ppdev->pulCtrlBase[0]));
  1355. DBG_GDI((7, " mapped registers[1] at 0x%x",
  1356. ppdev->pulCtrlBase[1]));
  1357. DBG_GDI((7, " mapped dense control registers at 0x%x",
  1358. ppdev->pulDenseCtrlBase));
  1359. //
  1360. // Get the linear memory address range.
  1361. //
  1362. VideoMemory.RequestedVirtualAddress = NULL;
  1363. if ( EngDeviceIoControl(ppdev->hDriver,
  1364. IOCTL_VIDEO_MAP_VIDEO_MEMORY,
  1365. &VideoMemory, // input buffer
  1366. sizeof(VIDEO_MEMORY),
  1367. &VideoMemoryInfo, // output buffer
  1368. sizeof(VideoMemoryInfo),
  1369. &dLength) )
  1370. {
  1371. DBG_GDI((0, "bEnableHardware: error mapping buffer address"));
  1372. goto errExit;
  1373. }
  1374. DBG_GDI((7, "bEnableHardware: frameBufferBase addr = %lx",
  1375. VideoMemoryInfo.FrameBufferBase));
  1376. DBG_GDI((7, " frameBufferLength = %l",
  1377. VideoMemoryInfo.FrameBufferLength));
  1378. DBG_GDI((7, " videoRamBase addr = %lx",
  1379. VideoMemoryInfo.VideoRamBase));
  1380. DBG_GDI((7, " videoRamLength = %l",
  1381. VideoMemoryInfo.VideoRamLength));
  1382. //
  1383. // Record the Frame Buffer Linear Address.
  1384. //
  1385. ppdev->pjScreen = (BYTE*)VideoMemoryInfo.FrameBufferBase;
  1386. ppdev->FrameBufferLength = VideoMemoryInfo.FrameBufferLength;
  1387. //
  1388. // Set hardware states, like ppdev->lVidMemWidth, lVidMemHeight, cxMemory,
  1389. // cyMemory etc
  1390. //
  1391. if ( !bAssertModeHardware(ppdev, TRUE) )
  1392. {
  1393. goto errExit;
  1394. }
  1395. DBG_GDI((7, "bEnableHardware: width = %li height = %li",
  1396. ppdev->cxMemory, ppdev->cyMemory));
  1397. DBG_GDI((7, "bEnableHardware: stride = %li flCaps = 0x%lx",
  1398. ppdev->lDelta, ppdev->flCaps));
  1399. return (TRUE);
  1400. errExit:
  1401. DBG_GDI((0, "bEnableHardware: failed"));
  1402. return (FALSE);
  1403. }// bEnableHardware()
  1404. //-----------------------------------------------------------------------------
  1405. //
  1406. // VOID vDisableHardware
  1407. //
  1408. // Undoes anything done in bEnableHardware.
  1409. //
  1410. // Note: In an error case, we may call this before bEnableHardware is
  1411. // completely done.
  1412. //
  1413. //-----------------------------------------------------------------------------
  1414. VOID
  1415. vDisableHardware(PDev* ppdev)
  1416. {
  1417. DWORD ReturnedDataLength;
  1418. VIDEO_MEMORY VideoMemory[3];
  1419. DBG_GDI((6, "vDisableHardware"));
  1420. if (ppdev->pjScreen)
  1421. {
  1422. VideoMemory[0].RequestedVirtualAddress = ppdev->pjScreen;
  1423. if ( EngDeviceIoControl(ppdev->hDriver,
  1424. IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
  1425. &VideoMemory[0],
  1426. sizeof(VIDEO_MEMORY),
  1427. NULL,
  1428. 0,
  1429. &ReturnedDataLength))
  1430. {
  1431. DBG_GDI((0, "vDisableHardware: failed IOCTL_VIDEO_UNMAP_VIDEO"));
  1432. }
  1433. }
  1434. VideoMemory[0].RequestedVirtualAddress = ppdev->pulCtrlBase[0];
  1435. VideoMemory[1].RequestedVirtualAddress = ppdev->pulCtrlBase[1];
  1436. VideoMemory[2].RequestedVirtualAddress = ppdev->pulDenseCtrlBase;
  1437. if ( EngDeviceIoControl(ppdev->hDriver,
  1438. IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES,
  1439. &VideoMemory[0],
  1440. sizeof(VideoMemory),
  1441. NULL,
  1442. 0,
  1443. &ReturnedDataLength) )
  1444. {
  1445. DBG_GDI((0, "vDisableHardware: failed IOCTL_VIDEO_FREE_PUBLIC_ACCESS"));
  1446. }
  1447. }// vDisableHardware()
  1448. //-----------------------------------------------------------------------------
  1449. //
  1450. // ULONG ulLog2(ULONG ulVal)
  1451. //
  1452. // Returns the log base 2 of the given value. The ulVal must be a power of
  1453. // two otherwise the return value is undefined. If ulVal is zero the return
  1454. // value is undefined.
  1455. //
  1456. //-----------------------------------------------------------------------------
  1457. ULONG
  1458. ulLog2(ULONG ulVal)
  1459. {
  1460. ULONG ulLog2 = 0;
  1461. ULONG ulTemp = ulVal >> 1;
  1462. while( ulTemp )
  1463. {
  1464. ulTemp >>= 1;
  1465. ulLog2++;
  1466. }
  1467. ASSERTDD(ulVal == (1UL << ulLog2), "ulLog2: bad value given");
  1468. return ulLog2;
  1469. }// ulLog2()
  1470. //-----------------------------------------------------------------------------
  1471. //
  1472. // BOOL bInitializeModeFields
  1473. //
  1474. // Initializes a bunch of fields in the pdev, devcaps (aka gdiinfo), and
  1475. // devinfo based on the requested mode.
  1476. //
  1477. //-----------------------------------------------------------------------------
  1478. BOOL
  1479. bInitializeModeFields(PDev* ppdev,
  1480. GDIINFO* pgdi,
  1481. DEVINFO* pdi,
  1482. DEVMODEW* pdm)
  1483. {
  1484. ULONG cModes;
  1485. PVIDEO_MODE_INFORMATION pVideoBuffer;
  1486. PVIDEO_MODE_INFORMATION pVideoModeSelected;
  1487. PVIDEO_MODE_INFORMATION pVideoTemp;
  1488. VIDEO_MODE_INFORMATION vmi;
  1489. ULONG cbModeSize;
  1490. BOOL bSelectDefault; // Used for NT4.0 compat only
  1491. DBG_GDI((6, "bInitializeModeFields"));
  1492. //
  1493. // Call the miniport to get mode information, result will be in
  1494. // "pVideoBuffer"
  1495. //
  1496. // Note: the lower level function allocates memory for us in "pVideoBuffer"
  1497. // so we should take care of this later
  1498. //
  1499. cModes = getAvailableModes(ppdev->hDriver, &pVideoBuffer, &cbModeSize);
  1500. if ( cModes == 0 )
  1501. {
  1502. goto errExit;
  1503. }
  1504. //
  1505. // Now see if the requested mode has a match in that table.
  1506. //
  1507. pVideoModeSelected = NULL;
  1508. pVideoTemp = pVideoBuffer;
  1509. if(g_bOnNT40)
  1510. {
  1511. if ( (pdm->dmPelsWidth == 0)
  1512. &&(pdm->dmPelsHeight == 0)
  1513. &&(pdm->dmBitsPerPel == 0)
  1514. &&(pdm->dmDisplayFrequency == 0) )
  1515. {
  1516. DBG_GDI((2, "bInitializeModeFields: default mode requested"));
  1517. bSelectDefault = TRUE;
  1518. }
  1519. else
  1520. {
  1521. DBG_GDI((2, "bInitializeModeFields: Request width = %li height = %li",
  1522. pdm->dmPelsWidth, pdm->dmPelsHeight));
  1523. DBG_GDI((2, " bpp = %li frequency = %li",
  1524. pdm->dmBitsPerPel, pdm->dmDisplayFrequency));
  1525. bSelectDefault = FALSE;
  1526. }
  1527. }
  1528. else
  1529. {
  1530. //
  1531. // On NT5.0 we should never get an old sytle default mode request.
  1532. //
  1533. ASSERTDD(pdm->dmPelsWidth != 0 &&
  1534. pdm->dmPelsHeight != 0 &&
  1535. pdm->dmBitsPerPel != 0 &&
  1536. pdm->dmDisplayFrequency != 0,
  1537. "bInitializeModeFields: old style default mode request");
  1538. }
  1539. while ( cModes-- )
  1540. {
  1541. if ( pVideoTemp->Length != 0 )
  1542. {
  1543. DBG_GDI((7, "bInitializeModeFields: check width = %li height = %li",
  1544. pVideoTemp->VisScreenWidth,
  1545. pVideoTemp->VisScreenHeight));
  1546. DBG_GDI((7, " bpp = %li freq = %li",
  1547. pVideoTemp->BitsPerPlane * pVideoTemp->NumberOfPlanes,
  1548. pVideoTemp->Frequency));
  1549. //
  1550. // Handle old style default mode case only on NT4.0
  1551. //
  1552. if(g_bOnNT40 && bSelectDefault)
  1553. {
  1554. pVideoModeSelected = pVideoTemp;
  1555. DBG_GDI((7, "bInitializeModeFields: found a mode match(default)"));
  1556. break;
  1557. }
  1558. if ( (pVideoTemp->VisScreenWidth == pdm->dmPelsWidth)
  1559. && (pVideoTemp->VisScreenHeight == pdm->dmPelsHeight)
  1560. && (pVideoTemp->BitsPerPlane * pVideoTemp->NumberOfPlanes
  1561. == pdm->dmBitsPerPel)
  1562. && (pVideoTemp->Frequency == pdm->dmDisplayFrequency) )
  1563. {
  1564. pVideoModeSelected = pVideoTemp;
  1565. DBG_GDI((7, "bInitializeModeFields: found a mode match!"));
  1566. break;
  1567. }
  1568. }// if the video mode info structure buffer is not empty
  1569. //
  1570. // Move on to next video mode structure
  1571. //
  1572. pVideoTemp = (PVIDEO_MODE_INFORMATION)(((PUCHAR)pVideoTemp)
  1573. + cbModeSize);
  1574. }// while ( cModes-- )
  1575. //
  1576. // If no mode has been found, return an error
  1577. //
  1578. if ( pVideoModeSelected == NULL )
  1579. {
  1580. DBG_GDI((0, "bInitializeModeFields: couldn't find a mode match!"));
  1581. ENGFREEMEM(pVideoBuffer);
  1582. goto errExit;
  1583. }
  1584. //
  1585. // We have chosen the one we want. Save it in a stack buffer and
  1586. // get rid of allocated memory before we forget to free it.
  1587. //
  1588. vmi = *pVideoModeSelected;
  1589. ENGFREEMEM(pVideoBuffer);
  1590. //
  1591. // Set up screen information from the mini-port:
  1592. //
  1593. ppdev->ulMode = vmi.ModeIndex;
  1594. ppdev->cxScreen = vmi.VisScreenWidth;
  1595. ppdev->cyScreen = vmi.VisScreenHeight;
  1596. ppdev->cBitsPerPel = vmi.BitsPerPlane;
  1597. DBG_GDI((7, "bInitializeModeFields: screenStride = %li", vmi.ScreenStride));
  1598. ppdev->flHooks = HOOK_SYNCHRONIZE
  1599. | HOOK_FILLPATH
  1600. | HOOK_STROKEPATH
  1601. | HOOK_LINETO
  1602. | HOOK_TEXTOUT
  1603. | HOOK_BITBLT
  1604. | HOOK_COPYBITS;
  1605. if(!g_bOnNT40)
  1606. ppdev->flHooks |= HOOK_TRANSPARENTBLT |
  1607. HOOK_ALPHABLEND |
  1608. HOOK_STRETCHBLT |
  1609. HOOK_GRADIENTFILL;
  1610. //
  1611. // Fill in the GDIINFO data structure with the default 8bpp values:
  1612. //
  1613. *pgdi = ggdiDefault;
  1614. //
  1615. // Now overwrite the defaults with the relevant information returned
  1616. // from the kernel driver:
  1617. //
  1618. pgdi->ulHorzSize = vmi.XMillimeter;
  1619. pgdi->ulVertSize = vmi.YMillimeter;
  1620. pgdi->ulHorzRes = vmi.VisScreenWidth;
  1621. pgdi->ulVertRes = vmi.VisScreenHeight;
  1622. pgdi->ulPanningHorzRes = vmi.VisScreenWidth;
  1623. pgdi->ulPanningVertRes = vmi.VisScreenHeight;
  1624. pgdi->cBitsPixel = vmi.BitsPerPlane;
  1625. pgdi->cPlanes = vmi.NumberOfPlanes;
  1626. pgdi->ulVRefresh = vmi.Frequency;
  1627. pgdi->ulDACRed = vmi.NumberRedBits;
  1628. pgdi->ulDACGreen = vmi.NumberGreenBits;
  1629. pgdi->ulDACBlue = vmi.NumberBlueBits;
  1630. pgdi->ulLogPixelsX = pdm->dmLogPixels;
  1631. pgdi->ulLogPixelsY = pdm->dmLogPixels;
  1632. //
  1633. // Fill in the devinfo structure with the default 8bpp values:
  1634. //
  1635. *pdi = gdevinfoDefault;
  1636. //
  1637. // Bytes per pel 4/2/1 for 32/16/8 bpp
  1638. //
  1639. ppdev->cjPelSize = vmi.BitsPerPlane >> 3;
  1640. //
  1641. // Bytes per pel log 2
  1642. //
  1643. ppdev->cPelSize = ulLog2(ppdev->cjPelSize);
  1644. //
  1645. // = 2,1,0 for 32,16,8 depth. Shifts needed to calculate bytes/pixel
  1646. //
  1647. ppdev->bPixShift = (BYTE) ppdev->cPelSize;
  1648. //
  1649. // = 0,1,2 for 32/16/8.
  1650. //
  1651. ppdev->bBppShift = 2 - ppdev->bPixShift;
  1652. //
  1653. // = 3,1,0 for 8,16,32 bpp
  1654. //
  1655. ppdev->dwBppMask = 3 >> ppdev->bPixShift;
  1656. switch ( vmi.BitsPerPlane )
  1657. {
  1658. case 8:
  1659. ppdev->iBitmapFormat = BMF_8BPP;
  1660. ASSERTDD(vmi.AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN,
  1661. "bInitializeModeFields: unexpected non-palette 8bpp mode");
  1662. ppdev->ulWhite = 0xff;
  1663. ppdev->ulPermFormat = PERMEDIA_8BIT_PALETTEINDEX;
  1664. ppdev->ulPermFormatEx = PERMEDIA_8BIT_PALETTEINDEX_EXTENSION;
  1665. if(g_bOnNT40)
  1666. pdi->flGraphicsCaps &= ~GCAPS_COLOR_DITHER;
  1667. // No AntiAliased text support in 8bpp mode.
  1668. pdi->flGraphicsCaps &= ~GCAPS_GRAY16;
  1669. break;
  1670. case 16:
  1671. ppdev->iBitmapFormat = BMF_16BPP;
  1672. ppdev->flRed = vmi.RedMask;
  1673. ppdev->flGreen = vmi.GreenMask;
  1674. ppdev->flBlue = vmi.BlueMask;
  1675. pgdi->ulNumColors = (ULONG)-1;
  1676. pgdi->ulNumPalReg = 0;
  1677. pgdi->ulHTOutputFormat = HT_FORMAT_16BPP;
  1678. pdi->iDitherFormat = BMF_16BPP;
  1679. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1680. // support gamma ramp changes
  1681. pdi->flGraphicsCaps2 |= GCAPS2_CHANGEGAMMARAMP;
  1682. ppdev->ulWhite = vmi.RedMask
  1683. | vmi.GreenMask
  1684. | vmi.BlueMask;
  1685. ppdev->ulPermFormat = PERMEDIA_565_RGB;
  1686. ppdev->ulPermFormatEx = PERMEDIA_565_RGB_EXTENSION;
  1687. break;
  1688. case 32:
  1689. ppdev->iBitmapFormat = BMF_32BPP;
  1690. ppdev->flRed = vmi.RedMask;
  1691. ppdev->flGreen = vmi.GreenMask;
  1692. ppdev->flBlue = vmi.BlueMask;
  1693. pgdi->ulNumColors = (ULONG)-1;
  1694. pgdi->ulNumPalReg = 0;
  1695. pgdi->ulHTOutputFormat = HT_FORMAT_32BPP;
  1696. pdi->iDitherFormat = BMF_32BPP;
  1697. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1698. //
  1699. // Support gamma ramp changes
  1700. //
  1701. pdi->flGraphicsCaps2 |= GCAPS2_CHANGEGAMMARAMP;
  1702. ppdev->ulWhite = vmi.RedMask
  1703. | vmi.GreenMask
  1704. | vmi.BlueMask;
  1705. ppdev->ulPermFormat = PERMEDIA_888_RGB;
  1706. ppdev->ulPermFormatEx = PERMEDIA_888_RGB_EXTENSION;
  1707. break;
  1708. default:
  1709. ASSERTDD(0, "bInitializeModeFields: bit depth not supported");
  1710. goto errExit;
  1711. }// switch on clor depth
  1712. return(TRUE);
  1713. errExit:
  1714. DBG_GDI((0, "bInitializeModeFields: failed"));
  1715. return(FALSE);
  1716. }// bInitializeModeFields()
  1717. //-----------------------------------------------------------------------------
  1718. //
  1719. // DWORD getAvailableModes
  1720. //
  1721. // Calls the miniport to get the list of modes supported by the kernel driver.
  1722. // Prunes the list to only those modes supported by this driver.
  1723. //
  1724. // Returns the number of entries supported and returned in the
  1725. // modeInformation array. If the return value is non-zero, then
  1726. // modeInformation was set to point to a valid mode information array. It is
  1727. // the responsibility of the caller to free this array when it is no longer
  1728. // needed.
  1729. //
  1730. //-----------------------------------------------------------------------------
  1731. DWORD
  1732. getAvailableModes(HANDLE hDriver,
  1733. PVIDEO_MODE_INFORMATION* modeInformation,
  1734. DWORD* cbModeSize)
  1735. {
  1736. ULONG ulTemp;
  1737. VIDEO_NUM_MODES modes;
  1738. PVIDEO_MODE_INFORMATION pVideoTemp;
  1739. //
  1740. // Get the number of modes supported by the mini-port
  1741. //
  1742. if ( EngDeviceIoControl(hDriver,
  1743. IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES,
  1744. NULL,
  1745. 0,
  1746. &modes,
  1747. sizeof(VIDEO_NUM_MODES),
  1748. &ulTemp) )
  1749. {
  1750. DBG_GDI((0, "getAvailableModes: failed VIDEO_QUERY_NUM_AVAIL_MODES"));
  1751. return(0);
  1752. }
  1753. *cbModeSize = modes.ModeInformationLength;
  1754. //
  1755. // Allocate the buffer for the mini-port to write the modes in.
  1756. //
  1757. *modeInformation = (VIDEO_MODE_INFORMATION*)ENGALLOCMEM(FL_ZERO_MEMORY,
  1758. modes.NumModes * modes.ModeInformationLength,
  1759. ALLOC_TAG);
  1760. if ( *modeInformation == (PVIDEO_MODE_INFORMATION)NULL )
  1761. {
  1762. DBG_GDI((0, "getAvailableModes: fFailed memory allocation"));
  1763. return 0;
  1764. }
  1765. //
  1766. // Ask the mini-port to fill in the available modes.
  1767. //
  1768. if ( EngDeviceIoControl(hDriver,
  1769. IOCTL_VIDEO_QUERY_AVAIL_MODES,
  1770. NULL,
  1771. 0,
  1772. *modeInformation,
  1773. modes.NumModes * modes.ModeInformationLength,
  1774. &ulTemp) )
  1775. {
  1776. DBG_GDI((0, "getAvailableModes: failed VIDEO_QUERY_AVAIL_MODES"));
  1777. ENGFREEMEM(*modeInformation);
  1778. *modeInformation = (PVIDEO_MODE_INFORMATION)NULL;
  1779. return (0);
  1780. }
  1781. //
  1782. // Now see which of these modes are supported by the display driver.
  1783. // A non-supported mode is invalidated by setting the length to 0.
  1784. //
  1785. ulTemp = modes.NumModes;
  1786. pVideoTemp = *modeInformation;
  1787. //
  1788. // Mode is rejected if it is not one plane, or not graphics, or is not
  1789. // one of 8, 16 or 32 bits per pel.
  1790. //
  1791. while ( ulTemp-- )
  1792. {
  1793. if ( (pVideoTemp->NumberOfPlanes != 1 )
  1794. ||!(pVideoTemp->AttributeFlags & VIDEO_MODE_GRAPHICS)
  1795. ||( (pVideoTemp->BitsPerPlane != 8)
  1796. &&(pVideoTemp->BitsPerPlane != 16)
  1797. &&(pVideoTemp->BitsPerPlane != 32))
  1798. || (pVideoTemp->VisScreenWidth > 2000)
  1799. || (pVideoTemp->VisScreenHeight > 2000) )
  1800. {
  1801. DBG_GDI((2, "getAvailableModes: rejecting miniport mode"));
  1802. DBG_GDI((2, " width = %li height = %li",
  1803. pVideoTemp->VisScreenWidth,
  1804. pVideoTemp->VisScreenHeight));
  1805. DBG_GDI((2, " bpp = %li freq = %li",
  1806. pVideoTemp->BitsPerPlane * pVideoTemp->NumberOfPlanes,
  1807. pVideoTemp->Frequency));
  1808. pVideoTemp->Length = 0;
  1809. }
  1810. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  1811. (((PUCHAR)pVideoTemp) + modes.ModeInformationLength);
  1812. }
  1813. return (modes.NumModes);
  1814. }// getAvailableModes()
  1815. //-----------------------------Public*Routine----------------------------------
  1816. //
  1817. // BOOL DrvNotify
  1818. //
  1819. //-----------------------------------------------------------------------------
  1820. VOID
  1821. DrvNotify(SURFOBJ* pso,
  1822. ULONG iType,
  1823. PVOID pvData)
  1824. {
  1825. PPDev ppdev = (PPDev) pso->dhpdev;
  1826. switch( iType )
  1827. {
  1828. case DN_DEVICE_ORIGIN:
  1829. {
  1830. ppdev->ptlOrigin = *((POINTL*) pvData);
  1831. DBG_GDI((6,"DrvNotify: origin at %ld, %ld",
  1832. ppdev->ptlOrigin.x, ppdev->ptlOrigin.y));
  1833. }
  1834. break;
  1835. case DN_DRAWING_BEGIN:
  1836. {
  1837. bEnablePointer(ppdev);
  1838. bEnableBrushCache(ppdev);
  1839. }
  1840. break;
  1841. default:
  1842. // do nothing
  1843. break;
  1844. }
  1845. }// DrvNotify()
  1846. //-----------------------------Public*Routine----------------------------------
  1847. //
  1848. // ULONG DrvResetDevice
  1849. //
  1850. // This function is used by GDI to request that the specified device be
  1851. // reset to an operational state. Safe steps should be taken to keep
  1852. // data loss at a minimum. It may be called anytime between DrvEnablePDEV
  1853. // and DrvDisablePDEV.
  1854. //
  1855. // Parameters
  1856. // dhpdev------Identifies a handle to a PDEV. This value is the return value
  1857. // of DrvEnablePDEV. The PDEV describes the physical device for
  1858. // which a reset is requested.
  1859. //
  1860. // Upon successful reset of the device DRD_SUCCESS should be returned.
  1861. // Otherwise return DRD_ERROR.
  1862. //
  1863. //-----------------------------------------------------------------------------
  1864. ULONG
  1865. DrvResetDevice(
  1866. DHPDEV dhpdev,
  1867. PVOID Reserved
  1868. )
  1869. {
  1870. DBG_GDI((0, "DrvResetDevice called."));
  1871. // TODO: Place code to reset device here.
  1872. return DRD_ERROR;
  1873. }// DrvResetDevice()