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.

462 lines
13 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: pixelfmt.cxx
  3. *
  4. * This contains the pixel format functions.
  5. *
  6. * Created: 21-Sep-1993
  7. * Author: Hock San Lee [hockl]
  8. *
  9. * 02-Nov-1995 -by- Drew Bliss [drewb]
  10. * Restored in kernel mode in minimal form
  11. *
  12. * Copyright (c) 1993-1999 Microsoft Corporation
  13. \**************************************************************************/
  14. #include "precomp.hxx"
  15. // Number of generic pixel formats. There are 5 pixel depths (4,8,16,24,32).
  16. // See GreDescribePixelFormat for details.
  17. #define MIN_GENERIC_PFD 1
  18. #define MAX_GENERIC_PFD 24
  19. /******************************Public*Routine******************************\
  20. * LONG XDCOBJ::ipfdDevMaxGet()
  21. *
  22. * Initialize and return the maximum device supported pixel format index.
  23. *
  24. * The ipfdDevMax is set to -1 initially but is set to 0 or the maximum
  25. * device pixel format index here. This function should be called at most
  26. * once for the given DC.
  27. *
  28. * History:
  29. * Tue Sep 21 14:25:04 1993 -by- Hock San Lee [hockl]
  30. * Wrote it.
  31. \**************************************************************************/
  32. LONG XDCOBJ::ipfdDevMaxGet()
  33. {
  34. PDEVOBJ pdo(hdev());
  35. int ipfd = 0;
  36. DEVLOCKOBJ dlo(pdo);
  37. #ifdef OPENGL_MM
  38. if (pdo.bMetaDriver())
  39. {
  40. // We need to change the meta-PDEV into a hardware specific PDEV
  41. HDEV hdevDevice = hdevFindDeviceHdev(
  42. hdev(), (RECTL) pdc->erclWindow(), NULL);
  43. if (hdevDevice)
  44. {
  45. // replace meta pdevobj with device specific hdev.
  46. pdo.vInit(hdevDevice);
  47. }
  48. }
  49. #endif // OPENGL_MM
  50. if (PPFNVALID(pdo, DescribePixelFormat))
  51. {
  52. ipfd = (*PPFNDRV(pdo, DescribePixelFormat))(pdo.dhpdev(), 1, 0, NULL);
  53. if (ipfd < 0)
  54. {
  55. ipfd = 0;
  56. }
  57. }
  58. ipfdDevMax((SHORT)ipfd);
  59. return ipfd;
  60. }
  61. /******************************Public*Routine******************************\
  62. * GreDescribePixelFormat
  63. *
  64. * Request pixel format information from a driver
  65. * If cjpfd is 0, just return the maximum driver pixel format index.
  66. *
  67. * Returns: 0 if error; maximum driver pixel format index otherwise
  68. *
  69. * History:
  70. * 02-Nov-95 -by- Drew Bliss [drewb]
  71. * Stripped down to driver-only support for kernel-mode
  72. * Mon Apr 25 15:34:32 1994 -by- Hock San Lee [hockl]
  73. * Added 16-bit Z buffer formats and removed double buffered formats for bitmaps.
  74. * Tue Sep 21 14:25:04 1993 -by- Hock San Lee [hockl]
  75. * Wrote it.
  76. \**************************************************************************/
  77. int GreDescribePixelFormat(HDC hdc, int ipfd, UINT cjpfd,
  78. PPIXELFORMATDESCRIPTOR ppfd)
  79. {
  80. // Validate DC.
  81. DCOBJ dco(hdc);
  82. if (!dco.bValid())
  83. {
  84. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  85. return(0);
  86. }
  87. int ipfdDevMax = dco.ipfdDevMax();
  88. // If cjpfd is 0, just return the maximum pixel format index.
  89. if (cjpfd == 0)
  90. return ipfdDevMax;
  91. // Validate the size of the pixel format descriptor.
  92. if (cjpfd < sizeof(PIXELFORMATDESCRIPTOR))
  93. {
  94. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  95. return(0);
  96. }
  97. // Validate pixel format index.
  98. // If a driver support device pixel formats 1..ipfdDevMax, the generic
  99. // pixel formats will be (ipfdDevMax+1)..(ipfdDevMax+MAX_GENERIC_PFD).
  100. // Otherwise, ipfdDevMax is 0 and the generic pixel formats are
  101. // 1..MAX_GENERIC_PFD.
  102. if ((ipfd < 1) || (ipfd > ipfdDevMax))
  103. {
  104. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  105. return(0);
  106. }
  107. PDEVOBJ po(dco.hdev());
  108. DEVLOCKOBJ dlo(po);
  109. #ifdef OPENGL_MM
  110. if (po.bMetaDriver())
  111. {
  112. // We need to change the meta-PDEV into a hardware specific PDEV
  113. HDEV hdevDevice = hdevFindDeviceHdev(
  114. dco.hdev(), (RECTL)dco.erclWindow(), NULL);
  115. if (hdevDevice)
  116. {
  117. // replace meta pdevobj with device specific hdev.
  118. po.vInit(hdevDevice);
  119. }
  120. }
  121. #endif // OPENGL_MM
  122. int iRet = 0;
  123. if (PPFNVALID(po, DescribePixelFormat))
  124. {
  125. iRet = (int) (*PPFNDRV(po, DescribePixelFormat))
  126. (po.dhpdev(), ipfd, cjpfd, ppfd);
  127. }
  128. if (iRet == 0)
  129. return(0);
  130. ASSERTGDI(iRet == ipfdDevMax, "Bad ipfdDevMax");
  131. return ipfdDevMax;
  132. }
  133. /******************************Public*Routine******************************\
  134. * NtGdiSetPixelFormat
  135. *
  136. * Set the pixel format.
  137. *
  138. * This is a special function. It is one of the three (the other two are
  139. * ExtEscape for WNDOBJ_SETUP escape and ExtEscape for 3D-DDI
  140. * RX_CREATECONTEXT escape) functions that allow WNDOBJ to be created in
  141. * the DDI. We need to be in the user critical section and grab the devlock
  142. * in the function before calling the DrvSetPixelFormat function to ensure
  143. * that the new WNDOBJ created is current.
  144. *
  145. * Returns: FALSE if error; TRUE otherwise
  146. *
  147. * History:
  148. * 02-Nov-95 -by- Drew Bliss [drewb]
  149. * Changed to driver-only kernel-mode form
  150. * Tue Sep 21 14:25:04 1993 -by- Hock San Lee [hockl]
  151. * Wrote it.
  152. \**************************************************************************/
  153. BOOL NtGdiSetPixelFormat(HDC hdc,int ipfd)
  154. {
  155. // Validate DC and surface. Info DC is not allowed.
  156. DCOBJ dco(hdc);
  157. if (!dco.bValid() || !dco.bHasSurface())
  158. {
  159. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  160. return(FALSE);
  161. }
  162. // Validate pixel format index.
  163. // If a driver support device pixel formats 1..ipfdDevMax, the generic
  164. // pixel formats will be (ipfdDevMax+1)..(ipfdDevMax+MAX_GENERIC_PFD).
  165. // Otherwise, ipfdDevMax is 0 and the generic pixel formats are
  166. // 1..MAX_GENERIC_PFD.
  167. int ipfdDevMax = dco.ipfdDevMax();
  168. if ((ipfd < 1) || (ipfd > ipfdDevMax))
  169. {
  170. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  171. return(FALSE);
  172. }
  173. // Make sure that we don't have devlock before entering user critical section.
  174. // Otherwise, it can cause deadlock.
  175. if (dco.bDisplay())
  176. {
  177. ASSERTGDI(dco.dctp() == DCTYPE_DIRECT,"ERROR it has to be direct");
  178. CHECKDEVLOCKOUT(dco);
  179. }
  180. // Enter user critical section.
  181. USERCRIT usercrit;
  182. // We are modifying the pixel format of the window for the first time.
  183. // Grab the devlock.
  184. // We don't need to validate the devlock since we do not care if it is full screen.
  185. DEVLOCKOBJ dlo(dco);
  186. // If it is a display DC, get the hwnd that the hdc is associated with.
  187. // If it is a printer or memory DC, hwnd is NULL.
  188. HWND hwnd;
  189. if (dco.bDisplay())
  190. {
  191. PEWNDOBJ pwo;
  192. ASSERTGDI(dco.dctp() == DCTYPE_DIRECT,
  193. "ERROR it has to be direct really");
  194. if (!UserGetHwnd(hdc, &hwnd, (PVOID *) &pwo, FALSE))
  195. {
  196. SAVE_ERROR_CODE(ERROR_INVALID_WINDOW_STYLE);
  197. return(FALSE);
  198. }
  199. // If another thread has changed the pixel format of the window
  200. // after we queried it earlier in this function, make sure that
  201. // the pixel format is compatible.
  202. // If a previous 3D-DDI wndobj with pixel format 0 has been created
  203. // for this window, fail the call here.
  204. if (pwo)
  205. {
  206. WARNING("GreSetPixelFormat: pixel format set asynchrously!\n");
  207. if (pwo->ipfd != ipfd)
  208. {
  209. SAVE_ERROR_CODE(ERROR_INVALID_PIXEL_FORMAT);
  210. return(FALSE);
  211. }
  212. return(TRUE);
  213. }
  214. }
  215. else
  216. {
  217. hwnd = (HWND)NULL;
  218. }
  219. // Dispatch driver formats. Call DrvSetPixelFormat.
  220. PDEVOBJ pdo(dco.hdev());
  221. SURFOBJ *pso = dco.pSurface()->pSurfobj();
  222. #ifdef OPENGL_MM
  223. if (pdo.bMetaDriver())
  224. {
  225. // We need to change the meta-PDEV into a hardware specific PDEV
  226. HDEV hdevDevice = hdevFindDeviceHdev(
  227. dco.hdev(), (RECTL)dco.erclWindow(), NULL);
  228. if (hdevDevice)
  229. {
  230. // If the surface is pdev's primary surface, we will replace it with
  231. // new device pdev's surface.
  232. if (pdo.bPrimary(dco.pSurface()))
  233. {
  234. PDEVOBJ pdoDevice(hdevDevice);
  235. pso = pdoDevice.pSurface()->pSurfobj();
  236. }
  237. // replace meta pdevobj with device specific hdev.
  238. pdo.vInit(hdevDevice);
  239. }
  240. }
  241. #endif // OPENGL_MM
  242. if (!PPFNVALID(pdo,SwapBuffers) ||
  243. !((SURFOBJ_TO_SURFACE_NOT_NULL(pso)->bDriverCreated()) &&
  244. (*PPFNDRV(pdo, SetPixelFormat))(pso, ipfd, hwnd)))
  245. return(FALSE);
  246. // If a new WNDOBJ is created, we need to update the window client regions
  247. // in the driver.
  248. if (gbWndobjUpdate)
  249. {
  250. gbWndobjUpdate = FALSE;
  251. vForceClientRgnUpdate();
  252. }
  253. return(TRUE);
  254. }
  255. /******************************Public*Routine******************************\
  256. * NtGdiSwapBuffers
  257. *
  258. * Since SwapBuffers is a GDI function, it has to work even if OpenGL is
  259. * not called. That is, we will eventually support 2D double buffering in
  260. * GDI. As a result, we need to define a DDI function DrvSwapBuffers() that
  261. * works with both OpenGL and GDI. The complication is that we have to
  262. * deal with the generic opengl server, the install opengl driver and GDI.
  263. * I will outline how this function works here:
  264. *
  265. * 1. On the client side, SwapBuffers() call glFinish() to flush all the
  266. * OpenGL functions in the current thread. It then calls the server side
  267. * GreSwapBuffers(). Note that this flushes all GDI functions in the
  268. * current thread.
  269. * 2. Once on the server side, we know that all GDI/OpenGL calls have been
  270. * flushed. We first find the hwnd id that corresponding to the hdc.
  271. * Note that SwapBuffers really applies to the window but not to the dc.
  272. * There is only one back buffer for a window but possibly multiple
  273. * dc's referring to the same back buffer. We find out the hwnd id
  274. * for the dc and do one of the following:
  275. * A. hdc has the device pixel formats.
  276. * This is simple. We call the device driver to swap the buffer with
  277. * the hwnd id.
  278. * B. hdc has the generic pixel formats.
  279. * Call the opengl server to swap the buffer. The OpenGL server uses
  280. * the hwnd id to bitblt the buffer that is associated with the window.
  281. *
  282. * Note that in this implementation, we do not flush calls in other threads.
  283. * Applications are responsible for coordinating SwapBuffers in multiple
  284. * threads.
  285. *
  286. * History:
  287. * 02-Nov-95 -by- Drew Bliss [drewb]
  288. * Stripped down to driver-only kernel-mode form
  289. * Thu Jan 06 12:32:11 1994 -by- Hock San Lee [hockl]
  290. * Added some code and wrote the above comment.
  291. * 21-Nov-1993 -by- Gilman Wong [gilmanw]
  292. * Wrote it.
  293. \**************************************************************************/
  294. BOOL NtGdiSwapBuffers(HDC hdc)
  295. {
  296. // Validate DC and surface. Info DC is not allowed.
  297. DCOBJ dco(hdc);
  298. if (!dco.bValid() || !dco.bHasSurface())
  299. {
  300. WARNING("GreSwapBuffers(): invalid hdc\n");
  301. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  302. return(FALSE);
  303. }
  304. // Early out -- nothing to do if memory DC.
  305. if (dco.dctp() == DCTYPE_MEMORY)
  306. return(TRUE);
  307. // Lock display.
  308. DEVLOCKOBJ_WNDOBJ dlo(dco);
  309. if (!dlo.bValidDevlock())
  310. {
  311. if (!dco.bFullScreen())
  312. {
  313. WARNING("GreSwapBuffers: could not lock device\n");
  314. return(FALSE);
  315. }
  316. else
  317. return(TRUE);
  318. }
  319. if (!dlo.bValidWndobj())
  320. {
  321. WARNING("GreSwapBuffers: invalid wndobj\n");
  322. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  323. return FALSE;
  324. }
  325. if (dlo.pwo()->erclExclude().bEmpty())
  326. return(TRUE);
  327. // Pointer exclusion.
  328. // Increment the surface uniqueness. This only needs to be done once
  329. // per DEVLOCK.
  330. DEVEXCLUDEOBJ dxo;
  331. dxo.vExclude(dco.hdev(), &dlo.pwo()->rclClient, (ECLIPOBJ *) dlo.pwo());
  332. INC_SURF_UNIQ(dco.pSurface());
  333. // Dispatch driver formats.
  334. PEWNDOBJ pwo;
  335. pwo = dlo.pwo();
  336. PDEVOBJ pdo(dco.hdev());
  337. SURFOBJ *pso = dco.pSurface()->pSurfobj();
  338. #ifdef OPENGL_MM
  339. if (pdo.bMetaDriver())
  340. {
  341. // We need to change the meta-PDEV into a hardware specific PDEV
  342. HDEV hdevDevice = hdevFindDeviceHdev(
  343. dco.hdev(), (RECTL)dco.erclWindow(), pwo);
  344. if (hdevDevice)
  345. {
  346. // If the surface is pdev's primary surface, we will replace it with
  347. // new device pdev's surface.
  348. if (pdo.bPrimary(dco.pSurface()))
  349. {
  350. PDEVOBJ pdoDevice(hdevDevice);
  351. pso = pdoDevice.pSurface()->pSurfobj();
  352. }
  353. // replace meta pdevobj with device specific hdev.
  354. pdo.vInit(hdevDevice);
  355. }
  356. }
  357. #endif // OPENGL_MM
  358. if ( !PPFNVALID(pdo,SwapBuffers) ||
  359. !((*PPFNDRV(pdo,SwapBuffers))(pso, (WNDOBJ *)pwo)))
  360. return(FALSE);
  361. return(TRUE);
  362. }