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.

512 lines
18 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: savescr.c *
  3. * *
  4. * DrvSaveScreenBits *
  5. * *
  6. * Copyright (c) 1994 Microsoft Corporation *
  7. \**************************************************************************/
  8. #include <driver.h>
  9. // This is just a unique ID that the driver will recongize. Hopefully,
  10. // nothing will ever call with this ID by pure chance.
  11. #define SAVED_OFFSCREEN_ID 0x7813
  12. ULONG ulSaveOrRestoreBits(SURFOBJ *,PPDEV,RECTL *,BOOL);
  13. /******************************Public*Routine******************************\
  14. * DrvSaveScreenBits(pso,iMode,iIdent,prcl) *
  15. * *
  16. * Saves and restores the specified area of the screen *
  17. * *
  18. \**************************************************************************/
  19. ULONG DrvSaveScreenBits(SURFOBJ *pso, ULONG iMode, ULONG iIdent, RECTL *prcl)
  20. {
  21. PPDEV ppdev;
  22. ULONG ulRet;
  23. ppdev = (PPDEV) pso->dhpdev; // find the PDEV that goes with this surface
  24. if (!((ppdev->fl & DRIVER_OFFSCREEN_REFRESHED) &&
  25. (ppdev->fl & DRIVER_HAS_OFFSCREEN)))
  26. {
  27. return(0);
  28. }
  29. switch(iMode)
  30. {
  31. case SS_SAVE:
  32. //
  33. // Save a block of screen bits.
  34. //
  35. if (ppdev->bBitsSaved)
  36. {
  37. DISPDBG((1, "DrvSaveScreenBits: off screen area is already in use\n"));
  38. return(FALSE); // there are already valid bits saved
  39. }
  40. ulRet = ulSaveOrRestoreBits(pso, ppdev, prcl, TRUE);
  41. if (ulRet)
  42. {
  43. ppdev->bBitsSaved = TRUE;
  44. }
  45. else
  46. {
  47. DISPDBG((1, "DrvSaveScreenBits (save): save couldn't fit\n"));
  48. }
  49. return(ulRet);
  50. case SS_RESTORE:
  51. //
  52. // Restore a saved screen bits block to the screen, then free it.
  53. //
  54. ASSERTVGA(iIdent == SAVED_OFFSCREEN_ID,
  55. "DrvSaveScreenBits (restore): invalid iIdent\n");
  56. ASSERTVGA(ppdev->bBitsSaved == TRUE,
  57. "DrvSaveScreenBits (restore): there are no saved bits\n");
  58. ppdev->bBitsSaved = FALSE; // successful or not, destroy the bits
  59. if (!ulSaveOrRestoreBits(pso, ppdev, prcl, FALSE))
  60. {
  61. RIP("DrvSaveScreenBits (restore): restore failed\n");
  62. }
  63. return(TRUE);
  64. case SS_FREE:
  65. //
  66. // Free up the saved screen bits
  67. //
  68. ppdev->bBitsSaved = FALSE;
  69. return(TRUE);
  70. default:
  71. //
  72. // An unknown mode was passed in.
  73. //
  74. RIP("DrvSaveScreenBits: invalid iMode");
  75. }
  76. //
  77. // error if you get to here
  78. //
  79. return(FALSE);
  80. }
  81. /******************************Public*Routine******************************\
  82. * vCopyRects(pso,ppdev,prclSrc,prclTrg,cxPad,bIsSave) *
  83. * *
  84. * Breaks prclSrc up and copies the parts into prclTrg *
  85. * *
  86. \**************************************************************************/
  87. VOID vCopyRects(SURFOBJ *pso, PPDEV ppdev, RECTL * prclSrc, RECTL * prclTrg,
  88. LONG cxPad, BOOL bIsSave)
  89. {
  90. RECTL rclOnScreen;
  91. RECTL rclOffScreen;
  92. POINTL * pptlSrcTmp;
  93. RECTL * prclTrgTmp;
  94. ULONG cx, cy;
  95. ULONG cAlign;
  96. // We are assuming here that either the Trg is wider than the Src, or
  97. // the Trg is taller than the src.
  98. // We are assuming that if there is a nonzero cxPad, we are copying to
  99. // a rectangle such that the src is taller than the dst.
  100. // In other words, the prclTrg is a rectangle in the bottom offscreen
  101. // memory region, and the prclSrc needs to be broken up.
  102. ASSERTVGA(cxPad == 0 ||
  103. (prclSrc->bottom - prclSrc->top > prclTrg->bottom - prclTrg->top),
  104. "DrvSaveScreenBits: vCopyRects - cxPad is invalid\n");
  105. // Make sure that the src and trg are dword aligned.
  106. cAlign = (((prclSrc->left) - (prclTrg->left)) & (PELS_PER_DWORD - 1));
  107. if ((prclSrc->right - prclSrc->left) > prclTrg->right - prclTrg->left)
  108. {
  109. if ((prclSrc->bottom - prclSrc->top) >= prclTrg->bottom - prclTrg->top)
  110. {
  111. RIP("DrvSaveScreenBits: vCopyRects src is bigger than trg\n");
  112. }
  113. //
  114. // we need to break it up into vertical strips
  115. //
  116. cx = prclTrg->right - prclTrg->left;
  117. cy = prclSrc->bottom - prclSrc->top;
  118. ASSERTVGA(cx != 0, "DrvSaveScreenBits: vCopyRects (v save width == 0)\n");
  119. ASSERTVGA(cy != 0, "DrvSaveScreenBits: vCopyRects (v save height == 0)\n");
  120. rclOnScreen.right = prclSrc->left;
  121. rclOnScreen.top = prclSrc->top;
  122. rclOnScreen.bottom = prclSrc->top + cy;
  123. rclOffScreen.left = prclTrg->left;
  124. rclOffScreen.bottom = prclTrg->top;
  125. // align offscreen rect to src
  126. rclOffScreen.left += cAlign;
  127. /* local variable used without having been initialized */
  128. // rclOffScreen.right += cAlign;
  129. while (rclOnScreen.right < prclSrc->right)
  130. {
  131. cx = min(cx,(ULONG)(prclSrc->right - rclOnScreen.right));
  132. ASSERTVGA(cx != 0, "DrvSaveScreenBits: vCopyRects (cx == 0)\n");
  133. rclOnScreen.left = rclOnScreen.right;
  134. rclOnScreen.right += cx;
  135. rclOffScreen.right = rclOffScreen.left + cx; // in case cx is thinner on last
  136. rclOffScreen.top = rclOffScreen.bottom;
  137. rclOffScreen.bottom += cy;
  138. if (rclOffScreen.bottom > prclTrg->bottom)
  139. {
  140. RIP("DrvSaveScreenBits: vCopyRects can't fit src into trg (vertical)\n");
  141. }
  142. if (bIsSave)
  143. {
  144. // save
  145. pptlSrcTmp = (POINTL *) &rclOnScreen;
  146. prclTrgTmp = &rclOffScreen;
  147. DISPDBG((1,"DrvSaveScreenBits (v save): "));
  148. }
  149. else
  150. {
  151. // restore
  152. pptlSrcTmp = (POINTL *) &rclOffScreen;
  153. prclTrgTmp = &rclOnScreen;
  154. DISPDBG((1,"DrvSaveScreenBits (v restore): "));
  155. }
  156. DISPDBG((1,"%08x,%08x,%08x,%08x %lux%lu\n",
  157. rclOffScreen.left,
  158. rclOffScreen.top,
  159. rclOffScreen.right,
  160. rclOffScreen.bottom,
  161. rclOffScreen.right - rclOffScreen.left,
  162. rclOffScreen.bottom - rclOffScreen.top
  163. ));
  164. ASSERTVGA (((prclTrgTmp->left ^ pptlSrcTmp->x) &
  165. (PELS_PER_DWORD - 1)) == 0,
  166. "DrvSaveScreenBits (v): Src and Target are not aligned\n");
  167. DrvCopyBits(pso, // psoDst (screen)
  168. pso, // psoSrc (screen)
  169. NULL, // pco (none)
  170. NULL, // pxlo (none)
  171. prclTrgTmp, // prclDst
  172. pptlSrcTmp); // pptlSrc
  173. }
  174. }
  175. else if ((prclSrc->bottom - prclSrc->top) > prclTrg->bottom - prclTrg->top)
  176. {
  177. //
  178. // we need to break it up into horizontal strips
  179. //
  180. cx = prclSrc->right - prclSrc->left;
  181. cy = prclTrg->bottom - prclTrg->top;
  182. ASSERTVGA(cx != 0, "DrvSaveScreenBits: vCopyRects (h save width == 0)\n");
  183. ASSERTVGA(cy != 0, "DrvSaveScreenBits: vCopyRects (h save height == 0)\n");
  184. rclOnScreen.bottom = prclSrc->top;
  185. rclOnScreen.left = prclSrc->left;
  186. rclOnScreen.right = prclSrc->left + cx;
  187. rclOffScreen.top = prclTrg->top;
  188. rclOffScreen.right = prclTrg->left - cxPad;
  189. // align offscreen rect to src
  190. rclOffScreen.right += cAlign;
  191. while (rclOnScreen.bottom < prclSrc->bottom)
  192. {
  193. cy = min(cy,(ULONG)(prclSrc->bottom - rclOnScreen.bottom));
  194. ASSERTVGA(cy != 0, "DrvSaveScreenBits: vCopyRects (cy == 0)\n");
  195. rclOnScreen.top = rclOnScreen.bottom;
  196. rclOnScreen.bottom += cy;
  197. rclOffScreen.bottom = rclOffScreen.top + cy; // in case cy is shorter on last
  198. rclOffScreen.left = rclOffScreen.right + cxPad;
  199. rclOffScreen.right = rclOffScreen.left + cx;
  200. if (rclOffScreen.right > (prclTrg->right + (LONG)cAlign))
  201. {
  202. RIP("DrvSaveScreenBits: vCopyRects can't fit src into trg (horizontal)\n");
  203. }
  204. if (bIsSave)
  205. {
  206. // save
  207. pptlSrcTmp = (POINTL *) &rclOnScreen;
  208. prclTrgTmp = &rclOffScreen;
  209. DISPDBG((1,"DrvSaveScreenBits (h save): "));
  210. }
  211. else
  212. {
  213. // restore
  214. pptlSrcTmp = (POINTL *) &rclOffScreen;
  215. prclTrgTmp = &rclOnScreen;
  216. DISPDBG((1,"DrvSaveScreenBits (h restore): "));
  217. }
  218. DISPDBG((1,"%08x,%08x,%08x,%08x %lux%lu\n",
  219. rclOffScreen.left,
  220. rclOffScreen.top,
  221. rclOffScreen.right,
  222. rclOffScreen.bottom,
  223. rclOffScreen.right - rclOffScreen.left,
  224. rclOffScreen.bottom - rclOffScreen.top
  225. ));
  226. ASSERTVGA (((prclTrgTmp->left ^ pptlSrcTmp->x) &
  227. (PELS_PER_DWORD - 1)) == 0,
  228. "DrvSaveScreenBits (h): Src and Target are not aligned\n");
  229. DrvCopyBits(pso, // psoDst (screen)
  230. pso, // psoSrc (screen)
  231. NULL, // pco (none)
  232. NULL, // pxlo (none)
  233. prclTrgTmp, // prclDst
  234. pptlSrcTmp); // pptlSrc
  235. }
  236. }
  237. else
  238. {
  239. // we don't need to break it up at all
  240. cx = prclSrc->right - prclSrc->left;
  241. cy = prclSrc->bottom - prclSrc->top;
  242. ASSERTVGA(cx != 0, "DrvSaveScreenBits: vCopyRects (save width == 0)\n");
  243. ASSERTVGA(cy != 0, "DrvSaveScreenBits: vCopyRects (save height == 0)\n");
  244. rclOffScreen.left = prclTrg->left;
  245. rclOffScreen.right = prclTrg->left + cx;
  246. rclOffScreen.top = prclTrg->top;
  247. rclOffScreen.bottom = prclTrg->top + cy;
  248. // align offscreen rect to src
  249. rclOffScreen.left += cAlign;
  250. rclOffScreen.right += cAlign;
  251. if (bIsSave)
  252. {
  253. // save
  254. pptlSrcTmp = (POINTL *) prclSrc;
  255. prclTrgTmp = &rclOffScreen;
  256. DISPDBG((1,"DrvSaveScreenBits (save): "));
  257. }
  258. else
  259. {
  260. // restore
  261. pptlSrcTmp = (POINTL *) &rclOffScreen;
  262. prclTrgTmp = prclSrc;
  263. DISPDBG((1,"DrvSaveScreenBits (restore): "));
  264. }
  265. DISPDBG((1,"%08x,%08x,%08x,%08x %lux%lu\n",
  266. rclOffScreen.left,
  267. rclOffScreen.top,
  268. rclOffScreen.right,
  269. rclOffScreen.bottom,
  270. rclOffScreen.right - rclOffScreen.left,
  271. rclOffScreen.bottom - rclOffScreen.top
  272. ));
  273. ASSERTVGA (((prclTrgTmp->left ^ pptlSrcTmp->x) &
  274. (PELS_PER_DWORD - 1)) == 0,
  275. "DrvSaveScreenBits: Src and Target are not aligned\n");
  276. DrvCopyBits(pso, // psoDst (screen)
  277. pso, // psoSrc (screen)
  278. NULL, // pco (none)
  279. NULL, // pxlo (none)
  280. prclTrgTmp, // prclDst
  281. pptlSrcTmp); // pptlSrc
  282. }
  283. return;
  284. }
  285. /******************************Public*Routine******************************\
  286. * ulSaveOrRestoreBits(pso, ppdev,prcl,bIsSave) *
  287. * *
  288. * Saves or restores the specified area of the screen *
  289. * *
  290. \**************************************************************************/
  291. ULONG ulSaveOrRestoreBits(SURFOBJ *pso, PPDEV ppdev, RECTL * prcl, BOOL bIsSave)
  292. {
  293. ULONG dxDstBottom, dyDstBottom; // width, height of bottom edge off screen area
  294. ULONG dxDstRight, dyDstRight; // width, height of right edge off screen area
  295. ULONG dxSrc, dySrc; // width, height of screen area to copy
  296. RECTL rclSrcRight; // portion of *prcl to go into right edge area
  297. RECTL rclSrcBottom; // portion of *prcl to go into bottom edge area
  298. ULONG dxPadBottom; // width of spacer required to keep all copies
  299. // after the first aligned in the bottom
  300. // rectangle
  301. //
  302. // Saves bits from visible VGA memory in unused VGA memory
  303. //
  304. dxDstBottom = ppdev->rclSavedBitsBottom.right - ppdev->rclSavedBitsBottom.left;
  305. dyDstBottom = ppdev->rclSavedBitsBottom.bottom - ppdev->rclSavedBitsBottom.top;
  306. dxDstRight = ppdev->rclSavedBitsRight.right - ppdev->rclSavedBitsRight.left;
  307. dyDstRight = ppdev->rclSavedBitsRight.bottom - ppdev->rclSavedBitsRight.top;
  308. dxSrc = prcl->right - prcl->left;
  309. dySrc = prcl->bottom - prcl->top;
  310. // see if rect fits in lower rect, unbroken
  311. // this is the most common case!
  312. if (dySrc <= dyDstBottom && dxSrc <= dxDstBottom)
  313. {
  314. // YES!
  315. DISPDBG((1,"DrvSaveScreenBits: bits all fit into bottom rect\n"));
  316. vCopyRects(pso,
  317. ppdev,
  318. prcl,
  319. &ppdev->rclSavedBitsBottom,
  320. 0,
  321. bIsSave);
  322. return(SAVED_OFFSCREEN_ID);
  323. }
  324. // see if rect fits in right rect, unbroken
  325. if (dySrc <= dyDstRight && dxSrc <= dxDstRight)
  326. {
  327. // YES!
  328. DISPDBG((1,"DrvSaveScreenBits: bits all fit into right rect\n"));
  329. vCopyRects(pso,
  330. ppdev,
  331. prcl,
  332. &ppdev->rclSavedBitsRight,
  333. 0,
  334. bIsSave);
  335. return(SAVED_OFFSCREEN_ID);
  336. }
  337. //
  338. // before we bother to break it up, see if it could even POSSIBLY fit
  339. //
  340. if ((dxSrc * dySrc) > ((dxDstRight * dyDstRight) + (dxDstBottom * dyDstBottom)))
  341. {
  342. // Forget it bud. There are more bytes to save than we have total.
  343. // Don't bother checking for best fit.
  344. return(0);
  345. }
  346. // ARGGGHHHH!
  347. //
  348. // split source rectangle into two rectangles and see if they fit
  349. //
  350. rclSrcRight = rclSrcBottom = *prcl;
  351. //
  352. // see how many strips of height dySrc we can get into the rclDstRight
  353. // (of height dyDstRight) and then divide the rclSrc rectangles so
  354. // that rclSrcRight has that many strips and rclSrcBottom has what's left
  355. //
  356. rclSrcBottom.left = rclSrcRight.right =
  357. min(rclSrcBottom.right,
  358. rclSrcRight.left + (LONG)(dxDstRight * (dyDstRight/dySrc)));
  359. //
  360. // FYI: rclSrcRight WILL fit into ppdev->rclSavedBitsBottom because that's
  361. // how its size was determined
  362. //
  363. // dxPadBottom = (-x) & (PELS_PER_DWORD - 1) where x is the width of
  364. // the rectangle that we want to break up and put into the bottom offscreen
  365. // area. Therefore, ((rclSrcBottom.right-rclSrcBottom.left)+dxPadBottom)
  366. // will be a number of pels that is a DWORD multiple.
  367. dxPadBottom = (rclSrcBottom.left-rclSrcBottom.right) & (PELS_PER_DWORD - 1);
  368. if (((rclSrcBottom.right-rclSrcBottom.left) == 0) ||
  369. ((dySrc/dyDstBottom) <
  370. (dxDstBottom/((rclSrcBottom.right-rclSrcBottom.left)+dxPadBottom))))
  371. {
  372. //
  373. // rclSrcBottom fits into ppdev->rclSavedBitsBottom
  374. //
  375. if ((rclSrcRight.right - rclSrcRight.left) > 0)
  376. {
  377. //
  378. // there is data that should go into the right edge area
  379. //
  380. vCopyRects(pso,
  381. ppdev,
  382. &rclSrcRight,
  383. &ppdev->rclSavedBitsRight,
  384. 0,
  385. bIsSave);
  386. }
  387. if (((rclSrcBottom.right - rclSrcBottom.left) > 0) &&
  388. ((rclSrcBottom.bottom - rclSrcBottom.top) > 0))
  389. {
  390. //
  391. // there is data that should go into the bottom area
  392. //
  393. vCopyRects(pso,
  394. ppdev,
  395. &rclSrcBottom,
  396. &ppdev->rclSavedBitsBottom,
  397. dxPadBottom,
  398. bIsSave);
  399. }
  400. return(SAVED_OFFSCREEN_ID);
  401. }
  402. // All that @#!&ing work, and we just barely missed fitting in.
  403. return(0);
  404. }