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.

2279 lines
69 KiB

  1. //******************************Module*Header*******************************
  2. // Module Name: mcd.c
  3. //
  4. // Main module for Mini Client Driver wrapper library.
  5. //
  6. // Copyright (c) 1995 Microsoft Corporation
  7. //**************************************************************************
  8. #include <nt.h>
  9. #include <ntrtl.h>
  10. #include <nturtl.h>
  11. #include <stddef.h>
  12. #include <stdarg.h>
  13. #include <ddrawp.h>
  14. #include <ddrawi.h>
  15. #include <windows.h>
  16. #include <wtypes.h>
  17. #include <windef.h>
  18. #include <wingdi.h>
  19. #include <winddi.h>
  20. #include <glp.h>
  21. #include <glgenwin.h>
  22. #include <mcdrv.h>
  23. #include <mcd2hack.h>
  24. #include <mcd.h>
  25. #include <mcdint.h>
  26. #ifdef MCD95
  27. #include "mcdrvint.h"
  28. #endif
  29. #include "debug.h"
  30. ULONG verMajor, verMinor;
  31. // Checks MCD version to see if the driver can accept direct buffer
  32. // access. Direct access was introduced in 1.1.
  33. #define SUPPORTS_DIRECT() \
  34. (verMinor >= 0x10 || verMajor > 1)
  35. // Checks for version 2.0 or higher
  36. #define SUPPORTS_20() \
  37. (verMajor >= 2)
  38. extern ULONG McdFlags;
  39. extern ULONG McdPrivateFlags;
  40. #if DBG
  41. extern ULONG McdDebugFlags;
  42. #endif
  43. #ifdef MCD95
  44. MCDRVINITFUNC pMCDrvInit = (MCDRVINITFUNC) NULL;
  45. MCDENGESCFILTERFUNC pMCDEngEscFilter = (MCDENGESCFILTERFUNC) NULL;
  46. MCDENGESCPREPFUNC pMCDEngEscPrep = (MCDENGESCPREPFUNC) NULL;
  47. DHPDEV gdhpdev = (DHPDEV) NULL;
  48. #define EXTESCAPE Mcd95EscapeBypass
  49. #else
  50. #define EXTESCAPE ExtEscape
  51. #endif
  52. #ifdef MCD95
  53. //
  54. // Local driver semaphore.
  55. //
  56. extern CRITICAL_SECTION gsemMcd;
  57. /******************************Public*Routine******************************\
  58. * Mcd95EscapeBypass
  59. *
  60. * Escape function for MCD95.
  61. *
  62. * Call via the function pointer retrieved via LoadLibrary/GetProcAddress.
  63. * Synchronize to the global
  64. *
  65. * History:
  66. * 09-Feb-1997 -by- Gilman Wong [gilmanw]
  67. * Wrote it.
  68. \**************************************************************************/
  69. LONG WINAPI Mcd95EscapeBypass(HDC hdc, int iEscape,
  70. int cjIn, PVOID pvIn,
  71. int cjOut, PVOID pvOut)
  72. {
  73. LONG lRet = 0;
  74. if ((iEscape == RXFUNCS) && pMCDEngEscPrep && pMCDEngEscFilter)
  75. {
  76. MCDHDR McdHdr;
  77. SURFOBJ bogusSurf;
  78. bogusSurf.dhpdev = gdhpdev;
  79. EnterCriticalSection(&gsemMcd);
  80. //
  81. // Prep the MCDHDR buffer. Required before invoking
  82. // MCDEngEscFilter.
  83. //
  84. if ((*pMCDEngEscPrep)(sizeof(McdHdr), &McdHdr, cjIn, pvIn))
  85. {
  86. //
  87. // Pass to dispatch function.
  88. //
  89. (*pMCDEngEscFilter)(&bogusSurf, iEscape,
  90. sizeof(McdHdr), &McdHdr,
  91. cjOut, pvOut, (ULONG_PTR *) &lRet);
  92. }
  93. else
  94. {
  95. DBGPRINT("Mcd95EscapeBypass: MCDEngEscPrep failed\n");
  96. }
  97. LeaveCriticalSection(&gsemMcd);
  98. }
  99. return lRet;
  100. }
  101. /******************************Public*Routine******************************\
  102. * Mcd95DriverInit
  103. *
  104. * Initialize the MCD driver.
  105. *
  106. * History:
  107. * 14-Apr-1997 -by- Gilman Wong [gilmanw]
  108. * Wrote it.
  109. \**************************************************************************/
  110. typedef enum {
  111. MCDRV_NEEDINIT,
  112. MCDRV_INITFAIL,
  113. MCDRV_INITOK
  114. } MCDRVSTATE;
  115. BOOL Mcd95DriverInit(HDC hdc)
  116. {
  117. HMODULE hmodMCD;
  118. MCDGETDRIVERNAME mcdDriverNames;
  119. MCDCMDI mcdCmd;
  120. static MCDRVSTATE McdInitState = MCDRV_NEEDINIT;
  121. EnterCriticalSection(&gsemMcd);
  122. if (McdInitState == MCDRV_NEEDINIT)
  123. {
  124. //
  125. // One shot at init. Assume failure for now.
  126. //
  127. McdInitState = MCDRV_INITFAIL;
  128. //
  129. // Call Escape to determine name of MCD driver DLL and the
  130. // name of its Init entry point.
  131. //
  132. mcdCmd.command = MCDCMD_GETDRIVERNAME;
  133. mcdDriverNames.ulVersion = 1;
  134. if ((EXTESCAPE(hdc, RXFUNCS, sizeof(mcdCmd), (char *) &mcdCmd,
  135. sizeof(mcdDriverNames),
  136. (char *) &mcdDriverNames) <= 0) ||
  137. (!mcdDriverNames.pchDriverName) ||
  138. (!mcdDriverNames.pchFuncName))
  139. {
  140. DBGPRINT("MCDGetDriverInfo: MCDCMD_GETDRIVERNAME failed\n");
  141. goto Mcd95DriverInit_exit;
  142. }
  143. //
  144. // Load the MCD driver DLL and get entry points.
  145. //
  146. if (hmodMCD = LoadLibraryA(mcdDriverNames.pchDriverName))
  147. {
  148. HMODULE hmodMCDSRV;
  149. //
  150. // Get MCDrvInit entry point first.
  151. //
  152. pMCDrvInit = (MCDRVINITFUNC)
  153. GetProcAddress(hmodMCD, mcdDriverNames.pchFuncName);
  154. if (pMCDrvInit)
  155. {
  156. //
  157. // Call MCDrvInit to get MCDSRV32.DLL module handle.
  158. //
  159. hmodMCDSRV = (*pMCDrvInit)(hdc, &gdhpdev);
  160. if (hmodMCDSRV)
  161. {
  162. //
  163. // Get the MCDEngEscPrep and MCDEngEscFilter entry
  164. // points.
  165. //
  166. pMCDEngEscPrep = (MCDENGESCPREPFUNC)
  167. GetProcAddress(hmodMCDSRV, MCDENGESCPREPNAME);
  168. pMCDEngEscFilter = (MCDENGESCFILTERFUNC)
  169. GetProcAddress(hmodMCDSRV, MCDENGESCFILTERNAME);
  170. if (pMCDEngEscPrep && pMCDEngEscFilter)
  171. {
  172. McdInitState = MCDRV_INITOK;
  173. }
  174. else
  175. {
  176. pMCDEngEscPrep = (MCDENGESCPREPFUNC) NULL;
  177. pMCDEngEscFilter = (MCDENGESCFILTERFUNC) NULL;
  178. DBGPRINT("Mcd95DriverInit: GetProcAddress failed\n");
  179. }
  180. }
  181. }
  182. else
  183. {
  184. DBGPRINT1("MCDGetDriverInfo: GetProcAddress(%s) failed\n",
  185. mcdDriverNames.pchFuncName);
  186. }
  187. }
  188. else
  189. {
  190. DBGPRINT1("MCDGetDriverInfo: LoadLibrary(%s) failed\n",
  191. mcdDriverNames.pchDriverName);
  192. }
  193. }
  194. Mcd95DriverInit_exit:
  195. LeaveCriticalSection(&gsemMcd);
  196. return (McdInitState == MCDRV_INITOK);
  197. }
  198. #endif
  199. //*****************************Private*Routine******************************
  200. //
  201. // InitMcdEsc
  202. //
  203. // Initializes an MCDESC_HEADER for filling in
  204. //
  205. //**************************************************************************
  206. // Placeholder in case any generic initialization becomes necessary
  207. #define InitMcdEsc(pmeh) (pmeh)
  208. //*****************************Private*Routine******************************
  209. //
  210. // InitMcdEscEmpty
  211. //
  212. // Initializes an MCDESC_HEADER for filling in
  213. //
  214. //**************************************************************************
  215. #define InitMcdEscEmpty(pmeh) \
  216. (InitMcdEsc(pmeh), \
  217. (pmeh)->hRC = NULL, \
  218. (pmeh)->hSharedMem = NULL, \
  219. (pmeh)->pSharedMem = NULL, \
  220. (pmeh)->dwWindow = 0, \
  221. (pmeh))
  222. //*****************************Private*Routine******************************
  223. //
  224. // InitMcdEscContext
  225. //
  226. // Initializes an MCDESC_HEADER for filling in
  227. //
  228. //**************************************************************************
  229. #define InitMcdEscContext(pmeh, pmctx) \
  230. (InitMcdEsc(pmeh), \
  231. (pmeh)->hRC = (pmctx)->hMCDContext, \
  232. (pmeh)->dwWindow = (pmctx)->dwMcdWindow, \
  233. (pmeh))
  234. //*****************************Private*Routine******************************
  235. //
  236. // InitMcdEscSurfaces
  237. //
  238. // Fills in some MCDESC_HEADER fields from context information
  239. //
  240. //**************************************************************************
  241. #if DBG
  242. extern ULONG APIENTRY glDebugEntry(int param, void *data);
  243. #endif
  244. MCDESC_HEADER *InitMcdEscSurfaces(MCDESC_HEADER *pmeh, MCDCONTEXT *pmctx)
  245. {
  246. GENMCDSTATE *pmst;
  247. InitMcdEscContext(pmeh, pmctx);
  248. // We're assuming that the context passed in is always the one
  249. // statically placed in the GENMCDSTATE. Attempt to verify this
  250. // by checking that the allocation size for the context is
  251. // the same as for a GENMCDSTATE.
  252. ASSERTOPENGL(glDebugEntry(3, pmctx) == sizeof(GENMCDSTATE),
  253. "InitMcdEscSurfaces: Bad context\n");
  254. pmst = (GENMCDSTATE *)pmctx;
  255. pmeh->msrfColor.hSurf = pmst->hDdColor;
  256. pmeh->msrfDepth.hSurf = pmst->hDdDepth;
  257. return pmeh;
  258. }
  259. //******************************Public*Routine******************************
  260. //
  261. // BOOL APIENTRY MCDGetDriverInfo(HDC hdc, MCDDRIVERINFOI *pMCDDriverInfo)
  262. //
  263. // Checks to determine if the device driver reports MCD capabilities.
  264. //
  265. //**************************************************************************
  266. BOOL APIENTRY MCDGetDriverInfo(HDC hdc, MCDDRIVERINFOI *pMCDDriverInfo)
  267. {
  268. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDDRIVERINFOCMDI)];
  269. MCDESC_HEADER *pmeh;
  270. MCDDRIVERINFOCMDI *pInfoCmd;
  271. if ( !(McdPrivateFlags & MCDPRIVATE_MCD_ENABLED) )
  272. {
  273. return FALSE;
  274. }
  275. #ifdef MCD95
  276. if (!Mcd95DriverInit(hdc))
  277. {
  278. return FALSE;
  279. }
  280. #endif
  281. pmeh = InitMcdEscEmpty((MCDESC_HEADER *)(cmdBuffer));
  282. pmeh->flags = 0;
  283. pInfoCmd = (MCDDRIVERINFOCMDI *)(pmeh + 1);
  284. pInfoCmd->command = MCD_DRIVERINFO;
  285. // Force the table to empty
  286. memset(&pMCDDriverInfo->mcdDriver, 0, sizeof(MCDDRIVER));
  287. // Force the version to 0
  288. pMCDDriverInfo->mcdDriverInfo.verMajor = 0;
  289. if (!(BOOL)EXTESCAPE(hdc, MCDFUNCS,
  290. sizeof(cmdBuffer),
  291. (char *)pmeh, sizeof(MCDDRIVERINFOI),
  292. (char *)pMCDDriverInfo))
  293. return FALSE;
  294. // See if the driver filled in a non-null version:
  295. if (pMCDDriverInfo->mcdDriverInfo.verMajor != 0)
  296. {
  297. verMajor = pMCDDriverInfo->mcdDriverInfo.verMajor;
  298. verMinor = pMCDDriverInfo->mcdDriverInfo.verMinor;
  299. return TRUE;
  300. }
  301. else
  302. {
  303. return FALSE;
  304. }
  305. }
  306. //******************************Public*Routine******************************
  307. //
  308. // LONG APIENTRY MCDDescribeMcdPixelFormat(HDC hdc,
  309. // LONG iPixelFormat,
  310. // MCDPIXELFORMAT *ppfd)
  311. //
  312. // Returns information about the specified hardware-dependent pixel format.
  313. //
  314. //**************************************************************************
  315. LONG APIENTRY MCDDescribeMcdPixelFormat(HDC hdc, LONG iPixelFormat,
  316. MCDPIXELFORMAT *pMcdPixelFmt)
  317. {
  318. LONG lRet = 0;
  319. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDPIXELFORMATCMDI)];
  320. MCDESC_HEADER *pmeh;
  321. MCDPIXELFORMATCMDI *pPixelFmtCmd;
  322. if ( !(McdPrivateFlags & MCDPRIVATE_PALETTEFORMATS) &&
  323. ((GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES)) == 8) &&
  324. (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) )
  325. {
  326. return lRet;
  327. }
  328. pmeh = InitMcdEscEmpty((MCDESC_HEADER *)(cmdBuffer));
  329. pmeh->flags = 0;
  330. pPixelFmtCmd = (MCDPIXELFORMATCMDI *)(pmeh + 1);
  331. pPixelFmtCmd->command = MCD_DESCRIBEPIXELFORMAT;
  332. pPixelFmtCmd->iPixelFormat = iPixelFormat;
  333. lRet = (LONG)EXTESCAPE(hdc, MCDFUNCS,
  334. sizeof(cmdBuffer),
  335. (char *)pmeh, sizeof(MCDPIXELFORMAT),
  336. (char *)pMcdPixelFmt);
  337. // Limit overlay/underlay planes to 15 each (as per spec).
  338. if (pMcdPixelFmt)
  339. {
  340. if (pMcdPixelFmt->cOverlayPlanes > 15)
  341. pMcdPixelFmt->cOverlayPlanes = 15;
  342. if (pMcdPixelFmt->cUnderlayPlanes > 15)
  343. pMcdPixelFmt->cUnderlayPlanes = 15;
  344. }
  345. return lRet;
  346. }
  347. //******************************Public*Routine******************************
  348. //
  349. // LONG APIENTRY MCDDescribePixelFormat(HDC hdc,
  350. // LONG iPixelFormat,
  351. // LPPIXELFORMATDESCRIPTOR ppfd)
  352. //
  353. // Returns a PIXELFORMATDESCRIPTOR describing the specified hardware-dependent
  354. // pixel format.
  355. //
  356. //**************************************************************************
  357. #define STANDARD_MCD_FLAGS \
  358. (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT | \
  359. PFD_GENERIC_ACCELERATED)
  360. LONG APIENTRY MCDDescribePixelFormat(HDC hdc, LONG iPixelFormat,
  361. LPPIXELFORMATDESCRIPTOR ppfd)
  362. {
  363. LONG lRet = 0;
  364. MCDPIXELFORMAT mcdPixelFmt;
  365. lRet = MCDDescribeMcdPixelFormat(hdc, iPixelFormat,
  366. ppfd ? &mcdPixelFmt : NULL);
  367. if (ppfd && lRet)
  368. {
  369. ppfd->nSize = sizeof(*ppfd);
  370. ppfd->nVersion = 1;
  371. ppfd->dwFlags = mcdPixelFmt.dwFlags | STANDARD_MCD_FLAGS |
  372. ((mcdPixelFmt.dwFlags & PFD_DOUBLEBUFFER) ?
  373. 0 : PFD_SUPPORT_GDI);
  374. if (McdPrivateFlags & MCDPRIVATE_EMULATEICD)
  375. ppfd->dwFlags &= ~PFD_GENERIC_FORMAT;
  376. memcpy(&ppfd->iPixelType, &mcdPixelFmt.iPixelType,
  377. offsetof(MCDPIXELFORMAT, cDepthBits) -
  378. offsetof(MCDPIXELFORMAT, iPixelType));
  379. ppfd->cDepthBits = mcdPixelFmt.cDepthBits;
  380. if (ppfd->iPixelType == PFD_TYPE_RGBA)
  381. {
  382. if (ppfd->cColorBits < 8)
  383. {
  384. ppfd->cAccumBits = 16;
  385. ppfd->cAccumRedBits = 5;
  386. ppfd->cAccumGreenBits = 6;
  387. ppfd->cAccumBlueBits = 5;
  388. ppfd->cAccumAlphaBits = 0;
  389. }
  390. else
  391. {
  392. if (ppfd->cColorBits <= 16)
  393. {
  394. ppfd->cAccumBits = 32;
  395. ppfd->cAccumRedBits = 11;
  396. ppfd->cAccumGreenBits = 11;
  397. ppfd->cAccumBlueBits = 10;
  398. ppfd->cAccumAlphaBits = 0;
  399. }
  400. else
  401. {
  402. ppfd->cAccumBits = 64;
  403. ppfd->cAccumRedBits = 16;
  404. ppfd->cAccumGreenBits = 16;
  405. ppfd->cAccumBlueBits = 16;
  406. ppfd->cAccumAlphaBits = 0;
  407. }
  408. }
  409. }
  410. else
  411. {
  412. ppfd->cAccumBits = 0;
  413. ppfd->cAccumRedBits = 0;
  414. ppfd->cAccumGreenBits = 0;
  415. ppfd->cAccumBlueBits = 0;
  416. ppfd->cAccumAlphaBits = 0;
  417. }
  418. if (mcdPixelFmt.cStencilBits)
  419. {
  420. ppfd->cStencilBits = mcdPixelFmt.cStencilBits;
  421. }
  422. else
  423. {
  424. if (McdPrivateFlags & MCDPRIVATE_USEGENERICSTENCIL)
  425. ppfd->cStencilBits = 8;
  426. else
  427. ppfd->cStencilBits = 0;
  428. }
  429. ppfd->cAuxBuffers = 0;
  430. ppfd->iLayerType = PFD_MAIN_PLANE;
  431. ppfd->bReserved = (BYTE) (mcdPixelFmt.cOverlayPlanes |
  432. (mcdPixelFmt.cUnderlayPlanes << 4));
  433. ppfd->dwLayerMask = 0;
  434. ppfd->dwVisibleMask = mcdPixelFmt.dwTransparentColor;
  435. ppfd->dwDamageMask = 0;
  436. }
  437. return lRet;
  438. }
  439. //******************************Public*Routine******************************
  440. //
  441. // BOOL APIENTRY MCDCreateContext(MCDCONTEXT *pMCDContext,
  442. // MCDRCINFO *pRcInfo,
  443. // GLSURF *pgsurf,
  444. // ULONG flags)
  445. //
  446. // Creates an MCD rendering context for the specified hdc/hwnd according
  447. // to the specified flags.
  448. //
  449. //**************************************************************************
  450. BOOL APIENTRY MCDCreateContext(MCDCONTEXT *pMCDContext,
  451. MCDRCINFOPRIV *pRcInfo,
  452. GLSURF *pgsurf,
  453. int ipfd,
  454. ULONG flags)
  455. {
  456. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDCREATECONTEXT)];
  457. MCDESC_HEADER *pmeh;
  458. MCDCREATECONTEXT *pmcc;
  459. if (flags & MCDSURFACE_HWND)
  460. {
  461. // We don't have surfaces to pass in this case
  462. pmeh = InitMcdEscContext((MCDESC_HEADER *)cmdBuffer, pMCDContext);
  463. pmeh->flags = MCDESC_FL_CREATE_CONTEXT;
  464. }
  465. else if (SUPPORTS_DIRECT())
  466. {
  467. pmeh = InitMcdEscSurfaces((MCDESC_HEADER *)cmdBuffer, pMCDContext);
  468. pmeh->flags = MCDESC_FL_CREATE_CONTEXT | MCDESC_FL_SURFACES;
  469. }
  470. else
  471. {
  472. return FALSE;
  473. }
  474. pmeh->hSharedMem = NULL;
  475. pmeh->pSharedMem = (VOID *)NULL;
  476. pmcc = (MCDCREATECONTEXT *)(pmeh + 1);
  477. if (flags & MCDSURFACE_HWND)
  478. {
  479. pmcc->escCreate.hwnd = pgsurf->hwnd;
  480. }
  481. else
  482. {
  483. pmcc->escCreate.hwnd = NULL;
  484. }
  485. pmcc->escCreate.flags = flags;
  486. pmcc->ipfd = ipfd;
  487. pmcc->iLayer = pgsurf->iLayer;
  488. pmcc->mcdFlags = McdFlags;
  489. pmcc->pRcInfo = pRcInfo;
  490. pMCDContext->hMCDContext =
  491. (MCDHANDLE)IntToPtr( EXTESCAPE(pgsurf->hdc, MCDFUNCS,
  492. sizeof(MCDESC_HEADER) + sizeof(MCDCREATECONTEXT),
  493. (char *)cmdBuffer, sizeof(MCDRCINFOPRIV),
  494. (char *)pRcInfo) );
  495. pMCDContext->hdc = pgsurf->hdc;
  496. pMCDContext->dwMcdWindow = pRcInfo->dwMcdWindow;
  497. return (pMCDContext->hMCDContext != (HANDLE)NULL);
  498. }
  499. #define MCD_MEM_ALIGN 32
  500. //******************************Public*Routine******************************
  501. //
  502. // UCHAR * APIENTRY MCDAlloc(MCDCONTEXT *pMCDContext,
  503. // ULONG numBytes,
  504. // MCDHANDLE *pMCDHandle,
  505. // ULONG flags);
  506. //
  507. // Allocate a chunk of shared memory to use for vertex and pixel data.
  508. //
  509. // The return value is a pointer to a shared memory region which can be
  510. // subsequently used by the caller. For vertex processing, caller should
  511. // use MCDLockMemory()/MCDUnlockMemory to serialize hardware access to the
  512. // memory.
  513. //
  514. //**************************************************************************
  515. UCHAR * APIENTRY MCDAlloc(MCDCONTEXT *pMCDContext, ULONG numBytes,
  516. HANDLE *pMCDHandle, ULONG flags)
  517. {
  518. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDALLOCCMDI)];
  519. ULONG outBuffer;
  520. ULONG totalSize = numBytes + MCD_MEM_ALIGN + sizeof(MCDMEMHDRI);
  521. MCDALLOCCMDI *pCmdAlloc;
  522. MCDESC_HEADER *pmeh;
  523. VOID *pResult;
  524. MCDMEMHDRI *pMCDMemHdr;
  525. UCHAR *pBase;
  526. UCHAR *pAlign;
  527. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  528. pmeh->hSharedMem = NULL;
  529. pmeh->pSharedMem = NULL;
  530. pmeh->flags = 0;
  531. pCmdAlloc = (MCDALLOCCMDI *)(pmeh + 1);
  532. pCmdAlloc->command = MCD_ALLOC;
  533. pCmdAlloc->sourceProcessID = GetCurrentProcessId();
  534. pCmdAlloc->numBytes = totalSize;
  535. pCmdAlloc->flags = flags;
  536. pBase = (UCHAR *)IntToPtr( EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  537. sizeof(cmdBuffer),
  538. (char *)pmeh, 4, (char *)pMCDHandle) );
  539. if (!pBase)
  540. return (VOID *)NULL;
  541. pAlign = (UCHAR *)(((ULONG_PTR)(pBase + sizeof(MCDMEMHDRI)) +
  542. (MCD_MEM_ALIGN - 1)) &
  543. ~(MCD_MEM_ALIGN - 1));
  544. pMCDMemHdr = (MCDMEMHDRI *)(pAlign - sizeof(MCDMEMHDRI));
  545. pMCDMemHdr->flags = 0;
  546. pMCDMemHdr->numBytes = numBytes;
  547. pMCDMemHdr->pMaxMem = (VOID *)((char *)pMCDMemHdr + totalSize);
  548. pMCDMemHdr->hMCDMem = *pMCDHandle;
  549. pMCDMemHdr->pBase = pBase;
  550. return (VOID *)(pAlign);
  551. }
  552. //******************************Public*Routine******************************
  553. //
  554. // BOOL APIENTRY MCDFree(MCDCONTEXT *pMCDContext,
  555. // VOID *pMem);
  556. //
  557. // Frees a chunk of driver-allocated shared memory.
  558. //
  559. // Returns TRUE for success, FALSE for failure.
  560. //
  561. //**************************************************************************
  562. BOOL APIENTRY MCDFree(MCDCONTEXT *pMCDContext, VOID *pMCDMem)
  563. {
  564. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDFREECMDI)];
  565. MCDFREECMDI *pCmdFree;
  566. MCDESC_HEADER *pmeh;
  567. MCDMEMHDRI *pMCDMemHdr;
  568. #ifdef MCD95
  569. //
  570. // Driver already shutdown, therefore memory already deleted.
  571. //
  572. if (!pMCDEngEscFilter)
  573. return TRUE;
  574. #endif
  575. pMCDMemHdr = (MCDMEMHDRI *)((char *)pMCDMem - sizeof(MCDMEMHDRI));
  576. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  577. pmeh->hSharedMem = NULL;
  578. pmeh->pSharedMem = NULL;
  579. pmeh->flags = 0;
  580. pCmdFree = (MCDFREECMDI *)(pmeh + 1);
  581. pCmdFree->command = MCD_FREE;
  582. pCmdFree->hMCDMem = pMCDMemHdr->hMCDMem;
  583. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  584. sizeof(cmdBuffer),
  585. (char *)pmeh, 0, (char *)NULL);
  586. }
  587. //******************************Public*Routine******************************
  588. //
  589. // VOID APIENTRY MCDBeginState(MCDCONTEXT *pMCDContext, VOID *pMCDMem);
  590. //
  591. // Begins a batch of state commands to issue to the driver.
  592. //
  593. //**************************************************************************
  594. VOID APIENTRY MCDBeginState(MCDCONTEXT *pMCDContext, VOID *pMCDMem)
  595. {
  596. MCDMEMHDRI *pMCDMemHdr;
  597. MCDSTATECMDI *pMCDStateCmd;
  598. pMCDMemHdr = (MCDMEMHDRI *)((char *)pMCDMem - sizeof(MCDMEMHDRI));
  599. pMCDStateCmd = (MCDSTATECMDI *)pMCDMem;
  600. pMCDStateCmd->command = MCD_STATE;
  601. pMCDStateCmd->numStates = 0;
  602. pMCDStateCmd->pNextState = (MCDSTATE *)(pMCDStateCmd + 1);
  603. pMCDStateCmd->pMaxState = (MCDSTATE *)(pMCDMemHdr->pMaxMem);
  604. pMCDMemHdr->pMCDContext = pMCDContext;
  605. }
  606. //******************************Public*Routine******************************
  607. //
  608. // BOOL APIENTRY MCDFlushState(VOID pMCDMem);
  609. //
  610. // Flushes a batch of state commands to the driver.
  611. //
  612. // Returns TRUE for success, FALSE for failure.
  613. //
  614. //**************************************************************************
  615. BOOL APIENTRY MCDFlushState(VOID *pMCDMem)
  616. {
  617. MCDESC_HEADER meh;
  618. MCDMEMHDRI *pMCDMemHdr;
  619. MCDSTATECMDI *pMCDStateCmd;
  620. pMCDMemHdr = (MCDMEMHDRI *)((char *)pMCDMem - sizeof(MCDMEMHDRI));
  621. pMCDStateCmd = (MCDSTATECMDI *)pMCDMem;
  622. InitMcdEscContext(&meh, pMCDMemHdr->pMCDContext);
  623. meh.hSharedMem = pMCDMemHdr->hMCDMem;
  624. meh.pSharedMem = (char *)pMCDMem;
  625. meh.sharedMemSize = (ULONG)((char *)pMCDStateCmd->pNextState -
  626. (char *)pMCDStateCmd);
  627. meh.flags = 0;
  628. if (!meh.sharedMemSize)
  629. return TRUE;
  630. return (BOOL)EXTESCAPE(pMCDMemHdr->pMCDContext->hdc, MCDFUNCS,
  631. sizeof(MCDESC_HEADER), (char *)&meh,
  632. 0, (char *)NULL);
  633. }
  634. //******************************Public*Routine******************************
  635. //
  636. // BOOL APIENTRY MCDAddState(VOID *pMCDMem, ULONG stateToChange,
  637. // ULONG stateValue);
  638. //
  639. // Adds a state to a state buffer (started with MCDBeginState). If there
  640. // is no room in the state stream (i.e., the memory buffer), the current
  641. // batch of state commands is automatically flushed.
  642. //
  643. //
  644. // Returns TRUE for success, FALSE for failure. A FALSE return will occur
  645. // if an automatic flush is performed which fails.
  646. //
  647. //**************************************************************************
  648. BOOL APIENTRY MCDAddState(VOID *pMCDMem, ULONG stateToChange,
  649. ULONG stateValue)
  650. {
  651. MCDSTATECMDI *pMCDStateCmd;
  652. MCDSTATE *pState;
  653. BOOL retVal = TRUE;
  654. pMCDStateCmd = (MCDSTATECMDI *)pMCDMem;
  655. if (((char *)pMCDStateCmd->pNextState + sizeof(MCDSTATE)) >=
  656. (char *)pMCDStateCmd->pMaxState) {
  657. MCDMEMHDRI *pMCDMemHdr = (MCDMEMHDRI *)
  658. ((char *)pMCDMem - sizeof(MCDMEMHDRI));
  659. retVal = MCDFlushState(pMCDMem);
  660. pMCDStateCmd = (MCDSTATECMDI *)pMCDMem;
  661. pMCDStateCmd->command = MCD_STATE;
  662. pMCDStateCmd->numStates = 0;
  663. pMCDStateCmd->pNextState = (MCDSTATE *)(pMCDStateCmd + 1);
  664. pMCDStateCmd->pMaxState = (MCDSTATE *)(pMCDMemHdr->pMaxMem);
  665. }
  666. pMCDStateCmd->numStates++;
  667. pState = pMCDStateCmd->pNextState;
  668. pState->size = sizeof(MCDSTATE);
  669. pState->state = stateToChange;
  670. pState->stateValue = stateValue;
  671. pMCDStateCmd->pNextState++;
  672. return retVal;
  673. }
  674. //******************************Public*Routine******************************
  675. //
  676. // BOOL APIENTRY MCDAddStateStruct(VOID *pMCDMem, ULONG stateToChange,
  677. // VOID *pStateValue, ULONG stateValueSize)
  678. //
  679. //
  680. // Adds a state structure to a state buffer (started with MCDBeginState). If
  681. // there is no room in the state stream (i.e., the memory buffer), the current
  682. // batch of state commands is automatically flushed.
  683. //
  684. //
  685. // Returns TRUE for success, FALSE for failure. A FALSE return will occur
  686. // if an automatic flush is performed which fails.
  687. //
  688. //**************************************************************************
  689. BOOL APIENTRY MCDAddStateStruct(VOID *pMCDMem, ULONG stateToChange,
  690. VOID *pStateValue, ULONG stateValueSize)
  691. {
  692. MCDSTATECMDI *pMCDStateCmd;
  693. MCDSTATE *pState;
  694. BOOL retVal = FALSE;
  695. pMCDStateCmd = (MCDSTATECMDI *)pMCDMem;
  696. if (((char *)pMCDStateCmd->pNextState + stateValueSize) >=
  697. (char *)pMCDStateCmd->pMaxState) {
  698. MCDMEMHDRI *pMCDMemHdr = (MCDMEMHDRI *)
  699. ((char *)pMCDMem - sizeof(MCDMEMHDRI));
  700. retVal = MCDFlushState(pMCDMem);
  701. pMCDStateCmd = (MCDSTATECMDI *)pMCDMem;
  702. pMCDStateCmd->command = MCD_STATE;
  703. pMCDStateCmd->numStates = 0;
  704. pMCDStateCmd->pNextState = (MCDSTATE *)(pMCDStateCmd + 1);
  705. pMCDStateCmd->pMaxState = (MCDSTATE *)(pMCDMemHdr->pMaxMem);
  706. }
  707. pMCDStateCmd->numStates++;
  708. pState = pMCDStateCmd->pNextState;
  709. pState->state = stateToChange;
  710. pState->size = offsetof(MCDSTATE, stateValue) + stateValueSize;
  711. memcpy((char *)&pState->stateValue, (char *)pStateValue, stateValueSize);
  712. pMCDStateCmd->pNextState =
  713. (MCDSTATE *)(((char *)pMCDStateCmd->pNextState) + pState->size);
  714. return retVal;
  715. }
  716. //******************************Public*Routine******************************
  717. //
  718. // BOOL APIENTRY MCDSetViewport(MCDCONTEXT *pMCDContext, VOID pMCDMem,
  719. // MCDVIEWPORT pMCDViewport)
  720. //
  721. // Establishes the viewport scaling to convert transformed coordinates to
  722. // screen coordinates.
  723. //
  724. //**************************************************************************
  725. BOOL APIENTRY MCDSetViewport(MCDCONTEXT *pMCDContext, VOID *pMCDMem,
  726. MCDVIEWPORT *pMCDViewport)
  727. {
  728. MCDESC_HEADER meh;
  729. MCDMEMHDRI *pMCDMemHdr;
  730. MCDVIEWPORTCMDI *pMCDViewportCmd;
  731. pMCDMemHdr = (MCDMEMHDRI *)((char *)pMCDMem - sizeof(MCDMEMHDRI));
  732. pMCDViewportCmd = (MCDVIEWPORTCMDI *)pMCDMem;
  733. pMCDViewportCmd->MCDViewport = *pMCDViewport;
  734. pMCDViewportCmd->command = MCD_VIEWPORT;
  735. InitMcdEscContext(&meh, pMCDContext);
  736. meh.hSharedMem = pMCDMemHdr->hMCDMem;
  737. meh.pSharedMem = (char *)pMCDMem;
  738. meh.sharedMemSize = sizeof(MCDVIEWPORTCMDI);
  739. meh.flags = 0;
  740. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  741. sizeof(MCDESC_HEADER), (char *)&meh,
  742. 0, (char *)NULL);
  743. }
  744. //******************************Public*Routine******************************
  745. //
  746. // ULONG APIENTRY MCDQueryMemStatus((VOID *pMCDMem);
  747. //
  748. // Returns the status of the specified memory block. Return values are:
  749. //
  750. // MCD_MEM_READY - memory is available for client access
  751. // MCD_MEM_BUSY - memory is busy due to driver access
  752. // MCD_MEM_INVALID - queried memory is invalid
  753. //
  754. //**************************************************************************
  755. ULONG APIENTRY MCDQueryMemStatus(VOID *pMCDMem)
  756. {
  757. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDMEMSTATUSCMDI)];
  758. MCDMEMHDRI *pMCDMemHdr =
  759. (MCDMEMHDRI *)((char *)pMCDMem - sizeof(MCDMEMHDRI));
  760. MCDMEMSTATUSCMDI *pCmdMemStatus;
  761. MCDESC_HEADER *pmeh;
  762. #ifdef MCD95
  763. //
  764. // Driver already shutdown, therefore memory already deleted.
  765. //
  766. if (!pMCDEngEscFilter)
  767. return MCD_MEM_INVALID;
  768. #endif
  769. pmeh = InitMcdEscEmpty((MCDESC_HEADER *)(cmdBuffer));
  770. pmeh->flags = 0;
  771. pCmdMemStatus = (MCDMEMSTATUSCMDI *)(pmeh + 1);
  772. pCmdMemStatus->command = MCD_QUERYMEMSTATUS;
  773. pCmdMemStatus->hMCDMem = pMCDMemHdr->hMCDMem;
  774. return (ULONG)EXTESCAPE(pMCDMemHdr->pMCDContext->hdc, MCDFUNCS,
  775. sizeof(cmdBuffer),
  776. (char *)pmeh, 0, (char *)NULL);
  777. }
  778. //******************************Public*Routine******************************
  779. //
  780. // BOOL APIENTRY MCDProcessBatch(MCDCONTEXT *pMCDContext, VOID pMCDMem,
  781. // ULONG batchSize, VOID *pMCDFirstCmd)
  782. //
  783. // Processes a batch of primitives pointed to by pMCDMem.
  784. //
  785. // Returns TRUE if the batch was processed without error, FALSE otherwise.
  786. //
  787. //**************************************************************************
  788. PVOID APIENTRY MCDProcessBatch(MCDCONTEXT *pMCDContext, VOID *pMCDMem,
  789. ULONG batchSize, VOID *pMCDFirstCmd,
  790. int cExtraSurfaces,
  791. LPDIRECTDRAWSURFACE *pdds)
  792. {
  793. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + MCD_MAXMIPMAPLEVEL*sizeof(DWORD)];
  794. MCDESC_HEADER *pmeh;
  795. MCDMEMHDRI *pMCDMemHdr;
  796. int i;
  797. ULONG_PTR *pdwSurf;
  798. #if DBG
  799. if (McdDebugFlags & MCDDEBUG_DISABLE_PROCBATCH)
  800. {
  801. MCDSync(pMCDContext);
  802. return pMCDFirstCmd;
  803. }
  804. #endif
  805. pMCDMemHdr = (MCDMEMHDRI *)((char *)pMCDMem - sizeof(MCDMEMHDRI));
  806. pmeh = InitMcdEscSurfaces((MCDESC_HEADER *)cmdBuffer, pMCDContext);
  807. pmeh->hSharedMem = pMCDMemHdr->hMCDMem;
  808. pmeh->pSharedMem = (char *)pMCDFirstCmd;
  809. pmeh->sharedMemSize = batchSize;
  810. pmeh->flags = MCDESC_FL_DISPLAY_LOCK | MCDESC_FL_BATCH;
  811. if (SUPPORTS_DIRECT())
  812. {
  813. pmeh->flags |= MCDESC_FL_SURFACES | MCDESC_FL_LOCK_SURFACES;
  814. }
  815. else if (pmeh->msrfColor.hSurf != NULL ||
  816. pmeh->msrfDepth.hSurf != NULL ||
  817. cExtraSurfaces != 0)
  818. {
  819. return pMCDFirstCmd;
  820. }
  821. // Assert that we won't exceed the kernel's expectations
  822. ASSERTOPENGL(MCD_MAXMIPMAPLEVEL <= MCDESC_MAX_LOCK_SURFACES,
  823. "MCD_MAXMIPMAPLEVEL too large\n");
  824. pmeh->cLockSurfaces = cExtraSurfaces;
  825. pdwSurf = (ULONG_PTR *)(pmeh+1);
  826. for (i = 0; i < cExtraSurfaces; i++)
  827. {
  828. *pdwSurf++ = ((LPDDRAWI_DDRAWSURFACE_INT)pdds[i])->lpLcl->hDDSurface;
  829. }
  830. return (PVOID)IntToPtr( EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  831. sizeof(cmdBuffer), (char *)pmeh,
  832. 0, (char *)NULL) );
  833. }
  834. //******************************Public*Routine******************************
  835. //
  836. // BOOL APIENTRY MCDReadSpan(MCDCONTEXT *pMCDContext, VOID pMCDMem,
  837. // ULONG x, ULONG y, ULONG numPixels, ULONG type)
  838. //
  839. // Reads a span of pixel data from the buffer requested by "type".
  840. // The pixel values are returned in pMCDMem.
  841. //
  842. // Returns TRUE for success, FALSE for failure.
  843. //
  844. //**************************************************************************
  845. BOOL APIENTRY MCDReadSpan(MCDCONTEXT *pMCDContext, VOID *pMCDMem,
  846. ULONG x, ULONG y, ULONG numPixels, ULONG type)
  847. {
  848. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDSPANCMDI)];
  849. MCDESC_HEADER *pmeh;
  850. MCDMEMHDRI *pMCDMemHdr;
  851. MCDSPANCMDI *pMCDSpanCmd;
  852. pMCDMemHdr = (MCDMEMHDRI *)((char *)pMCDMem - sizeof(MCDMEMHDRI));
  853. pmeh = InitMcdEscSurfaces((MCDESC_HEADER *)cmdBuffer, pMCDContext);
  854. pmeh->hSharedMem = NULL;
  855. pmeh->pSharedMem = (VOID *)NULL;
  856. pmeh->sharedMemSize = 0;
  857. pmeh->flags = 0;
  858. if (SUPPORTS_DIRECT())
  859. {
  860. pmeh->flags |= MCDESC_FL_SURFACES;
  861. }
  862. else if (pmeh->msrfColor.hSurf != NULL ||
  863. pmeh->msrfDepth.hSurf != NULL)
  864. {
  865. return FALSE;
  866. }
  867. pMCDSpanCmd = (MCDSPANCMDI *)(pmeh + 1);
  868. pMCDSpanCmd->command = MCD_READSPAN;
  869. pMCDSpanCmd->hMem = pMCDMemHdr->hMCDMem;
  870. pMCDSpanCmd->MCDSpan.x = x;
  871. pMCDSpanCmd->MCDSpan.y = y;
  872. pMCDSpanCmd->MCDSpan.numPixels = numPixels;
  873. pMCDSpanCmd->MCDSpan.type = type;
  874. pMCDSpanCmd->MCDSpan.pPixels = (VOID *)((char *)pMCDMem);
  875. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  876. sizeof(cmdBuffer), (char *)pmeh, 0, (char *)NULL);
  877. }
  878. //******************************Public*Routine******************************
  879. //
  880. // BOOL APIENTRY MCDWriteSpan(MCDCONTEXT *pMCDContext, VOID pMCDMem,
  881. // ULONG x, ULONG y, ULONG numPixels, ULONG type)
  882. //
  883. // Writes a span of pixel data to the buffer requested by "type".
  884. // The pixel values are given in pMCDMem.
  885. //
  886. // Returns TRUE for success, FALSE for failure.
  887. //
  888. //**************************************************************************
  889. BOOL APIENTRY MCDWriteSpan(MCDCONTEXT *pMCDContext, VOID *pMCDMem,
  890. ULONG x, ULONG y, ULONG numPixels, ULONG type)
  891. {
  892. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDSPANCMDI)];
  893. MCDESC_HEADER *pmeh;
  894. MCDMEMHDRI *pMCDMemHdr;
  895. MCDSPANCMDI *pMCDSpanCmd;
  896. pMCDMemHdr = (MCDMEMHDRI *)((char *)pMCDMem - sizeof(MCDMEMHDRI));
  897. pmeh = InitMcdEscSurfaces((MCDESC_HEADER *)cmdBuffer, pMCDContext);
  898. pmeh->hSharedMem = NULL;
  899. pmeh->pSharedMem = (VOID *)NULL;
  900. pmeh->sharedMemSize = 0;
  901. pmeh->flags = 0;
  902. if (SUPPORTS_DIRECT())
  903. {
  904. pmeh->flags |= MCDESC_FL_SURFACES;
  905. }
  906. else if (pmeh->msrfColor.hSurf != NULL ||
  907. pmeh->msrfDepth.hSurf != NULL)
  908. {
  909. return FALSE;
  910. }
  911. pMCDSpanCmd = (MCDSPANCMDI *)(pmeh + 1);
  912. pMCDSpanCmd->command = MCD_WRITESPAN;
  913. pMCDSpanCmd->hMem = pMCDMemHdr->hMCDMem;
  914. pMCDSpanCmd->MCDSpan.x = x;
  915. pMCDSpanCmd->MCDSpan.y = y;
  916. pMCDSpanCmd->MCDSpan.numPixels = numPixels;
  917. pMCDSpanCmd->MCDSpan.type = type;
  918. pMCDSpanCmd->MCDSpan.pPixels = (VOID *)((char *)pMCDMem);
  919. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  920. sizeof(cmdBuffer), (char *)pmeh, 0, (char *)NULL);
  921. }
  922. //******************************Public*Routine******************************
  923. //
  924. // BOOL APIENTRY MCDClear(MCDCONTEXT *pMCDContext, RECTL rect, ULONG buffers);
  925. //
  926. // Clears buffers specified for the given rectangle. The current fill values
  927. // will be used.
  928. //
  929. //**************************************************************************
  930. BOOL APIENTRY MCDClear(MCDCONTEXT *pMCDContext, RECTL rect, ULONG buffers)
  931. {
  932. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDCLEARCMDI)];
  933. MCDCLEARCMDI *pClearCmd;
  934. MCDESC_HEADER *pmeh;
  935. #if DBG
  936. if (McdDebugFlags & MCDDEBUG_DISABLE_CLEAR)
  937. {
  938. MCDSync(pMCDContext);
  939. return FALSE;
  940. }
  941. #endif
  942. pmeh = InitMcdEscSurfaces((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  943. pmeh->hSharedMem = NULL;
  944. pmeh->pSharedMem = (VOID *)NULL;
  945. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  946. if (SUPPORTS_DIRECT())
  947. {
  948. pmeh->flags |= MCDESC_FL_SURFACES;
  949. }
  950. else if (pmeh->msrfColor.hSurf != NULL ||
  951. pmeh->msrfDepth.hSurf != NULL)
  952. {
  953. return FALSE;
  954. }
  955. pClearCmd = (MCDCLEARCMDI *)(pmeh + 1);
  956. pClearCmd->command = MCD_CLEAR;
  957. pClearCmd->buffers = buffers;
  958. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  959. sizeof(cmdBuffer),
  960. (char *)pmeh, 0, (char *)NULL);
  961. }
  962. //******************************Public*Routine******************************
  963. //
  964. // BOOL APIENTRY MCDSetScissorRect(MCDCONTEXT *pMCDContext, RECTL *pRect,
  965. // BOOL bEnabled);
  966. //
  967. // Sets the scissor rectangle.
  968. //
  969. //**************************************************************************
  970. //!! Need semaphore to remove display lock !!
  971. BOOL APIENTRY MCDSetScissorRect(MCDCONTEXT *pMCDContext, RECTL *pRect,
  972. BOOL bEnabled)
  973. {
  974. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDSCISSORCMDI)];
  975. MCDSCISSORCMDI *pScissorCmd;
  976. MCDESC_HEADER *pmeh;
  977. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  978. pmeh->hSharedMem = NULL;
  979. pmeh->pSharedMem = (VOID *)NULL;
  980. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  981. pScissorCmd = (MCDSCISSORCMDI *)(pmeh + 1);
  982. pScissorCmd->command = MCD_SCISSOR;
  983. pScissorCmd->rect = *pRect;
  984. pScissorCmd->bEnabled = bEnabled;
  985. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  986. sizeof(cmdBuffer),
  987. (char *)pmeh, 0, (char *)NULL);
  988. }
  989. //******************************Public*Routine******************************
  990. //
  991. // BOOL APIENTRY MCDSwap(MCDCONTEXT *pMCDContext, ULONG flags);
  992. //
  993. // Swaps the front and back buffers.
  994. //
  995. //**************************************************************************
  996. BOOL APIENTRY MCDSwap(MCDCONTEXT *pMCDContext, ULONG flags)
  997. {
  998. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDSWAPCMDI)];
  999. MCDSWAPCMDI *pSwapCmd;
  1000. MCDESC_HEADER *pmeh;
  1001. // InitMcdEscSurfaces cannot be used because the context given
  1002. // is a temporary one constructed on the fly since SwapBuffers
  1003. // has only surface information.
  1004. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1005. pmeh->hSharedMem = NULL;
  1006. pmeh->pSharedMem = (VOID *)NULL;
  1007. // Swap cannot be called on DirectDraw surfaces because DirectDraw
  1008. // contexts cannot be double-buffered. These handles can therefore
  1009. // be forced to NULL.
  1010. pmeh->msrfColor.hSurf = NULL;
  1011. pmeh->msrfDepth.hSurf = NULL;
  1012. #ifdef MCD95
  1013. pmeh->flags = MCDESC_FL_DISPLAY_LOCK | MCDESC_FL_SWAPBUFFER;
  1014. #else
  1015. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  1016. #endif
  1017. if (SUPPORTS_DIRECT())
  1018. {
  1019. pmeh->flags |= MCDESC_FL_SURFACES;
  1020. }
  1021. pSwapCmd = (MCDSWAPCMDI *)(pmeh + 1);
  1022. pSwapCmd->command = MCD_SWAP;
  1023. pSwapCmd->flags = flags;
  1024. #ifdef MCD95
  1025. pSwapCmd->hwnd = WindowFromDC(pMCDContext->hdc);
  1026. #endif
  1027. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1028. sizeof(cmdBuffer),
  1029. (char *)pmeh, 0, (char *)NULL);
  1030. }
  1031. //******************************Public*Routine******************************
  1032. //
  1033. // BOOL APIENTRY MCDDeleteContext(MCDCONTEXT *pMCDContext);
  1034. //
  1035. // Deletes the specified context. This will free the buffers associated with
  1036. // the context, but will *not* free memory or textures created with the
  1037. // context.
  1038. //
  1039. //**************************************************************************
  1040. BOOL APIENTRY MCDDeleteContext(MCDCONTEXT *pMCDContext)
  1041. {
  1042. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDDELETERCCMDI)];
  1043. MCDDELETERCCMDI *pDeleteRcCmd;
  1044. MCDESC_HEADER *pmeh;
  1045. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1046. pmeh->hSharedMem = NULL;
  1047. pmeh->pSharedMem = (VOID *)NULL;
  1048. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  1049. pDeleteRcCmd = (MCDDELETERCCMDI *)(pmeh + 1);
  1050. pDeleteRcCmd->command = MCD_DELETERC;
  1051. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1052. sizeof(cmdBuffer),
  1053. (char *)pmeh, 0, (char *)NULL);
  1054. }
  1055. //******************************Public*Routine******************************
  1056. //
  1057. // BOOL APIENTRY MCDAllocBuffers(MCDCONTEXT *pMCDContext)
  1058. //
  1059. // Allocates the buffers required for the specified context.
  1060. //
  1061. //**************************************************************************
  1062. BOOL APIENTRY MCDAllocBuffers(MCDCONTEXT *pMCDContext, RECTL *pWndRect)
  1063. {
  1064. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDALLOCBUFFERSCMDI)];
  1065. MCDESC_HEADER *pmeh;
  1066. MCDALLOCBUFFERSCMDI *pAllocBuffersCmd;
  1067. #if DBG
  1068. if (McdDebugFlags & MCDDEBUG_DISABLE_ALLOCBUF)
  1069. {
  1070. return FALSE;
  1071. }
  1072. #endif
  1073. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1074. pmeh->hSharedMem = NULL;
  1075. pmeh->pSharedMem = (VOID *)NULL;
  1076. pmeh->flags = 0;
  1077. pAllocBuffersCmd = (MCDALLOCBUFFERSCMDI *)(pmeh + 1);
  1078. pAllocBuffersCmd->command = MCD_ALLOCBUFFERS;
  1079. pAllocBuffersCmd->WndRect = *pWndRect;
  1080. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1081. sizeof(cmdBuffer),
  1082. (char *)pmeh, 0, (char *)NULL);
  1083. }
  1084. //******************************Public*Routine******************************
  1085. //
  1086. // BOOL APIENTRY MCDGetBuffers(MCDCONTEXT *pMCDContext,
  1087. // MCDRECTBUFFERS *pMCDBuffers);
  1088. //
  1089. // Returns information about the buffers (front, back, and depth) associated
  1090. // with the specified context.
  1091. //
  1092. //**************************************************************************
  1093. BOOL APIENTRY MCDGetBuffers(MCDCONTEXT *pMCDContext,
  1094. MCDRECTBUFFERS *pMCDBuffers)
  1095. {
  1096. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDGETBUFFERSCMDI)];
  1097. MCDESC_HEADER *pmeh;
  1098. MCDGETBUFFERSCMDI *pGetBuffersCmd;
  1099. #if DBG
  1100. if (McdDebugFlags & MCDDEBUG_DISABLE_GETBUF)
  1101. {
  1102. if (pMCDBuffers)
  1103. {
  1104. pMCDBuffers->mcdFrontBuf.bufFlags &= ~MCDBUF_ENABLED;
  1105. pMCDBuffers->mcdBackBuf.bufFlags &= ~MCDBUF_ENABLED;
  1106. pMCDBuffers->mcdDepthBuf.bufFlags &= ~MCDBUF_ENABLED;
  1107. }
  1108. return TRUE;
  1109. }
  1110. #endif
  1111. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1112. pmeh->hSharedMem = NULL;
  1113. pmeh->pSharedMem = (VOID *)NULL;
  1114. pmeh->flags = 0;
  1115. pGetBuffersCmd = (MCDGETBUFFERSCMDI *)(pmeh + 1);
  1116. pGetBuffersCmd->command = MCD_GETBUFFERS;
  1117. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1118. sizeof(cmdBuffer),
  1119. (char *)pmeh, sizeof(MCDRECTBUFFERS),
  1120. (char *)pMCDBuffers);
  1121. }
  1122. //******************************Public*Routine******************************
  1123. //
  1124. // ULONG MCDLock();
  1125. //
  1126. // Grab the MCD synchronization lock.
  1127. //
  1128. //**************************************************************************
  1129. static ULONG __MCDLockRequest(MCDCONTEXT *pMCDContext, ULONG tid)
  1130. {
  1131. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDLOCKCMDI)];
  1132. MCDLOCKCMDI *pCmd;
  1133. MCDESC_HEADER *pmeh;
  1134. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1135. pmeh->hSharedMem = NULL;
  1136. pmeh->pSharedMem = (VOID *)NULL;
  1137. pmeh->flags = 0;
  1138. pCmd = (MCDLOCKCMDI *)(pmeh + 1);
  1139. pCmd->command = MCD_LOCK;
  1140. return EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1141. sizeof(cmdBuffer),
  1142. (char *)pmeh, 0, (char *)NULL);
  1143. }
  1144. ULONG APIENTRY MCDLock(MCDCONTEXT *pMCDContext)
  1145. {
  1146. ULONG ulRet;
  1147. ULONG tid;
  1148. tid = GetCurrentThreadId();
  1149. do
  1150. {
  1151. ulRet = __MCDLockRequest(pMCDContext, tid);
  1152. if (ulRet == MCD_LOCK_BUSY)
  1153. Sleep(0);
  1154. }
  1155. while (ulRet == MCD_LOCK_BUSY);
  1156. return ulRet;
  1157. }
  1158. //******************************Public*Routine******************************
  1159. //
  1160. // VOID MCDUnlock();
  1161. //
  1162. // Release the MCD synchronization lock.
  1163. //
  1164. //**************************************************************************
  1165. VOID APIENTRY MCDUnlock(MCDCONTEXT *pMCDContext)
  1166. {
  1167. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDLOCKCMDI)];
  1168. MCDLOCKCMDI *pCmd;
  1169. MCDESC_HEADER *pmeh;
  1170. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1171. pmeh->hSharedMem = NULL;
  1172. pmeh->pSharedMem = (VOID *)NULL;
  1173. pmeh->flags = 0;
  1174. pCmd = (MCDLOCKCMDI *)(pmeh + 1);
  1175. pCmd->command = MCD_UNLOCK;
  1176. EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1177. sizeof(cmdBuffer),
  1178. (char *)pmeh, 0, (char *)NULL);
  1179. }
  1180. //******************************Public*Routine******************************
  1181. //
  1182. // VOID MCDBindContext();
  1183. //
  1184. // Bind a new window to the specified context.
  1185. //
  1186. //**************************************************************************
  1187. BOOL APIENTRY MCDBindContext(MCDCONTEXT *pMCDContext, HDC hdc,
  1188. GLGENwindow *pwnd)
  1189. {
  1190. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDBINDCONTEXTCMDI)];
  1191. MCDBINDCONTEXTCMDI *pCmd;
  1192. MCDESC_HEADER *pmeh;
  1193. ULONG_PTR dwMcdWindow;
  1194. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1195. pmeh->dwWindow = pwnd->dwMcdWindow;
  1196. pmeh->hSharedMem = NULL;
  1197. pmeh->pSharedMem = (VOID *)NULL;
  1198. pmeh->flags = 0;
  1199. pCmd = (MCDBINDCONTEXTCMDI *)(pmeh + 1);
  1200. pCmd->command = MCD_BINDCONTEXT;
  1201. pCmd->hWnd = pwnd->gwid.hwnd;
  1202. dwMcdWindow = EXTESCAPE(hdc, MCDFUNCS,
  1203. sizeof(cmdBuffer),
  1204. (char *)pmeh, 0, (char *)NULL);
  1205. if (dwMcdWindow != 0)
  1206. {
  1207. pMCDContext->hdc = hdc;
  1208. pMCDContext->dwMcdWindow = dwMcdWindow;
  1209. if (pwnd->dwMcdWindow == 0)
  1210. {
  1211. // Save MCD server-side window handle in the GENwindow
  1212. pwnd->dwMcdWindow = dwMcdWindow;
  1213. }
  1214. else
  1215. {
  1216. ASSERTOPENGL(pwnd->dwMcdWindow == dwMcdWindow,
  1217. "dwMcdWindow mismatch\n");
  1218. }
  1219. return TRUE;
  1220. }
  1221. else
  1222. {
  1223. return FALSE;
  1224. }
  1225. }
  1226. //******************************Public*Routine******************************
  1227. //
  1228. // BOOL MCDSync();
  1229. //
  1230. // Synchronizes the 3D hardware.
  1231. //
  1232. //**************************************************************************
  1233. BOOL APIENTRY MCDSync(MCDCONTEXT *pMCDContext)
  1234. {
  1235. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDSYNCCMDI)];
  1236. MCDSYNCCMDI *pCmd;
  1237. MCDESC_HEADER *pmeh;
  1238. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1239. pmeh->hSharedMem = NULL;
  1240. pmeh->pSharedMem = (VOID *)NULL;
  1241. pmeh->flags = 0;
  1242. pCmd = (MCDSYNCCMDI *)(pmeh + 1);
  1243. pCmd->command = MCD_SYNC;
  1244. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1245. sizeof(cmdBuffer),
  1246. (char *)pmeh, 0, (char *)NULL);
  1247. }
  1248. //******************************Public*Routine******************************
  1249. //
  1250. // MCDHANDLE MCDCreateTexture();
  1251. //
  1252. // Creates and loads a texture on the MCD device.
  1253. //
  1254. //**************************************************************************
  1255. MCDHANDLE APIENTRY MCDCreateTexture(MCDCONTEXT *pMCDContext,
  1256. MCDTEXTUREDATA *pTexData,
  1257. ULONG flags,
  1258. VOID *pSurface)
  1259. {
  1260. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDCREATETEXCMDI)];
  1261. MCDCREATETEXCMDI *pCmd;
  1262. MCDESC_HEADER *pmeh;
  1263. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1264. pmeh->hSharedMem = NULL;
  1265. pmeh->pSharedMem = (VOID *)NULL;
  1266. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  1267. pCmd = (MCDCREATETEXCMDI *)(pmeh + 1);
  1268. pCmd->command = MCD_CREATE_TEXTURE;
  1269. pCmd->pTexData = pTexData;
  1270. pCmd->flags = flags;
  1271. pCmd->pSurface = pSurface;
  1272. return (MCDHANDLE)IntToPtr( EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1273. sizeof(cmdBuffer),
  1274. (char *)pmeh, 0, (char *)NULL) );
  1275. }
  1276. //******************************Public*Routine******************************
  1277. //
  1278. // BOOL APIENTRY MCDDeleteTexture(MCDCONTEXT *pMCDContext,
  1279. // MCDHANDLE hMCDTexture);
  1280. //
  1281. // Deletes the specified texture. This will free the device memory associated
  1282. // with the texture.
  1283. //
  1284. //**************************************************************************
  1285. BOOL APIENTRY MCDDeleteTexture(MCDCONTEXT *pMCDContext, MCDHANDLE hTex)
  1286. {
  1287. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDDELETETEXCMDI)];
  1288. MCDDELETETEXCMDI *pDeleteTexCmd;
  1289. MCDESC_HEADER *pmeh;
  1290. #ifdef MCD95
  1291. //
  1292. // Driver already shutdown, therefore memory already deleted.
  1293. //
  1294. if (!pMCDEngEscFilter)
  1295. return MCD_MEM_INVALID;
  1296. #endif
  1297. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1298. pmeh->hSharedMem = NULL;
  1299. pmeh->pSharedMem = (VOID *)NULL;
  1300. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  1301. pDeleteTexCmd = (MCDDELETETEXCMDI *)(pmeh + 1);
  1302. pDeleteTexCmd->command = MCD_DELETE_TEXTURE;
  1303. pDeleteTexCmd->hTex = hTex;
  1304. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1305. sizeof(cmdBuffer),
  1306. (char *)pmeh, 0, (char *)NULL);
  1307. }
  1308. //******************************Public*Routine******************************
  1309. //
  1310. // BOOL MCDUpdateSubTexture();
  1311. //
  1312. // Updates a texture (or region of a texture).
  1313. //
  1314. //**************************************************************************
  1315. BOOL APIENTRY MCDUpdateSubTexture(MCDCONTEXT *pMCDContext,
  1316. MCDTEXTUREDATA *pTexData, MCDHANDLE hTex,
  1317. ULONG lod, RECTL *pRect)
  1318. {
  1319. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDUPDATESUBTEXCMDI)];
  1320. MCDUPDATESUBTEXCMDI *pCmd;
  1321. MCDESC_HEADER *pmeh;
  1322. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1323. pmeh->hSharedMem = NULL;
  1324. pmeh->pSharedMem = (VOID *)NULL;
  1325. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  1326. pCmd = (MCDUPDATESUBTEXCMDI *)(pmeh + 1);
  1327. pCmd->command = MCD_UPDATE_SUB_TEXTURE;
  1328. pCmd->hTex = hTex;
  1329. pCmd->pTexData = pTexData;
  1330. pCmd->lod = lod;
  1331. pCmd->rect = *pRect;
  1332. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1333. sizeof(cmdBuffer),
  1334. (char *)pmeh, 0, (char *)NULL);
  1335. }
  1336. //******************************Public*Routine******************************
  1337. //
  1338. // BOOL MCDUpdateTexturePalette();
  1339. //
  1340. // Updates the palette for the specified texture.
  1341. //
  1342. //**************************************************************************
  1343. BOOL APIENTRY MCDUpdateTexturePalette(MCDCONTEXT *pMCDContext,
  1344. MCDTEXTUREDATA *pTexData, MCDHANDLE hTex,
  1345. ULONG start, ULONG numEntries)
  1346. {
  1347. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDUPDATETEXPALETTECMDI)];
  1348. MCDUPDATETEXPALETTECMDI *pCmd;
  1349. MCDESC_HEADER *pmeh;
  1350. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1351. pmeh->hSharedMem = NULL;
  1352. pmeh->pSharedMem = (VOID *)NULL;
  1353. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  1354. pCmd = (MCDUPDATETEXPALETTECMDI *)(pmeh + 1);
  1355. pCmd->command = MCD_UPDATE_TEXTURE_PALETTE;
  1356. pCmd->hTex = hTex;
  1357. pCmd->pTexData = pTexData;
  1358. pCmd->start = start;
  1359. pCmd->numEntries = numEntries;
  1360. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1361. sizeof(cmdBuffer),
  1362. (char *)pmeh, 0, (char *)NULL);
  1363. }
  1364. //******************************Public*Routine******************************
  1365. //
  1366. // BOOL MCDUpdateTexturePriority();
  1367. //
  1368. // Updates the priority for the specified texture.
  1369. //
  1370. //**************************************************************************
  1371. BOOL APIENTRY MCDUpdateTexturePriority(MCDCONTEXT *pMCDContext,
  1372. MCDTEXTUREDATA *pTexData,
  1373. MCDHANDLE hTex)
  1374. {
  1375. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDUPDATETEXPRIORITYCMDI)];
  1376. MCDUPDATETEXPRIORITYCMDI *pCmd;
  1377. MCDESC_HEADER *pmeh;
  1378. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1379. pmeh->hSharedMem = NULL;
  1380. pmeh->pSharedMem = (VOID *)NULL;
  1381. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  1382. pCmd = (MCDUPDATETEXPRIORITYCMDI *)(pmeh + 1);
  1383. pCmd->command = MCD_UPDATE_TEXTURE_PRIORITY;
  1384. pCmd->hTex = hTex;
  1385. pCmd->pTexData = pTexData;
  1386. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1387. sizeof(cmdBuffer),
  1388. (char *)pmeh, 0, (char *)NULL);
  1389. }
  1390. //******************************Public*Routine******************************
  1391. //
  1392. // BOOL MCDUpdateTextureStata();
  1393. //
  1394. // Updates the state for the specified texture.
  1395. //
  1396. //**************************************************************************
  1397. BOOL APIENTRY MCDUpdateTextureState(MCDCONTEXT *pMCDContext,
  1398. MCDTEXTUREDATA *pTexData,
  1399. MCDHANDLE hTex)
  1400. {
  1401. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDUPDATETEXSTATECMDI)];
  1402. MCDUPDATETEXSTATECMDI *pCmd;
  1403. MCDESC_HEADER *pmeh;
  1404. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1405. pmeh->hSharedMem = NULL;
  1406. pmeh->pSharedMem = (VOID *)NULL;
  1407. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  1408. pCmd = (MCDUPDATETEXSTATECMDI *)(pmeh + 1);
  1409. pCmd->command = MCD_UPDATE_TEXTURE_STATE;
  1410. pCmd->hTex = hTex;
  1411. pCmd->pTexData = pTexData;
  1412. return (BOOL)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1413. sizeof(cmdBuffer),
  1414. (char *)pmeh, 0, (char *)NULL);
  1415. }
  1416. //******************************Public*Routine******************************
  1417. //
  1418. // ULONG MCDTextureStatus();
  1419. //
  1420. // Returns the status for the specified texture.
  1421. //
  1422. //**************************************************************************
  1423. ULONG APIENTRY MCDTextureStatus(MCDCONTEXT *pMCDContext, MCDHANDLE hTex)
  1424. {
  1425. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDTEXSTATUSCMDI)];
  1426. MCDTEXSTATUSCMDI *pCmd;
  1427. MCDESC_HEADER *pmeh;
  1428. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1429. pmeh->hSharedMem = NULL;
  1430. pmeh->pSharedMem = (VOID *)NULL;
  1431. pmeh->flags = 0;
  1432. pCmd = (MCDTEXSTATUSCMDI *)(pmeh + 1);
  1433. pCmd->command = MCD_TEXTURE_STATUS;
  1434. pCmd->hTex = hTex;
  1435. return (ULONG)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1436. sizeof(cmdBuffer),
  1437. (char *)pmeh, 0, (char *)NULL);
  1438. }
  1439. //******************************Public*Routine******************************
  1440. //
  1441. // ULONG MCDTextureKey();
  1442. //
  1443. // Returns the driver-managed "key" for the specified texture.
  1444. //
  1445. //**************************************************************************
  1446. ULONG APIENTRY MCDTextureKey(MCDCONTEXT *pMCDContext, MCDHANDLE hTex)
  1447. {
  1448. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDTEXKEYCMDI)];
  1449. MCDTEXKEYCMDI *pCmd;
  1450. MCDESC_HEADER *pmeh;
  1451. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1452. pmeh->hSharedMem = NULL;
  1453. pmeh->pSharedMem = (VOID *)NULL;
  1454. pmeh->flags = 0;
  1455. pCmd = (MCDTEXKEYCMDI *)(pmeh + 1);
  1456. pCmd->command = MCD_GET_TEXTURE_KEY;
  1457. pCmd->hTex = hTex;
  1458. return (ULONG)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1459. sizeof(cmdBuffer),
  1460. (char *)pmeh, 0, (char *)NULL);
  1461. }
  1462. //******************************Public*Routine******************************
  1463. //
  1464. // BOOL APIENTRY MCDDescribeMcdLayerPlane(HDC hdc, LONG iPixelFormat,
  1465. // LONG iLayerPlane,
  1466. // MCDLAYERPLANE *pMcdPixelFmt)
  1467. //
  1468. // Returns hardware specific information about the specified layer plane.
  1469. //
  1470. //**************************************************************************
  1471. BOOL APIENTRY MCDDescribeMcdLayerPlane(HDC hdc, LONG iPixelFormat,
  1472. LONG iLayerPlane,
  1473. MCDLAYERPLANE *pMcdLayer)
  1474. {
  1475. BOOL bRet = FALSE;
  1476. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDLAYERPLANECMDI)];
  1477. MCDESC_HEADER *pmeh;
  1478. MCDLAYERPLANECMDI *pLayerPlaneCmd;
  1479. pmeh = InitMcdEscEmpty((MCDESC_HEADER *)(cmdBuffer));
  1480. pmeh->flags = 0;
  1481. pLayerPlaneCmd = (MCDLAYERPLANECMDI *)(pmeh + 1);
  1482. pLayerPlaneCmd->command = MCD_DESCRIBELAYERPLANE;
  1483. pLayerPlaneCmd->iPixelFormat = iPixelFormat;
  1484. pLayerPlaneCmd->iLayerPlane = iLayerPlane;
  1485. bRet = (BOOL)EXTESCAPE(hdc, MCDFUNCS,
  1486. sizeof(cmdBuffer),
  1487. (char *)pmeh, sizeof(MCDLAYERPLANE),
  1488. (char *)pMcdLayer);
  1489. return bRet;
  1490. }
  1491. //******************************Public*Routine******************************
  1492. //
  1493. // BOOL APIENTRY MCDDescribeLayerPlane(HDC hdc, LONG iPixelFormat,
  1494. // LONG iLayerPlane,
  1495. // LPLAYERPLANEDESCRIPTOR ppfd)
  1496. //
  1497. // Returns LAYERPLANEDESCRIPTOR describing the specified layer plane.
  1498. //
  1499. //**************************************************************************
  1500. BOOL APIENTRY MCDDescribeLayerPlane(HDC hdc, LONG iPixelFormat,
  1501. LONG iLayerPlane,
  1502. LPLAYERPLANEDESCRIPTOR plpd)
  1503. {
  1504. BOOL bRet = FALSE;
  1505. MCDLAYERPLANE McdLayer;
  1506. if (!MCDDescribeMcdLayerPlane(hdc, iPixelFormat, iLayerPlane, &McdLayer))
  1507. return bRet;
  1508. if (plpd)
  1509. {
  1510. plpd->nSize = sizeof(*plpd);
  1511. memcpy(&plpd->nVersion, &McdLayer.nVersion,
  1512. offsetof(LAYERPLANEDESCRIPTOR, cAccumBits) -
  1513. offsetof(LAYERPLANEDESCRIPTOR, nVersion));
  1514. plpd->cAccumBits = 0;
  1515. plpd->cAccumRedBits = 0;
  1516. plpd->cAccumGreenBits = 0;
  1517. plpd->cAccumBlueBits = 0;
  1518. plpd->cAccumAlphaBits = 0;
  1519. plpd->cDepthBits = 0;
  1520. plpd->cStencilBits = 0;
  1521. plpd->cAuxBuffers = McdLayer.cAuxBuffers;
  1522. plpd->iLayerPlane = McdLayer.iLayerPlane;
  1523. plpd->bReserved = 0;
  1524. plpd->crTransparent = McdLayer.crTransparent;
  1525. bRet = TRUE;
  1526. }
  1527. return bRet;
  1528. }
  1529. //******************************Public*Routine******************************
  1530. //
  1531. // LONG APIENTRY MCDSetLayerPalette(HDC hdc, BOOL bRealize,
  1532. // LONG cEntries, COLORREF *pcr)
  1533. //
  1534. // Sets the palette of the specified layer plane.
  1535. //
  1536. //**************************************************************************
  1537. LONG APIENTRY MCDSetLayerPalette(HDC hdc, LONG iLayerPlane, BOOL bRealize,
  1538. LONG cEntries, COLORREF *pcr)
  1539. {
  1540. LONG lRet = 0;
  1541. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDSETLAYERPALCMDI) +
  1542. (255 * sizeof(COLORREF))];
  1543. BYTE *pjBuffer = (BYTE *) NULL;
  1544. MCDESC_HEADER *pmeh;
  1545. MCDSETLAYERPALCMDI *pSetLayerPalCmd;
  1546. // Use stack allocation if possible; otherwise, allocate heap memory for
  1547. // the command buffer.
  1548. if (cEntries <= 256)
  1549. {
  1550. pmeh = (MCDESC_HEADER *)(cmdBuffer);
  1551. }
  1552. else
  1553. {
  1554. LONG lBytes;
  1555. lBytes = sizeof(MCDESC_HEADER) + sizeof(MCDSETLAYERPALCMDI) +
  1556. ((cEntries - 1) * sizeof(COLORREF));
  1557. pjBuffer = (BYTE *) LocalAlloc(LMEM_FIXED, lBytes);
  1558. pmeh = (MCDESC_HEADER *)pjBuffer;
  1559. }
  1560. if (pmeh != (MCDESC_HEADER *) NULL)
  1561. {
  1562. InitMcdEscEmpty(pmeh);
  1563. pmeh->flags = MCDESC_FL_DISPLAY_LOCK;
  1564. pSetLayerPalCmd = (MCDSETLAYERPALCMDI *)(pmeh + 1);
  1565. pSetLayerPalCmd->command = MCD_SETLAYERPALETTE;
  1566. pSetLayerPalCmd->iLayerPlane = iLayerPlane;
  1567. pSetLayerPalCmd->bRealize = bRealize;
  1568. pSetLayerPalCmd->cEntries = cEntries;
  1569. memcpy(&pSetLayerPalCmd->acr[0], pcr, cEntries * sizeof(COLORREF));
  1570. lRet = (BOOL)EXTESCAPE(hdc, MCDFUNCS,
  1571. sizeof(cmdBuffer),
  1572. (char *)pmeh, 0, (char *)NULL);
  1573. }
  1574. // Delete the heap memory if it was allocated for the command buffer.
  1575. if (pjBuffer)
  1576. {
  1577. LocalFree(pjBuffer);
  1578. }
  1579. return lRet;
  1580. }
  1581. //******************************Public*Routine******************************
  1582. //
  1583. // ULONG APIENTRY MCDDrawPixels(MCDCONTEXT *pMCDContext, ULONG width,
  1584. // ULONG height, ULONG format, ULONG type,
  1585. // VOID *pPixels, BOOL packed)
  1586. //
  1587. // MCD version of glDrawPixels
  1588. //
  1589. //**************************************************************************
  1590. ULONG APIENTRY MCDDrawPixels(MCDCONTEXT *pMCDContext, ULONG width,
  1591. ULONG height, ULONG format, ULONG type,
  1592. VOID *pPixels, BOOL packed)
  1593. {
  1594. ULONG ulRet = (ULONG) FALSE;
  1595. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDDRAWPIXELSCMDI)];
  1596. MCDESC_HEADER *pmeh;
  1597. MCDDRAWPIXELSCMDI *pPixelsCmd;
  1598. pmeh = InitMcdEscSurfaces((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1599. pmeh->hSharedMem = NULL;
  1600. pmeh->pSharedMem = (VOID *)NULL;
  1601. pmeh->flags = 0;
  1602. if (SUPPORTS_DIRECT())
  1603. {
  1604. pmeh->flags |= MCDESC_FL_SURFACES;
  1605. }
  1606. else if (pmeh->msrfColor.hSurf != NULL ||
  1607. pmeh->msrfDepth.hSurf != NULL)
  1608. {
  1609. return 0;
  1610. }
  1611. pPixelsCmd = (MCDDRAWPIXELSCMDI *)(pmeh + 1);
  1612. pPixelsCmd->command = MCD_DRAW_PIXELS;
  1613. pPixelsCmd->width = width;
  1614. pPixelsCmd->height = height;
  1615. pPixelsCmd->format = format;
  1616. pPixelsCmd->type = type;
  1617. pPixelsCmd->packed = packed;
  1618. pPixelsCmd->pPixels = pPixels;
  1619. ulRet = (ULONG)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1620. sizeof(cmdBuffer), (char *)pmeh,
  1621. 0, (char *)NULL);
  1622. return ulRet;
  1623. }
  1624. //******************************Public*Routine******************************
  1625. //
  1626. // ULONG APIENTRY MCDReadPixels(MCDCONTEXT *pMCDContext, LONG x, LONG y,
  1627. // ULONG width, ULONG height, ULONG format,
  1628. // ULONG type, VOID *pPixels)
  1629. //
  1630. // MCD version of glReadPixels
  1631. //
  1632. //**************************************************************************
  1633. ULONG APIENTRY MCDReadPixels(MCDCONTEXT *pMCDContext, LONG x, LONG y,
  1634. ULONG width, ULONG height, ULONG format,
  1635. ULONG type, VOID *pPixels)
  1636. {
  1637. ULONG ulRet = (ULONG) FALSE;
  1638. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDREADPIXELSCMDI)];
  1639. MCDESC_HEADER *pmeh;
  1640. MCDREADPIXELSCMDI *pPixelsCmd;
  1641. pmeh = InitMcdEscSurfaces((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1642. pmeh->hSharedMem = NULL;
  1643. pmeh->pSharedMem = (VOID *)NULL;
  1644. pmeh->flags = 0;
  1645. if (SUPPORTS_DIRECT())
  1646. {
  1647. pmeh->flags |= MCDESC_FL_SURFACES;
  1648. }
  1649. else if (pmeh->msrfColor.hSurf != NULL ||
  1650. pmeh->msrfDepth.hSurf != NULL)
  1651. {
  1652. return 0;
  1653. }
  1654. pPixelsCmd = (MCDREADPIXELSCMDI *)(pmeh + 1);
  1655. pPixelsCmd->command = MCD_READ_PIXELS;
  1656. pPixelsCmd->x = x;
  1657. pPixelsCmd->y = y;
  1658. pPixelsCmd->width = width;
  1659. pPixelsCmd->height = height;
  1660. pPixelsCmd->format = format;
  1661. pPixelsCmd->type = type;
  1662. pPixelsCmd->pPixels = pPixels;
  1663. ulRet = (ULONG)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1664. sizeof(cmdBuffer), (char *)pmeh,
  1665. 0, (char *)NULL);
  1666. return ulRet;
  1667. }
  1668. //******************************Public*Routine******************************
  1669. //
  1670. // ULONG APIENTRY MCDCopyPixels(MCDCONTEXT *pMCDContext, LONG x, LONG y,
  1671. // ULONG width, ULONG height, ULONG type)
  1672. //
  1673. // MCD version of glCopyPixels
  1674. //
  1675. //**************************************************************************
  1676. ULONG APIENTRY MCDCopyPixels(MCDCONTEXT *pMCDContext, LONG x, LONG y,
  1677. ULONG width, ULONG height, ULONG type)
  1678. {
  1679. ULONG ulRet = (ULONG) FALSE;
  1680. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDCOPYPIXELSCMDI)];
  1681. MCDESC_HEADER *pmeh;
  1682. MCDCOPYPIXELSCMDI *pPixelsCmd;
  1683. pmeh = InitMcdEscSurfaces((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1684. pmeh->hSharedMem = NULL;
  1685. pmeh->pSharedMem = (VOID *)NULL;
  1686. pmeh->flags = 0;
  1687. if (SUPPORTS_DIRECT())
  1688. {
  1689. pmeh->flags |= MCDESC_FL_SURFACES;
  1690. }
  1691. else if (pmeh->msrfColor.hSurf != NULL ||
  1692. pmeh->msrfDepth.hSurf != NULL)
  1693. {
  1694. return 0;
  1695. }
  1696. pPixelsCmd = (MCDCOPYPIXELSCMDI *)(pmeh + 1);
  1697. pPixelsCmd->command = MCD_COPY_PIXELS;
  1698. pPixelsCmd->x = x;
  1699. pPixelsCmd->y = y;
  1700. pPixelsCmd->width = width;
  1701. pPixelsCmd->height = height;
  1702. pPixelsCmd->type = type;
  1703. ulRet = (ULONG)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1704. sizeof(cmdBuffer), (char *)pmeh,
  1705. 0, (char *)NULL);
  1706. return ulRet;
  1707. }
  1708. //******************************Public*Routine******************************
  1709. //
  1710. // ULONG APIENTRY MCDPixelMap(MCDCONTEXT *pMCDContext, ULONG mapType,
  1711. // ULONG mapSize, VOID *pMap)
  1712. //
  1713. // MCD version of glPixelMap
  1714. //
  1715. //**************************************************************************
  1716. ULONG APIENTRY MCDPixelMap(MCDCONTEXT *pMCDContext, ULONG mapType,
  1717. ULONG mapSize, VOID *pMap)
  1718. {
  1719. ULONG ulRet = (ULONG) FALSE;
  1720. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDPIXELMAPCMDI)];
  1721. MCDESC_HEADER *pmeh;
  1722. MCDPIXELMAPCMDI *pPixelsCmd;
  1723. pmeh = InitMcdEscContext((MCDESC_HEADER *)(cmdBuffer), pMCDContext);
  1724. pmeh->hSharedMem = NULL;
  1725. pmeh->pSharedMem = (VOID *)NULL;
  1726. pmeh->flags = 0;
  1727. pPixelsCmd = (MCDPIXELMAPCMDI *)(pmeh + 1);
  1728. pPixelsCmd->command = MCD_PIXEL_MAP;
  1729. pPixelsCmd->mapType = mapType;
  1730. pPixelsCmd->mapSize = mapSize;
  1731. pPixelsCmd->pMap = pMap;
  1732. ulRet = (ULONG)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1733. sizeof(cmdBuffer), (char *)pmeh,
  1734. 0, (char *)NULL);
  1735. return ulRet;
  1736. }
  1737. //******************************Public*Routine******************************
  1738. //
  1739. // MCDDestroyWindow
  1740. //
  1741. // Forwards user-mode window destruction notification to the server for
  1742. // resource cleanup
  1743. //
  1744. //**************************************************************************
  1745. void APIENTRY MCDDestroyWindow(HDC hdc, ULONG_PTR dwMcdWindow)
  1746. {
  1747. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDPIXELMAPCMDI)];
  1748. MCDESC_HEADER *pmeh;
  1749. MCDDESTROYWINDOWCMDI *pmdwc;
  1750. pmeh = InitMcdEscEmpty((MCDESC_HEADER *)cmdBuffer);
  1751. pmeh->dwWindow = dwMcdWindow;
  1752. pmeh->flags = 0;
  1753. pmdwc = (MCDDESTROYWINDOWCMDI *)(pmeh + 1);
  1754. pmdwc->command = MCD_DESTROY_WINDOW;
  1755. EXTESCAPE(hdc, MCDFUNCS,
  1756. sizeof(cmdBuffer), (char *)pmeh,
  1757. 0, (char *)NULL);
  1758. }
  1759. //******************************Public*Routine******************************
  1760. //
  1761. // MCDGetTextureFormats
  1762. //
  1763. //**************************************************************************
  1764. int APIENTRY MCDGetTextureFormats(MCDCONTEXT *pMCDContext, int nFmts,
  1765. struct _DDSURFACEDESC *pddsd)
  1766. {
  1767. BYTE cmdBuffer[sizeof(MCDESC_HEADER) + sizeof(MCDGETTEXTUREFORMATSCMDI)];
  1768. MCDESC_HEADER *pmeh;
  1769. MCDGETTEXTUREFORMATSCMDI *pmgtf;
  1770. pmeh = InitMcdEscContext((MCDESC_HEADER *)cmdBuffer, pMCDContext);
  1771. pmeh->hSharedMem = NULL;
  1772. pmeh->pSharedMem = (VOID *)NULL;
  1773. pmeh->flags = 0;
  1774. pmgtf = (MCDGETTEXTUREFORMATSCMDI *)(pmeh + 1);
  1775. pmgtf->command = MCD_GET_TEXTURE_FORMATS;
  1776. pmgtf->nFmts = nFmts;
  1777. return (int)EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1778. sizeof(cmdBuffer), (char *)pmeh,
  1779. nFmts*sizeof(DDSURFACEDESC), (char *)pddsd);
  1780. }
  1781. //******************************Public*Routine******************************
  1782. //
  1783. // MCDSwapMultiple
  1784. //
  1785. //**************************************************************************
  1786. DWORD APIENTRY MCDSwapMultiple(HDC hdc, UINT cBuffers, GENMCDSWAP *pgms)
  1787. {
  1788. BYTE cmdBuffer[sizeof(MCDESC_HEADER)+
  1789. sizeof(HDC)*MCDESC_MAX_EXTRA_WNDOBJ+
  1790. sizeof(MCDSWAPMULTIPLECMDI)];
  1791. MCDSWAPMULTIPLECMDI *pSwapMultCmd;
  1792. MCDESC_HEADER *pmeh;
  1793. UINT i;
  1794. HDC *phdc;
  1795. // InitMcdEscSurfaces cannot be used because the context given
  1796. // is a temporary one constructed on the fly since SwapBuffers
  1797. // has only surface information.
  1798. pmeh = InitMcdEscEmpty((MCDESC_HEADER *)cmdBuffer);
  1799. pmeh->flags = MCDESC_FL_DISPLAY_LOCK | MCDESC_FL_EXTRA_WNDOBJ;
  1800. pmeh->cExtraWndobj = cBuffers;
  1801. phdc = (HDC *)(pmeh+1);
  1802. pSwapMultCmd = (MCDSWAPMULTIPLECMDI *)((BYTE *)phdc+cBuffers*sizeof(HDC));
  1803. pSwapMultCmd->command = MCD_SWAP_MULTIPLE;
  1804. pSwapMultCmd->cBuffers = cBuffers;
  1805. for (i = 0; i < cBuffers; i++)
  1806. {
  1807. *phdc++ = pgms->pwswap->hdc;
  1808. pSwapMultCmd->auiFlags[i] = pgms->pwswap->uiFlags;
  1809. pSwapMultCmd->adwMcdWindow[i] = pgms->pwnd->dwMcdWindow;
  1810. }
  1811. return (DWORD)EXTESCAPE(hdc, MCDFUNCS, sizeof(cmdBuffer),
  1812. (char *)pmeh, 0, (char *)NULL);
  1813. }
  1814. //******************************Public*Routine******************************
  1815. //
  1816. // MCDProcessBatch2
  1817. //
  1818. // Processes a batch of primitives pointed to by pMCDMem.
  1819. // This is the 2.0 front-end processing entry point.
  1820. //
  1821. // Returns last command processed or NULL if all are processed.
  1822. //
  1823. //**************************************************************************
  1824. PVOID APIENTRY MCDProcessBatch2(MCDCONTEXT *pMCDContext,
  1825. VOID *pMCDCmdMem,
  1826. VOID *pMCDPrimMem,
  1827. MCDCOMMAND *pMCDFirstCmd,
  1828. int cExtraSurfaces,
  1829. LPDIRECTDRAWSURFACE *pdds,
  1830. ULONG cmdFlagsAll,
  1831. ULONG primFlags,
  1832. MCDTRANSFORM *pMCDTransform,
  1833. MCDMATERIALCHANGES *pMCDMatChanges)
  1834. {
  1835. BYTE cmdBuffer[sizeof(MCDESC_HEADER)+
  1836. MCD_MAXMIPMAPLEVEL*sizeof(DWORD)];
  1837. MCDESC_HEADER *pmeh;
  1838. MCDMEMHDRI *pMCDCmdMemHdr, *pMCDPrimMemHdr;
  1839. int i;
  1840. ULONG_PTR *pdwSurf;
  1841. MCDPROCESSCMDI *pProcessCmd;
  1842. // Version is checked in mcdcx.c.
  1843. ASSERTOPENGL(SUPPORTS_20(), "MCDProcessBatch2 requires 2.0\n");
  1844. // This function requires 2.0 so direct support should also exist.
  1845. ASSERTOPENGL(SUPPORTS_DIRECT(), "MCDProcessBatch2 requires direct\n");
  1846. #if DBG
  1847. if (McdDebugFlags & MCDDEBUG_DISABLE_PROCBATCH)
  1848. {
  1849. MCDSync(pMCDContext);
  1850. return pMCDFirstCmd;
  1851. }
  1852. #endif
  1853. pMCDCmdMemHdr = (MCDMEMHDRI *)((char *)pMCDCmdMem - sizeof(MCDMEMHDRI));
  1854. pMCDPrimMemHdr = (MCDMEMHDRI *)((char *)pMCDPrimMem - sizeof(MCDMEMHDRI));
  1855. pmeh = InitMcdEscSurfaces((MCDESC_HEADER *)cmdBuffer, pMCDContext);
  1856. pmeh->hSharedMem = pMCDCmdMemHdr->hMCDMem;
  1857. pmeh->pSharedMem = (char *)pMCDCmdMem;
  1858. pmeh->sharedMemSize = sizeof(MCDPROCESSCMDI);
  1859. pmeh->flags = MCDESC_FL_DISPLAY_LOCK |
  1860. MCDESC_FL_SURFACES | MCDESC_FL_LOCK_SURFACES;
  1861. // Assert that we won't exceed the kernel's expectations
  1862. ASSERTOPENGL(MCD_MAXMIPMAPLEVEL <= MCDESC_MAX_LOCK_SURFACES,
  1863. "MCD_MAXMIPMAPLEVEL too large\n");
  1864. pmeh->cLockSurfaces = cExtraSurfaces;
  1865. pdwSurf = (ULONG_PTR *)(pmeh+1);
  1866. for (i = 0; i < cExtraSurfaces; i++)
  1867. {
  1868. *pdwSurf++ = ((LPDDRAWI_DDRAWSURFACE_INT)pdds[i])->lpLcl->hDDSurface;
  1869. }
  1870. pProcessCmd = (MCDPROCESSCMDI *)pMCDCmdMem;
  1871. pProcessCmd->command = MCD_PROCESS;
  1872. pProcessCmd->hMCDPrimMem = pMCDPrimMemHdr->hMCDMem;
  1873. pProcessCmd->pMCDFirstCmd = pMCDFirstCmd;
  1874. pProcessCmd->cmdFlagsAll = cmdFlagsAll;
  1875. pProcessCmd->primFlags = primFlags;
  1876. pProcessCmd->pMCDTransform = pMCDTransform;
  1877. pProcessCmd->pMCDMatChanges = pMCDMatChanges;
  1878. return (PVOID)IntToPtr( EXTESCAPE(pMCDContext->hdc, MCDFUNCS,
  1879. sizeof(cmdBuffer), (char *)pmeh,
  1880. 0, (char *)NULL) );
  1881. }