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.

373 lines
13 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: dci.c
  3. *
  4. * This module contains the functions required to support DCI.
  5. *
  6. * Copyright (c) 1992-1995 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.h"
  9. #if (TARGET_BUILD == 351)
  10. /*
  11. * DCI support requires the use of structures and defined values
  12. * found in a header file that is only present in versions of
  13. * the DDK that support DCI, rather than having these items
  14. * in a DCI section of one of the standard header files. For this
  15. * reason, we can't do conditional compilation based on whether
  16. * the DCI-specific values are defined, because our first indication
  17. * would be an error due to the header file not being found.
  18. *
  19. * Explicit DCI support is only needed when building for NT 3.51,
  20. * since it was added for this version, but for version 4.0 (next
  21. * version) and above it is incorporated into Direct Draw rather
  22. * than being handled separately.
  23. *
  24. * Since this entire module depends on DCI being supported by the
  25. * build environment, null it out if this is not the case.
  26. */
  27. #include <dciddi.h>
  28. #include "dci.h"
  29. /******************************Public*Routine******************************\
  30. * DCIRVAL BeginAccess
  31. *
  32. * Map in the screen memory so that the DCI application can access it.
  33. \**************************************************************************/
  34. DCIRVAL BeginAccess(DCISURF* pDCISurf, LPRECT rcl)
  35. {
  36. PDEV* ppdev;
  37. VIDEO_SHARE_MEMORY shareMemory;
  38. VIDEO_SHARE_MEMORY_INFORMATION shareMemoryInformation;
  39. DWORD returnedDataLength;
  40. DISPDBG((DEBUG_ENTRY_EXIT, "--> BeginAccess with pDCISurf %08lx", pDCISurf));
  41. ppdev = pDCISurf->ppdev;
  42. if (pDCISurf->SurfaceInfo.dwOffSurface != 0)
  43. {
  44. /*
  45. * We have already mapped in the frame buffer. All our
  46. * accelerators unmap the frame buffer in the
  47. * DestroySurface() call, so if this is the beginning
  48. * of the second or subsequent BeginAccess()/EndAccess()
  49. * pair since the surface was created, we don't need to
  50. * map the frame buffer again.
  51. *
  52. * Wait for any pending accelerator operations to complete before
  53. * yielding control, in case it affects the same screen region
  54. * that DCI wants.
  55. */
  56. if (ppdev->iMachType == MACH_MM_64)
  57. {
  58. vM64QuietDown(ppdev, ppdev->pjMmBase);
  59. }
  60. else if (ppdev->iMachType == MACH_MM_32)
  61. {
  62. vM32QuietDown(ppdev, ppdev->pjMmBase);
  63. }
  64. else /* if (ppdev->iMachType == MACH_IO_32) */
  65. {
  66. vI32QuietDown(ppdev, ppdev->pjIoBase);
  67. }
  68. DISPDBG((DEBUG_ENTRY_EXIT, "<-- BeginAccess"));
  69. return(DCI_OK);
  70. }
  71. else
  72. {
  73. shareMemory.ProcessHandle = EngGetProcessHandle();
  74. shareMemory.RequestedVirtualAddress = 0;
  75. shareMemory.ViewOffset = pDCISurf->Offset;
  76. shareMemory.ViewSize = pDCISurf->Size;
  77. /*
  78. * Wait for any pending accelerator operations to complete
  79. * before yielding control, in case it affects the same
  80. * screen region that DCI wants.
  81. */
  82. if (ppdev->iMachType == MACH_MM_64)
  83. {
  84. vM64QuietDown(ppdev, ppdev->pjMmBase);
  85. }
  86. else if (ppdev->iMachType == MACH_MM_32)
  87. {
  88. vM32QuietDown(ppdev, ppdev->pjMmBase);
  89. }
  90. else /* if (ppdev->iMachType == MACH_IO_32) */
  91. {
  92. vI32QuietDown(ppdev, ppdev->pjIoBase);
  93. }
  94. /*
  95. * Now map the frame buffer into the caller's address space:
  96. *
  97. * Be careful when mixing VideoPortMapBankedMemory (i.e., vflatd)
  98. * access with explicit banking in the driver -- the two may get
  99. * out of sync with respect to what bank they think the hardware
  100. * is currently configured for. The easiest way to avoid any
  101. * problem is to call VideoPortMapBankedMemory/VideoPortUnmapMemory
  102. * in the miniport for every BeginAccess/EndAccess pair, and to
  103. * always explicitly reset the bank after the EndAccess.
  104. * (VideoPortMapBankedMemory will always reset vflatd's current
  105. * bank.)
  106. */
  107. if (!AtiDeviceIoControl(pDCISurf->ppdev->hDriver,
  108. IOCTL_VIDEO_SHARE_VIDEO_MEMORY,
  109. &shareMemory,
  110. sizeof(VIDEO_SHARE_MEMORY),
  111. &shareMemoryInformation,
  112. sizeof(VIDEO_SHARE_MEMORY_INFORMATION),
  113. &returnedDataLength))
  114. {
  115. DISPDBG((DEBUG_ERROR, "BeginAccess: failed IOCTL_VIDEO_SHARE_VIDEO_MEMORY"));
  116. return(DCI_FAIL_GENERIC);
  117. }
  118. pDCISurf->SurfaceInfo.wSelSurface = 0;
  119. pDCISurf->SurfaceInfo.dwOffSurface =
  120. (ULONG) shareMemoryInformation.VirtualAddress;
  121. /*
  122. * We return DCI_STATUS_POINTERCHANGED because we have
  123. * just created a new pointer to the frame buffer.
  124. * Repeated BeginAccess()/EndAccess() calls without
  125. * a call to DestroySurface() will hit this case on the
  126. * first call, but meet the "if" condition (buffer
  127. * already mapped) on subsequent calls.
  128. *
  129. * We would only need to map the DCI pointer on every
  130. * call to BeginAccess() and unmap it on every call
  131. * to EndAccess() if we couldn't support simultaneous
  132. * accelerator and frame buffer access. All our cards
  133. * with frame buffer capability support such access,
  134. * and it's GDI's responsibility to ensure that no
  135. * GDI call is made between the calls to BeginAccess()
  136. * and EndAccess(), so we don't need a critical section
  137. * to ensure that a GDI call doesn't change the page
  138. * while DCI is accessing the frame buffer if we are
  139. * using a banked aperture.
  140. */
  141. #if DBG
  142. DISPDBG((DEBUG_ENTRY_EXIT, "<-- BeginAccess DCI_STATUS_POINTERCHANGED %08lx\n", pDCISurf));
  143. #endif
  144. return(DCI_STATUS_POINTERCHANGED);
  145. }
  146. }
  147. /******************************Public*Routine******************************\
  148. * VOID vUnmap
  149. *
  150. * Unmap the screen memory so that the DCI application can no longer access
  151. * it.
  152. \**************************************************************************/
  153. VOID vUnmap(DCISURF* pDCISurf)
  154. {
  155. PDEV* ppdev;
  156. VIDEO_SHARE_MEMORY shareMemory;
  157. DWORD returnedDataLength;
  158. ppdev = pDCISurf->ppdev;
  159. /*
  160. * We no longer need to have the frame buffer mapped for DCI,
  161. * so unmap it.
  162. */
  163. shareMemory.ProcessHandle = EngGetProcessHandle();
  164. shareMemory.ViewOffset = 0;
  165. shareMemory.ViewSize = 0;
  166. shareMemory.RequestedVirtualAddress =
  167. (VOID*) pDCISurf->SurfaceInfo.dwOffSurface;
  168. if (!AtiDeviceIoControl(pDCISurf->ppdev->hDriver,
  169. IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY,
  170. &shareMemory,
  171. sizeof(VIDEO_SHARE_MEMORY),
  172. NULL,
  173. 0,
  174. &returnedDataLength))
  175. {
  176. DISPDBG((DEBUG_ERROR, "EndAccess failed IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY"));
  177. }
  178. else
  179. {
  180. /*
  181. * Be sure to signal to GDI that the surface is no longer mapped.
  182. */
  183. pDCISurf->SurfaceInfo.dwOffSurface = 0;
  184. }
  185. }
  186. /******************************Public*Routine******************************\
  187. * DCIRVAL EndAccess
  188. *
  189. * Switch control of the frame buffer from DCI back to GDI.
  190. \**************************************************************************/
  191. DCIRVAL EndAccess(DCISURF* pDCISurf)
  192. {
  193. PDEV* ppdev;
  194. /*
  195. * We would only need to unmap the frame buffer at this
  196. * point if our cards couldn't support simultaneous frame
  197. * buffer and accelerator access. Since our cards with
  198. * frame buffer capability all support such access (provided
  199. * the two accesses refer to different parts of the screen,
  200. * since otherwise they'd corrupt each other, but it's
  201. * GDI's responsibility to ensure that this is the case),
  202. * this function only needs to ensure that no call to
  203. * EndAccess() is made without a corresponding call to
  204. * BeginAccess() having already been made.
  205. */
  206. DISPDBG((DEBUG_ENTRY_EXIT, "EndAccess with pDCISurf %08lx\n", pDCISurf));
  207. ASSERTDD(pDCISurf->SurfaceInfo.dwOffSurface != 0,
  208. "GDI should assure us that EndAccess can't be recursive");
  209. ppdev = pDCISurf->ppdev;
  210. return(DCI_OK);
  211. }
  212. /******************************Public*Routine******************************\
  213. * VOID DestroySurface
  214. *
  215. * Destroy the DCI surface and free up any allocations.
  216. \**************************************************************************/
  217. VOID DestroySurface(DCISURF* pDCISurf)
  218. {
  219. DISPDBG((DEBUG_ENTRY_EXIT, "DestroySurface with pDCISurf %08lx\n", pDCISurf));
  220. if (pDCISurf->SurfaceInfo.dwOffSurface != 0)
  221. {
  222. /*
  223. * Because we can support simultaneous frame buffer and
  224. * accelerator access, we optimized a bit by not unmapping
  225. * the frame buffer on every EndAccess() call, but we
  226. * finally have to do the unmap now. The dwOffSurface field
  227. * should always be nonzero (a frame buffer has been mapped),
  228. * but there's no harm in checking.
  229. */
  230. vUnmap(pDCISurf);
  231. }
  232. LocalFree(pDCISurf);
  233. }
  234. /******************************Public*Routine******************************\
  235. * ULONG DCICreatePrimarySurface
  236. *
  237. * Create a DCI surface to provide access to the visible screen.
  238. \**************************************************************************/
  239. ULONG DCICreatePrimarySurface(PDEV* ppdev, ULONG cjIn, VOID* pvIn, ULONG cjOut, VOID* pvOut)
  240. {
  241. DCISURF* pDCISurf;
  242. LPDCICREATEINPUT pInput;
  243. LONG lRet;
  244. #if defined(MIPS) || defined(_PPC_)
  245. {
  246. /*
  247. * !!! vflatd seems to currently have a bug on Mips and PowerPC:
  248. */
  249. return (ULONG) (DCI_FAIL_UNSUPPORTED);
  250. }
  251. #endif
  252. if( !(ppdev->FeatureFlags & EVN_DENSE_CAPABLE) )
  253. {
  254. /*
  255. * We don't support DCI on the Alpha when running in sparse
  256. * space, because we can't.
  257. */
  258. lRet = DCI_FAIL_UNSUPPORTED;
  259. }
  260. else
  261. {
  262. pInput = (DCICREATEINPUT*) pvIn;
  263. if (cjIn >= sizeof(DCICREATEINPUT))
  264. {
  265. pDCISurf = (DCISURF*) LocalAlloc(LMEM_ZEROINIT, sizeof(DCISURF));
  266. if (pDCISurf)
  267. {
  268. /*
  269. * Initializate all public information about the primary
  270. * surface.
  271. */
  272. pDCISurf->SurfaceInfo.dwSize = sizeof(DCISURFACEINFO);
  273. pDCISurf->SurfaceInfo.dwDCICaps = DCI_PRIMARY | DCI_VISIBLE;
  274. pDCISurf->SurfaceInfo.BeginAccess = BeginAccess;
  275. pDCISurf->SurfaceInfo.EndAccess = EndAccess;
  276. pDCISurf->SurfaceInfo.DestroySurface = DestroySurface;
  277. pDCISurf->SurfaceInfo.dwMask[0] = ppdev->flRed;
  278. pDCISurf->SurfaceInfo.dwMask[1] = ppdev->flGreen;
  279. pDCISurf->SurfaceInfo.dwMask[2] = ppdev->flBlue;
  280. pDCISurf->SurfaceInfo.dwBitCount = ppdev->cBitsPerPel;
  281. pDCISurf->SurfaceInfo.dwWidth = ppdev->cxScreen;
  282. pDCISurf->SurfaceInfo.dwHeight = ppdev->cyScreen;
  283. pDCISurf->SurfaceInfo.lStride = ppdev->lDelta;
  284. pDCISurf->SurfaceInfo.wSelSurface = 0;
  285. pDCISurf->SurfaceInfo.dwOffSurface = 0;
  286. if (pDCISurf->SurfaceInfo.dwBitCount <= 8)
  287. {
  288. pDCISurf->SurfaceInfo.dwCompression = BI_RGB;
  289. }
  290. else
  291. {
  292. pDCISurf->SurfaceInfo.dwCompression = BI_BITFIELDS;
  293. }
  294. /*
  295. * Now initialize our private fields that we want associated
  296. * with the DCI surface:
  297. */
  298. pDCISurf->ppdev = ppdev;
  299. pDCISurf->Offset = 0;
  300. /*
  301. * Under NT, all mapping is done with a 64K granularity.
  302. */
  303. pDCISurf->Size = ROUND_UP_TO_64K(ppdev->cyScreen * ppdev->lDelta);
  304. /*
  305. * Return a pointer to the DCISURF to GDI by placing
  306. * it in the 'pvOut' buffer.
  307. */
  308. *((DCISURF**) pvOut) = pDCISurf;
  309. lRet = DCI_OK;
  310. }
  311. else
  312. {
  313. lRet = DCI_ERR_OUTOFMEMORY;
  314. }
  315. }
  316. else
  317. {
  318. lRet = DCI_FAIL_GENERIC;
  319. }
  320. }
  321. return(lRet);
  322. }
  323. #endif /* TARGET_BUILD == 351 */
  324.