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.

646 lines
20 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: p2ctxt.c
  8. *
  9. * Content: Context switching for Permedia 2. Used to create and swap
  10. * contexts in and out.
  11. * The GDI, DDraw and D3D part each have another context.
  12. *
  13. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  14. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  15. \*****************************************************************************/
  16. #include "precomp.h"
  17. #include "p2ctxt.h"
  18. #include "gdi.h"
  19. #define ALLOC_TAG ALLOC_TAG_XC2P
  20. static DWORD readableRegistersP2[] = {
  21. __Permedia2TagStartXDom,
  22. __Permedia2TagdXDom,
  23. __Permedia2TagStartXSub,
  24. __Permedia2TagdXSub,
  25. __Permedia2TagStartY,
  26. __Permedia2TagdY,
  27. __Permedia2TagCount,
  28. __Permedia2TagRasterizerMode,
  29. __Permedia2TagYLimits,
  30. __Permedia2TagXLimits,
  31. __Permedia2TagScissorMode,
  32. __Permedia2TagScissorMinXY,
  33. __Permedia2TagScissorMaxXY,
  34. __Permedia2TagScreenSize,
  35. __Permedia2TagAreaStippleMode,
  36. __Permedia2TagWindowOrigin,
  37. __Permedia2TagAreaStipplePattern0,
  38. __Permedia2TagAreaStipplePattern1,
  39. __Permedia2TagAreaStipplePattern2,
  40. __Permedia2TagAreaStipplePattern3,
  41. __Permedia2TagAreaStipplePattern4,
  42. __Permedia2TagAreaStipplePattern5,
  43. __Permedia2TagAreaStipplePattern6,
  44. __Permedia2TagAreaStipplePattern7,
  45. __Permedia2TagTextureAddressMode,
  46. __Permedia2TagSStart,
  47. __Permedia2TagdSdx,
  48. __Permedia2TagdSdyDom,
  49. __Permedia2TagTStart,
  50. __Permedia2TagdTdx,
  51. __Permedia2TagdTdyDom,
  52. __Permedia2TagQStart,
  53. __Permedia2TagdQdx,
  54. __Permedia2TagdQdyDom,
  55. // texellutindex..transfer are treated seperately
  56. __Permedia2TagTextureBaseAddress,
  57. __Permedia2TagTextureMapFormat,
  58. __Permedia2TagTextureDataFormat,
  59. __Permedia2TagTexel0,
  60. __Permedia2TagTextureReadMode,
  61. __Permedia2TagTexelLUTMode,
  62. __Permedia2TagTextureColorMode,
  63. __Permedia2TagFogMode,
  64. __Permedia2TagFogColor,
  65. __Permedia2TagFStart,
  66. __Permedia2TagdFdx,
  67. __Permedia2TagdFdyDom,
  68. __Permedia2TagKsStart,
  69. __Permedia2TagdKsdx,
  70. __Permedia2TagdKsdyDom,
  71. __Permedia2TagKdStart,
  72. __Permedia2TagdKddx,
  73. __Permedia2TagdKddyDom,
  74. __Permedia2TagRStart,
  75. __Permedia2TagdRdx,
  76. __Permedia2TagdRdyDom,
  77. __Permedia2TagGStart,
  78. __Permedia2TagdGdx,
  79. __Permedia2TagdGdyDom,
  80. __Permedia2TagBStart,
  81. __Permedia2TagdBdx,
  82. __Permedia2TagdBdyDom,
  83. __Permedia2TagAStart,
  84. __Permedia2TagColorDDAMode,
  85. __Permedia2TagConstantColor,
  86. __Permedia2TagAlphaBlendMode,
  87. __Permedia2TagDitherMode,
  88. __Permedia2TagFBSoftwareWriteMask,
  89. __Permedia2TagLogicalOpMode,
  90. __Permedia2TagLBReadMode,
  91. __Permedia2TagLBReadFormat,
  92. __Permedia2TagLBSourceOffset,
  93. __Permedia2TagLBWindowBase,
  94. __Permedia2TagLBWriteMode,
  95. __Permedia2TagLBWriteFormat,
  96. __Permedia2TagTextureDownloadOffset,
  97. __Permedia2TagWindow,
  98. __Permedia2TagStencilMode,
  99. __Permedia2TagStencilData,
  100. __Permedia2TagStencil,
  101. __Permedia2TagDepthMode,
  102. __Permedia2TagDepth,
  103. __Permedia2TagZStartU,
  104. __Permedia2TagZStartL,
  105. __Permedia2TagdZdxU,
  106. __Permedia2TagdZdxL,
  107. __Permedia2TagdZdyDomU,
  108. __Permedia2TagdZdyDomL,
  109. __Permedia2TagFBReadMode,
  110. __Permedia2TagFBSourceOffset,
  111. __Permedia2TagFBPixelOffset,
  112. __Permedia2TagFBWindowBase,
  113. __Permedia2TagFBWriteMode,
  114. __Permedia2TagFBHardwareWriteMask,
  115. __Permedia2TagFBBlockColor,
  116. __Permedia2TagFBReadPixel,
  117. __Permedia2TagFilterMode,
  118. __Permedia2TagStatisticMode,
  119. __Permedia2TagMinRegion,
  120. __Permedia2TagMaxRegion,
  121. __Permedia2TagFBBlockColorU,
  122. __Permedia2TagFBBlockColorL,
  123. __Permedia2TagFBSourceBase,
  124. __Permedia2TagTexelLUT0,
  125. __Permedia2TagTexelLUT1,
  126. __Permedia2TagTexelLUT2,
  127. __Permedia2TagTexelLUT3,
  128. __Permedia2TagTexelLUT4,
  129. __Permedia2TagTexelLUT5,
  130. __Permedia2TagTexelLUT6,
  131. __Permedia2TagTexelLUT7,
  132. __Permedia2TagTexelLUT8,
  133. __Permedia2TagTexelLUT9,
  134. __Permedia2TagTexelLUT10,
  135. __Permedia2TagTexelLUT11,
  136. __Permedia2TagTexelLUT12,
  137. __Permedia2TagTexelLUT13,
  138. __Permedia2TagTexelLUT14,
  139. __Permedia2TagTexelLUT15,
  140. __Permedia2TagYUVMode,
  141. __Permedia2TagChromaUpperBound,
  142. __Permedia2TagChromaLowerBound,
  143. __Permedia2TagAlphaMapUpperBound,
  144. __Permedia2TagAlphaMapLowerBound,
  145. // delta tag values. must be at the end of this array
  146. // v0/1/2 fixed are not used and for that reason not in the context
  147. __Permedia2TagV0FloatS,
  148. __Permedia2TagV0FloatT,
  149. __Permedia2TagV0FloatQ,
  150. __Permedia2TagV0FloatKs,
  151. __Permedia2TagV0FloatKd,
  152. __Permedia2TagV0FloatR,
  153. __Permedia2TagV0FloatG,
  154. __Permedia2TagV0FloatB,
  155. __Permedia2TagV0FloatA,
  156. __Permedia2TagV0FloatF,
  157. __Permedia2TagV0FloatX,
  158. __Permedia2TagV0FloatY,
  159. __Permedia2TagV0FloatZ,
  160. __Permedia2TagV1FloatS,
  161. __Permedia2TagV1FloatT,
  162. __Permedia2TagV1FloatQ,
  163. __Permedia2TagV1FloatKs,
  164. __Permedia2TagV1FloatKd,
  165. __Permedia2TagV1FloatR,
  166. __Permedia2TagV1FloatG,
  167. __Permedia2TagV1FloatB,
  168. __Permedia2TagV1FloatA,
  169. __Permedia2TagV1FloatF,
  170. __Permedia2TagV1FloatX,
  171. __Permedia2TagV1FloatY,
  172. __Permedia2TagV1FloatZ,
  173. __Permedia2TagV2FloatS,
  174. __Permedia2TagV2FloatT,
  175. __Permedia2TagV2FloatQ,
  176. __Permedia2TagV2FloatKs,
  177. __Permedia2TagV2FloatKd,
  178. __Permedia2TagV2FloatR,
  179. __Permedia2TagV2FloatG,
  180. __Permedia2TagV2FloatB,
  181. __Permedia2TagV2FloatA,
  182. __Permedia2TagV2FloatF,
  183. __Permedia2TagV2FloatX,
  184. __Permedia2TagV2FloatY,
  185. __Permedia2TagV2FloatZ,
  186. __Permedia2TagDeltaMode
  187. };
  188. #define N_READABLE_TAGSP2 (sizeof(readableRegistersP2) / sizeof(readableRegistersP2[0]))
  189. //-----------------------------------------------------------------------------
  190. //
  191. // P2AllocateNewContext:
  192. //
  193. // allocate a new context. If all registers are to be saved in the context then
  194. // pTag is passed as null.
  195. // ppdev--------ppdev
  196. // pTag---------user can supply list of registers to save and restore on
  197. // context switch. NULL defaults to all registers.
  198. // Holds pointer to user function if dwCtxtType==P2CtxtUserFunc
  199. // lTags--------number of tags in user supplied register list
  200. // dwCtxtType---P2CtxtReadWrite (default)
  201. // on a context switch, all Permedia 2 registers are
  202. // saved and restored.
  203. // P2CtxtWriteOnly
  204. // registers of context will be saved once at the first
  205. // context switch. After that they will always be restored
  206. // to the state ate the very beginning. This method avoids
  207. // readback of registers when switching away from context.
  208. // P2CtxtUserFunc
  209. // User can supply a user function to set context to a known
  210. // state, to avoid readback when switching away from context.
  211. //
  212. //-----------------------------------------------------------------------------
  213. P2CtxtPtr
  214. P2AllocateNewContext(PPDev ppdev,
  215. DWORD *pTag,
  216. LONG lTags,
  217. P2CtxtType dwCtxtType
  218. )
  219. {
  220. P2CtxtTablePtr pCtxtTable, pNewCtxtTable;
  221. P2CtxtPtr pEntry;
  222. P2CtxtData *pData;
  223. LONG lEntries;
  224. LONG lExtraSize;
  225. LONG lSize;
  226. LONG lCtxtId;
  227. PERMEDIA_DECL;
  228. PERMEDIA_DEFS(ppdev);
  229. // first time round allocate the context table of pointers. We will
  230. // grow this table as required.
  231. //
  232. if (permediaInfo->ContextTable == NULL)
  233. {
  234. DISPDBG((7, "creating context table"));
  235. lSize = sizeof(P2CtxtTableRec);
  236. pCtxtTable = (P2CtxtTableRec *)
  237. ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(P2CtxtTableRec), ALLOC_TAG);
  238. if (pCtxtTable == NULL)
  239. {
  240. DISPDBG((0, "failed to allocate Permedia2 context table. out of memory"));
  241. return(NULL);
  242. }
  243. pCtxtTable->lEntries = CTXT_CHUNK;
  244. pCtxtTable->lSize = lSize;
  245. permediaInfo->ContextTable = pCtxtTable;
  246. permediaInfo->pCurrentCtxt = NULL;
  247. }
  248. // find an empty entry in the table
  249. // I suppose if we have hundreds of contexts this could be a bit slow but then
  250. // allocating the context isn't time critical, swapping in and out is.
  251. //
  252. pCtxtTable = (P2CtxtTablePtr) permediaInfo->ContextTable;
  253. lEntries = pCtxtTable->lEntries;
  254. for (lCtxtId = 0; lCtxtId < lEntries; ++lCtxtId)
  255. if(pCtxtTable->pEntry[lCtxtId] == NULL)
  256. break;
  257. // if we found no free entries try to grow the table
  258. if (lCtxtId == lEntries) {
  259. DISPDBG((1, "context table full so enlarging"));
  260. lSize = pCtxtTable->lSize + (CTXT_CHUNK * sizeof(P2CtxtPtr));
  261. pNewCtxtTable =
  262. (P2CtxtTablePtr) ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(BYTE)*lSize, ALLOC_TAG);
  263. if (pNewCtxtTable == NULL) {
  264. DISPDBG((0, "failed to increase Permedia 2 context table. out of memory"));
  265. return(NULL);
  266. }
  267. // copy the old table to the new one
  268. RtlCopyMemory(pNewCtxtTable, pCtxtTable, pCtxtTable->lSize);
  269. pNewCtxtTable->lSize = lSize;
  270. pNewCtxtTable->lEntries = lEntries + CTXT_CHUNK;
  271. permediaInfo->ContextTable = (PVOID)pNewCtxtTable;
  272. // first of the newly allocated entries is next free one
  273. lCtxtId = lEntries;
  274. // free the old context table and reassign some variables
  275. ENGFREEMEM(pCtxtTable);
  276. pCtxtTable = pNewCtxtTable;
  277. lEntries = pCtxtTable->lEntries;
  278. }
  279. // if pTag is passed as null then we are to add all readable registers to the
  280. // context.
  281. lExtraSize = 0;
  282. if (dwCtxtType != P2CtxtUserFunc)
  283. {
  284. if (pTag == 0)
  285. {
  286. DISPDBG((7, "adding all readable registers to the context"));
  287. DISPDBG((7, "Using PERMEDIA 2 register set for other context switch"));
  288. pTag = readableRegistersP2;
  289. lTags = N_READABLE_TAGSP2;
  290. }
  291. } else
  292. {
  293. lTags = 1;
  294. }
  295. // now allocate space for the new entry. We are given the number of tags to save
  296. // when context switching. Allocate twice this much memory as we have to hold the
  297. // data values as well.
  298. DISPDBG((7, "Allocating space for context. lTags = %d", lTags));
  299. lSize = sizeof(P2CtxtRec) + (lTags-1) * sizeof(P2CtxtData);
  300. pEntry = (P2CtxtPtr)
  301. ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(BYTE)*(lSize+lExtraSize), ALLOC_TAG);
  302. if (pEntry == NULL) {
  303. DISPDBG((0, "out of memory trying to allocate space for new context"));
  304. return(NULL);
  305. }
  306. DISPDBG((7, "Got pEntry 0x%x", pEntry));
  307. pCtxtTable->pEntry[lCtxtId] = pEntry;
  308. // allocate enough space for the Texel LUT: 256 entries
  309. pEntry->dwCtxtType=dwCtxtType;
  310. pEntry->bInitialized=FALSE;
  311. pEntry->pTexelLUTCtxt = (PULONG)
  312. ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(ULONG)*256, ALLOC_TAG);
  313. if (pEntry->pTexelLUTCtxt!=0)
  314. {
  315. pEntry->ulTexelLUTEntries = 256;
  316. } else
  317. {
  318. pEntry->ulTexelLUTEntries = 0;
  319. }
  320. pEntry->lNumOfTags = lTags;
  321. pEntry->P2UserFunc = NULL;
  322. pData = pEntry->pData;
  323. if (dwCtxtType != P2CtxtUserFunc)
  324. {
  325. // we must initialize the new context to something reasonable. We choose to
  326. // initialize to the current state of the chip. We can't leave it uninitialized
  327. // since the first thing the caller will do when he wants to draw is validate
  328. // the new context which will load junk into the chip. At some point we
  329. // should define a reasonable starting context which would mean we wouldn't
  330. // have to do this readback.
  331. // copy the tags and read the data back from the chip. We don't sync since we are
  332. // only initialising the context to something reasonable. i.e. we don't care if
  333. // the FIFO is still draining while we do this.
  334. DISPDBG((7, "Reading current chip context back"));
  335. while (--lTags >= 0) {
  336. pData->dwTag = *pTag++;
  337. READ_PERMEDIA_FIFO_REG(pData->dwTag, pData->dwData);
  338. ++pData;
  339. }
  340. // save the texel LUT
  341. if(pEntry->ulTexelLUTEntries &&
  342. pEntry->pTexelLUTCtxt!=NULL)
  343. {
  344. ULONG *pul;
  345. INT i=0;
  346. lEntries = pEntry->ulTexelLUTEntries;
  347. pul = pEntry->pTexelLUTCtxt;
  348. //special mechanism: reset readback index to 0
  349. READ_PERMEDIA_FIFO_REG(__Permedia2TagTexelLUTIndex, i);
  350. for(i = 0; i < lEntries; ++i, ++pul)
  351. {
  352. READ_PERMEDIA_FIFO_REG(__Permedia2TagTexelLUTData, *pul);
  353. }
  354. }
  355. } else
  356. {
  357. pEntry->P2UserFunc = (PCtxtUserFunc) pTag;
  358. }
  359. DISPDBG((1, "Allocated context %lx", pEntry));
  360. return(pEntry);
  361. } // P2AllocateNewContext
  362. //-----------------------------------------------------------------------------
  363. //
  364. // P2FreeContext:
  365. //
  366. // free a previously allocated context.
  367. //
  368. //-----------------------------------------------------------------------------
  369. VOID
  370. P2FreeContext( PPDev ppdev,
  371. P2CtxtPtr pEntry)
  372. {
  373. PERMEDIA_DECL;
  374. P2CtxtTablePtr pCtxtTable;
  375. ULONG lCtxtId;
  376. pCtxtTable = (P2CtxtTablePtr) permediaInfo->ContextTable;
  377. for (lCtxtId = 0; lCtxtId < pCtxtTable->lEntries; ++lCtxtId)
  378. if(pCtxtTable->pEntry[lCtxtId] == pEntry)
  379. break;
  380. ASSERTDD(lCtxtId != pCtxtTable->lEntries, "P2FreeContext: context not found");
  381. // free LUT Table
  382. if(pEntry->pTexelLUTCtxt)
  383. {
  384. ENGFREEMEM( pEntry->pTexelLUTCtxt);
  385. }
  386. ENGFREEMEM( pEntry);
  387. pCtxtTable->pEntry[lCtxtId] = NULL;
  388. // if this was the current context, mark the current context as invalid so we
  389. // force a reload next time.
  390. if (permediaInfo->pCurrentCtxt == pEntry)
  391. {
  392. permediaInfo->pCurrentCtxt = NULL;
  393. }
  394. DISPDBG((1, "Released context %lx", pEntry));
  395. }
  396. //-----------------------------------------------------------------------------
  397. //
  398. // VOID P2SwitchContext:
  399. //
  400. // load a new context into the hardware. We assume that this call is
  401. // protected by a test that the given context is not the current one -
  402. // hence the assertion.
  403. // The code would work but the driver should never try to load an already
  404. // loaded context so we trap it as an error.
  405. //
  406. //-----------------------------------------------------------------------------
  407. VOID
  408. P2SwitchContext(
  409. PPDev ppdev,
  410. P2CtxtPtr pEntry)
  411. {
  412. P2CtxtTablePtr pCtxtTable;
  413. P2CtxtData *pData;
  414. P2CtxtPtr pOldCtxt;
  415. LONG lTags;
  416. LONG i;
  417. ULONG *pul;
  418. LONG lEntries;
  419. PERMEDIA_DECL;
  420. PERMEDIA_DEFS(ppdev);
  421. //@@BEGIN_DDKSPLIT
  422. #if MULTITHREADED
  423. EngAcquireSemaphore(ppdev->hsemLock);
  424. ASSERTDD(ppdev->ulLockCount, "P2SwitchContext: ulLockCount = 0\n Context could change as caller is NOT protected!");
  425. ppdev->ulLockCount++;
  426. #endif
  427. //@@END_DDKSPLIT
  428. pCtxtTable = (P2CtxtTablePtr)permediaInfo->ContextTable;
  429. ASSERTDD(pCtxtTable, "Can't perform context switch: no contexts have been created!");
  430. pOldCtxt = permediaInfo->pCurrentCtxt;
  431. DISPDBG((3, "swapping from context %d to context %d", pOldCtxt, pEntry));
  432. if(pOldCtxt == permediaInfo->pGDICtxt)
  433. {
  434. DISPDBG((6, "Switching from GDI context"));
  435. ASSERTDD(ppdev->bNeedSync ||
  436. (ppdev->pulInFifoPtr == ppdev->pulInFifoStart),
  437. "P2SwitchContext: bNeedSync flag is wrong");
  438. InputBufferSync(ppdev);
  439. ppdev->bGdiContext = FALSE;
  440. ppdev->pP2dma->bEnabled = TRUE;
  441. }
  442. // for each register in the old context, read it back
  443. if (pOldCtxt != NULL) {
  444. //
  445. // P2CtxtWriteOnly will only be readback once after context initialization
  446. //
  447. if ((pOldCtxt->dwCtxtType==P2CtxtReadWrite) ||
  448. (pOldCtxt->dwCtxtType==P2CtxtWriteOnly && !pOldCtxt->bInitialized)
  449. )
  450. {
  451. // sync with the chip before reading back the current state. The flag
  452. // is used to control context manipulation on lockup recovery.
  453. SYNC_WITH_PERMEDIA;
  454. pData = pOldCtxt->pData;
  455. lTags = pOldCtxt->lNumOfTags;
  456. while (--lTags >= 0) {
  457. READ_PERMEDIA_FIFO_REG(pData->dwTag, pData->dwData);
  458. ++pData;
  459. }
  460. // save the texel LUT
  461. if(pOldCtxt->ulTexelLUTEntries &&
  462. pOldCtxt->pTexelLUTCtxt!=NULL)
  463. {
  464. lEntries = pOldCtxt->ulTexelLUTEntries;
  465. pul = pOldCtxt->pTexelLUTCtxt;
  466. //special mechanism: reset readback index to 0
  467. READ_PERMEDIA_FIFO_REG(__Permedia2TagTexelLUTIndex, i);
  468. for(i = 0; i < lEntries; ++i, ++pul)
  469. {
  470. READ_PERMEDIA_FIFO_REG(__Permedia2TagTexelLUTData, *pul);
  471. }
  472. }
  473. pOldCtxt->bInitialized=TRUE;
  474. }
  475. }
  476. // load the new context. We allow -1 to be passed so that we can force a
  477. // save of the current context and force the current context to be
  478. // undefined.
  479. //
  480. if (pEntry != NULL)
  481. {
  482. if (pEntry->dwCtxtType==P2CtxtUserFunc)
  483. {
  484. ASSERTDD(pEntry->P2UserFunc!=NULL,"supplied user function not initialized");
  485. (*pEntry->P2UserFunc)(ppdev);
  486. } else
  487. if (pEntry->dwCtxtType==P2CtxtWriteOnly ||
  488. pEntry->dwCtxtType==P2CtxtReadWrite)
  489. {
  490. lTags = pEntry->lNumOfTags;
  491. pData = pEntry->pData;
  492. while (lTags > 0) {
  493. lEntries = MAX_P2_FIFO_ENTRIES;
  494. lTags -= lEntries;
  495. if (lTags < 0)
  496. lEntries += lTags;
  497. RESERVEDMAPTR(lEntries);
  498. while (--lEntries >= 0) {
  499. LD_INPUT_FIFO(pData->dwTag, pData->dwData);
  500. DISPDBG((20, "loading tag 0x%x, data 0x%x", pData->dwTag, pData->dwData));
  501. ++pData;
  502. }
  503. COMMITDMAPTR();
  504. }
  505. // restore the texel LUT
  506. if(pEntry->ulTexelLUTEntries &&
  507. pEntry->pTexelLUTCtxt!=NULL )
  508. {
  509. lEntries = pEntry->ulTexelLUTEntries;
  510. pul = pEntry->pTexelLUTCtxt;
  511. RESERVEDMAPTR(lEntries+1);
  512. LD_INPUT_FIFO(__Permedia2TagTexelLUTIndex, 0);
  513. for(i = 0; i < lEntries; ++i, ++pul)
  514. {
  515. LD_INPUT_FIFO(__Permedia2TagTexelLUTData, *pul);
  516. }
  517. COMMITDMAPTR();
  518. FLUSHDMA();
  519. }
  520. } else
  521. {
  522. ASSERTDD( FALSE, "undefined state for entry in context table");
  523. }
  524. }
  525. if(pEntry == permediaInfo->pGDICtxt)
  526. {
  527. DISPDBG((6, "Switching to GDI context"));
  528. //
  529. // we have to do a full sync here, because GDI and DDraw
  530. // share the same DMA buffer. To make sure nothing will be
  531. // overridden, we do a complete sync
  532. //
  533. SYNC_WITH_PERMEDIA;
  534. //
  535. // Turn off permedia interrupt handler
  536. //
  537. WRITE_CTRL_REG( PREG_INTENABLE, 0);
  538. ppdev->bGdiContext = TRUE;
  539. ppdev->pP2dma->bEnabled = FALSE;
  540. // invalidate the mono brush cache entry
  541. // stipple unit was restored to default values
  542. ppdev->abeMono.prbVerify = NULL;
  543. }
  544. DISPDBG((6, "context %lx now current", pEntry));
  545. permediaInfo->pCurrentCtxt = pEntry;
  546. //@@BEGIN_DDKSPLIT
  547. #if MULTITHREADED
  548. ppdev->ulLockCount--;
  549. EngReleaseSemaphore(ppdev->hsemLock);
  550. #endif
  551. //@@END_DDKSPLIT
  552. }