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.

614 lines
18 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 Microsoft Corporation
  8. \**************************************************************************/
  9. #include "driver.h"
  10. //
  11. // Build the driver function table gadrvfn with function index/address pairs
  12. //
  13. DRVFN gadrvfn[] = {
  14. { INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
  15. { INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
  16. { INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
  17. { INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
  18. { INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
  19. { INDEX_DrvAssertMode, (PFN) DrvAssertMode },
  20. { INDEX_DrvGetModes, (PFN) DrvGetModes },
  21. { INDEX_DrvDitherColor, (PFN) DrvDitherColor },
  22. { INDEX_DrvSetPalette, (PFN) DrvSetPalette },
  23. { INDEX_DrvCopyBits, (PFN) DrvCopyBits },
  24. { INDEX_DrvBitBlt, (PFN) DrvBitBlt },
  25. { INDEX_DrvTextOut, (PFN) DrvTextOut },
  26. { INDEX_DrvStrokePath, (PFN) DrvStrokePath },
  27. { INDEX_DrvFillPath, (PFN) DrvFillPath },
  28. { INDEX_DrvRealizeBrush, (PFN) DrvRealizeBrush },
  29. { INDEX_DrvStretchBlt, (PFN) DrvStretchBlt },
  30. { INDEX_DrvSaveScreenBits, (PFN) DrvSaveScreenBits },
  31. { INDEX_DrvPaint, (PFN) DrvPaint },
  32. { INDEX_DrvDisableDriver, (PFN) DrvDisableDriver }
  33. };
  34. /********************************* COMMENT ********************************\
  35. This routine allocates a 4K global buffer for temporary working storage
  36. which is used by several routines. We wanted to get the most space for
  37. the least paging impact, so a page aligned 4K buffer was chosen. Any
  38. access to this buffer will cause at most one page fault. Because it is
  39. aligned, we can access the entire 4K without causing another page fault.
  40. Any buffer requirement over 4K must be allocated. If we find that we
  41. are still having a low hit rate on the buffer (using lot's of allocs)
  42. then the buffer size should be increased to 8K.
  43. The ONLY reason that it is OK to have this global buffer is that this
  44. driver does not support DFBs, and accesses to the screen are synhronized
  45. by the engine. In other words, it is currently never possible to have
  46. two threads executing code in the driver at the same time.
  47. \**************************************************************************/
  48. /******************************Public*Routine******************************\
  49. * DrvEnableDriver
  50. *
  51. * Enables the driver by retrieving the drivers function table and version.
  52. *
  53. \**************************************************************************/
  54. BOOL DrvEnableDriver(
  55. ULONG iEngineVersion,
  56. ULONG cj,
  57. PDRVENABLEDATA pded)
  58. {
  59. UNREFERENCED_PARAMETER(iEngineVersion);
  60. // Engine Version is passed down so future drivers can support previous
  61. // engine versions. A next generation driver can support both the old
  62. // and new engine conventions if told what version of engine it is
  63. // working with. For the first version the driver does nothing with it.
  64. // Fill in as much as we can.
  65. if (cj >= sizeof(DRVENABLEDATA))
  66. pded->pdrvfn = gadrvfn;
  67. if (cj >= (sizeof(ULONG) * 2))
  68. pded->c = sizeof(gadrvfn) / sizeof(DRVFN);
  69. // DDI version this driver was targeted for is passed back to engine.
  70. // Future graphic's engine may break calls down to old driver format.
  71. if (cj >= sizeof(ULONG))
  72. pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
  73. return(TRUE);
  74. }
  75. /******************************Public*Routine******************************\
  76. * DrvDisableDriver
  77. *
  78. * Tells the driver it is being disabled. Release any resources allocated in
  79. * DrvEnableDriver.
  80. *
  81. \**************************************************************************/
  82. VOID DrvDisableDriver(VOID)
  83. {
  84. return;
  85. }
  86. /******************************Public*Routine******************************\
  87. * DrvEnablePDEV
  88. *
  89. * DDI function, Enables the Physical Device.
  90. *
  91. * Return Value: device handle to pdev.
  92. *
  93. \**************************************************************************/
  94. DHPDEV DrvEnablePDEV(
  95. DEVMODEW *pDevmode, // Pointer to DEVMODE
  96. PWSTR pwszLogAddress, // Logical address
  97. ULONG cPatterns, // number of patterns
  98. HSURF *ahsurfPatterns, // return standard patterns
  99. ULONG cjGdiInfo, // Length of memory pointed to by pGdiInfo
  100. ULONG *pGdiInfo, // Pointer to GdiInfo structure
  101. ULONG cjDevInfo, // Length of following PDEVINFO structure
  102. DEVINFO *pDevInfo, // physical device information structure
  103. HDEV hdev, // HDEV, used for callbacks
  104. PWSTR pwszDeviceName, // DeviceName - not used
  105. HANDLE hDriver) // Handle to base driver
  106. {
  107. GDIINFO GdiInfo;
  108. DEVINFO DevInfo;
  109. PPDEV ppdev;
  110. BYTE *pjTemp;
  111. INT i;
  112. UNREFERENCED_PARAMETER(pwszLogAddress);
  113. UNREFERENCED_PARAMETER(pwszDeviceName);
  114. // Allocate a physical device structure.
  115. ppdev = (PPDEV) EngAllocMem(FL_ZERO_MEMORY, sizeof(PDEV), ALLOC_TAG);
  116. if (ppdev == (PPDEV) NULL)
  117. {
  118. DISPDBG((0, "VGA256: Couldn't allocate PDEV buffer"));
  119. goto error0;
  120. }
  121. // Create the table used for flipping bits 0-3 and 4-7 when drawing text.
  122. // This table must be aligned to a 256-byte boundary.
  123. ppdev->pjGlyphFlipTableBase =
  124. (BYTE *) EngAllocMem((FL_ZERO_MEMORY),
  125. ((256+256)*sizeof(UCHAR)), ALLOC_TAG);
  126. if (ppdev->pjGlyphFlipTableBase == NULL) {
  127. DISPDBG((0, "VGA256: Couldn't allocate pjGlyphFlipTableBase"));
  128. goto error01;
  129. }
  130. // Round the table start up to the nearest 256 byte boundary, because the
  131. // table must start on 256-byte boundaries for look-up reasons
  132. ppdev->pjGlyphFlipTable =
  133. (BYTE *) ((ULONG) (ppdev->pjGlyphFlipTableBase + 0xFF) & ~0xFF);
  134. // Set the table to convert bits 76543210 to 45670123, which we need for
  135. // drawing text in planar mode (because plane 0 is the leftmost, not
  136. // rightmost, pixel)
  137. pjTemp = ppdev->pjGlyphFlipTable;
  138. for (i=0; i<256; i++) {
  139. *pjTemp++ = ((i & 0x80) >> 3) |
  140. ((i & 0x40) >> 1) |
  141. ((i & 0x20) << 1) |
  142. ((i & 0x10) << 3) |
  143. ((i & 0x08) >> 3) |
  144. ((i & 0x04) >> 1) |
  145. ((i & 0x02) << 1) |
  146. ((i & 0x01) << 3);
  147. }
  148. // Save the screen handle in the PDEV.
  149. ppdev->hDriver = hDriver;
  150. // Get the current screen mode information. Set up device caps and devinfo.
  151. if (!bInitPDEV(ppdev,pDevmode, &GdiInfo, &DevInfo))
  152. {
  153. DISPDBG((0,"VGA256: Couldn't initialize PDEV"));
  154. goto error1;
  155. }
  156. // Initialize palette information.
  157. if (!bInitPaletteInfo(ppdev, &DevInfo))
  158. {
  159. DISPDBG((0, "VGA256: Couldn't initialize palette"));
  160. goto error1;
  161. }
  162. // Copy the devinfo into the engine buffer.
  163. memcpy(pDevInfo, &DevInfo, min(sizeof(DEVINFO), cjDevInfo));
  164. // Set the pdevCaps with GdiInfo we have prepared to the list of caps for this
  165. // pdev.
  166. memcpy(pGdiInfo, &GdiInfo, min(cjGdiInfo, sizeof(GDIINFO)));
  167. // Create a clip object we can use when we're given a NULL clip object:
  168. ppdev->pcoNull = EngCreateClip();
  169. if (ppdev->pcoNull == NULL)
  170. {
  171. DISPDBG((0, "VGA256: Couldn't create clip"));
  172. goto error2;
  173. }
  174. ppdev->pcoNull->iDComplexity = DC_RECT;
  175. ppdev->pcoNull->rclBounds.left = 0;
  176. ppdev->pcoNull->rclBounds.top = 0;
  177. ppdev->pcoNull->rclBounds.right = ppdev->cxScreen;
  178. ppdev->pcoNull->rclBounds.bottom = ppdev->cyScreen;
  179. ppdev->pcoNull->fjOptions = OC_BANK_CLIP;
  180. // pvSaveScan0 is non-NULL only when enumerating banks:
  181. ppdev->pvSaveScan0 = NULL;
  182. // We're all done:
  183. return((DHPDEV) ppdev);
  184. error2:
  185. vDisablePalette(ppdev);
  186. error1:
  187. EngFreeMem(ppdev->pjGlyphFlipTableBase);
  188. error01:
  189. EngFreeMem(ppdev);
  190. error0:
  191. return((DHPDEV) 0);
  192. }
  193. /******************************Public*Routine******************************\
  194. * DrvCompletePDEV
  195. *
  196. * Store the HPDEV, the engines handle for this PDEV, in the DHPDEV.
  197. *
  198. \**************************************************************************/
  199. VOID DrvCompletePDEV(
  200. DHPDEV dhpdev,
  201. HDEV hdev)
  202. {
  203. ((PPDEV) dhpdev)->hdevEng = hdev;
  204. }
  205. /******************************Public*Routine******************************\
  206. * DrvDisablePDEV
  207. *
  208. * Release the resources allocated in DrvEnablePDEV. If a surface has been
  209. * enabled DrvDisableSurface will have already been called.
  210. *
  211. \**************************************************************************/
  212. VOID DrvDisablePDEV(
  213. DHPDEV dhpdev)
  214. {
  215. PPDEV ppdev = (PPDEV) dhpdev;
  216. EngDeleteClip(ppdev->pcoNull);
  217. vDisablePalette(ppdev);
  218. EngFreeMem(ppdev->pjGlyphFlipTableBase);
  219. EngFreeMem(dhpdev);
  220. }
  221. /******************************Public*Routine******************************\
  222. * DrvEnableSurface
  223. *
  224. * Enable the surface for the device. Hook the calls this driver supports.
  225. *
  226. * Return: Handle to the surface if successful, 0 for failure.
  227. *
  228. \**************************************************************************/
  229. HSURF DrvEnableSurface(
  230. DHPDEV dhpdev)
  231. {
  232. PPDEV ppdev;
  233. HSURF hsurf;
  234. HSURF hsurfBm;
  235. SIZEL sizl;
  236. ULONG ulBitmapType;
  237. FLONG flHooks;
  238. // Create engine bitmap around frame buffer.
  239. ppdev = (PPDEV) dhpdev;
  240. if (!bInitSURF(ppdev, TRUE))
  241. goto error0;
  242. if (!bInit256ColorPalette(ppdev))
  243. goto error0;
  244. sizl.cx = ppdev->cxScreen;
  245. sizl.cy = ppdev->cyScreen;
  246. ulBitmapType = BMF_8BPP;
  247. flHooks = HOOKS_BMF8BPP;
  248. ASSERTVGA(ppdev->ulBitCount == 8, "Can only handle 8bpp VGAs");
  249. hsurfBm = (HSURF) EngCreateBitmap(sizl,
  250. ppdev->lDeltaScreen,
  251. (ULONG) (ulBitmapType),
  252. (FLONG) (((ppdev->lDeltaScreen > 0)
  253. ? BMF_TOPDOWN
  254. : 0)),
  255. (PVOID) (ppdev->pjScreen));
  256. if (hsurfBm == 0)
  257. {
  258. RIP("Couldn't create surface");
  259. goto error0;
  260. }
  261. if (!EngAssociateSurface(hsurfBm, ppdev->hdevEng, 0))
  262. {
  263. RIP("Couldn't create or associate surface");
  264. goto error1;
  265. }
  266. ppdev->hsurfBm = hsurfBm;
  267. ppdev->pSurfObj = EngLockSurface(hsurfBm);
  268. if (ppdev->pSurfObj == NULL)
  269. {
  270. RIP("Couldn't lock surface");
  271. goto error1;
  272. }
  273. hsurf = EngCreateDeviceSurface((DHSURF) ppdev, sizl, BMF_8BPP);
  274. if (hsurf == 0)
  275. {
  276. RIP("Couldn't create surface");
  277. goto error2;
  278. }
  279. if (!EngAssociateSurface(hsurf, ppdev->hdevEng, flHooks))
  280. {
  281. RIP("Couldn't associate surface");
  282. goto error3;
  283. }
  284. ppdev->hsurfEng = hsurf;
  285. // Disable all the clipping.
  286. if (!bEnableBanking(ppdev))
  287. {
  288. RIP("Couldn't initialize banking");
  289. goto error3;
  290. }
  291. ppdev->pvTmpBuf = EngAllocMem(FL_ZERO_MEMORY,
  292. GLOBAL_BUFFER_SIZE,
  293. ALLOC_TAG);
  294. if (ppdev->pvTmpBuf == NULL)
  295. {
  296. DISPDBG((0, "VGA256: Couldn't allocate global buffer"));
  297. goto error4;
  298. }
  299. ASSERTVGA(ppdev->lNextScan != 0, "lNextScan shouldn't be zero");
  300. sizl.cx = ppdev->lNextScan;
  301. sizl.cy = GLOBAL_BUFFER_SIZE / abs(ppdev->lNextScan);
  302. ppdev->hbmTmp = EngCreateBitmap(sizl, sizl.cx, BMF_8BPP, 0, ppdev->pvTmpBuf);
  303. if (ppdev->hbmTmp == (HBITMAP) 0)
  304. {
  305. RIP("Couldn't create temporary bitmap");
  306. goto error5;
  307. }
  308. ppdev->psoTmp = EngLockSurface((HSURF) ppdev->hbmTmp);
  309. if (ppdev->psoTmp == (SURFOBJ*) NULL)
  310. {
  311. RIP("Couldn't lock temporary surface");
  312. goto error6;
  313. }
  314. // Attempt to initialize the brush cache; if this fails, it sets a flag in
  315. // the PDEV instructing us to punt brush fills to the engine
  316. vInitBrushCache(ppdev);
  317. vInitSavedBits(ppdev);
  318. return(hsurf);
  319. error6:
  320. EngDeleteSurface((HSURF) ppdev->hbmTmp);
  321. error5:
  322. EngFreeMem(ppdev->pvTmpBuf);
  323. error4:
  324. vDisableBanking(ppdev);
  325. error3:
  326. EngDeleteSurface(hsurf);
  327. error2:
  328. EngUnlockSurface(ppdev->pSurfObj);
  329. error1:
  330. EngDeleteSurface(hsurfBm);
  331. error0:
  332. return((HSURF) 0);
  333. }
  334. /******************************Public*Routine******************************\
  335. * DrvDisableSurface
  336. *
  337. * Free resources allocated by DrvEnableSurface. Release the surface.
  338. *
  339. \**************************************************************************/
  340. VOID DrvDisableSurface(
  341. DHPDEV dhpdev)
  342. {
  343. PPDEV ppdev = (PPDEV) dhpdev;
  344. EngUnlockSurface(ppdev->psoTmp);
  345. EngDeleteSurface((HSURF) ppdev->hbmTmp);
  346. EngFreeMem(ppdev->pvTmpBuf);
  347. EngDeleteSurface(ppdev->hsurfEng);
  348. vDisableSURF(ppdev);
  349. vDisableBrushCache(ppdev);
  350. ppdev->hsurfEng = (HSURF) 0;
  351. vDisableBanking(ppdev);
  352. }
  353. /******************************Public*Routine******************************\
  354. * DrvAssertMode
  355. *
  356. * This asks the device to reset itself to the mode of the pdev passed in.
  357. *
  358. \**************************************************************************/
  359. BOOL
  360. DrvAssertMode(
  361. DHPDEV dhpdev,
  362. BOOL bEnable)
  363. {
  364. BOOL bRet = TRUE;
  365. PPDEV ppdev = (PPDEV) dhpdev;
  366. ULONG ulReturn;
  367. if (bEnable)
  368. {
  369. // The screen must be reenabled, reinitialize the device to
  370. // a clean state.
  371. bRet = bInitSURF(ppdev, FALSE);
  372. // Restore the off screen data. This protects the Desktop
  373. // from a DOS application that might trash the off screen
  374. // memory.
  375. ppdev->bBitsSaved = FALSE; // clear the DrvSaveScreenBits info flag
  376. // ie. blow away cached screen region
  377. // Blow away our brush cache because a full-screen app may have
  378. // overwritten the video memory where we cache our brushes:
  379. vResetBrushCache(ppdev);
  380. }
  381. else
  382. {
  383. // Call the kernel driver to reset the device to a known state.
  384. if (EngDeviceIoControl(ppdev->hDriver,
  385. IOCTL_VIDEO_RESET_DEVICE,
  386. NULL,
  387. 0,
  388. NULL,
  389. 0,
  390. &ulReturn))
  391. {
  392. RIP("VIDEO_RESET_DEVICE failed");
  393. bRet = FALSE;
  394. }
  395. }
  396. return bRet;
  397. }
  398. /******************************Public*Routine******************************\
  399. * DrvGetModes
  400. *
  401. * Returns the list of available modes for the device.
  402. *
  403. \**************************************************************************/
  404. ULONG DrvGetModes(
  405. HANDLE hDriver,
  406. ULONG cjSize,
  407. DEVMODEW *pdm)
  408. {
  409. DWORD cModes;
  410. DWORD cbOutputSize;
  411. PVIDEO_MODE_INFORMATION pVideoModeInformation, pVideoTemp;
  412. DWORD cOutputModes = cjSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  413. DWORD cbModeSize;
  414. DISPDBG((2, "Vga256.dll: DrvGetModes\n"));
  415. cModes = getAvailableModes(hDriver,
  416. (PVIDEO_MODE_INFORMATION *) &pVideoModeInformation,
  417. &cbModeSize);
  418. if (cModes == 0)
  419. {
  420. DISPDBG((0, "VGA256 DISP DrvGetModes failed to get mode information"));
  421. return 0;
  422. }
  423. if (pdm == NULL)
  424. {
  425. cbOutputSize = cModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  426. }
  427. else
  428. {
  429. //
  430. // Now copy the information for the supported modes back into the output
  431. // buffer
  432. //
  433. cbOutputSize = 0;
  434. pVideoTemp = pVideoModeInformation;
  435. do
  436. {
  437. if (pVideoTemp->Length != 0)
  438. {
  439. if (cOutputModes == 0)
  440. {
  441. break;
  442. }
  443. //
  444. // Zero the entire structure to start off with.
  445. //
  446. memset(pdm, 0, sizeof(DEVMODEW));
  447. //
  448. // Set the name of the device to the name of the DLL.
  449. //
  450. memcpy(pdm->dmDeviceName, DLL_NAME, sizeof(DLL_NAME));
  451. pdm->dmSpecVersion = DM_SPECVERSION;
  452. pdm->dmDriverVersion = DM_SPECVERSION;
  453. pdm->dmSize = sizeof(DEVMODEW);
  454. pdm->dmDriverExtra = DRIVER_EXTRA_SIZE;
  455. pdm->dmBitsPerPel = pVideoTemp->NumberOfPlanes *
  456. pVideoTemp->BitsPerPlane;
  457. pdm->dmPelsWidth = pVideoTemp->VisScreenWidth;
  458. pdm->dmPelsHeight = pVideoTemp->VisScreenHeight;
  459. pdm->dmDisplayFrequency = pVideoTemp->Frequency;
  460. pdm->dmDisplayFlags = 0;
  461. pdm->dmFields = DM_BITSPERPEL |
  462. DM_PELSWIDTH |
  463. DM_PELSHEIGHT |
  464. DM_DISPLAYFREQUENCY |
  465. DM_DISPLAYFLAGS ;
  466. //
  467. // Go to the next DEVMODE entry in the buffer.
  468. //
  469. cOutputModes--;
  470. pdm = (LPDEVMODEW) ( ((ULONG)pdm) + sizeof(DEVMODEW) +
  471. DRIVER_EXTRA_SIZE);
  472. cbOutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  473. }
  474. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  475. (((PUCHAR)pVideoTemp) + cbModeSize);
  476. } while (--cModes);
  477. }
  478. EngFreeMem(pVideoModeInformation);
  479. return cbOutputSize;
  480. }