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.

479 lines
14 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: swapmult.c
  3. *
  4. * wglSwapMultiple implementation
  5. *
  6. * Created: 02-10-1997
  7. * Author: Drew Bliss [drewb]
  8. *
  9. * Copyright (c) 1993-1997 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include <gencx.h>
  14. #include <mcdcx.h>
  15. /******************************Public*Routine******************************\
  16. *
  17. * BufferSwapperType
  18. *
  19. * Determines what basic type of swapper is responsible for the given
  20. * swap info.
  21. *
  22. * History:
  23. * Mon Oct 14 18:46:28 1996 -by- Drew Bliss [drewb]
  24. * Created
  25. *
  26. \**************************************************************************/
  27. #define BSWP_ICD 0
  28. #define BSWP_MCD 1
  29. #define BSWP_GENERIC 2
  30. int BufferSwapperType(GENMCDSWAP *pgms)
  31. {
  32. // The buffer can be for an ICD, an MCD or generic
  33. // 1. ICD buffers have an ICD pixel format
  34. // 2. MCD buffers have MCD state
  35. if (pgms->pwnd->ipfd <= pgms->pwnd->ipfdDevMax)
  36. {
  37. return BSWP_ICD;
  38. }
  39. else
  40. {
  41. if (pgms->pwnd->buffers != NULL)
  42. {
  43. if (pgms->pwnd->buffers->pMcdSurf != NULL)
  44. {
  45. return BSWP_MCD;
  46. }
  47. }
  48. }
  49. return BSWP_GENERIC;
  50. }
  51. /******************************Public*Routine******************************\
  52. *
  53. * SameSwapper
  54. *
  55. * Checks whether the two swapinfos are swapped by the same swapping
  56. * agency.
  57. *
  58. * History:
  59. * Mon Oct 14 18:49:26 1996 -by- Drew Bliss [drewb]
  60. * Created
  61. *
  62. \**************************************************************************/
  63. BOOL SameSwapper(int iSwapperTypeA, GENMCDSWAP *pgmsA, GENMCDSWAP *pgmsB)
  64. {
  65. switch(iSwapperTypeA)
  66. {
  67. case BSWP_ICD:
  68. // Must be the same ICD
  69. if (BufferSwapperType(pgmsB) != BSWP_ICD ||
  70. pgmsA->pwnd->pvDriver != pgmsB->pwnd->pvDriver)
  71. {
  72. return FALSE;
  73. }
  74. return TRUE;
  75. case BSWP_MCD:
  76. case BSWP_GENERIC:
  77. // No way to refine the comparison any more
  78. return BufferSwapperType(pgmsB) == iSwapperTypeA;
  79. default:
  80. ASSERTOPENGL(FALSE, "SameSwapper UNREACHED\n");
  81. return FALSE;
  82. }
  83. }
  84. /******************************Public*Routine******************************\
  85. *
  86. * wglSwapMultipleBuffers
  87. *
  88. * Swaps as many of the given buffers as possible.
  89. * Returns a bitmask of the buffers that were swapped.
  90. *
  91. * History:
  92. * Mon Oct 14 17:19:09 1996 -by- Drew Bliss [drewb]
  93. * Created
  94. *
  95. \**************************************************************************/
  96. // #define VERBOSE_MULTI
  97. DWORD WINAPI wglSwapMultipleBuffers(UINT cBuffers, CONST WGLSWAP *pwswapAll)
  98. {
  99. GENMCDSWAP agmsAll[WGL_SWAPMULTIPLE_MAX];
  100. GENMCDSWAP *pgmsFirst;
  101. GENMCDSWAP *pgmsEnd;
  102. GENMCDSWAP *pgms;
  103. GENMCDSWAP *apgmsGroup[WGL_SWAPMULTIPLE_MAX];
  104. GENMCDSWAP **ppgmsGroup;
  105. WGLSWAP *pwswap;
  106. DWORD dwMask;
  107. UINT uiCur;
  108. UINT uiIdx;
  109. GLWINDOWID gwid;
  110. GLGENwindow *pwnd;
  111. DWORD dwBit;
  112. DWORD dwCallMask;
  113. DWORD adwCallIndex[WGL_SWAPMULTIPLE_MAX];
  114. DWORD *pdwCallIndex;
  115. DWORD cGroup;
  116. DWORD cDone;
  117. int iSwapperType;
  118. BOOL bCall;
  119. ASSERTOPENGL(WGL_SWAPMULTIPLE_MAX <= 16,
  120. "WGL_SWAPMULTIPLE_MAX too large\n");
  121. ASSERTOPENGL(WGL_SWAPMULTIPLE_MAX == OPENGLCMD_MAXMULTI &&
  122. WGL_SWAPMULTIPLE_MAX == MCDESC_MAX_EXTRA_WNDOBJ,
  123. "WGL_SWAPMULTIPLE_MAX mismatch\n");
  124. if (cBuffers > WGL_SWAPMULTIPLE_MAX)
  125. {
  126. SetLastError(ERROR_INVALID_FUNCTION);
  127. return 0;
  128. }
  129. dwMask = 0;
  130. // Validate all input buffers and do one-time information gathering for
  131. // them.
  132. pgms = agmsAll;
  133. pwswap = (WGLSWAP *)pwswapAll;
  134. for (uiCur = 0; uiCur < cBuffers; uiCur++, pwswap++)
  135. {
  136. // Validate DC
  137. if (IsDirectDrawDevice(pwswap->hdc))
  138. {
  139. continue;
  140. }
  141. switch(GetObjectType(pwswap->hdc))
  142. {
  143. case OBJ_DC:
  144. break;
  145. case OBJ_MEMDC:
  146. // Nothing to do for memdc
  147. dwMask |= 1 << uiCur;
  148. // Fall through
  149. default:
  150. continue;
  151. }
  152. // Look up pwnd
  153. WindowIdFromHdc(pwswap->hdc, &gwid);
  154. pwnd = pwndGetFromID(&gwid);
  155. if (pwnd == NULL)
  156. {
  157. continue;
  158. }
  159. if (pwnd->ipfd == 0)
  160. {
  161. pwndRelease(pwnd);
  162. continue;
  163. }
  164. // We have a valid candidate for swapping. Remember it.
  165. pgms->pwswap = pwswap;
  166. pgms->pwnd = pwnd;
  167. pgms++;
  168. }
  169. #ifdef VERBOSE_MULTI
  170. DbgPrint("%d cand\n", pgms-agmsAll);
  171. #endif
  172. // Walk list of candidates and gather by swapper
  173. pgmsEnd = pgms;
  174. pgmsFirst = agmsAll;
  175. while (pgmsFirst < pgmsEnd)
  176. {
  177. // Skip over any candidates that have already been swapped
  178. if (pgmsFirst->pwswap == NULL)
  179. {
  180. pgmsFirst++;
  181. continue;
  182. }
  183. iSwapperType = BufferSwapperType(pgmsFirst);
  184. #ifdef VERBOSE_MULTI
  185. DbgPrint(" Gathering for %d, type %d\n", pgmsFirst-agmsAll,
  186. iSwapperType);
  187. #endif
  188. ppgmsGroup = apgmsGroup;
  189. *ppgmsGroup++ = pgmsFirst;
  190. pgmsFirst++;
  191. pgms = pgmsFirst;
  192. while (pgms < pgmsEnd)
  193. {
  194. if (pgms->pwswap != NULL)
  195. {
  196. if (SameSwapper(iSwapperType, apgmsGroup[0], pgms))
  197. {
  198. #ifdef VERBOSE_MULTI
  199. DbgPrint(" Match with %d\n", pgms-agmsAll);
  200. #endif
  201. *ppgmsGroup++ = pgms;
  202. }
  203. }
  204. pgms++;
  205. }
  206. // Dispatch group to swapper for swapping. This may require
  207. // multiple attempts because the same swapper may be responsible
  208. // for multiple devices and only one device can be handled at
  209. // a time.
  210. cGroup = (DWORD)((ULONG_PTR)(ppgmsGroup-apgmsGroup));
  211. #ifdef VERBOSE_MULTI
  212. DbgPrint(" Group of %d\n", cGroup);
  213. #endif
  214. cDone = 0;
  215. while (cDone < cGroup)
  216. {
  217. WGLSWAP awswapIcdCall[WGL_SWAPMULTIPLE_MAX];
  218. PGLDRIVER pgldrv;
  219. GENMCDSWAP agmsMcdCall[WGL_SWAPMULTIPLE_MAX];
  220. GENMCDSWAP *pgmsCall;
  221. // Collect any remaining swaps into calling format
  222. pdwCallIndex = adwCallIndex;
  223. pgms = NULL;
  224. // After each case, uiCur must be set to the number of
  225. // swaps attempted and dwMask must be set to the
  226. // attempted/succeeded mask.
  227. switch(iSwapperType)
  228. {
  229. case BSWP_ICD:
  230. pwswap = awswapIcdCall;
  231. for (uiCur = 0; uiCur < cGroup; uiCur++)
  232. {
  233. if (apgmsGroup[uiCur] != NULL)
  234. {
  235. pgms = apgmsGroup[uiCur];
  236. *pwswap++ = *pgms->pwswap;
  237. *pdwCallIndex++ = uiCur;
  238. }
  239. }
  240. uiCur = (UINT)((ULONG_PTR)(pwswap-awswapIcdCall));
  241. // Quit if nothing remaining
  242. if (uiCur == 0)
  243. {
  244. dwCallMask = 0;
  245. }
  246. else
  247. {
  248. pgldrv = (PGLDRIVER)pgms->pwnd->pvDriver;
  249. ASSERTOPENGL(pgldrv != NULL,
  250. "ICD not loaded\n");
  251. // Ask for swap
  252. // If the ICD supports SwapMultiple, pass the call on
  253. if (pgldrv->pfnDrvSwapMultipleBuffers != NULL)
  254. {
  255. dwCallMask = pgldrv->
  256. pfnDrvSwapMultipleBuffers(uiCur, awswapIcdCall);
  257. }
  258. else if (pgldrv->pfnDrvSwapLayerBuffers != NULL)
  259. {
  260. // The ICD doesn't support multiple swap but
  261. // it does support layer swaps so iterate
  262. // through all the separate swaps.
  263. dwCallMask = 0;
  264. dwBit = 1 << (uiCur-1);
  265. while (--pwswap >= awswapIcdCall)
  266. {
  267. // Every swap is attempted
  268. dwCallMask |= dwBit << (32-WGL_SWAPMULTIPLE_MAX);
  269. if (pgldrv->
  270. pfnDrvSwapLayerBuffers(pwswap->hdc,
  271. pwswap->uiFlags))
  272. {
  273. dwCallMask |= dwBit;
  274. }
  275. dwBit >>= 1;
  276. }
  277. }
  278. else
  279. {
  280. // The ICD only supports SwapBuffers so
  281. // iterate and swap all main plane requests.
  282. // Any overlay plane swaps are ignored and
  283. // reported as successful.
  284. dwCallMask = 0;
  285. dwBit = 1 << (uiCur-1);
  286. while (--pwswap >= awswapIcdCall)
  287. {
  288. // Every swap is attempted
  289. dwCallMask |= dwBit << (32-WGL_SWAPMULTIPLE_MAX);
  290. if (pwswap->uiFlags & WGL_SWAP_MAIN_PLANE)
  291. {
  292. bCall = __DrvSwapBuffers(pwswap->hdc, FALSE);
  293. }
  294. else
  295. {
  296. bCall = TRUE;
  297. }
  298. if (bCall)
  299. {
  300. dwCallMask |= dwBit;
  301. }
  302. dwBit >>= 1;
  303. }
  304. }
  305. }
  306. break;
  307. case BSWP_MCD:
  308. pgmsCall = agmsMcdCall;
  309. for (uiCur = 0; uiCur < cGroup; uiCur++)
  310. {
  311. if (apgmsGroup[uiCur] != NULL)
  312. {
  313. pgms = apgmsGroup[uiCur];
  314. *pgmsCall++ = *pgms;
  315. *pdwCallIndex++ = uiCur;
  316. }
  317. }
  318. uiCur = (UINT)((ULONG_PTR)(pgmsCall-agmsMcdCall));
  319. // Quit if nothing remaining
  320. if (uiCur == 0)
  321. {
  322. dwCallMask = 0;
  323. }
  324. else
  325. {
  326. // Ask for swap
  327. dwCallMask = GenMcdSwapMultiple(uiCur, agmsMcdCall);
  328. }
  329. break;
  330. case BSWP_GENERIC:
  331. // No accleration exists so just iterate and swap
  332. dwCallMask = 0;
  333. dwBit = 1;
  334. for (uiCur = 0; uiCur < cGroup; uiCur++)
  335. {
  336. pgms = apgmsGroup[uiCur];
  337. *pdwCallIndex++ = uiCur;
  338. // Every swap is attempted
  339. dwCallMask |= dwBit << (32-WGL_SWAPMULTIPLE_MAX);
  340. // Since this is a generic swap we only swap the
  341. // main plane. Overlay planes are ignored and
  342. // reported as successful.
  343. if (pgms->pwswap->uiFlags & WGL_SWAP_MAIN_PLANE)
  344. {
  345. ENTER_WINCRIT(pgms->pwnd);
  346. bCall = glsrvSwapBuffers(pgms->pwswap->hdc,
  347. pgms->pwnd);
  348. LEAVE_WINCRIT(pgms->pwnd);
  349. }
  350. else
  351. {
  352. bCall = TRUE;
  353. }
  354. if (bCall)
  355. {
  356. dwCallMask |= dwBit;
  357. }
  358. dwBit <<= 1;
  359. }
  360. break;
  361. }
  362. #ifdef VERBOSE_MULTI
  363. DbgPrint(" Attempted %d, mask %X\n", uiCur, dwCallMask);
  364. #endif
  365. // Quit if nothing was swapped.
  366. if (dwCallMask == 0)
  367. {
  368. break;
  369. }
  370. // Determine which buffers were really swapped and
  371. // clear any buffers for which a swap was attempted.
  372. dwBit = 1 << (uiCur-1);
  373. while (uiCur-- > 0)
  374. {
  375. uiIdx = adwCallIndex[uiCur];
  376. pgms = apgmsGroup[uiIdx];
  377. if (dwCallMask & dwBit)
  378. {
  379. dwMask |= 1 << (pgms->pwswap-pwswapAll);
  380. }
  381. if ((dwCallMask >> (32-WGL_SWAPMULTIPLE_MAX)) & dwBit)
  382. {
  383. // Take out of overall list
  384. pgms->pwswap = NULL;
  385. // Take out of group list
  386. apgmsGroup[uiIdx] = NULL;
  387. cDone++;
  388. }
  389. dwBit >>= 1;
  390. }
  391. #ifdef VERBOSE_MULTI
  392. DbgPrint(" Done with %d, mask %X\n", cDone, dwMask);
  393. #endif
  394. }
  395. }
  396. // Release all the pwnds
  397. pgms = agmsAll;
  398. while (pgms < pgmsEnd)
  399. {
  400. pwndRelease(pgms->pwnd);
  401. pgms++;
  402. }
  403. #ifdef VERBOSE_MULTI
  404. DbgPrint("Final mask %X\n", dwMask);
  405. #endif
  406. return dwMask;
  407. }