Source code of Windows XP (NT5)
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.

2002 lines
68 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: enable.c
  3. *
  4. * This module contains the functions that enable and disable the
  5. * driver, the pdev, and the surface.
  6. *
  7. * Copyright (c) 1992-1996 Microsoft Corporation
  8. * Copyright (c) 1993-1996 Matrox Electronic Systems, Ltd.
  9. \**************************************************************************/
  10. #include "precomp.h"
  11. #define DBG_MCD 0
  12. /******************************Public*Structure****************************\
  13. * GDIINFO ggdiDefault
  14. *
  15. * This contains the default GDIINFO fields that are passed back to GDI
  16. * during DrvEnablePDEV.
  17. *
  18. * NOTE: This structure defaults to values for an 8bpp palette device.
  19. * Some fields are overwritten for different colour depths.
  20. \**************************************************************************/
  21. GDIINFO ggdiDefault = {
  22. GDI_DRIVER_VERSION,
  23. DT_RASDISPLAY, // ulTechnology
  24. 0, // ulHorzSize (filled in later)
  25. 0, // ulVertSize (filled in later)
  26. 0, // ulHorzRes (filled in later)
  27. 0, // ulVertRes (filled in later)
  28. 0, // cBitsPixel (filled in later)
  29. 0, // cPlanes (filled in later)
  30. 20, // ulNumColors (palette managed)
  31. 0, // flRaster (DDI reserved field)
  32. 0, // ulLogPixelsX (filled in later)
  33. 0, // ulLogPixelsY (filled in later)
  34. TC_RA_ABLE, // flTextCaps -- If we had wanted console windows
  35. // to scroll by repainting the entire window,
  36. // instead of doing a screen-to-screen blt, we
  37. // would have set TC_SCROLLBLT (yes, the flag is
  38. // bass-ackwards).
  39. 0, // ulDACRed (filled in later)
  40. 0, // ulDACGreen (filled in later)
  41. 0, // ulDACBlue (filled in later)
  42. 0x0024, // ulAspectX
  43. 0x0024, // ulAspectY
  44. 0x0033, // ulAspectXY (one-to-one aspect ratio)
  45. 1, // xStyleStep
  46. 1, // yStyleSte;
  47. 3, // denStyleStep -- Styles have a one-to-one aspect
  48. // ratio, and every 'dot' is 3 pixels long
  49. { 0, 0 }, // ptlPhysOffset
  50. { 0, 0 }, // szlPhysSize
  51. 256, // ulNumPalReg
  52. // These fields are for halftone initialization. The actual values are
  53. // a bit magic, but seem to work well on our display.
  54. { // ciDevice
  55. { 6700, 3300, 0 }, // Red
  56. { 2100, 7100, 0 }, // Green
  57. { 1400, 800, 0 }, // Blue
  58. { 1750, 3950, 0 }, // Cyan
  59. { 4050, 2050, 0 }, // Magenta
  60. { 4400, 5200, 0 }, // Yellow
  61. { 3127, 3290, 0 }, // AlignmentWhite
  62. 20000, // RedGamma
  63. 20000, // GreenGamma
  64. 20000, // BlueGamma
  65. 0, 0, 0, 0, 0, 0 // No dye correction for raster displays
  66. },
  67. 0, // ulDevicePelsDPI (for printers only)
  68. PRIMARY_ORDER_CBA, // ulPrimaryOrder
  69. HT_PATSIZE_4x4_M, // ulHTPatternSize
  70. HT_FORMAT_8BPP, // ulHTOutputFormat
  71. HT_FLAG_ADDITIVE_PRIMS, // flHTFlags
  72. 0, // ulVRefresh
  73. 0, // ulBltAlignment
  74. 0, // ulPanningHorzRes
  75. 0, // ulPanningVertRes
  76. };
  77. /******************************Public*Structure****************************\
  78. * DEVINFO gdevinfoDefault
  79. *
  80. * This contains the default DEVINFO fields that are passed back to GDI
  81. * during DrvEnablePDEV.
  82. *
  83. * NOTE: This structure defaults to values for an 8bpp palette device.
  84. * Some fields are overwritten for different colour depths.
  85. \**************************************************************************/
  86. #define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\
  87. CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\
  88. VARIABLE_PITCH | FF_DONTCARE,L"System"}
  89. #define HELVE_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\
  90. CLIP_STROKE_PRECIS,PROOF_QUALITY,\
  91. VARIABLE_PITCH | FF_DONTCARE,L"MS Sans Serif"}
  92. #define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\
  93. CLIP_STROKE_PRECIS,PROOF_QUALITY,\
  94. FIXED_PITCH | FF_DONTCARE, L"Courier"}
  95. DEVINFO gdevinfoDefault = {
  96. (GCAPS_OPAQUERECT |
  97. GCAPS_DITHERONREALIZE |
  98. GCAPS_PALMANAGED |
  99. GCAPS_ALTERNATEFILL |
  100. GCAPS_WINDINGFILL |
  101. GCAPS_MONO_DITHER |
  102. GCAPS_COLOR_DITHER |
  103. GCAPS_DIRECTDRAW |
  104. GCAPS_ASYNCMOVE), // NOTE: Only enable ASYNCMOVE if your code
  105. // and hardware can handle DrvMovePointer
  106. // calls at any time, even while another
  107. // thread is in the middle of a drawing
  108. // call such as DrvBitBlt.
  109. // flGraphicsCaps
  110. SYSTM_LOGFONT, // lfDefaultFont
  111. HELVE_LOGFONT, // lfAnsiVarFont
  112. COURI_LOGFONT, // lfAnsiFixFont
  113. 0, // cFonts
  114. BMF_8BPP, // iDitherFormat
  115. 8, // cxDither
  116. 8, // cyDither
  117. 0, // hpalDefault (filled in later)
  118. GCAPS2_CHANGEGAMMARAMP // flGraphicsCaps2
  119. };
  120. /******************************Public*Structure****************************\
  121. * DFVFN gadrvfn[]
  122. *
  123. * Build the driver function table gadrvfn with function index/address
  124. * pairs. This table tells GDI which DDI calls we support, and their
  125. * location (GDI does an indirect call through this table to call us).
  126. *
  127. * Why haven't we implemented DrvSaveScreenBits? To save code.
  128. *
  129. * When the driver doesn't hook DrvSaveScreenBits, USER simulates on-
  130. * the-fly by creating a temporary device-format-bitmap, and explicitly
  131. * calling DrvCopyBits to save/restore the bits. Since we already hook
  132. * DrvCreateDeviceBitmap, we'll end up using off-screen memory to store
  133. * the bits anyway (which would have been the main reason for implementing
  134. * DrvSaveScreenBits). So we may as well save some working set.
  135. \**************************************************************************/
  136. #if MULTI_BOARDS
  137. // Multi-board support has its own thunks...
  138. DRVFN gadrvfn[] = {
  139. { INDEX_DrvEnablePDEV, (PFN) MulEnablePDEV },
  140. { INDEX_DrvCompletePDEV, (PFN) MulCompletePDEV },
  141. { INDEX_DrvDisablePDEV, (PFN) MulDisablePDEV },
  142. { INDEX_DrvEnableSurface, (PFN) MulEnableSurface },
  143. { INDEX_DrvDisableSurface, (PFN) MulDisableSurface },
  144. { INDEX_DrvAssertMode, (PFN) MulAssertMode },
  145. { INDEX_DrvSynchronize, (PFN) DrvSynchronize },
  146. { INDEX_DrvMovePointer, (PFN) MulMovePointer },
  147. { INDEX_DrvSetPointerShape, (PFN) MulSetPointerShape },
  148. { INDEX_DrvDitherColor, (PFN) MulDitherColor },
  149. { INDEX_DrvSetPalette, (PFN) MulSetPalette },
  150. { INDEX_DrvCopyBits, (PFN) MulCopyBits },
  151. { INDEX_DrvBitBlt, (PFN) MulBitBlt },
  152. { INDEX_DrvTextOut, (PFN) MulTextOut },
  153. { INDEX_DrvGetModes, (PFN) MulGetModes },
  154. { INDEX_DrvStrokePath, (PFN) MulStrokePath },
  155. { INDEX_DrvFillPath, (PFN) MulFillPath },
  156. { INDEX_DrvPaint, (PFN) MulPaint },
  157. { INDEX_DrvRealizeBrush, (PFN) MulRealizeBrush },
  158. { INDEX_DrvDestroyFont, (PFN) MulDestroyFont },
  159. // Note that DrvStretchBlt is not supported for multi-boards
  160. // Note that DrvCreateDeviceBitmap is not supported for multi-boards
  161. // Note that DrvDeleteDeviceBitmap is not supported for multi-boards
  162. // Note that DrvEscape is not supported for multi-boards
  163. // Note that DrvLineTo is not supported for multi-boards
  164. // Note that DrvDirectDraw functions are not supported for multi-boards
  165. };
  166. #elif DBG
  167. // On Checked builds, or when we have to synchronize access, thunk
  168. // everything through Dbg calls...
  169. DRVFN gadrvfn[] = {
  170. { INDEX_DrvEnablePDEV, (PFN) DbgEnablePDEV },
  171. { INDEX_DrvCompletePDEV, (PFN) DbgCompletePDEV },
  172. { INDEX_DrvDisablePDEV, (PFN) DbgDisablePDEV },
  173. { INDEX_DrvEnableSurface, (PFN) DbgEnableSurface },
  174. { INDEX_DrvDisableSurface, (PFN) DbgDisableSurface },
  175. { INDEX_DrvAssertMode, (PFN) DbgAssertMode },
  176. { INDEX_DrvSynchronize, (PFN) DrvSynchronize },
  177. { INDEX_DrvOffset, (PFN) DbgOffset },
  178. { INDEX_DrvMovePointer, (PFN) DbgMovePointer },
  179. { INDEX_DrvSetPointerShape, (PFN) DbgSetPointerShape },
  180. { INDEX_DrvDitherColor, (PFN) DbgDitherColor },
  181. { INDEX_DrvSetPalette, (PFN) DbgSetPalette },
  182. { INDEX_DrvCopyBits, (PFN) DbgCopyBits },
  183. { INDEX_DrvBitBlt, (PFN) DbgBitBlt },
  184. { INDEX_DrvTextOut, (PFN) DbgTextOut },
  185. { INDEX_DrvGetModes, (PFN) DbgGetModes },
  186. { INDEX_DrvStrokePath, (PFN) DbgStrokePath },
  187. { INDEX_DrvLineTo, (PFN) DbgLineTo },
  188. { INDEX_DrvFillPath, (PFN) DbgFillPath },
  189. { INDEX_DrvPaint, (PFN) DbgPaint },
  190. { INDEX_DrvRealizeBrush, (PFN) DbgRealizeBrush },
  191. { INDEX_DrvCreateDeviceBitmap, (PFN) DbgCreateDeviceBitmap },
  192. { INDEX_DrvDeleteDeviceBitmap, (PFN) DbgDeleteDeviceBitmap },
  193. { INDEX_DrvDestroyFont, (PFN) DbgDestroyFont },
  194. { INDEX_DrvStretchBlt, (PFN) DbgStretchBlt },
  195. { INDEX_DrvGetDirectDrawInfo, (PFN) DbgGetDirectDrawInfo },
  196. { INDEX_DrvEnableDirectDraw, (PFN) DbgEnableDirectDraw },
  197. { INDEX_DrvDisableDirectDraw, (PFN) DbgDisableDirectDraw },
  198. { INDEX_DrvEscape, (PFN) DbgEscape },
  199. { INDEX_DrvResetPDEV, (PFN) DbgResetPDEV },
  200. { INDEX_DrvIcmSetDeviceGammaRamp, (PFN) DbgIcmSetDeviceGammaRamp },
  201. { INDEX_DrvDeriveSurface, (PFN) DrvDeriveSurface },
  202. };
  203. #else
  204. // On Free builds, directly call the appropriate functions...
  205. DRVFN gadrvfn[] = {
  206. { INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
  207. { INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
  208. { INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
  209. { INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
  210. { INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
  211. { INDEX_DrvAssertMode, (PFN) DrvAssertMode },
  212. { INDEX_DrvSynchronize, (PFN) DrvSynchronize },
  213. { INDEX_DrvOffset, (PFN) DrvOffset },
  214. { INDEX_DrvMovePointer, (PFN) DrvMovePointer },
  215. { INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape },
  216. { INDEX_DrvDitherColor, (PFN) DrvDitherColor },
  217. { INDEX_DrvSetPalette, (PFN) DrvSetPalette },
  218. { INDEX_DrvCopyBits, (PFN) DrvCopyBits },
  219. { INDEX_DrvBitBlt, (PFN) DrvBitBlt },
  220. { INDEX_DrvTextOut, (PFN) DrvTextOut },
  221. { INDEX_DrvGetModes, (PFN) DrvGetModes },
  222. { INDEX_DrvStrokePath, (PFN) DrvStrokePath },
  223. { INDEX_DrvLineTo, (PFN) DrvLineTo },
  224. { INDEX_DrvFillPath, (PFN) DrvFillPath },
  225. { INDEX_DrvPaint, (PFN) DrvPaint },
  226. { INDEX_DrvRealizeBrush, (PFN) DrvRealizeBrush },
  227. { INDEX_DrvCreateDeviceBitmap, (PFN) DrvCreateDeviceBitmap },
  228. { INDEX_DrvDeleteDeviceBitmap, (PFN) DrvDeleteDeviceBitmap },
  229. { INDEX_DrvDestroyFont, (PFN) DrvDestroyFont },
  230. { INDEX_DrvStretchBlt, (PFN) DrvStretchBlt },
  231. { INDEX_DrvGetDirectDrawInfo, (PFN) DrvGetDirectDrawInfo },
  232. { INDEX_DrvEnableDirectDraw, (PFN) DrvEnableDirectDraw },
  233. { INDEX_DrvDisableDirectDraw, (PFN) DrvDisableDirectDraw },
  234. { INDEX_DrvEscape, (PFN) DrvEscape },
  235. { INDEX_DrvResetPDEV, (PFN) DrvResetPDEV },
  236. { INDEX_DrvIcmSetDeviceGammaRamp, (PFN) DrvIcmSetDeviceGammaRamp },
  237. { INDEX_DrvDeriveSurface, (PFN) DrvDeriveSurface },
  238. };
  239. #endif
  240. ULONG gcdrvfn = sizeof(gadrvfn) / sizeof(DRVFN);
  241. /******************************Public*Routine******************************\
  242. * ULONG GetDisplayUniqueness(PDEV *ppdev)
  243. *
  244. * Returns the display uniqueness.
  245. *
  246. \**************************************************************************/
  247. ULONG GetDisplayUniqueness(PDEV *ppdev)
  248. {
  249. return ppdev->iUniqueness;
  250. }
  251. /******************************Public*Routine******************************\
  252. * BOOL DrvResetPDEV
  253. *
  254. * Notifies the driver of a dynamic mode change.
  255. *
  256. \**************************************************************************/
  257. BOOL DrvResetPDEV(
  258. DHPDEV dhpdevOld,
  259. DHPDEV dhpdevNew)
  260. {
  261. PDEV* ppdevNew = (PDEV*) dhpdevNew;
  262. PDEV* ppdevOld = (PDEV*) dhpdevOld;
  263. ppdevNew->iUniqueness = ppdevOld->iUniqueness + 1;
  264. return(TRUE);
  265. }
  266. /******************************Public*Routine******************************\
  267. * BOOL DrvEnableDriver
  268. *
  269. * Enables the driver by retrieving the drivers function table and version.
  270. *
  271. \**************************************************************************/
  272. BOOL DrvEnableDriver(
  273. ULONG iEngineVersion,
  274. ULONG cj,
  275. DRVENABLEDATA* pded)
  276. {
  277. // Engine Version is passed down so future drivers can support previous
  278. // engine versions. A next generation driver can support both the old
  279. // and new engine conventions if told what version of engine it is
  280. // working with. For the first version the driver does nothing with it.
  281. // Fill in as much as we can.
  282. if (cj >= sizeof(DRVENABLEDATA))
  283. pded->pdrvfn = gadrvfn;
  284. if (cj >= (sizeof(ULONG) * 2))
  285. pded->c = gcdrvfn;
  286. // DDI version this driver was targeted for is passed back to engine.
  287. // Future graphic's engine may break calls down to old driver format.
  288. if (cj >= sizeof(ULONG))
  289. pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
  290. return(TRUE);
  291. }
  292. /******************************Public*Routine******************************\
  293. * VOID DrvDisableDriver
  294. *
  295. * Tells the driver it is being disabled. Release any resources allocated in
  296. * DrvEnableDriver.
  297. *
  298. \**************************************************************************/
  299. VOID DrvDisableDriver(VOID)
  300. {
  301. return;
  302. }
  303. /******************************Public*Routine******************************\
  304. * DHPDEV DrvEnablePDEV
  305. *
  306. * Initializes a bunch of fields for GDI, based on the mode we've been asked
  307. * to do. This is the first thing called after DrvEnableDriver, when GDI
  308. * wants to get some information about us.
  309. *
  310. * (This function mostly returns back information; DrvEnableSurface is used
  311. * for initializing the hardware and driver components.)
  312. *
  313. \**************************************************************************/
  314. DHPDEV DrvEnablePDEV(
  315. DEVMODEW* pdm, // Contains data pertaining to requested mode
  316. PWSTR pwszLogAddr, // Logical address
  317. ULONG cPat, // Count of standard patterns
  318. HSURF* phsurfPatterns, // Buffer for standard patterns
  319. ULONG cjCaps, // Size of buffer for device caps 'pdevcaps'
  320. ULONG* pdevcaps, // Buffer for device caps, also known as 'gdiinfo'
  321. ULONG cjDevInfo, // Number of bytes in device info 'pdi'
  322. DEVINFO* pdi, // Device information
  323. HDEV hdev, // HDEV, used for callbacks
  324. PWSTR pwszDeviceName, // Device name
  325. HANDLE hDriver) // Kernel driver handle
  326. {
  327. PDEV* ppdev;
  328. DISPDBG((1, "DrvEnablePDEV - Entry"));
  329. // Future versions of NT had better supply 'devcaps' and 'devinfo'
  330. // structures that are the same size or larger than the current
  331. // structures:
  332. if ((cjCaps < sizeof(GDIINFO)) || (cjDevInfo < sizeof(DEVINFO)))
  333. {
  334. DISPDBG((0, "DrvEnablePDEV - Buffer size too small"));
  335. goto ReturnFailure0;
  336. }
  337. // Allocate a physical device structure. Note that we definitely
  338. // rely on the zero initialization:
  339. ppdev = (PDEV*) EngAllocMem(FL_ZERO_MEMORY, sizeof(PDEV), ALLOC_TAG);
  340. if (ppdev == NULL)
  341. {
  342. DISPDBG((0, "DrvEnablePDEV - Failed EngAllocMem"));
  343. goto ReturnFailure0;
  344. }
  345. ppdev->hDriver = hDriver;
  346. // Get the current screen mode information. Set up device caps and
  347. // devinfo:
  348. if (!bInitializeModeFields(ppdev, (GDIINFO*) pdevcaps, pdi, pdm))
  349. {
  350. DISPDBG((0, "DrvEnablePDEV - Failed bInitializeModeFields"));
  351. goto ReturnFailure1;
  352. }
  353. // Initialize palette information.
  354. if (!bInitializePalette(ppdev, pdi))
  355. {
  356. DISPDBG((0, "DrvEnablePDEV - Failed bInitializePalette"));
  357. goto ReturnFailure1;
  358. }
  359. return((DHPDEV) ppdev);
  360. ReturnFailure1:
  361. DrvDisablePDEV((DHPDEV) ppdev);
  362. ReturnFailure0:
  363. DISPDBG((0, "Failed DrvEnablePDEV"));
  364. return(0);
  365. }
  366. /******************************Public*Routine******************************\
  367. * VOID DrvDisablePDEV
  368. *
  369. * Release the resources allocated in DrvEnablePDEV. If a surface has been
  370. * enabled DrvDisableSurface will have already been called.
  371. *
  372. * Note that this function will be called when previewing modes in the
  373. * Display Applet, but not at system shutdown. If you need to reset the
  374. * hardware at shutdown, you can do it in the miniport by providing a
  375. * 'HwResetHw' entry point in the VIDEO_HW_INITIALIZATION_DATA structure.
  376. *
  377. * Note: In an error, we may call this before DrvEnablePDEV is done.
  378. *
  379. \**************************************************************************/
  380. VOID DrvDisablePDEV(
  381. DHPDEV dhpdev)
  382. {
  383. PDEV* ppdev;
  384. ppdev = (PDEV*) dhpdev;
  385. vUninitializePalette(ppdev);
  386. EngFreeMem(ppdev);
  387. }
  388. /******************************Public*Routine******************************\
  389. * VOID DrvCompletePDEV
  390. *
  391. * Store the HPDEV, the engines handle for this PDEV, in the DHPDEV.
  392. *
  393. \**************************************************************************/
  394. VOID DrvCompletePDEV(
  395. DHPDEV dhpdev,
  396. HDEV hdev)
  397. {
  398. ((PDEV*) dhpdev)->hdevEng = hdev;
  399. }
  400. /******************************Public*Routine******************************\
  401. * HSURF DrvEnableSurface
  402. *
  403. * Creates the drawing surface, initializes the hardware, and initializes
  404. * driver components. This function is called after DrvEnablePDEV, and
  405. * performs the final device initialization.
  406. *
  407. \**************************************************************************/
  408. HSURF DrvEnableSurface(
  409. DHPDEV dhpdev)
  410. {
  411. PDEV* ppdev;
  412. HSURF hsurf;
  413. SIZEL sizl;
  414. DSURF* pdsurf;
  415. VOID* pvTmpBuffer;
  416. SURFOBJ* pso;
  417. ppdev = (PDEV*) dhpdev;
  418. /////////////////////////////////////////////////////////////////////
  419. // First enable all the subcomponents.
  420. //
  421. // Note that the order in which these 'Enable' functions are called
  422. // may be significant in low off-screen memory conditions, because
  423. // the off-screen heap manager may fail some of the later
  424. // allocations...
  425. if (!bEnableHardware(ppdev))
  426. goto ReturnFailure;
  427. if (!bEnableOffscreenHeap(ppdev))
  428. goto ReturnFailure;
  429. if (!bEnablePointer(ppdev))
  430. goto ReturnFailure;
  431. if (!bEnableText(ppdev))
  432. goto ReturnFailure;
  433. if (!bEnableBrushCache(ppdev))
  434. goto ReturnFailure;
  435. if (!bEnablePalette(ppdev))
  436. goto ReturnFailure;
  437. if (!bEnableDirectDraw(ppdev))
  438. goto ReturnFailure;
  439. if (!bEnableMCD(ppdev))
  440. goto ReturnFailure;
  441. /////////////////////////////////////////////////////////////////////
  442. // Now create our private surface structure.
  443. //
  444. // Whenever we get a call to draw directly to the screen, we'll get
  445. // passed a pointer to a SURFOBJ whose 'dhpdev' field will point
  446. // to our PDEV structure, and whose 'dhsurf' field will point to the
  447. // following DSURF structure.
  448. //
  449. // Every device bitmap we create in DrvCreateDeviceBitmap will also
  450. // have its own unique DSURF structure allocated (but will share the
  451. // same PDEV). To make our code more polymorphic for handling drawing
  452. // to either the screen or an off-screen bitmap, we have the same
  453. // structure for both.
  454. pdsurf = EngAllocMem(FL_ZERO_MEMORY, sizeof(DSURF), ALLOC_TAG);
  455. if (pdsurf == NULL)
  456. {
  457. DISPDBG((0, "DrvEnableSurface - Failed pdsurf EngAllocMem"));
  458. goto ReturnFailure;
  459. }
  460. ppdev->pdsurfScreen = pdsurf; // Remember it for clean-up
  461. pdsurf->poh = ppdev->pohScreen; // The screen is a surface, too
  462. pdsurf->dt = DT_SCREEN; // Not to be confused with a DIB
  463. pdsurf->sizl.cx = ppdev->cxScreen;
  464. pdsurf->sizl.cy = ppdev->cyScreen;
  465. pdsurf->ppdev = ppdev;
  466. /////////////////////////////////////////////////////////////////////
  467. // Next, have GDI create the actual SURFOBJ.
  468. //
  469. // Since we can map the entire framebuffer linearly into main memory
  470. // (i.e., we didn't have to go through a 64k aperture), it is
  471. // beneficial to create the surface via EngCreateBitmap, giving GDI a
  472. // pointer to the framebuffer bits.
  473. sizl.cx = ppdev->cxScreen;
  474. sizl.cy = ppdev->cyScreen;
  475. if (ppdev->ulBoardId == MGA_STORM) {
  476. // We should have a linear frame buffer, so create an
  477. // engine managed surface.
  478. hsurf = (HSURF) EngCreateBitmap(sizl,
  479. ppdev->lDelta,
  480. ppdev->iBitmapFormat,
  481. BMF_TOPDOWN,
  482. ppdev->pjScreen +
  483. (ppdev->ulYDstOrg * ppdev->cjPelSize));
  484. if (hsurf == 0)
  485. {
  486. DISPDBG((0, "DrvEnableSurface - Failed EngCreateBitmap"));
  487. goto ReturnFailure;
  488. }
  489. // Set it up so that the when we are passed a SURFOBJ for the
  490. // screen, the 'dhsurf' will point to the screen's surface structure:
  491. // !!! Grody?
  492. pso = EngLockSurface(hsurf);
  493. if (pso == NULL)
  494. {
  495. DISPDBG((0, "DrvEnableSurface - Couldn't lock our surface"));
  496. goto ReturnFailure;
  497. }
  498. pso->dhsurf = (DHSURF) pdsurf;
  499. EngUnlockSurface(pso);
  500. if (!EngAssociateSurface(hsurf, ppdev->hdevEng, ppdev->flHooks))
  501. {
  502. DISPDBG((0, "DrvEnableSurface - Failed EngAssociateSurface"));
  503. goto ReturnFailure;
  504. }
  505. } else {
  506. // Device-managed surface:
  507. hsurf = EngCreateDeviceSurface((DHSURF) pdsurf, sizl, ppdev->iBitmapFormat);
  508. if (hsurf == 0)
  509. {
  510. DISPDBG((0, "DrvEnableSurface - Failed EngCreateDeviceSurface"));
  511. goto ReturnFailure;
  512. }
  513. /////////////////////////////////////////////////////////////////////
  514. // Now associate the surface and the PDEV.
  515. //
  516. // We have to associate the surface we just created with our physical
  517. // device so that GDI can get information related to the PDEV when
  518. // it's drawing to the surface (such as, for example, the length of
  519. // styles on the device when simulating styled lines).
  520. if (!EngAssociateSurface(hsurf, ppdev->hdevEng, ppdev->flHooks))
  521. {
  522. DISPDBG((0, "DrvEnableSurface - Failed EngAssociateSurface"));
  523. goto ReturnFailure;
  524. }
  525. }
  526. ppdev->hsurfScreen = hsurf; // Remember it for clean-up
  527. ppdev->bEnabled = TRUE; // We'll soon be in graphics mode
  528. // Create our generic temporary buffer, which may be used by any
  529. // component.
  530. pvTmpBuffer = EngAllocMem(0, TMP_BUFFER_SIZE, ALLOC_TAG);
  531. if (pvTmpBuffer == NULL)
  532. {
  533. DISPDBG((0, "DrvEnableSurface - Failed EngAllocMem"));
  534. goto ReturnFailure;
  535. }
  536. ppdev->pvTmpBuffer = pvTmpBuffer;
  537. DISPDBG((5, "Passed DrvEnableSurface"));
  538. return(hsurf);
  539. ReturnFailure:
  540. DrvDisableSurface((DHPDEV) ppdev);
  541. DISPDBG((0, "Failed DrvEnableSurface"));
  542. return(0);
  543. }
  544. /******************************Public*Routine******************************\
  545. * VOID DrvDisableSurface
  546. *
  547. * Free resources allocated by DrvEnableSurface. Release the surface.
  548. *
  549. * Note that this function will be called when previewing modes in the
  550. * Display Applet, but not at system shutdown. If you need to reset the
  551. * hardware at shutdown, you can do it in the miniport by providing a
  552. * 'HwResetHw' entry point in the VIDEO_HW_INITIALIZATION_DATA structure.
  553. *
  554. * Note: In an error case, we may call this before DrvEnableSurface is
  555. * completely done.
  556. *
  557. \**************************************************************************/
  558. VOID DrvDisableSurface(
  559. DHPDEV dhpdev)
  560. {
  561. PDEV* ppdev;
  562. ppdev = (PDEV*) dhpdev;
  563. // Note: In an error case, some of the following relies on the
  564. // fact that the PDEV is zero-initialized, so fields like
  565. // 'hsurfScreen' will be zero unless the surface has been
  566. // sucessfully initialized, and makes the assumption that
  567. // EngDeleteSurface can take '0' as a parameter.
  568. vDisableMCD(ppdev);
  569. vDisableDirectDraw(ppdev);
  570. vDisablePalette(ppdev);
  571. vDisableBrushCache(ppdev);
  572. vDisableText(ppdev);
  573. vDisablePointer(ppdev);
  574. vDisableOffscreenHeap(ppdev);
  575. vDisableHardware(ppdev);
  576. EngFreeMem(ppdev->pvTmpBuffer);
  577. EngDeleteSurface(ppdev->hsurfScreen);
  578. EngFreeMem(ppdev->pdsurfScreen);
  579. }
  580. /******************************Public*Routine******************************\
  581. * VOID DrvOffset
  582. *
  583. * DescriptionText
  584. *
  585. \**************************************************************************/
  586. BOOL DrvOffset(
  587. SURFOBJ* pso,
  588. LONG x,
  589. LONG y,
  590. FLONG flReserved)
  591. {
  592. PDEV* ppdev = (PDEV*) pso->dhpdev;
  593. OH* poh = ppdev->pohScreen;
  594. LONG dx = x - poh->x;
  595. LONG dy = y - poh->y;
  596. poh->x -= dx;
  597. poh->y -= dy;
  598. (BYTE*)poh->pvScan0 -= ((dy * ppdev->lDelta) +
  599. (dx * ppdev->cjPelSize));
  600. return(TRUE);
  601. }
  602. /******************************Public*Routine******************************\
  603. * VOID DrvAssertMode
  604. *
  605. * This asks the device to reset itself to the mode of the pdev passed in.
  606. *
  607. \**************************************************************************/
  608. BOOL DrvAssertMode(
  609. DHPDEV dhpdev,
  610. BOOL bEnable)
  611. {
  612. PDEV* ppdev;
  613. ppdev = (PDEV*) dhpdev;
  614. if (!bEnable)
  615. {
  616. //////////////////////////////////////////////////////////////
  617. // Disable - Switch to full-screen mode
  618. vAssertModeMCD(ppdev, FALSE);
  619. vAssertModeDirectDraw(ppdev, FALSE);
  620. vAssertModePalette(ppdev, FALSE);
  621. vAssertModeBrushCache(ppdev, FALSE);
  622. vAssertModeText(ppdev, FALSE);
  623. vAssertModePointer(ppdev, FALSE);
  624. if (bAssertModeOffscreenHeap(ppdev, FALSE))
  625. {
  626. if (bAssertModeHardware(ppdev, FALSE))
  627. {
  628. ppdev->bEnabled = FALSE;
  629. return(TRUE);
  630. }
  631. //////////////////////////////////////////////////////////
  632. // We failed to switch to full-screen. So undo everything:
  633. bAssertModeOffscreenHeap(ppdev, TRUE); // We don't need to check
  634. } // return code with TRUE
  635. vAssertModePointer(ppdev, TRUE);
  636. vAssertModeText(ppdev, TRUE);
  637. vAssertModeBrushCache(ppdev, TRUE);
  638. vAssertModePalette(ppdev, TRUE);
  639. vAssertModeDirectDraw(ppdev, TRUE);
  640. vAssertModeMCD(ppdev, TRUE);
  641. }
  642. else
  643. {
  644. //////////////////////////////////////////////////////////////
  645. // Enable - Switch back to graphics mode
  646. // We have to enable every subcomponent in the reverse order
  647. // in which it was disabled:
  648. if (bAssertModeHardware(ppdev, TRUE))
  649. {
  650. bAssertModeOffscreenHeap(ppdev, TRUE); // We don't need to check
  651. // return code with TRUE
  652. vAssertModePointer(ppdev, TRUE);
  653. vAssertModeText(ppdev, TRUE);
  654. vAssertModeBrushCache(ppdev, TRUE);
  655. vAssertModePalette(ppdev, TRUE);
  656. vAssertModeDirectDraw(ppdev, TRUE);
  657. vAssertModeMCD(ppdev, TRUE);
  658. ppdev->bEnabled = TRUE;
  659. return(TRUE);
  660. }
  661. }
  662. return(FALSE);
  663. }
  664. /******************************Public*Routine******************************\
  665. * ULONG DrvGetModes
  666. *
  667. * Returns the list of available modes for the device.
  668. *
  669. \**************************************************************************/
  670. ULONG DrvGetModes(
  671. HANDLE hDriver,
  672. ULONG cjSize,
  673. DEVMODEW* pdm)
  674. {
  675. DWORD cModes;
  676. DWORD cbOutputSize;
  677. PVIDEO_MODE_INFORMATION pVideoModeInformation;
  678. PVIDEO_MODE_INFORMATION pVideoTemp;
  679. DWORD cOutputModes = cjSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  680. DWORD cbModeSize;
  681. VIDEO_MODE_INFORMATION DefaultMode;
  682. cModes = getAvailableModes(hDriver,
  683. (PVIDEO_MODE_INFORMATION *) &pVideoModeInformation,
  684. &cbModeSize);
  685. if (cModes == 0)
  686. {
  687. DISPDBG((0, "DrvGetModes failed to get mode information"));
  688. return(0);
  689. }
  690. if (pdm == NULL)
  691. {
  692. cbOutputSize = cModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  693. }
  694. else
  695. {
  696. //
  697. // Now copy the information for the supported modes back into the
  698. // output buffer
  699. //
  700. cbOutputSize = 0;
  701. pVideoTemp = pVideoModeInformation;
  702. do
  703. {
  704. if (pVideoTemp->Length != 0)
  705. {
  706. if (cOutputModes == 0)
  707. {
  708. break;
  709. }
  710. //
  711. // Zero the entire structure to start off with.
  712. //
  713. memset(pdm, 0, sizeof(DEVMODEW));
  714. //
  715. // Set the name of the device to the name of the DLL.
  716. //
  717. memcpy(pdm->dmDeviceName, DLL_NAME, sizeof(DLL_NAME));
  718. pdm->dmSpecVersion = DM_SPECVERSION;
  719. pdm->dmDriverVersion = DM_SPECVERSION;
  720. pdm->dmSize = sizeof(DEVMODEW);
  721. pdm->dmDriverExtra = DRIVER_EXTRA_SIZE;
  722. pdm->dmBitsPerPel = pVideoTemp->NumberOfPlanes *
  723. pVideoTemp->BitsPerPlane;
  724. pdm->dmPelsWidth = pVideoTemp->VisScreenWidth;
  725. pdm->dmPelsHeight = pVideoTemp->VisScreenHeight;
  726. pdm->dmDisplayFrequency = pVideoTemp->Frequency;
  727. pdm->dmDisplayFlags = 0;
  728. pdm->dmFields = DM_BITSPERPEL |
  729. DM_PELSWIDTH |
  730. DM_PELSHEIGHT |
  731. DM_DISPLAYFREQUENCY |
  732. DM_DISPLAYFLAGS ;
  733. //
  734. // Fill in some DriverExtra information if necessary
  735. //
  736. // *((PDWORD)(pdm+1)) = 0x11111111;
  737. // *(((PDWORD)(pdm+1))+1) = 0x22222222;
  738. // *(((PDWORD)(pdm+1))+2) = 0x33333333;
  739. // *(((PDWORD)(pdm+1))+3) = 0x44444444;
  740. //
  741. // Go to the next DEVMODE entry in the buffer.
  742. //
  743. cOutputModes--;
  744. pdm = (LPDEVMODEW) ( ((ULONG_PTR)pdm) + sizeof(DEVMODEW) +
  745. DRIVER_EXTRA_SIZE);
  746. cbOutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  747. }
  748. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  749. (((PUCHAR)pVideoTemp) + cbModeSize);
  750. } while (--cModes);
  751. }
  752. EngFreeMem(pVideoModeInformation);
  753. return(cbOutputSize);
  754. }
  755. /******************************Public*Routine******************************\
  756. * BOOL bSetModeAndWarmupHardware
  757. *
  758. * Sets the requested actual mode and initializes the hardware to a known
  759. * state.
  760. *
  761. \**************************************************************************/
  762. BOOL bSetModeAndWarmupHardware(
  763. PDEV* ppdev)
  764. {
  765. BYTE* pjBase;
  766. DWORD ReturnedDataLength;
  767. ULONG ulReturn;
  768. HW_DATA HwData;
  769. pjBase = ppdev->pjBase;
  770. // Call the miniport via a public IOCTL to set the graphics mode.
  771. if (EngDeviceIoControl(ppdev->hDriver,
  772. IOCTL_VIDEO_SET_CURRENT_MODE,
  773. &ppdev->ulMode, // Input
  774. sizeof(DWORD),
  775. NULL, // Output
  776. 0,
  777. &ReturnedDataLength))
  778. {
  779. DISPDBG((0, "bSetModeAndWarmupHardware - Failed VIDEO_SET_CURRENT_MODE"));
  780. goto ReturnFalse;
  781. }
  782. if (ppdev->ulBoardId == MGA_STORM)
  783. {
  784. // There might be multiple MGA boards installed in the system. Since
  785. // we're here only when a single board is required by the selected
  786. // resolution, we should make sure that the miniport knows that the
  787. // current board is board 0.
  788. LONG lHwBoard;
  789. lHwBoard = 0;
  790. if (EngDeviceIoControl(ppdev->hDriver,
  791. IOCTL_VIDEO_MTX_MAKE_BOARD_CURRENT,
  792. &lHwBoard, // input buffer
  793. sizeof(LONG),
  794. NULL, // output buffer
  795. 0,
  796. &ReturnedDataLength))
  797. {
  798. DISPDBG((0, "bSetModeAndWarmupHardware - Failed MTX_MAKE_BOARD_CURRENT"));
  799. goto ReturnFalse;
  800. }
  801. }
  802. // Get the MGA's linear offset using a private IOCTL:
  803. if (EngDeviceIoControl(ppdev->hDriver,
  804. IOCTL_VIDEO_MTX_QUERY_HW_DATA,
  805. NULL, // Input
  806. 0,
  807. &HwData, // Output
  808. sizeof(HW_DATA),
  809. &ReturnedDataLength))
  810. {
  811. DISPDBG((0, "bSetModeAndWarmupHardware -- failed MTX_QUERY_HW_DATA"));
  812. goto ReturnFalse;
  813. }
  814. ppdev->ulYDstOrg = HwData.YDstOrg;
  815. ppdev->flFeatures = HwData.Features;
  816. if (ppdev->ulBoardId == MGA_STORM)
  817. {
  818. ppdev->cjMemAvail = HwData.MemAvail;
  819. // Floor((4M-(ulYDstOrg*cBpp))/(1600*3)) == scan where 4M break occurs.
  820. // This array would be stored on pdev or at least calculated in a temp
  821. if (ppdev->flFeatures & INTERLEAVE_MODE)
  822. {
  823. DISPDBG((1, "This mode is interleaved"));
  824. ppdev->ayBreak[0] = (0x400000 - ppdev->ulYDstOrg)/(ppdev->lDelta);
  825. if ((HwData.MemAvail == 0x200000)||
  826. (HwData.MemAvail == 0x400000))
  827. {
  828. ppdev->cyBreak = 0;
  829. }
  830. else
  831. {
  832. ASSERTDD (HwData.MemAvail == 0x800000, "HwData.MemAvail is invalid");
  833. ppdev->cyBreak = 1;
  834. }
  835. }
  836. else
  837. {
  838. DISPDBG((1,"This mode is non-interleaved"));
  839. ppdev->ayBreak[0] = (0x200000 - ppdev->ulYDstOrg)/(ppdev->lDelta);
  840. ppdev->ayBreak[1] = (0x400000 - ppdev->ulYDstOrg)/(ppdev->lDelta);
  841. ppdev->ayBreak[2] = (0x600000 - ppdev->ulYDstOrg)/(ppdev->lDelta);
  842. if (HwData.MemAvail == 0x200000)
  843. {
  844. ppdev->cyBreak = 0;
  845. }
  846. else if (HwData.MemAvail == 0x400000)
  847. {
  848. ppdev->cyBreak = 1;
  849. }
  850. else
  851. {
  852. ASSERTDD (HwData.MemAvail == 0x800000, "HwData.MemAvail is invalid");
  853. ppdev->cyBreak = 3;
  854. }
  855. }
  856. DISPDBG((1, "cyBreak = %d", ppdev->cyBreak));
  857. }
  858. else
  859. {
  860. //
  861. // This field is uninitliazed on non-storm boards.
  862. //
  863. ppdev->cjMemAvail = HwData.MemAvail;
  864. }
  865. ppdev->HopeFlags = 0;
  866. CHECK_FIFO_SPACE(pjBase, 5);
  867. CP_WRITE(pjBase, DWG_MACCESS, ppdev->ulAccess);
  868. CP_WRITE(pjBase, DWG_SHIFT, 0);
  869. CP_WRITE(pjBase, DWG_YDSTORG, ppdev->ulYDstOrg);
  870. CP_WRITE(pjBase, DWG_PLNWT, ppdev->ulPlnWt);
  871. CP_WRITE(pjBase, DWG_PITCH, ppdev->cxMemory);
  872. if (ppdev->ulBoardId != MGA_STORM)
  873. {
  874. CP_WRITE_REGISTER(pjBase + HST_OPMODE,
  875. CP_READ_REGISTER(pjBase + HST_OPMODE) | 0x01000000);
  876. }
  877. vResetClipping(ppdev);
  878. // At this point, the RAMDAC should be okay, but it looks
  879. // like it's not quite ready to accept data, particularly
  880. // on VL boards. Adding a delay seems to fix things.
  881. // Sleep(100);
  882. return(TRUE);
  883. ReturnFalse:
  884. return(FALSE);
  885. }
  886. VOID
  887. DrvSynchronize(
  888. IN DHPDEV dhpdev,
  889. IN RECTL *prcl
  890. )
  891. {
  892. PDEV *ppdev = (PDEV *) dhpdev;
  893. //
  894. // We need to do a wait for blt complete before we
  895. // let the engine party on our frame buffer
  896. //
  897. WAIT_NOT_BUSY(ppdev->pjBase)
  898. }
  899. /******************************Public*Routine******************************\
  900. * BOOL bAssertModeHardware
  901. *
  902. * Sets the appropriate hardware state when entering or leaving graphics
  903. * mode or full-screen.
  904. *
  905. \**************************************************************************/
  906. BOOL bAssertModeHardware(
  907. PDEV* ppdev,
  908. BOOL bEnable)
  909. {
  910. ULONG ulNewFileSize;
  911. DWORD ReturnedDataLength;
  912. ULONG ulReturn;
  913. if (bEnable)
  914. {
  915. // The MGA miniport requires that the screen must be reenabled
  916. // and reinitialized to a clean state. This should not be done
  917. // for more than one board when supporting multiple boards:
  918. if (IBOARD(ppdev) == 0)
  919. {
  920. // Re-enable the MGA's screen via a private IOCTL:
  921. if (EngDeviceIoControl(ppdev->hDriver,
  922. IOCTL_VIDEO_MTX_INITIALIZE_MGA,
  923. NULL,
  924. 0,
  925. &ulNewFileSize,
  926. sizeof(ULONG),
  927. &ReturnedDataLength))
  928. {
  929. DISPDBG((0, "bAssertModeHardware - Failed VIDEO_MTX_INITAILIZE_MGA"));
  930. goto ReturnFalse;
  931. }
  932. // The miniport should also build a new mode table, via a
  933. // private IOCTL:
  934. if (EngDeviceIoControl(ppdev->hDriver,
  935. IOCTL_VIDEO_MTX_INIT_MODE_LIST,
  936. NULL,
  937. 0,
  938. NULL,
  939. 0,
  940. &ReturnedDataLength))
  941. {
  942. DISPDBG((0, "bAssertModeHardware - Failed VIDEO_MTX_INIT_MODE_LIST"));
  943. goto ReturnFalse;
  944. }
  945. }
  946. if (!bSetModeAndWarmupHardware(ppdev))
  947. {
  948. DISPDBG((0, "bAssertModeHardware - Failed bSetModeAndWarmupHardware"));
  949. goto ReturnFalse;
  950. }
  951. }
  952. else
  953. {
  954. // Wait for all pending accelerator operations to finish:
  955. CHECK_FIFO_SPACE(ppdev->pjBase, FIFOSIZE);
  956. // Call the kernel driver to reset the device to a known state.
  957. // NTVDM will take things from there. One reset will affect
  958. // all boards:
  959. if (IBOARD(ppdev) == 0)
  960. {
  961. if (EngDeviceIoControl(ppdev->hDriver,
  962. IOCTL_VIDEO_RESET_DEVICE,
  963. NULL,
  964. 0,
  965. NULL,
  966. 0,
  967. &ulReturn))
  968. {
  969. DISPDBG((0, "bAssertModeHardware - Failed reset IOCTL"));
  970. return(FALSE);
  971. }
  972. }
  973. }
  974. DISPDBG((5, "Passed bAssertModeHardware"));
  975. return(TRUE);
  976. ReturnFalse:
  977. DISPDBG((0, "Failed bAssertModeHardware"));
  978. return(FALSE);
  979. }
  980. /******************************Public*Routine******************************\
  981. * BOOL bEnableHardware
  982. *
  983. * Puts the hardware in the requested mode and initializes it.
  984. *
  985. * Note: Should be called before any access is done to the hardware from
  986. * the display driver.
  987. *
  988. \**************************************************************************/
  989. BOOL bEnableHardware(
  990. PDEV* ppdev)
  991. {
  992. VIDEO_PUBLIC_ACCESS_RANGES VideoPublicAccessRanges;
  993. VIDEO_MEMORY VideoMemory;
  994. VIDEO_MEMORY_INFORMATION VideoMemoryInfo;
  995. ULONG ReturnedDataLength;
  996. // Get the coprocessor address range using a public IOCTL:
  997. if (EngDeviceIoControl(ppdev->hDriver,
  998. IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES,
  999. NULL, // Input
  1000. 0,
  1001. (VOID*) &VideoPublicAccessRanges, // Output
  1002. sizeof(VideoPublicAccessRanges),
  1003. &ReturnedDataLength))
  1004. {
  1005. DISPDBG((0, "bEnableHardware -- failed QUERY_PUBLIC_ACESS_RANGES"));
  1006. return(FALSE);
  1007. }
  1008. ppdev->pjBase = (BYTE*) VideoPublicAccessRanges.VirtualAddress;
  1009. if (ppdev->ulBoardId == MGA_STORM)
  1010. {
  1011. // Get an address for our frame buffer.
  1012. VideoMemory.RequestedVirtualAddress = NULL;
  1013. if (EngDeviceIoControl(ppdev->hDriver,
  1014. IOCTL_VIDEO_MAP_VIDEO_MEMORY,
  1015. &VideoMemory, // Input
  1016. sizeof(VIDEO_MEMORY),
  1017. &VideoMemoryInfo, // Output
  1018. sizeof(VideoMemoryInfo),
  1019. &ReturnedDataLength))
  1020. {
  1021. DISPDBG(( 0, "bEnableHardware - Failed VIDEO_MAP_VIDEO_MEMORY"));
  1022. return(FALSE);
  1023. }
  1024. // Record the mapped location of the MGA registers.
  1025. // We can now access the board!
  1026. ppdev->pjScreen = VideoMemoryInfo.FrameBufferBase;
  1027. }
  1028. else
  1029. {
  1030. // This should probably just be done in the IOCTL call
  1031. DISPDBG((2, "Video chip is not an MGA_STORM"));
  1032. ppdev->pjScreen = NULL;
  1033. }
  1034. DISPDBG((1, "bEnableHardware -- pjScreen = %x", ppdev->pjScreen));
  1035. ///////////////////////////////////////////////////////////////////
  1036. // Now we can set the mode, unlock the accelerator, and reset the
  1037. // clipping:
  1038. if (!bSetModeAndWarmupHardware(ppdev))
  1039. goto ReturnFalse;
  1040. DISPDBG((0, "Memory: %lix%li YDstOrg: %li",
  1041. ppdev->cxMemory, ppdev->cyMemory, ppdev->ulYDstOrg));
  1042. DISPDBG((5, "Passed bEnableHardware"));
  1043. return(TRUE);
  1044. ReturnFalse:
  1045. DISPDBG((0, "Failed bEnableHardware"));
  1046. return(FALSE);
  1047. }
  1048. /******************************Public*Routine******************************\
  1049. * VOID vDisableHardware
  1050. *
  1051. * Undoes anything done in bEnableHardware.
  1052. *
  1053. * Note: In an error case, we may call this before bEnableHardware is
  1054. * completely done.
  1055. *
  1056. \**************************************************************************/
  1057. VOID vDisableHardware(
  1058. PDEV* ppdev)
  1059. {
  1060. VIDEO_MEMORY VideoMemory;
  1061. ULONG ReturnedDataLength;
  1062. VideoMemory.RequestedVirtualAddress = ppdev->pjScreen;
  1063. if (EngDeviceIoControl(ppdev->hDriver,
  1064. IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
  1065. &VideoMemory,
  1066. sizeof(VideoMemory),
  1067. NULL,
  1068. 0,
  1069. &ReturnedDataLength))
  1070. {
  1071. DISPDBG((0, "vDisableHardware failed IOCTL_VIDEO_UNMAP_VIDEO"));
  1072. }
  1073. VideoMemory.RequestedVirtualAddress = ppdev->pjBase;
  1074. if (EngDeviceIoControl(ppdev->hDriver,
  1075. IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES,
  1076. &VideoMemory, // Input
  1077. sizeof(VideoMemory),
  1078. NULL, // Output
  1079. 0,
  1080. &ReturnedDataLength))
  1081. {
  1082. DISPDBG((0, "vDisableHardware -- failed FREE_PUBLIC_ACCESS_RANGES"));
  1083. }
  1084. }
  1085. /******************************Public*Routine******************************\
  1086. * BOOL bInitializeOffscreenFields
  1087. *
  1088. \**************************************************************************/
  1089. BOOL bInitializeOffscreenFields(
  1090. PDEV* ppdev,
  1091. VIDEO_MODE_INFORMATION* pVideoModeInformation)
  1092. {
  1093. VIDEO_NUM_OFFSCREEN_BLOCKS NumOffscreenBlocks;
  1094. OFFSCREEN_BLOCK* pOffscreenBlock;
  1095. OFFSCREEN_BLOCK* pBuffer;
  1096. ULONG ReturnedDataLength;
  1097. ULONG cjOffscreenBlock;
  1098. LONG i;
  1099. // Ask the MGA miniport about the number of offscreen areas available
  1100. // for our selected mode, using a private IOCTL:
  1101. if (EngDeviceIoControl(ppdev->hDriver,
  1102. IOCTL_VIDEO_MTX_QUERY_NUM_OFFSCREEN_BLOCKS,
  1103. pVideoModeInformation, // Input
  1104. sizeof(VIDEO_MODE_INFORMATION),
  1105. &NumOffscreenBlocks, // Output
  1106. sizeof(VIDEO_NUM_OFFSCREEN_BLOCKS),
  1107. &ReturnedDataLength))
  1108. {
  1109. DISPDBG((0, "bInitializeOffscreenFields -- failed QUERY_NUM_OFFSCREEN_BLOCKS"));
  1110. goto ReturnFalse;
  1111. }
  1112. cjOffscreenBlock = NumOffscreenBlocks.NumBlocks
  1113. * NumOffscreenBlocks.OffscreenBlockLength;
  1114. pBuffer = pOffscreenBlock = (OFFSCREEN_BLOCK*) EngAllocMem(FL_ZERO_MEMORY,
  1115. cjOffscreenBlock, ALLOC_TAG);
  1116. if (pOffscreenBlock == NULL)
  1117. {
  1118. DISPDBG((0, "bInitializeOffscreenFields -- failed pOffscreenBlock EngAllocMem"));
  1119. goto ReturnFalse;
  1120. }
  1121. // Ask the MGA miniport to fill in the available offscreen areas using
  1122. // a private IOCTL:
  1123. if (EngDeviceIoControl(ppdev->hDriver,
  1124. IOCTL_VIDEO_MTX_QUERY_OFFSCREEN_BLOCKS,
  1125. pVideoModeInformation, // Input
  1126. sizeof(VIDEO_MODE_INFORMATION),
  1127. pOffscreenBlock, // Output
  1128. cjOffscreenBlock,
  1129. &ReturnedDataLength))
  1130. {
  1131. DISPDBG((0, "bInitializeOffscreenFields -- failed QUERY_OFFSCREEN_BLOCKS"));
  1132. EngFreeMem(pOffscreenBlock);
  1133. goto ReturnFalse;
  1134. }
  1135. ppdev->cyMemory = ppdev->cyScreen;
  1136. for (i = NumOffscreenBlocks.NumBlocks; i != 0; i--, pOffscreenBlock++)
  1137. {
  1138. // We are just looking to add the offscreen block that immediately follows
  1139. // the screen block.
  1140. DISPDBG((1, "Offscreen blocks:"));
  1141. DISPDBG((1, " (%li, %li) at (%li, %li) Type: %li Planes: %lx ZOffset: %li",
  1142. pOffscreenBlock->Width, pOffscreenBlock->Height,
  1143. pOffscreenBlock->XStart, pOffscreenBlock->YStart,
  1144. pOffscreenBlock->Type, pOffscreenBlock->SafePlanes,
  1145. pOffscreenBlock->ZOffset));
  1146. // The miniport seems to be giving us garbage for some fields:
  1147. if ((pOffscreenBlock->YStart == (ULONG) ppdev->cyScreen) &&
  1148. (pOffscreenBlock->Width >= (ULONG) ppdev->cxScreen))
  1149. {
  1150. // Found the right one.
  1151. ppdev->cyMemory = ppdev->cyScreen + pOffscreenBlock->Height;
  1152. }
  1153. }
  1154. EngFreeMem(pBuffer);
  1155. // u The MGA miniport should be changed to never reserve space for 'Z'
  1156. // or the back buffer -- we want to do that ourselves. Right now,
  1157. // it does so for the only 3d enabled mode it thinks we can do,
  1158. // namely 5-5-5 on a 4MB Impression Plus:
  1159. if ((ppdev->ulBoardId == MGA_PCI_4M) &&
  1160. (ppdev->flGreen == 0x3e0))
  1161. {
  1162. // The total count of scans is the floor of 4MB divided by the
  1163. // screen stride, less one to account for a possible ulYDstOrg that
  1164. // we don't yet know:
  1165. ppdev->cyMemory = (4096 * 1024) / (ppdev->cxMemory * 2);
  1166. }
  1167. // On an Impression Lite (Atlas) card, we found that we couldn't use
  1168. // the last scan for keeping brush caches. We'll assume this is the
  1169. // same for other operations, as well, and simply decrease the amount of
  1170. // available off-screen by that many scans:
  1171. if (ppdev->cyMemory > ppdev->cyScreen)
  1172. {
  1173. ppdev->cyMemory--;
  1174. }
  1175. return(TRUE);
  1176. ReturnFalse:
  1177. return(FALSE);
  1178. }
  1179. /******************************Public*Routine******************************\
  1180. * BOOL bSelectMode
  1181. *
  1182. * Negotiates the video mode with the miniport.
  1183. *
  1184. \**************************************************************************/
  1185. BOOL bSelectMode(
  1186. HANDLE hDriver,
  1187. DEVMODEW* pdm, // Requested mode
  1188. VIDEO_MODE_INFORMATION* pVideoModeInformation, // Returns requested mode
  1189. ULONG* pulBoardId) // Returns MGA board ID
  1190. {
  1191. ULONG cModes;
  1192. PVIDEO_MODE_INFORMATION pVideoBuffer;
  1193. PVIDEO_MODE_INFORMATION pVideoModeSelected;
  1194. PVIDEO_MODE_INFORMATION pVideoTemp;
  1195. BOOL bSelectDefault;
  1196. VIDEO_MODE_INFORMATION VideoModeInformation;
  1197. VIDEO_PUBLIC_ACCESS_RANGES VideoPublicAccessRanges;
  1198. ULONG cbModeSize;
  1199. DWORD ReturnedDataLength;
  1200. ULONG ulBoardId;
  1201. ULONG cDefaultBitsPerPel;
  1202. if (EngDeviceIoControl(hDriver,
  1203. IOCTL_VIDEO_MTX_QUERY_BOARD_ID,
  1204. NULL, // Input
  1205. 0,
  1206. &ulBoardId,
  1207. sizeof(ULONG),
  1208. &ReturnedDataLength))
  1209. {
  1210. DISPDBG((0, "bSelectMode -- failed MTX_QUERY_BOARD_ID"));
  1211. goto ReturnFailure0;
  1212. }
  1213. // Use the driver's lowest pixel depth for the default mode:
  1214. *pulBoardId = ulBoardId;
  1215. DISPDBG((2, "ulBoardId = %x", ulBoardId));
  1216. if ((ulBoardId == MGA_PRO_4M5) || (ulBoardId == MGA_PRO_4M5_Z))
  1217. {
  1218. cDefaultBitsPerPel = 24;
  1219. }
  1220. else
  1221. {
  1222. cDefaultBitsPerPel = 8;
  1223. }
  1224. // Call the miniport to get mode information:
  1225. cModes = getAvailableModes(hDriver, &pVideoBuffer, &cbModeSize);
  1226. if (cModes == 0)
  1227. goto ReturnFailure0;
  1228. // Now see if the requested mode has a match in that table.
  1229. pVideoModeSelected = NULL;
  1230. pVideoTemp = pVideoBuffer;
  1231. if ((pdm->dmPelsWidth == 0) &&
  1232. (pdm->dmPelsHeight == 0) &&
  1233. (pdm->dmBitsPerPel == 0) &&
  1234. (pdm->dmDisplayFrequency == 0))
  1235. {
  1236. DISPDBG((1, "Default mode requested"));
  1237. bSelectDefault = TRUE;
  1238. }
  1239. else
  1240. {
  1241. DISPDBG((1, "Requested mode..."));
  1242. DISPDBG((1, " Screen width -- %li", pdm->dmPelsWidth));
  1243. DISPDBG((1, " Screen height -- %li", pdm->dmPelsHeight));
  1244. DISPDBG((1, " Bits per pel -- %li", pdm->dmBitsPerPel));
  1245. DISPDBG((1, " Frequency -- %li", pdm->dmDisplayFrequency));
  1246. bSelectDefault = FALSE;
  1247. }
  1248. while (cModes--)
  1249. {
  1250. if (pVideoTemp->Length != 0)
  1251. {
  1252. DISPDBG((2, " Checking against miniport mode:"));
  1253. DISPDBG((2, " Screen width -- %li", pVideoTemp->VisScreenWidth));
  1254. DISPDBG((2, " Screen height -- %li", pVideoTemp->VisScreenHeight));
  1255. DISPDBG((2, " Bits per pel -- %li", pVideoTemp->BitsPerPlane *
  1256. pVideoTemp->NumberOfPlanes));
  1257. DISPDBG((2, " Frequency -- %li", pVideoTemp->Frequency));
  1258. if (((bSelectDefault) &&
  1259. (pVideoTemp->BitsPerPlane == cDefaultBitsPerPel)) ||
  1260. ((pVideoTemp->VisScreenWidth == pdm->dmPelsWidth) &&
  1261. (pVideoTemp->VisScreenHeight == pdm->dmPelsHeight) &&
  1262. (pVideoTemp->BitsPerPlane *
  1263. pVideoTemp->NumberOfPlanes == pdm->dmBitsPerPel) &&
  1264. (pVideoTemp->Frequency == pdm->dmDisplayFrequency)))
  1265. {
  1266. pVideoModeSelected = pVideoTemp;
  1267. DISPDBG((1, "...Found a mode match!"));
  1268. break;
  1269. }
  1270. }
  1271. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  1272. (((PUCHAR)pVideoTemp) + cbModeSize);
  1273. }
  1274. // If no mode has been found, return an error:
  1275. if (pVideoModeSelected == NULL)
  1276. {
  1277. DISPDBG((1, "...Couldn't find a mode match!"));
  1278. goto ReturnFailure1;
  1279. }
  1280. // We have chosen the one we want. Save it in a stack buffer and
  1281. // get rid of allocated memory before we forget to free it.
  1282. *pVideoModeInformation = *pVideoModeSelected;
  1283. EngFreeMem(pVideoBuffer);
  1284. return(TRUE);
  1285. ReturnFailure1:
  1286. EngFreeMem(pVideoBuffer);
  1287. ReturnFailure0:
  1288. DISPDBG((0, "Failed bSelectMode"));
  1289. return(FALSE);
  1290. }
  1291. /******************************Public*Routine******************************\
  1292. * BOOL bInitializeModeFields
  1293. *
  1294. * Initializes a bunch of fields in the pdev, devcaps (aka gdiinfo), and
  1295. * devinfo based on the requested mode.
  1296. *
  1297. \**************************************************************************/
  1298. BOOL bInitializeModeFields(
  1299. PDEV* ppdev,
  1300. GDIINFO* pgdi,
  1301. DEVINFO* pdi,
  1302. DEVMODEW* pdm)
  1303. {
  1304. ULONG cModes;
  1305. PVIDEO_MODE_INFORMATION pVideoBuffer;
  1306. PVIDEO_MODE_INFORMATION pVideoModeSelected;
  1307. PVIDEO_MODE_INFORMATION pVideoTemp;
  1308. BOOL bSelectDefault;
  1309. VIDEO_MODE_INFORMATION VideoModeInformation;
  1310. VIDEO_PUBLIC_ACCESS_RANGES VideoPublicAccessRanges;
  1311. ULONG cbModeSize;
  1312. DWORD ReturnedDataLength;
  1313. ULONG ulBoardId;
  1314. ULONG cDefaultBitsPerPel;
  1315. // Tell the miniport what mode we want:
  1316. if (!bSelectMode(ppdev->hDriver,
  1317. pdm,
  1318. &VideoModeInformation,
  1319. &ppdev->ulBoardId))
  1320. {
  1321. DISPDBG((0, "bInitializeModeFields -- failed bSelectMode"));
  1322. goto ReturnFalse;
  1323. }
  1324. ppdev->ulMode = VideoModeInformation.ModeIndex;
  1325. ppdev->cxScreen = VideoModeInformation.VisScreenWidth;
  1326. ppdev->cyScreen = VideoModeInformation.VisScreenHeight;
  1327. ppdev->cxMemory = VideoModeInformation.VideoMemoryBitmapWidth;
  1328. ppdev->flRed = VideoModeInformation.RedMask;
  1329. ppdev->flGreen = VideoModeInformation.GreenMask;
  1330. ppdev->flBlue = VideoModeInformation.BlueMask;
  1331. ppdev->flHooks = (HOOK_BITBLT |
  1332. HOOK_TEXTOUT |
  1333. HOOK_FILLPATH |
  1334. HOOK_COPYBITS |
  1335. HOOK_STROKEPATH |
  1336. HOOK_LINETO |
  1337. HOOK_PAINT |
  1338. HOOK_STRETCHBLT |
  1339. HOOK_SYNCHRONIZE);
  1340. if (!bInitializeOffscreenFields(ppdev, &VideoModeInformation))
  1341. {
  1342. DISPDBG((0, "bInitializeModeFields -- failed bInitializeOffscreenFields"));
  1343. goto ReturnFalse;
  1344. }
  1345. #if DBG_MCD
  1346. if ((VideoModeInformation.VisScreenWidth == 1024) &&
  1347. (VideoModeInformation.BitsPerPlane > 16))
  1348. {
  1349. VideoModeInformation.VisScreenHeight = 256;
  1350. ppdev->cyScreen = VideoModeInformation.VisScreenHeight;
  1351. }
  1352. #endif
  1353. // Fill in the GDIINFO data structure with the default 8bpp values:
  1354. *pgdi = ggdiDefault;
  1355. // Now overwrite the defaults with the relevant information returned
  1356. // from the kernel driver:
  1357. pgdi->ulHorzSize = VideoModeInformation.XMillimeter;
  1358. pgdi->ulVertSize = VideoModeInformation.YMillimeter;
  1359. pgdi->ulHorzRes = VideoModeInformation.VisScreenWidth;
  1360. pgdi->ulVertRes = VideoModeInformation.VisScreenHeight;
  1361. pgdi->ulPanningHorzRes = VideoModeInformation.VisScreenWidth;
  1362. pgdi->ulPanningVertRes = VideoModeInformation.VisScreenHeight;
  1363. pgdi->cBitsPixel = VideoModeInformation.BitsPerPlane;
  1364. pgdi->cPlanes = VideoModeInformation.NumberOfPlanes;
  1365. pgdi->ulVRefresh = VideoModeInformation.Frequency;
  1366. pgdi->ulDACRed = VideoModeInformation.NumberRedBits;
  1367. pgdi->ulDACGreen = VideoModeInformation.NumberGreenBits;
  1368. pgdi->ulDACBlue = VideoModeInformation.NumberBlueBits;
  1369. pgdi->ulLogPixelsX = pdm->dmLogPixels;
  1370. pgdi->ulLogPixelsY = pdm->dmLogPixels;
  1371. // Fill in the devinfo structure with the default 8bpp values:
  1372. *pdi = gdevinfoDefault;
  1373. ppdev->ulRefresh = pgdi->ulVRefresh;
  1374. if (VideoModeInformation.BitsPerPlane == 8)
  1375. {
  1376. ppdev->cjPelSize = 1;
  1377. ppdev->cjHwPel = 1;
  1378. ppdev->lDelta = ppdev->cxMemory;
  1379. ppdev->iBitmapFormat = BMF_8BPP;
  1380. ppdev->ulWhite = 0xff;
  1381. ppdev->ulPlnWt = plnwt_MASK_8BPP;
  1382. ppdev->ulAccess = pwidth_PW8;
  1383. ppdev->ulBrushSize = (TOTAL_BRUSH_SIZE * 1);
  1384. if (ppdev->ulBoardId == MGA_STORM)
  1385. {
  1386. ppdev->pfnFillPatNative = vMilFillPat;
  1387. ppdev->pfnFillSolid = vMilFillSolid;
  1388. }
  1389. else
  1390. {
  1391. ppdev->pfnFillPatNative = vMgaFillPat8bpp;
  1392. ppdev->pfnFillSolid = vMgaFillSolid;
  1393. }
  1394. ppdev->cPaletteShift = 8 - pgdi->ulDACRed;
  1395. ppdev->lPatSrcAdd = 2;
  1396. // Device GammaRamp can not be changed on 8bpp mode
  1397. pdi->flGraphicsCaps2 &= ~GCAPS2_CHANGEGAMMARAMP;
  1398. }
  1399. else if ((VideoModeInformation.BitsPerPlane == 16) ||
  1400. (VideoModeInformation.BitsPerPlane == 15))
  1401. {
  1402. ppdev->cjPelSize = 2;
  1403. ppdev->cjHwPel = 2;
  1404. ppdev->lDelta = 2 * ppdev->cxMemory;
  1405. ppdev->iBitmapFormat = BMF_16BPP;
  1406. ppdev->ulWhite = (VideoModeInformation.BitsPerPlane == 16)
  1407. ? 0xffff : 0x7fff;
  1408. pgdi->ulNumColors = (ULONG) -1;
  1409. pgdi->ulNumPalReg = 0;
  1410. pgdi->ulHTOutputFormat = HT_FORMAT_16BPP;
  1411. ppdev->ulPlnWt = plnwt_MASK_16BPP;
  1412. ppdev->ulAccess = pwidth_PW16;
  1413. ppdev->ulBrushSize = (TOTAL_BRUSH_SIZE * 2);
  1414. if (ppdev->ulBoardId == MGA_STORM)
  1415. {
  1416. ppdev->pfnFillPatNative = vMilFillPat;
  1417. ppdev->pfnFillSolid = vMilFillSolid;
  1418. if (ppdev->flGreen != 0x7e0) // not 565
  1419. ppdev->ulAccess |= dither_555;
  1420. }
  1421. else
  1422. {
  1423. ppdev->pfnFillPatNative = vMgaFillPat16bpp;
  1424. ppdev->pfnFillSolid = vMgaFillSolid;
  1425. // Device GammaRamp can not be changed on non-Millenium board
  1426. pdi->flGraphicsCaps2 &= ~GCAPS2_CHANGEGAMMARAMP;
  1427. }
  1428. pdi->iDitherFormat = BMF_16BPP;
  1429. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1430. ppdev->lPatSrcAdd = 4;
  1431. }
  1432. else if (ppdev->ulBoardId == MGA_STORM)
  1433. {
  1434. if (VideoModeInformation.BitsPerPlane == 24)
  1435. {
  1436. ppdev->cjPelSize = 3;
  1437. ppdev->cjHwPel = 3;
  1438. ppdev->lDelta = 3 * ppdev->cxMemory;
  1439. ppdev->iBitmapFormat = BMF_24BPP;
  1440. ppdev->ulWhite = 0xffffff;
  1441. pgdi->ulNumColors = (ULONG) -1;
  1442. pgdi->ulNumPalReg = 0;
  1443. pgdi->ulHTOutputFormat = HT_FORMAT_24BPP;
  1444. ppdev->ulPlnWt = plnwt_MASK_24BPP;
  1445. ppdev->ulAccess = pwidth_PW24;
  1446. ppdev->ulBrushSize = (TOTAL_BRUSH_SIZE * 6);
  1447. ppdev->pfnFillPatNative = vMilFillPat24bpp;
  1448. ppdev->pfnFillSolid = vMilFillSolid;
  1449. pdi->iDitherFormat = BMF_24BPP;
  1450. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1451. ppdev->lPatSrcAdd = 7;
  1452. }
  1453. else
  1454. {
  1455. ASSERTDD((VideoModeInformation.BitsPerPlane == 32),
  1456. "This driver supports only 8, 16, 24, and 32bpp");
  1457. ppdev->cjPelSize = 4;
  1458. ppdev->cjHwPel = 4;
  1459. ppdev->lDelta = 4 * ppdev->cxMemory;
  1460. ppdev->iBitmapFormat = BMF_32BPP;
  1461. ppdev->ulWhite = 0xffffff;
  1462. pgdi->ulNumColors = (ULONG) -1;
  1463. pgdi->ulNumPalReg = 0;
  1464. pgdi->ulHTOutputFormat = HT_FORMAT_32BPP;
  1465. ppdev->ulPlnWt = plnwt_MASK_32BPP;
  1466. ppdev->ulAccess = pwidth_PW32;
  1467. ppdev->ulBrushSize = (TOTAL_BRUSH_SIZE * 4);
  1468. ppdev->pfnFillPatNative = vMilFillPat;
  1469. ppdev->pfnFillSolid = vMilFillSolid;
  1470. pdi->iDitherFormat = BMF_32BPP;
  1471. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1472. ppdev->lPatSrcAdd = 6;
  1473. }
  1474. }
  1475. else
  1476. {
  1477. ASSERTDD((VideoModeInformation.BitsPerPlane == 32) ||
  1478. (VideoModeInformation.BitsPerPlane == 24),
  1479. "This driver supports only 8, 16, 24, and 32bpp");
  1480. // The miniport may think it's 32bpp, but we're going to tell GDI
  1481. // that it's 24bpp. We do this so that out bitmap transfers will
  1482. // be more efficient, and compatible bitmaps will be smaller.
  1483. //
  1484. // Note that we also have to fudge the results returned from
  1485. // 'GetModes' if we're going to do this.
  1486. pgdi->cBitsPixel = 24;
  1487. ppdev->cjPelSize = 3;
  1488. ppdev->cjHwPel = 4;
  1489. ppdev->lDelta = 4 * ppdev->cxMemory;
  1490. ppdev->iBitmapFormat = BMF_24BPP;
  1491. ppdev->ulWhite = 0xffffff;
  1492. pgdi->ulNumColors = (ULONG) -1;
  1493. pgdi->ulNumPalReg = 0;
  1494. pgdi->ulHTOutputFormat = HT_FORMAT_24BPP;
  1495. ppdev->ulPlnWt = plnwt_MASK_24BPP;
  1496. ppdev->ulAccess = pwidth_PW32;
  1497. ppdev->ulBrushSize = (TOTAL_BRUSH_SIZE * 3);
  1498. ppdev->pfnFillPatNative = vMgaFillPat24bpp;
  1499. ppdev->pfnFillSolid = vMgaFillSolid;
  1500. pdi->iDitherFormat = BMF_24BPP;
  1501. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1502. // Device GammaRamp can not be changed on non-Millenium board.
  1503. pdi->flGraphicsCaps2 &= ~GCAPS2_CHANGEGAMMARAMP;
  1504. ppdev->lPatSrcAdd = 0; // not used for old MGA cards
  1505. }
  1506. // Several MIPS machines are broken in that 64 bit accesses to the
  1507. // framebuffer don't work.
  1508. if (VideoModeInformation.AttributeFlags & VIDEO_MODE_NO_64_BIT_ACCESS)
  1509. {
  1510. DISPDBG((0, "Disable 64 bit access on this device !\n"));
  1511. pdi->flGraphicsCaps |= GCAPS_NO64BITMEMACCESS;
  1512. }
  1513. // The following are the same for all color depths
  1514. if (ppdev->ulBoardId == MGA_STORM)
  1515. {
  1516. ppdev->pfnXfer1bpp = vMilXfer1bpp;
  1517. ppdev->pfnCopyBlt = vMilCopyBlt;
  1518. ppdev->pfnPuntBlt = bMilPuntBlt;
  1519. }
  1520. else
  1521. {
  1522. ppdev->pfnXfer1bpp = vMgaXfer1bpp;
  1523. ppdev->pfnCopyBlt = vMgaCopyBlt;
  1524. ppdev->pfnPuntBlt = bMgaPuntBlt;
  1525. }
  1526. DISPDBG((1, "Current mode: %dx%d %dbpp %dHz", ppdev->cxScreen,
  1527. ppdev->cyScreen,
  1528. ppdev->cjPelSize * 8,
  1529. ppdev->ulRefresh));
  1530. DISPDBG((5, "Passed bInitializeModeFields"));
  1531. return(TRUE);
  1532. ReturnFalse:
  1533. DISPDBG((0, "Failed bInitializeModeFields"));
  1534. return(FALSE);
  1535. }
  1536. /******************************Public*Routine******************************\
  1537. * DWORD getAvailableModes
  1538. *
  1539. * Calls the miniport to get the list of modes supported by the kernel driver,
  1540. * and returns the list of modes supported by the diplay driver among those
  1541. *
  1542. * returns the number of entries in the videomode buffer.
  1543. * 0 means no modes are supported by the miniport or that an error occured.
  1544. *
  1545. * NOTE: the buffer must be freed up by the caller.
  1546. *
  1547. \**************************************************************************/
  1548. DWORD getAvailableModes(
  1549. HANDLE hDriver,
  1550. PVIDEO_MODE_INFORMATION* modeInformation, // Must be freed by caller
  1551. DWORD* cbModeSize)
  1552. {
  1553. ULONG ulTemp;
  1554. VIDEO_NUM_MODES modes;
  1555. PVIDEO_MODE_INFORMATION pVideoTemp;
  1556. //
  1557. // Get the number of modes supported by the mini-port
  1558. //
  1559. if (EngDeviceIoControl(hDriver,
  1560. IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES,
  1561. NULL,
  1562. 0,
  1563. &modes,
  1564. sizeof(VIDEO_NUM_MODES),
  1565. &ulTemp))
  1566. {
  1567. DISPDBG((0, "getAvailableModes - Failed VIDEO_QUERY_NUM_AVAIL_MODES"));
  1568. return(0);
  1569. }
  1570. *cbModeSize = modes.ModeInformationLength;
  1571. //
  1572. // Allocate the buffer for the mini-port to write the modes in.
  1573. //
  1574. *modeInformation = (PVIDEO_MODE_INFORMATION)
  1575. EngAllocMem(FL_ZERO_MEMORY,
  1576. modes.NumModes *
  1577. modes.ModeInformationLength, ALLOC_TAG);
  1578. if (*modeInformation == (PVIDEO_MODE_INFORMATION) NULL)
  1579. {
  1580. DISPDBG((0, "getAvailableModes - Failed EngAllocMem"));
  1581. return 0;
  1582. }
  1583. //
  1584. // Ask the mini-port to fill in the available modes.
  1585. //
  1586. if (EngDeviceIoControl(hDriver,
  1587. IOCTL_VIDEO_QUERY_AVAIL_MODES,
  1588. NULL,
  1589. 0,
  1590. *modeInformation,
  1591. modes.NumModes * modes.ModeInformationLength,
  1592. &ulTemp))
  1593. {
  1594. DISPDBG((0, "getAvailableModes - Failed VIDEO_QUERY_AVAIL_MODES"));
  1595. EngFreeMem(*modeInformation);
  1596. *modeInformation = (PVIDEO_MODE_INFORMATION) NULL;
  1597. return(0);
  1598. }
  1599. //
  1600. // Now see which of these modes are supported by the display driver.
  1601. // As an internal mechanism, set the length to 0 for the modes we
  1602. // DO NOT support.
  1603. //
  1604. ulTemp = modes.NumModes;
  1605. pVideoTemp = *modeInformation;
  1606. //
  1607. // Mode is rejected if it is not one plane, or not graphics, or is not
  1608. // one of 8, 15, 16, 24, or 32 bits per pel.
  1609. //
  1610. while (ulTemp--)
  1611. {
  1612. if ((pVideoTemp->NumberOfPlanes != 1 ) ||
  1613. !(pVideoTemp->AttributeFlags & VIDEO_MODE_GRAPHICS) ||
  1614. ((pVideoTemp->BitsPerPlane != 8) &&
  1615. (pVideoTemp->BitsPerPlane != 15) &&
  1616. (pVideoTemp->BitsPerPlane != 16) &&
  1617. (pVideoTemp->BitsPerPlane != 24) &&
  1618. (pVideoTemp->BitsPerPlane != 32)))
  1619. {
  1620. DISPDBG((2, "Rejecting miniport mode:"));
  1621. DISPDBG((2, " Screen width -- %li", pVideoTemp->VisScreenWidth));
  1622. DISPDBG((2, " Screen height -- %li", pVideoTemp->VisScreenHeight));
  1623. DISPDBG((2, " Bits per pel -- %li", pVideoTemp->BitsPerPlane *
  1624. pVideoTemp->NumberOfPlanes));
  1625. DISPDBG((2, " Frequency -- %li", pVideoTemp->Frequency));
  1626. pVideoTemp->Length = 0;
  1627. }
  1628. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  1629. (((PUCHAR)pVideoTemp) + modes.ModeInformationLength);
  1630. }
  1631. return(modes.NumModes);
  1632. }