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.

434 lines
12 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: pointer.c
  3. *
  4. * This module contains the hardware Pointer support.
  5. *
  6. * Copyright (c) 1992-1995 Microsoft Corporation
  7. * Copyright (c) 1993-1995 Weitek Corporation
  8. \**************************************************************************/
  9. #include "precomp.h"
  10. /******************************Public*Routine******************************\
  11. * BOOL bCopyMonoPointer
  12. *
  13. * Copies two monochrome masks into a buffer of the maximum size handled by the
  14. * miniport, with any extra bits set to 0. The masks are converted to topdown
  15. * form if they aren't already. Returns TRUE if we can handle this pointer in
  16. * hardware, FALSE if not.
  17. *
  18. \**************************************************************************/
  19. BOOL bCopyMonoPointer(
  20. PDEV* ppdev,
  21. SURFOBJ* pso)
  22. {
  23. ULONG cy;
  24. BYTE* pjSrcAnd;
  25. BYTE* pjSrcXor;
  26. LONG lDeltaSrc;
  27. LONG lDeltaDst;
  28. LONG lSrcWidthInBytes;
  29. ULONG cxSrc;
  30. ULONG cySrc;
  31. ULONG cxSrcBytes;
  32. BYTE* pjDstAnd;
  33. BYTE* pjDstXor;
  34. PVIDEO_POINTER_ATTRIBUTES pPointerAttributes;
  35. pPointerAttributes = ppdev->pPointerAttributes;
  36. cxSrc = pso->sizlBitmap.cx;
  37. cySrc = pso->sizlBitmap.cy;
  38. pjDstAnd = pPointerAttributes->Pixels;
  39. pjDstXor = pPointerAttributes->Pixels;
  40. // Make sure the new pointer isn't too big to handle
  41. // (*2 because both masks are in there)
  42. if ((cxSrc > ppdev->PointerCapabilities.MaxWidth) ||
  43. (cySrc > (ppdev->PointerCapabilities.MaxHeight * 2)))
  44. {
  45. return(FALSE);
  46. }
  47. pjDstXor += ((ppdev->PointerCapabilities.MaxWidth + 7) / 8) *
  48. pPointerAttributes->Height;
  49. // Set the desk and mask to 0xff
  50. RtlFillMemory(pjDstAnd, pPointerAttributes->WidthInBytes *
  51. pPointerAttributes->Height, 0xFF);
  52. // Zero the dest XOR mask
  53. RtlZeroMemory(pjDstXor, pPointerAttributes->WidthInBytes *
  54. pPointerAttributes->Height);
  55. cxSrcBytes = (cxSrc + 7) / 8;
  56. if ((lDeltaSrc = pso->lDelta) < 0)
  57. {
  58. lSrcWidthInBytes = -lDeltaSrc;
  59. }
  60. else
  61. {
  62. lSrcWidthInBytes = lDeltaSrc;
  63. }
  64. pjSrcAnd = (BYTE*) pso->pvScan0;
  65. // Height of just AND mask
  66. cySrc = cySrc / 2;
  67. // Point to XOR mask
  68. pjSrcXor = pjSrcAnd + (cySrc * lDeltaSrc);
  69. // Offset from end of one dest scan to start of next
  70. lDeltaDst = pPointerAttributes->WidthInBytes;
  71. for (cy = 0; cy < cySrc; ++cy)
  72. {
  73. RtlCopyMemory(pjDstAnd, pjSrcAnd, cxSrcBytes);
  74. RtlCopyMemory(pjDstXor, pjSrcXor, cxSrcBytes);
  75. // Point to next source and dest scans
  76. pjSrcAnd += lDeltaSrc;
  77. pjSrcXor += lDeltaSrc;
  78. pjDstAnd += lDeltaDst;
  79. pjDstXor += lDeltaDst;
  80. }
  81. return(TRUE);
  82. }
  83. /******************************Public*Routine******************************\
  84. * BOOL bSetHardwarePointerShape
  85. *
  86. * Changes the shape of the Hardware Pointer.
  87. *
  88. * Returns: True if successful, False if Pointer shape can't be hardware.
  89. *
  90. \**************************************************************************/
  91. BOOL bSetHardwarePointerShape(
  92. SURFOBJ* pso,
  93. SURFOBJ* psoMask,
  94. SURFOBJ* psoColor,
  95. XLATEOBJ* pxlo,
  96. LONG x,
  97. LONG y,
  98. FLONG fl)
  99. {
  100. PDEV* ppdev;
  101. DWORD returnedDataLength;
  102. PVIDEO_POINTER_ATTRIBUTES pPointerAttributes;
  103. ppdev = (PDEV*) pso->dhpdev;
  104. pPointerAttributes = ppdev->pPointerAttributes;
  105. // Don't make any assumptions about the pointer flags.
  106. pPointerAttributes->Flags = 0;
  107. // We don't support color pointers.
  108. if (psoColor != NULL)
  109. {
  110. return(FALSE);
  111. }
  112. if ((ppdev->PointerCapabilities.Flags & VIDEO_MODE_MONO_POINTER) &&
  113. bCopyMonoPointer(ppdev, psoMask))
  114. {
  115. pPointerAttributes->Flags |= VIDEO_MODE_MONO_POINTER;
  116. }
  117. else
  118. {
  119. return(FALSE);
  120. }
  121. // Initialize Pointer attributes and position
  122. pPointerAttributes->Column = (SHORT)(x - ppdev->ptlHotSpot.x);
  123. pPointerAttributes->Row = (SHORT)(y - ppdev->ptlHotSpot.y);
  124. pPointerAttributes->Enable = 1;
  125. if (fl & SPS_ANIMATESTART)
  126. {
  127. pPointerAttributes->Flags |= VIDEO_MODE_ANIMATE_START;
  128. }
  129. else if (fl & SPS_ANIMATEUPDATE)
  130. {
  131. pPointerAttributes->Flags |= VIDEO_MODE_ANIMATE_UPDATE;
  132. }
  133. // Set the new Pointer shape.
  134. CP_WAIT(ppdev, ppdev->pjBase);
  135. if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_SET_POINTER_ATTR,
  136. pPointerAttributes, ppdev->cjPointerAttributes, NULL, 0,
  137. &returnedDataLength))
  138. {
  139. DISPDBG((0, "Failed IOCTL_VIDEO_SET_POINTER_ATTR call"));
  140. return(FALSE);
  141. }
  142. return(TRUE);
  143. }
  144. /******************************Public*Routine******************************\
  145. * VOID DrvMovePointer
  146. *
  147. * Moves the hardware pointer to a new position.
  148. *
  149. \**************************************************************************/
  150. VOID DrvMovePointer(
  151. SURFOBJ* pso,
  152. LONG x,
  153. LONG y,
  154. RECTL* prcl)
  155. {
  156. PDEV* ppdev;
  157. DWORD returnedDataLength;
  158. VIDEO_POINTER_POSITION NewPointerPosition;
  159. ppdev = (PDEV*) pso->dhpdev;
  160. // We don't use the exclusion rectangle because we only support
  161. // hardware Pointers. If we were doing our own Pointer simulations
  162. // we would want to update prcl so that the engine would call us
  163. // to exclude out pointer before drawing to the pixels in prcl.
  164. CP_WAIT(ppdev, ppdev->pjBase);
  165. if (x == -1)
  166. {
  167. // A new position of (-1,-1) means hide the pointer.
  168. if (EngDeviceIoControl(ppdev->hDriver,IOCTL_VIDEO_DISABLE_POINTER,
  169. NULL, 0, NULL, 0, &returnedDataLength))
  170. {
  171. // Not the end of the world, print warning in checked build.
  172. DISPDBG((0, "Failed IOCTL_VIDEO_DISABLE_POINTER"));
  173. }
  174. }
  175. else
  176. {
  177. NewPointerPosition.Column = (SHORT) x - (SHORT) (ppdev->ptlHotSpot.x);
  178. NewPointerPosition.Row = (SHORT) y - (SHORT) (ppdev->ptlHotSpot.y);
  179. // Call NT screen driver to move Pointer.
  180. if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_SET_POINTER_POSITION,
  181. &NewPointerPosition, sizeof(VIDEO_POINTER_POSITION), NULL,
  182. 0, &returnedDataLength))
  183. {
  184. // Not the end of the world, print warning in checked build.
  185. DISPDBG((0, "Failed IOCTL_VIDEO_SET_POINTER_POSITION"));
  186. }
  187. }
  188. }
  189. /******************************Public*Routine******************************\
  190. * ULONG DrvSetPointerShape
  191. *
  192. * Sets the new pointer shape.
  193. *
  194. \**************************************************************************/
  195. ULONG DrvSetPointerShape(
  196. SURFOBJ* pso,
  197. SURFOBJ* psoMask,
  198. SURFOBJ* psoColor,
  199. XLATEOBJ* pxlo,
  200. LONG xHot,
  201. LONG yHot,
  202. LONG x,
  203. LONG y,
  204. RECTL* prcl,
  205. FLONG fl)
  206. {
  207. PDEV* ppdev;
  208. DWORD returnedDataLength;
  209. ppdev = (PDEV*) pso->dhpdev;
  210. // We don't use the exclusion rectangle because we only support
  211. // hardware Pointers. If we were doing our own Pointer simulations
  212. // we would want to update prcl so that the engine would call us
  213. // to exclude out pointer before drawing to the pixels in prcl.
  214. if (ppdev->pPointerAttributes == (PVIDEO_POINTER_ATTRIBUTES) NULL)
  215. {
  216. // Mini-port has no hardware Pointer support.
  217. return(SPS_DECLINE);
  218. }
  219. // See if we are being asked to hide the pointer
  220. // !!! Wrong
  221. if (psoMask == (SURFOBJ *) NULL)
  222. {
  223. CP_WAIT(ppdev, ppdev->pjBase);
  224. if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_DISABLE_POINTER,
  225. NULL, 0, NULL, 0, &returnedDataLength))
  226. {
  227. // It should never be possible to fail.
  228. DISPDBG((0, "Failed IOCTL_VIDEO_DISABLE_POINTER"));
  229. }
  230. return(TRUE); // !!! Wrong
  231. }
  232. ppdev->ptlHotSpot.x = xHot;
  233. ppdev->ptlHotSpot.y = yHot;
  234. if (!bSetHardwarePointerShape(pso,psoMask,psoColor,pxlo,x,y,fl))
  235. {
  236. if (ppdev->bHwPointerActive)
  237. {
  238. ppdev->bHwPointerActive = FALSE;
  239. CP_WAIT(ppdev, ppdev->pjBase);
  240. if (EngDeviceIoControl(ppdev->hDriver,
  241. IOCTL_VIDEO_DISABLE_POINTER, NULL, 0, NULL, 0,
  242. &returnedDataLength))
  243. {
  244. DISPDBG((0, "Failed IOCTL_VIDEO_DISABLE_POINTER"));
  245. }
  246. }
  247. // Mini-port declines to realize this Pointer
  248. return(SPS_DECLINE);
  249. }
  250. else
  251. {
  252. ppdev->bHwPointerActive = TRUE;
  253. }
  254. return(SPS_ACCEPT_NOEXCLUDE);
  255. }
  256. /******************************Public*Routine******************************\
  257. * VOID vDisablePointer
  258. *
  259. \**************************************************************************/
  260. VOID vDisablePointer(
  261. PDEV* ppdev)
  262. {
  263. EngFreeMem(ppdev->pPointerAttributes);
  264. }
  265. /******************************Public*Routine******************************\
  266. * VOID vAssertModePointer
  267. *
  268. \**************************************************************************/
  269. VOID vAssertModePointer(
  270. PDEV* ppdev,
  271. BOOL bEnable)
  272. {
  273. }
  274. /******************************Public*Routine******************************\
  275. * BOOL bEnablePointer
  276. *
  277. * Note: We can return TRUE, as long as pPointerAttributes is set to NULL,
  278. * and we will make due with a software cursor.
  279. *
  280. \**************************************************************************/
  281. BOOL bEnablePointer(
  282. PDEV* ppdev)
  283. {
  284. DWORD returnedDataLength;
  285. DWORD MaxWidth;
  286. DWORD MaxHeight;
  287. VIDEO_POINTER_ATTRIBUTES* pPointerAttributes;
  288. ppdev->pPointerAttributes = NULL;
  289. ppdev->cjPointerAttributes = 0;
  290. // Ask the miniport whether it provides pointer support.
  291. if (EngDeviceIoControl(ppdev->hDriver,
  292. IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES, &ppdev->ulMode,
  293. sizeof(PVIDEO_MODE), &ppdev->PointerCapabilities,
  294. sizeof(ppdev->PointerCapabilities), &returnedDataLength))
  295. {
  296. return(TRUE);
  297. }
  298. // If neither mono nor color hardware pointer is supported, there's no
  299. // hardware pointer support and we're done.
  300. if ((!(ppdev->PointerCapabilities.Flags & VIDEO_MODE_MONO_POINTER)) &&
  301. (!(ppdev->PointerCapabilities.Flags & VIDEO_MODE_COLOR_POINTER)))
  302. {
  303. return(TRUE);
  304. }
  305. // Note: The buffer itself is allocated after we set the
  306. // mode. At that time we know the pixel depth and we can
  307. // allocate the correct size for the color pointer if supported.
  308. // It's a hardware pointer; set up pointer attributes.
  309. MaxHeight = ppdev->PointerCapabilities.MaxHeight;
  310. // Allocate space for two DIBs (data/mask) for the pointer. If this
  311. // device supports a color Pointer, we will allocate a larger bitmap.
  312. // If this is a color bitmap we allocate for the largest possible
  313. // bitmap because we have no idea of what the pixel depth might be.
  314. // Width rounded up to nearest byte multiple
  315. if (!(ppdev->PointerCapabilities.Flags & VIDEO_MODE_COLOR_POINTER))
  316. {
  317. MaxWidth = (ppdev->PointerCapabilities.MaxWidth + 7) / 8;
  318. }
  319. else
  320. {
  321. MaxWidth = ppdev->PointerCapabilities.MaxWidth * sizeof(DWORD);
  322. }
  323. ppdev->cjPointerAttributes =
  324. sizeof(VIDEO_POINTER_ATTRIBUTES) +
  325. ((sizeof(UCHAR) * MaxWidth * MaxHeight) * 2);
  326. pPointerAttributes = (PVIDEO_POINTER_ATTRIBUTES)
  327. EngAllocMem(FL_ZERO_MEMORY,
  328. ppdev->cjPointerAttributes, ALLOC_TAG);
  329. if (pPointerAttributes == NULL)
  330. {
  331. return(TRUE);
  332. }
  333. pPointerAttributes->WidthInBytes = MaxWidth;
  334. pPointerAttributes->Width = ppdev->PointerCapabilities.MaxWidth;
  335. pPointerAttributes->Height = MaxHeight;
  336. pPointerAttributes->Column = 0;
  337. pPointerAttributes->Row = 0;
  338. pPointerAttributes->Enable = 0;
  339. ppdev->pPointerAttributes = pPointerAttributes;
  340. return(TRUE);
  341. }