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.

2248 lines
81 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: mcd.c
  3. *
  4. * Main file for the Cirrus Logic 546X OpenGL MCD driver. This file contains
  5. * the entry points needed for an MCD driver.
  6. *
  7. * (based on mcd.c from NT4.0 DDK)
  8. *
  9. * Copyright (c) 1996 Microsoft Corporation
  10. * Copyright (c) 1997 Cirrus Logic, Inc.
  11. \**************************************************************************/
  12. #include "precomp.h"
  13. #include <excpt.h>
  14. //#define DBGBRK
  15. // uncomment the following to force render directly to visible frame
  16. //#define FORCE_SINGLE_BUF
  17. #if 0 // 1 here to avoid tons of prints for each texture load
  18. #define MCDBG_PRINT_TEX
  19. #else
  20. #define MCDBG_PRINT_TEX MCDBG_PRINT
  21. #endif
  22. #include "mcdhw.h"
  23. #include "mcdutil.h"
  24. #include "mcdmath.h"
  25. BOOL MCDrvInfo(MCDSURFACE *pMCDSurface, MCDDRIVERINFO *pMCDDriverInfo)
  26. {
  27. MCDBG_PRINT( "MCDrvInfo\n");
  28. pMCDDriverInfo->verMajor = MCD_VER_MAJOR;
  29. pMCDDriverInfo->verMinor = MCD_VER_MINOR;
  30. pMCDDriverInfo->verDriver = 0x10000;
  31. strcpy(pMCDDriverInfo->idStr, "Cirrus Logic 546X-Laguna3D (Cirrus Logic)");
  32. pMCDDriverInfo->drvMemFlags = 0; // if not 0, can't fail any part of MCDrvDraw
  33. pMCDDriverInfo->drvBatchMemSizeMax = 128000; // if 0, a default is used
  34. return TRUE;
  35. }
  36. #define TOTAL_PIXEL_FORMATS (2 * 2) // double-buffers * z-buffers
  37. // Base color pixel formats
  38. static DRVPIXELFORMAT drvFormats[] = { {8, 3, 3, 2, 0, 5, 2, 0, 0},// best except drawpix fails
  39. //static DRVPIXELFORMAT drvFormats[] = { {8, 3, 3, 2, 0, 0, 3, 6, 0}, // change for drawpix at 8bpp (wrong for all else)
  40. {16, 5, 5, 5, 0, 10, 5, 0, 0},
  41. {16, 5, 6, 5, 0, 11, 5, 0, 0},
  42. {24, 8, 8, 8, 0, 16, 8, 0, 0},
  43. {32, 8, 8, 8, 0, 16, 8, 0, 0},
  44. };
  45. LONG MCDrvDescribePixelFormat(MCDSURFACE *pMCDSurface, LONG iPixelFormat,
  46. ULONG nBytes, MCDPIXELFORMAT *pMCDPixelFormat,
  47. ULONG flags)
  48. {
  49. BOOL zEnabled;
  50. BOOL doubleBufferEnabled;
  51. DRVPIXELFORMAT *pDrvPixelFormat;
  52. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  53. MCDBG_PRINT( "MCDrvDescribePixelFormat, ipixf=%d devid=%x\n",iPixelFormat,ppdev->dwLgDevID);
  54. // return 0 here if no support at current bpp
  55. if (ppdev->iBitmapFormat == BMF_24BPP) return 0;
  56. // PDR 10892 - IBM doesn't like how OpenGL's stealing of the palette affects desktop colors
  57. // Due to MCD design, there's no way around it in 8bpp, so we won't accelerate 8bpp
  58. // Note that the 8bpp support has been left intact should we ever decide to reverse this decision
  59. // To enable 8bpp, just remove the following line
  60. if (ppdev->iBitmapFormat == BMF_8BPP) return 0;
  61. if (!pMCDPixelFormat)
  62. {
  63. if (ppdev->iBitmapFormat == BMF_8BPP)
  64. {
  65. // for 8bpp, at hi-res with z enabled, it's quite possible z pitch
  66. // requirement will exceed pitch, and MCDrvAllocBuffers will fail
  67. // in that case, the CopyTexture part of mustpass.c will fail, even
  68. // though punted to software. Otto Berkes of Microsoft agrees this
  69. // could be an acceptable WHQL failure, but MS would need to verify
  70. // the bug is in their code. Until then, the following is needed
  71. // to pass WHQL ;(
  72. // This says we don't support z buffering for hires 8bpp
  73. if (ppdev->cxScreen >= 1152) // frido: this used to be >= 1280
  74. return (TOTAL_PIXEL_FORMATS>>1);
  75. else
  76. return TOTAL_PIXEL_FORMATS;
  77. }
  78. else
  79. {
  80. return TOTAL_PIXEL_FORMATS;
  81. }
  82. }
  83. if (iPixelFormat > TOTAL_PIXEL_FORMATS)
  84. return 0;
  85. iPixelFormat--;
  86. // - see what possible vals for dwFlags is
  87. // - looks like TOTAL_PIXEL_FORMATS is independent of color depths
  88. // i.e. given a format like 332, how many permutations are supported
  89. // - z, single/double, stencil, overlay, texture?
  90. zEnabled = iPixelFormat >= (TOTAL_PIXEL_FORMATS / 2);
  91. doubleBufferEnabled = (iPixelFormat % (TOTAL_PIXEL_FORMATS / 2) ) >=
  92. (TOTAL_PIXEL_FORMATS / 4);
  93. // NOTE: PFD_ defines are in \msdev\include\wingdi.h
  94. pMCDPixelFormat->nSize = sizeof(MCDPIXELFORMAT);
  95. pMCDPixelFormat->dwFlags = PFD_SWAP_COPY;
  96. if (doubleBufferEnabled)
  97. pMCDPixelFormat->dwFlags |= PFD_DOUBLEBUFFER;
  98. pMCDPixelFormat->iPixelType = PFD_TYPE_RGBA;
  99. MCDBG_PRINT( " DPIXFMT - no early ret: ppdev->bmf=%d zen=%d dbuf=%d ppd->flg=%x\n",ppdev->iBitmapFormat,zEnabled,doubleBufferEnabled,ppdev->flGreen);
  100. // FUTURE: miniport only supports 888,565,indexed modes. Need 1555 mode as well?
  101. // FUTURE: also, miniport 8 bit indexed supports set nbit rgb=6 each, not 332?
  102. // FUTURE: I'll use the MGA stuff which had 332 for indexed, which is same a 5464 CGL.
  103. // FUTURE: See ChoosePixelFormat in Win32 SDK - input is pixel depth only (8/16/24/32)
  104. switch (ppdev->iBitmapFormat) {
  105. default:
  106. case BMF_8BPP:
  107. // Need the palette. This will mess up the desktop, but OpenGL looks good
  108. pDrvPixelFormat = &drvFormats[0];
  109. pMCDPixelFormat->dwFlags |= (PFD_NEED_SYSTEM_PALETTE | PFD_NEED_PALETTE);
  110. break;
  111. case BMF_16BPP:
  112. #ifdef _5464_1555_SUPPORT
  113. if (ppdev->flGreen != 0x7e0) // not 565
  114. pDrvPixelFormat = &drvFormats[1];
  115. else
  116. #endif //def _5464_1555_SUPPORT
  117. pDrvPixelFormat = &drvFormats[2];
  118. break;
  119. // NOTE: We never get this far if 24bpp
  120. case BMF_32BPP:
  121. pDrvPixelFormat = &drvFormats[4];
  122. break;
  123. }
  124. pMCDPixelFormat->cColorBits = pDrvPixelFormat->cColorBits;
  125. pMCDPixelFormat->cRedBits = pDrvPixelFormat->rBits;
  126. pMCDPixelFormat->cGreenBits = pDrvPixelFormat->gBits;
  127. pMCDPixelFormat->cBlueBits = pDrvPixelFormat->bBits;
  128. pMCDPixelFormat->cAlphaBits = pDrvPixelFormat->aBits;
  129. pMCDPixelFormat->cRedShift = pDrvPixelFormat->rShift;
  130. pMCDPixelFormat->cGreenShift = pDrvPixelFormat->gShift;
  131. pMCDPixelFormat->cBlueShift = pDrvPixelFormat->bShift;
  132. pMCDPixelFormat->cAlphaShift = pDrvPixelFormat->aShift;
  133. if (zEnabled)
  134. {
  135. pMCDPixelFormat->cDepthBits = 16;
  136. pMCDPixelFormat->cDepthBufferBits = 16;
  137. pMCDPixelFormat->cDepthShift = 16;
  138. }
  139. else
  140. {
  141. pMCDPixelFormat->cDepthBits = 0;
  142. pMCDPixelFormat->cDepthBufferBits = 0;
  143. pMCDPixelFormat->cDepthShift = 0;
  144. }
  145. // FUTURE: cl546x stencil support could be added here
  146. pMCDPixelFormat->cStencilBits = 0;
  147. pMCDPixelFormat->cOverlayPlanes = 0;
  148. pMCDPixelFormat->cUnderlayPlanes = 0;
  149. pMCDPixelFormat->dwTransparentColor = 0;
  150. return TOTAL_PIXEL_FORMATS;
  151. }
  152. BOOL MCDrvDescribeLayerPlane(MCDSURFACE *pMCDSurface,
  153. LONG iPixelFormat, LONG iLayerPlane,
  154. ULONG nBytes, MCDLAYERPLANE *pMCDLayerPlane,
  155. ULONG flags)
  156. {
  157. MCDBG_PRINT( "MCDrvDescribeLayerPlane\n");
  158. return FALSE;
  159. }
  160. LONG MCDrvSetLayerPalette(MCDSURFACE *pMCDSurface, LONG iLayerPlane,
  161. BOOL bRealize, LONG cEntries, COLORREF *pcr)
  162. {
  163. MCDBG_PRINT( "MCDrvSetLayerPalette\n");
  164. return FALSE;
  165. }
  166. HDEV MCDrvGetHdev(MCDSURFACE *pMCDSurface)
  167. {
  168. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  169. MCDBG_PRINT( "MCDrvGetHdev\n");
  170. return ppdev->hdevEng;
  171. }
  172. ULONG MCDrvCreateContext(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc,
  173. MCDRCINFO *pRcInfo)
  174. {
  175. DEVRC *pRc;
  176. MCDWINDOW *pMCDWnd = pMCDSurface->pWnd;
  177. DEVWND *pDevWnd;
  178. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  179. DRVPIXELFORMAT *pDrvPixelFormat;
  180. MCDVERTEX *pv;
  181. BOOL zEnabled;
  182. BOOL doubleBufferEnabled;
  183. ULONG i, maxVi;
  184. MCDBG_PRINT( "MCDrvCreateContext\n");
  185. // We only support window surfaces:
  186. if (! (pMCDSurface->surfaceFlags & MCDSURFACE_HWND) )
  187. return FALSE;
  188. // no support on pre-5464 devices
  189. if (ppdev->dwLgDevID == CL_GD5462)
  190. return FALSE;
  191. if ((pMCDRc->iPixelFormat > TOTAL_PIXEL_FORMATS) ||
  192. (pMCDRc->iPixelFormat < 0)) {
  193. MCDBG_PRINT( "MCDrvCreateContext: bad pixel format\n");
  194. return FALSE;
  195. }
  196. // We don't support overlay planes:
  197. if (pMCDRc->iLayerPlane)
  198. return FALSE;
  199. pRc = pMCDRc->pvUser = (DEVRC *)MCDAlloc(sizeof(DEVRC));
  200. if (!pRc) {
  201. MCDBG_PRINT("MCDrvCreateContext: couldn't allocate DEVRC\n");
  202. return FALSE;
  203. }
  204. #ifdef DBGBRK
  205. DBGBREAKPOINT();
  206. #endif
  207. zEnabled = (pMCDRc->iPixelFormat - 1) >= (TOTAL_PIXEL_FORMATS / 2);
  208. doubleBufferEnabled = ((pMCDRc->iPixelFormat - 1) % (TOTAL_PIXEL_FORMATS / 2) ) >=
  209. (TOTAL_PIXEL_FORMATS / 4);
  210. pRc->zBufEnabled = zEnabled;
  211. pRc->backBufEnabled = doubleBufferEnabled;
  212. // If we're not yet tracking this window, allocate the per-window DEVWND
  213. // structure for maintaining per-window info such as front/back/z buffer
  214. // resources:
  215. if (!pMCDWnd->pvUser) {
  216. pDevWnd = pMCDWnd->pvUser = (DEVWND *)MCDAlloc(sizeof(DEVWND));
  217. if (!pDevWnd) {
  218. MCDFree(pMCDRc->pvUser);
  219. pMCDRc->pvUser = NULL;
  220. MCDBG_PRINT("MCDrvCreateContext: couldn't allocate DEVWND");
  221. return FALSE;
  222. }
  223. pDevWnd->createFlags = pMCDRc->createFlags;
  224. pDevWnd->iPixelFormat = pMCDRc->iPixelFormat;
  225. // init ptrs so we know back and z buffers don't exist yet
  226. pDevWnd->pohZBuffer = NULL;
  227. pDevWnd->pohBackBuffer = NULL;
  228. pDevWnd->dispUnique = ppdev->iUniqueness;
  229. } else {
  230. // We already have a per-window DEVWND structure tracking this window.
  231. // In this case, do a sanity-check on the pixel format for this
  232. // context, since a window's pixel format can not change once it has been
  233. // set (by the first context bound to the window). So, if the pixel
  234. // format for the incoming context doesn't match the current pixel
  235. // format for the window, we have to fail context creation:
  236. pDevWnd = pMCDWnd->pvUser;
  237. if (pDevWnd->iPixelFormat != pMCDRc->iPixelFormat) {
  238. MCDFree(pMCDRc->pvUser);
  239. pMCDRc->pvUser = NULL;
  240. MCDBG_PRINT("MCDrvCreateContext: mismatched pixel formats, window = %d, context = %d",
  241. pDevWnd->iPixelFormat, pMCDRc->iPixelFormat);
  242. return FALSE;
  243. }
  244. }
  245. pRc->pEnumClip = pMCDSurface->pWnd->pClip;
  246. // Set up our color scale values so that color components are
  247. // normalized to 0..7fffff
  248. // NOTE: MGA normalizes colors to 0..7f,ffff -> 5464 needs 0->ff,ffff
  249. // We also need to make sure we don't fault due to bad FL data as well...
  250. try {
  251. if (pRcInfo->redScale != (MCDFLOAT)0.0)
  252. pRc->rScale = (MCDFLOAT)(0xffffff) / pRcInfo->redScale;
  253. else
  254. pRc->rScale = (MCDFLOAT)0.0;
  255. if (pRcInfo->greenScale != (MCDFLOAT)0.0)
  256. pRc->gScale = (MCDFLOAT)(0xffffff) / pRcInfo->greenScale;
  257. else
  258. pRc->gScale = (MCDFLOAT)0.0;
  259. if (pRcInfo->blueScale != (MCDFLOAT)0.0)
  260. pRc->bScale = (MCDFLOAT)(0xffffff) / pRcInfo->blueScale;
  261. else
  262. pRc->bScale = (MCDFLOAT)0.0;
  263. if (pRcInfo->alphaScale != (MCDFLOAT)0.0)
  264. pRc->aScale = (MCDFLOAT)(0xffff00) / pRcInfo->alphaScale;
  265. else
  266. pRc->aScale = (MCDFLOAT)0.0;
  267. } except (EXCEPTION_EXECUTE_HANDLER) {
  268. MCDBG_PRINT("!!Exception in MCDrvCreateContext!!");
  269. return FALSE;
  270. }
  271. pRc->zScale = (MCDFLOAT)65535.0;
  272. pRc->pickNeeded = TRUE; // We'll definitely need to re-pick
  273. // our rendering functions
  274. // Initialize the pColor pointer in the clip buffer:
  275. for (i = 0, pv = &pRc->clipTemp[0],
  276. maxVi = sizeof(pRc->clipTemp) / sizeof(MCDVERTEX);
  277. i < maxVi; i++, pv++) {
  278. pv->pColor = &pv->colors[__MCD_FRONTFACE];
  279. }
  280. // Set up those rendering functions which are state-invariant:
  281. pRc->clipLine = __MCDClipLine;
  282. pRc->clipTri = __MCDClipTriangle;
  283. pRc->clipPoly = __MCDClipPolygon;
  284. pRc->doClippedPoly = __MCDDoClippedPolygon;
  285. pRc->viewportXAdjust = pRcInfo->viewportXAdjust;
  286. pRc->viewportYAdjust = pRcInfo->viewportYAdjust;
  287. #ifdef TEST_REQ_FLAGS
  288. pRcInfo->requestFlags = MCDRCINFO_NOVIEWPORTADJUST |
  289. MCDRCINFO_Y_LOWER_LEFT |
  290. MCDRCINFO_DEVCOLORSCALE |
  291. MCDRCINFO_DEVZSCALE;
  292. pRcInfo->redScale = (MCDFLOAT)1.0;
  293. pRcInfo->greenScale = (MCDFLOAT)1.0;
  294. pRcInfo->blueScale = (MCDFLOAT)1.0;
  295. pRcInfo->alphaScale = (MCDFLOAT)1.0;
  296. pRcInfo->zScale = 0.99991;
  297. #endif
  298. pRc->dwControl0 = 0;
  299. pRc->Control0.Alpha_Mode = LL_ALPHA_INTERP; // alpha blend and fog both use interpolated alpha
  300. pRc->Control0.Light_Src_Sel = LL_LIGHTING_INTERP_RGB; // use poly engine output for light source
  301. switch( ppdev->iBitmapFormat )
  302. {
  303. case BMF_8BPP: pRc->Control0.Pixel_Mode = PIXEL_MODE_332; break;
  304. case BMF_16BPP: pRc->Control0.Pixel_Mode = PIXEL_MODE_565; break;
  305. //case BMF_24BPP: - 3d engine has no support for 24 bit
  306. case BMF_32BPP: pRc->Control0.Pixel_Mode = PIXEL_MODE_A888; break;
  307. }
  308. pRc->dwTxControl0=0;
  309. #if DRIVER_5465
  310. pRc->TxControl0.UV_Precision = 1;
  311. #endif
  312. pRc->TxControl0.Tex_Mask_Polarity = 1; // non-zero mask bit in texel will draw
  313. pRc->dwTxXYBase=0;
  314. pRc->dwColor0=0;
  315. SETREG_NC( CONTROL0_3D, pRc->dwControl0 );
  316. SETREG_NC( TX_CTL0_3D, pRc->dwTxControl0 );
  317. SETREG_NC( TX_XYBASE_3D, pRc->dwTxXYBase );
  318. SETREG_NC( COLOR0_3D, pRc->dwColor0 );
  319. pRc->pLastDevWnd = NULL;
  320. pRc->pLastTexture = TEXTURE_NOT_LOADED;
  321. pRc->fNumDraws = (float)0.0;
  322. pRc->punt_front_w_windowed_z = FALSE;
  323. ppdev->LL_State.pattern_ram_state = PATTERN_RAM_INVALID;
  324. ppdev->pLastDevRC = (ULONG)NULL;
  325. ppdev->NumMCDContexts++;
  326. MCDBG_PRINT( "MCDrvCreateContext - returns successfully\n");
  327. return TRUE;
  328. }
  329. VOID FASTCALL __MCDDummyProc(DEVRC *pRc)
  330. {
  331. MCDBG_PRINT( "MCDDummyProc (render support routine)\n");
  332. }
  333. ULONG MCDrvDeleteContext(MCDRC *pRc, DHPDEV dhpdev)
  334. {
  335. PDEV *ppdev = (PDEV *)dhpdev;
  336. MCDBG_PRINT( "MCDrvDeleteContext, num contexts left after this delete = %d\n",ppdev->NumMCDContexts-1);
  337. WAIT_HW_IDLE(ppdev);
  338. if (pRc->pvUser) {
  339. MCDFree(pRc->pvUser);
  340. pRc->pvUser = NULL;
  341. }
  342. if (ppdev->NumMCDContexts>0) ppdev->NumMCDContexts--;
  343. return (ULONG)TRUE;
  344. }
  345. ULONG MCDrvBindContext(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc)
  346. {
  347. DEVWND *pDevWnd = (DEVWND *)(pMCDSurface->pWnd->pvUser);
  348. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  349. DEVRC *pRc = pMCDRc->pvUser;
  350. MCDBG_PRINT( "MCDrvBindContext\n");
  351. // OK, this is a new binding, so create the per-window structure and
  352. // set the pixel format:
  353. if (!pDevWnd) {
  354. pDevWnd = pMCDSurface->pWnd->pvUser = (DEVWND *)MCDAlloc(sizeof(DEVWND));
  355. if (!pDevWnd) {
  356. MCDBG_PRINT( "MCDrvBindContext: couldn't allocate DEVWND");
  357. return FALSE;
  358. }
  359. pDevWnd->createFlags = pMCDRc->createFlags;
  360. pDevWnd->iPixelFormat = pMCDRc->iPixelFormat;
  361. // init ptrs so we know back and z buffers don't exist yet
  362. pDevWnd->pohZBuffer = NULL;
  363. pDevWnd->pohBackBuffer = NULL;
  364. pDevWnd->dispUnique = ppdev->iUniqueness;
  365. return TRUE;
  366. }
  367. if (pMCDRc->iPixelFormat != pDevWnd->iPixelFormat) {
  368. MCDBG_PRINT( "MCDrvBindContext: tried to bind unmatched pixel formats");
  369. return FALSE;
  370. }
  371. // 5464 doesn't need this....
  372. //HWUpdateBufferPos(pMCDSurface->pWnd, pMCDSurface->pso, TRUE);
  373. return TRUE;
  374. }
  375. ULONG MCDrvAllocBuffers(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc)
  376. {
  377. DEVRC *pRc = (DEVRC *)pMCDRc->pvUser;
  378. MCDWINDOW *pMCDWnd = pMCDSurface->pWnd;
  379. DEVWND *pDevWnd = (DEVWND *)(pMCDSurface->pWnd->pvUser);
  380. BOOL bZBuffer = (pDevWnd->pohZBuffer != NULL);
  381. BOOL bBackBuffer = (pDevWnd->pohBackBuffer != NULL);
  382. ULONG ret;
  383. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  384. MCDBG_PRINT( "MCDrvAllocBuffers\n");
  385. // Reject the call if we've already done an allocation for this window:
  386. if ((bZBuffer || bBackBuffer) &&
  387. ((DEVWND *)pMCDWnd->pvUser)->dispUnique == GetDisplayUniqueness((PDEV *)pMCDSurface->pso->dhpdev)) {
  388. MCDBG_PRINT( "MCDrvAllocBuffers - realloc attempt\n");
  389. ret = (bZBuffer == pRc->zBufEnabled) &&
  390. (bBackBuffer == pRc->backBufEnabled);
  391. MCDBG_PRINT( "MCDrvAllocBuffers ret=%d\n",ret);
  392. return ret;
  393. }
  394. // Update the display resolution uniqueness for this window:
  395. ((DEVWND *)pMCDWnd->pvUser)->dispUnique = GetDisplayUniqueness((PDEV *)pMCDSurface->pso->dhpdev);
  396. // indicate in DEVWND if z,back buffers wanted in case window size increase such that
  397. // re-alloc in MCDrvTrackWindow fails, and later window reduced so that buffers would fit
  398. // without this, there's no way for DEVWND to remember what buffers are really wanted
  399. // if some intermediate re-alloc fails.
  400. pDevWnd->bDesireZBuffer = pRc->zBufEnabled;
  401. pDevWnd->bDesireBackBuffer = pRc->backBufEnabled;
  402. ret = (ULONG)HWAllocResources(pMCDSurface->pWnd, pMCDSurface->pso,
  403. pRc->zBufEnabled, pRc->backBufEnabled);
  404. pDevWnd->dwBase0 = 0;
  405. pDevWnd->dwBase1 = 0;
  406. // setup 546x buffer pointers to z and back buffers here
  407. if (pRc->zBufEnabled && !pDevWnd->pohZBuffer)
  408. ret=FALSE;
  409. else if (pRc->zBufEnabled) {
  410. // FUTURE: z buffer location assumed to be in RDRAM - if buffer in system, need to change setup
  411. // FUTURE: see setup in LL_SetZBuffer in l3d\source\control.c
  412. pDevWnd->Base1.Z_Buffer_Y_Offset = pDevWnd->pohZBuffer->aligned_y >> 5;
  413. // MCD_QST2: if global full screen z buffer, clearing affects context established earlier.
  414. // MCD_QST2: IS THAT OK?
  415. // init z buffer to all 0xFF's, since GL z compare typically GL_LESS
  416. // NOTE that size is not full buffer size, since alignment restrictions may force top of
  417. // actual buffer to be down from top
  418. memset( ppdev->pjScreen + (pDevWnd->pohZBuffer->y * ppdev->lDeltaScreen),
  419. 0xff,
  420. ((pDevWnd->pohZBuffer->y+pDevWnd->pohZBuffer->sizey) //size = end...
  421. -pDevWnd->pohZBuffer->aligned_y) // minus top...
  422. * ppdev->lDeltaScreen ); // times pitch
  423. }
  424. if (pRc->backBufEnabled && !pDevWnd->pohBackBuffer)
  425. ret=FALSE;
  426. else if (pRc->backBufEnabled) {
  427. #ifndef FORCE_SINGLE_BUF
  428. pDevWnd->Base1.Color_Buffer_Y_Offset = pDevWnd->pohBackBuffer->aligned_y >> 5;
  429. pDevWnd->Base0.Color_Buffer_X_Offset = pDevWnd->pohBackBuffer->aligned_x >> 6;
  430. #endif // ndef FORCE_SINGLE_BUF
  431. }
  432. if (ret)
  433. {
  434. if (pDevWnd->pohBackBuffer && pDevWnd->pohZBuffer)
  435. {
  436. // both buffers alloc'd
  437. MCDBG_PRINT("FB at %x, FBlen=%x, FBhi=%x start OffSc at %x, Z offset = %x, backbuf offset = %x\n",
  438. ppdev->pjScreen,ppdev->lTotalMem,ppdev->cyScreen,ppdev->pjOffScreen,
  439. pDevWnd->pohZBuffer->aligned_y,pDevWnd->pohBackBuffer->aligned_y);
  440. }
  441. else if (pDevWnd->pohBackBuffer)
  442. {
  443. // only back buffer alloc'd
  444. MCDBG_PRINT("FB at %x, FBlen=%x, FBhi=%x start OffSc at %x, NO ZBUF, backbuf offset = %x\n",
  445. ppdev->pjScreen,ppdev->lTotalMem,ppdev->cyScreen,ppdev->pjOffScreen,
  446. pDevWnd->pohBackBuffer->aligned_y);
  447. }
  448. else if (pDevWnd->pohZBuffer)
  449. {
  450. // only Z buffer alloc'd
  451. MCDBG_PRINT("FB at %x, FBlen=%x, FBhi=%x start OffSc at %x, Z offset = %x, NO BACKBUF\n",
  452. ppdev->pjScreen,ppdev->lTotalMem,ppdev->cyScreen,ppdev->pjOffScreen,
  453. pDevWnd->pohZBuffer->aligned_y);
  454. }
  455. else
  456. {
  457. // no buffers alloc'd
  458. MCDBG_PRINT("FB at %x, FBlen=%x, FBhi=%x start OffSc at %x, NO ZBUF , NO BACKBUF\n",
  459. ppdev->pjScreen,ppdev->lTotalMem,ppdev->cyScreen,ppdev->pjOffScreen);
  460. }
  461. SETREG_NC( BASE0_ADDR_3D, pDevWnd->dwBase0 );
  462. SETREG_NC( BASE1_ADDR_3D, pDevWnd->dwBase1 );
  463. pRc->pLastDevWnd = pDevWnd;
  464. MCDBG_PRINT( "MCDrvAllocBuffers ret=%d\n",ret);
  465. }
  466. else
  467. {
  468. pRc->pLastDevWnd = NULL;
  469. }
  470. return ret;
  471. }
  472. ULONG MCDrvGetBuffers(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc,
  473. MCDBUFFERS *pMCDBuffers)
  474. {
  475. DEVRC *pRc = (DEVRC *)pMCDRc->pvUser;
  476. MCDWINDOW *pMCDWnd = pMCDSurface->pWnd;
  477. DEVWND *pDevWnd = (DEVWND *)(pMCDSurface->pWnd->pvUser);
  478. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  479. MCDBG_PRINT("MCDrvGetBuffers");
  480. MCD_CHECK_BUFFERS_VALID(pMCDSurface, pRc, FALSE);
  481. pMCDBuffers->mcdFrontBuf.bufFlags = MCDBUF_ENABLED;
  482. pMCDBuffers->mcdFrontBuf.bufOffset =
  483. (pMCDWnd->clientRect.top * ppdev->lDeltaScreen) +
  484. (pMCDWnd->clientRect.left * ppdev->iBytesPerPixel);
  485. pMCDBuffers->mcdFrontBuf.bufStride = ppdev->lDeltaScreen;
  486. if (pDevWnd->bValidBackBuffer) {
  487. pMCDBuffers->mcdBackBuf.bufFlags = MCDBUF_ENABLED;
  488. if ((ppdev->cDoubleBufferRef == 1) || (pMCDWnd->pClip->c == 1))
  489. pMCDBuffers->mcdBackBuf.bufFlags |= MCDBUF_NOCLIP;
  490. #ifndef FORCE_SINGLE_BUF
  491. if (ppdev->pohBackBuffer == pDevWnd->pohBackBuffer) {
  492. // offset from screen origin
  493. pMCDBuffers->mcdBackBuf.bufOffset =
  494. (pMCDWnd->clientRect.top * ppdev->lDeltaScreen) +
  495. (pMCDWnd->clientRect.left * ppdev->iBytesPerPixel) + pDevWnd->backBufferOffset;
  496. } else {
  497. // offset from window origin
  498. pMCDBuffers->mcdBackBuf.bufOffset = pDevWnd->backBufferOffset;
  499. }
  500. #else // FORCE_SINGLE_BUF
  501. pMCDBuffers->mcdBackBuf.bufOffset = pMCDBuffers->mcdFrontBuf.bufOffset;
  502. #endif // FORCE_SINGLE_BUF
  503. } else {
  504. pMCDBuffers->mcdBackBuf.bufFlags = 0;
  505. }
  506. pMCDBuffers->mcdBackBuf.bufStride = ppdev->lDeltaScreen;
  507. if (pDevWnd->bValidZBuffer) {
  508. pMCDBuffers->mcdDepthBuf.bufFlags = MCDBUF_ENABLED;
  509. if ((ppdev->cZBufferRef == 1) || (pMCDWnd->pClip->c == 1))
  510. pMCDBuffers->mcdDepthBuf.bufFlags |= MCDBUF_NOCLIP;
  511. if (ppdev->pohZBuffer == pDevWnd->pohZBuffer) {
  512. // offset from screen origin
  513. // NOTE: the mult by 2 below is because Z is always 2 byte/pix
  514. pMCDBuffers->mcdDepthBuf.bufOffset =
  515. (pMCDWnd->clientRect.top * ppdev->lDeltaScreen) +
  516. (pMCDWnd->clientRect.left * 2) + pDevWnd->zBufferOffset;
  517. } else {
  518. // offset from window origin
  519. // NOTE: the mult by 2 below is because Z is always 2 byte/pix
  520. pMCDBuffers->mcdDepthBuf.bufOffset = pDevWnd->zBufferOffset;
  521. }
  522. } else {
  523. pMCDBuffers->mcdDepthBuf.bufFlags = 0;
  524. }
  525. //NOTE: z stride same as frame stride on 546x
  526. pMCDBuffers->mcdDepthBuf.bufStride = ppdev->lDeltaScreen;
  527. return (ULONG)TRUE;
  528. }
  529. ULONG MCDrvSwap(MCDSURFACE *pMCDSurface, ULONG flags)
  530. {
  531. MCDWINDOW *pWnd;
  532. ULONG cClip;
  533. RECTL *pClip;
  534. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  535. DEVWND *pDevWnd = (DEVWND *)(pMCDSurface->pWnd->pvUser);
  536. MCDBG_PRINT("MCDrvSwap");
  537. pWnd = pMCDSurface->pWnd;
  538. // If we're not tracking this window, just return...
  539. if (!pWnd) {
  540. MCDBG_PRINT("MCDrvSwap: trying to swap an untracked window");\
  541. return FALSE;
  542. }
  543. if (!pDevWnd) {
  544. MCDBG_PRINT("MCDrvSwap: NULL buffers.");\
  545. return FALSE;
  546. }
  547. if (!pDevWnd->bValidBackBuffer) {
  548. MCDBG_PRINT("MCDrvSwap: back buffer invalid");
  549. return FALSE;
  550. }
  551. if (pDevWnd->dispUnique != GetDisplayUniqueness(ppdev)) {
  552. MCDBG_PRINT("MCDrvSwap: resolution changed but not updated");
  553. return FALSE;
  554. }
  555. // Just return if we have nothing to swap:
  556. //
  557. // - no visible rectangle
  558. // - per-plane swap, but none of the specified planes
  559. // are supported by driver
  560. if (!(cClip = pWnd->pClipUnscissored->c) ||
  561. (flags && !(flags & MCDSWAP_MAIN_PLANE)))
  562. return TRUE;
  563. #ifndef FORCE_SINGLE_BUF
  564. for (pClip = &pWnd->pClipUnscissored->arcl[0]; cClip; cClip--,
  565. pClip++)
  566. {
  567. // Do the fill:
  568. HW_COPY_RECT(pMCDSurface, pClip);
  569. }
  570. #endif // ndef FORCE_SINGLE_BUF
  571. return (ULONG)TRUE;
  572. }
  573. ULONG MCDrvState(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc, MCDMEM *pMCDMem,
  574. UCHAR *pStart, LONG length, ULONG numStates)
  575. {
  576. DEVRC *pRc = (DEVRC *)pMCDRc->pvUser;
  577. MCDSTATE *pState = (MCDSTATE *)pStart;
  578. MCDSTATE *pStateEnd = (MCDSTATE *)(pStart + length);
  579. MCDBG_PRINT("MCDrvState");
  580. MCD_CHECK_RC(pRc);
  581. while (pState < pStateEnd) {
  582. if (((UCHAR *)pStateEnd - (UCHAR *)pState) < sizeof(MCDSTATE)) {
  583. MCDBG_PRINT("MCDrvState: buffer too small");
  584. return FALSE;
  585. }
  586. switch (pState->state) {
  587. case MCD_RENDER_STATE:
  588. if (((UCHAR *)pState + sizeof(MCDRENDERSTATE)) >
  589. (UCHAR *)pStateEnd)
  590. return FALSE;
  591. memcpy(&pRc->MCDState, &pState->stateValue,
  592. sizeof(MCDRENDERSTATE));
  593. // Flag the fact that we need to re-pick the
  594. // rendering functions:
  595. pRc->pickNeeded = TRUE;
  596. pRc->MCDState.zOffsetUnits *= (float)100.0;
  597. pState = (MCDSTATE *)((UCHAR *)pState + sizeof(MCDSTATE_RENDER));
  598. break;
  599. case MCD_PIXEL_STATE:
  600. // Not accelerated in this driver, so we can ignore this state
  601. // (which implies that we do not need to set the pick flag).
  602. // FUTURE: MCDPIXELSTATE ignored - used by MCDDraw/Read/CopyPixels
  603. // FUTURE: MGA doesn't accelerate - 546x may want to some day
  604. pState = (MCDSTATE *)((UCHAR *)pState + sizeof(MCDSTATE_PIXEL));
  605. break;
  606. case MCD_SCISSOR_RECT_STATE:
  607. // Not needed in this driver, so we can ignore this state
  608. // (which implies that we do not need to set the pick flag).
  609. // FUTURE: MCDSCISSORRECTSTATE ignored - not mentioned in MCD spec
  610. // FUTURE: MGA doesn't accelerate - 546x may want to some day???
  611. pState = (MCDSTATE *)((UCHAR *)pState + sizeof(MCDSTATE_SCISSOR_RECT));
  612. break;
  613. case MCD_TEXENV_STATE:
  614. if (((UCHAR *)pState + sizeof(MCDSTATE_TEXENV)) >
  615. (UCHAR *)pStateEnd)
  616. return FALSE;
  617. memcpy(&pRc->MCDTexEnvState, &pState->stateValue,
  618. sizeof(MCDTEXENVSTATE));
  619. // Flag the fact that we need to re-pick the
  620. // rendering functions:
  621. pRc->pickNeeded = TRUE;
  622. pState = (MCDSTATE *)((UCHAR *)pState + sizeof(MCDSTATE_TEXENV));
  623. break;
  624. default:
  625. MCDBG_PRINT("MCDrvState: Unrecognized state %d.", pState->state);
  626. return FALSE;
  627. }
  628. }
  629. return (ULONG)TRUE;
  630. }
  631. ULONG MCDrvViewport(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc,
  632. MCDVIEWPORT *pMCDViewport)
  633. {
  634. DEVRC *pRc = (DEVRC *)pMCDRc->pvUser;
  635. MCDBG_PRINT("MCDrvViewport");
  636. MCD_CHECK_RC(pRc);
  637. pRc->MCDViewport = *pMCDViewport;
  638. return (ULONG)TRUE;
  639. }
  640. VOID MCDrvTrackWindow(WNDOBJ *pWndObj, MCDWINDOW *pMCDWnd, ULONG flags)
  641. {
  642. SURFOBJ *pso = pWndObj->psoOwner;
  643. PDEV *ppdev = (PDEV *)pso->dhpdev;
  644. MCDBG_PRINT( "MCDrvTrackWindow, flags=%x\n",flags);
  645. //
  646. // Note: pMCDWnd is NULL for surface notifications, so if needed
  647. // they should be handled before this check:
  648. //
  649. if (!pMCDWnd)
  650. return;
  651. if (!pMCDWnd->pvUser) {
  652. MCDBG_PRINT("MCDrvTrackWindow: NULL pDevWnd");
  653. return;
  654. }
  655. // MCD_QST2: should we reset more than ppdev->LL_State.pRegs at top of TrackWindow
  656. // MCD_QST2: when uniqueness has changed?? - see CLMCDInit in enable.c
  657. ppdev->LL_State.pRegs = (DWORD *)ppdev->pLgREGS;
  658. WAIT_HW_IDLE(ppdev);
  659. switch (flags) {
  660. case WOC_DELETE:
  661. MCDBG_PRINT("MCDrvTrackWindow: WOC_DELETE");
  662. // If the display resoultion has changed, the resources we had
  663. // bound to the tracked window are gone, so don't try to delete
  664. // the back- and z-buffer resources which are no longer present:
  665. if (((DEVWND *)pMCDWnd->pvUser)->dispUnique == GetDisplayUniqueness((PDEV *)(pso->dhpdev)))
  666. {
  667. HWFreeResources(pMCDWnd, pso);
  668. }
  669. MCDFree((VOID *)pMCDWnd->pvUser);
  670. pMCDWnd->pvUser = NULL;
  671. break;
  672. case WOC_RGN_CLIENT:
  673. // The resources we had bound to the tracked window have moved,
  674. // so update them:
  675. MCDBG_PRINT("MCDrvTrackWindow: WOC_RGN_CLIENT");
  676. {
  677. DEVWND *pWnd = (DEVWND *)pMCDWnd->pvUser;
  678. BOOL bZBuffer = pWnd->bDesireZBuffer;
  679. BOOL bBackBuffer = pWnd->bDesireBackBuffer;
  680. PDEV *ppdev = (PDEV *)pso->dhpdev;
  681. ULONG height = pMCDWnd->clientRect.bottom - pMCDWnd->clientRect.top;
  682. ULONG width = pMCDWnd->clientRect.right - pMCDWnd->clientRect.left;
  683. BOOL bWindowBuffer =
  684. (bZBuffer && !ppdev->pohZBuffer) ||
  685. (bBackBuffer && !ppdev->pohBackBuffer);
  686. // If the window is using a window-sized back/z resource, we need to
  687. // reallocate it if there has been a size change (or if reset)
  688. int need_new_resources =
  689. ((((height != pWnd->allocatedBufferHeight) ||
  690. (width != pWnd->allocatedBufferWidth)) &&
  691. bWindowBuffer) || (pWnd->dispUnique != GetDisplayUniqueness(ppdev))) ? 1 : 0;
  692. if (need_new_resources)
  693. {
  694. // free current resources (unless reset, in which case resources are already gone)
  695. if (pWnd->dispUnique == GetDisplayUniqueness(ppdev))
  696. {
  697. MCDBG_PRINT(" WOC_RGN_CLIENT: freeing resources");
  698. HWFreeResources(pMCDWnd, pso);
  699. }
  700. else
  701. {
  702. // recent reset, so associate new uniqueness with current window
  703. pWnd->dispUnique = GetDisplayUniqueness((PDEV *)pso->dhpdev);
  704. }
  705. MCDBG_PRINT(" WOC_RGN_CLIENT: alloc'ing new resources");
  706. if ( HWAllocResources(pMCDWnd, pso, bZBuffer, bBackBuffer) )
  707. {
  708. MCDBG_PRINT(" WOC_RGN_CLIENT: alloc of new resources WORKED");
  709. // setup 546x buffer pointers to z and back buffers here
  710. if (pWnd->pohZBuffer)
  711. {
  712. // FUTURE: z buffer location assumed to be in RDRAM - if buffer in system, need to change setup
  713. // FUTURE: see setup in LL_SetZBuffer in l3d\source\control.c
  714. pWnd->Base1.Z_Buffer_Y_Offset = pWnd->pohZBuffer->aligned_y >> 5;
  715. // init z buffer to all 0xFF's, since GL z compare typically GL_LESS
  716. memset( ppdev->pjScreen + (pWnd->pohZBuffer->aligned_y * ppdev->lDeltaScreen),
  717. 0xff,
  718. pWnd->pohZBuffer->sizey * ppdev->lDeltaScreen );
  719. }
  720. if (pWnd->pohBackBuffer)
  721. {
  722. #ifndef FORCE_SINGLE_BUF
  723. pWnd->Base1.Color_Buffer_Y_Offset = pWnd->pohBackBuffer->aligned_y >> 5;
  724. pWnd->Base0.Color_Buffer_X_Offset = pWnd->pohBackBuffer->aligned_x >> 6;
  725. #endif // ndef FORCE_SINGLE_BUF
  726. }
  727. // FUTURE: MCDrvTrackWindow should set base ptrs via Host3DData port to keep sync
  728. SETREG_NC( BASE0_ADDR_3D, pWnd->dwBase0 );
  729. SETREG_NC( BASE1_ADDR_3D, pWnd->dwBase1 );
  730. }
  731. else
  732. {
  733. MCDBG_PRINT(" WOC_RGN_CLIENT: alloc of new resources FAILED");
  734. }
  735. }
  736. }
  737. break;
  738. default:
  739. break;
  740. }
  741. return;
  742. }
  743. ULONG MCDrvCreateMem(MCDSURFACE *pMCDSurface, MCDMEM *pMCDMem)
  744. {
  745. MCDBG_PRINT("MCDrvCreateMem");
  746. return (ULONG)TRUE;
  747. }
  748. ULONG MCDrvDeleteMem(MCDMEM *pMCDMem, DHPDEV dhpdev)
  749. {
  750. MCDBG_PRINT("MCDrvDeleteMem");
  751. return (ULONG)TRUE;
  752. }
  753. #define TIME_STAMP_TEXTURE(pRc,pTexCtlBlk) pTexCtlBlk->fLastDrvDraw=pRc->fNumDraws;
  754. #define FAIL_ALL_DRAWING 0
  755. #define FORCE_SYNC 0
  756. BOOL __MCDTextureSetup(PDEV *ppdev, DEVRC *pRc)
  757. {
  758. MCDTEXTURESTATE *pTexState;
  759. if (pRc->pLastTexture->dwTxCtlBits & CLMCD_TEX_BOGUS)
  760. {
  761. MCDBG_PRINT("Attempting to use bogus texture, ret false in __MCDTextureSetup");
  762. return FALSE;
  763. }
  764. VERIFY_TEXTUREDATA_ACCESSIBLE(pRc->pLastTexture->pTex);
  765. VERIFY_TEXTURELEVEL_ACCESSIBLE(pRc->pLastTexture->pTex);
  766. pTexState= (MCDTEXTURESTATE *)&pRc->pLastTexture->pTex->pMCDTextureData->textureState;
  767. MCDFREE_PRINT("internalFormat = %x", pRc->pLastTexture->pTex->pMCDTextureData->level->internalFormat);
  768. if (((pTexState->minFilter == GL_NEAREST) ||
  769. (pTexState->minFilter == GL_LINEAR)) &&
  770. ((pTexState->magFilter == GL_NEAREST) ||
  771. (pTexState->magFilter == GL_LINEAR)))
  772. {
  773. // no filtering, or linear filtering, 5465 can do this...
  774. }
  775. else
  776. {
  777. // mipmapping - should punt on 5465
  778. // However, some apps use mipmapping extensively (like GLQuake) and punting
  779. // mipmapping makes them run very slow. Conformance test runs in a small
  780. // window, so only punt if window small.
  781. // Yes, this is a bit shady, but 5466 and following will have this fixed.
  782. // Nobody will likely notice the problem until the 5466 is out
  783. if ( (pRc->pMCDSurface->pWnd->clientRect.bottom -
  784. pRc->pMCDSurface->pWnd->clientRect.top) < 110)
  785. {
  786. return FALSE;
  787. }
  788. }
  789. if ( pRc->Control0.Frame_Scaling_Enable &&
  790. ((pRc->MCDState.blendDst == GL_ONE_MINUS_SRC_COLOR) &&
  791. !pRc->pLastTexture->bNegativeMap) ||
  792. ((pRc->MCDState.blendDst == GL_SRC_COLOR) &&
  793. pRc->pLastTexture->bNegativeMap) )
  794. {
  795. // must invert the map
  796. MCDFREE_PRINT("inverting map for framescaling");
  797. pRc->pLastTexture->bNegativeMap = !pRc->pLastTexture->bNegativeMap;
  798. if (pRc->pLastTexture->bNegativeMap &&
  799. (pRc->pLastTexture->pTex->pMCDTextureData->level->internalFormat!=GL_LUMINANCE) &&
  800. (pRc->pLastTexture->pTex->pMCDTextureData->level->internalFormat!=GL_LUMINANCE_ALPHA))
  801. {
  802. // FUTURE2: only LUMINANCE formats support inverted maps - should add all formats
  803. MCDFREE_PRINT("MCDrvDraw: negative map not supported -punt");
  804. // toggle back to original state - can use this texture when not frame scaling
  805. pRc->pLastTexture->bNegativeMap = !pRc->pLastTexture->bNegativeMap;
  806. return FALSE;
  807. }
  808. pRc->pLastTexture->pohTextureMap = NULL; // set to force reload
  809. }
  810. if (pRc->privateEnables & __MCDENABLE_TEXTUREMASKING)
  811. {
  812. #ifdef STRICT_CONFORMANCE
  813. // should punt here, but GLQuake does this & nonpunt OK visually
  814. if (!pRc->pLastTexture->bAlphaInTexture)
  815. {
  816. MCDFREE_PRINT("MCDrvDraw: alpha test, but no alpha in texture-punt");
  817. return FALSE;
  818. }
  819. #endif // def STRICT_CONFORMANCE
  820. // alphatest and frame scaling mutually exclusive
  821. // (for now - may be some situtations where they're enabled together)
  822. // masking only meaningful if texture has alpha
  823. if (pRc->pLastTexture->bAlphaInTexture && !pRc->pLastTexture->bMasking )
  824. {
  825. MCDFREE_PRINT("reformat for Masking");
  826. pRc->pLastTexture->bMasking = TRUE;
  827. pRc->pLastTexture->pohTextureMap = NULL;// set to force reload
  828. }
  829. }
  830. else if ( pRc->pLastTexture->bMasking )
  831. {
  832. // no alpha test, so reformat map if currently set for alpha test
  833. MCDFREE_PRINT("reformat for NON-Masking");
  834. pRc->pLastTexture->bMasking = FALSE;
  835. pRc->pLastTexture->pohTextureMap = NULL; // set to force reload
  836. }
  837. // Null pohTexture means texture must be loaded before use
  838. // also - must load before setting regs, since x/y loc determined
  839. // by loader must be known before registers setup.
  840. if (!pRc->pLastTexture->pohTextureMap)
  841. {
  842. // if load fails, punt
  843. if (! __MCDLoadTexture(ppdev, pRc) )
  844. {
  845. MCDFREE_PRINT("MCDrvDraw: texture load failed-punt");
  846. return FALSE;
  847. }
  848. }
  849. // setup for new texture - punt if requirements beyond hw
  850. if ( ! __MCDSetTextureRegisters(pRc) )
  851. {
  852. MCDFREE_PRINT("MCDrvDraw: texture regset failed-punt");
  853. return FALSE;
  854. }
  855. return TRUE;
  856. }
  857. #if 1 // 0 here for NULL MCDrvDraw - for measuring "Upper limit" performance
  858. ULONG MCDrvDraw(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc, MCDMEM *prxExecMem,
  859. UCHAR *pStart, UCHAR *pEnd)
  860. {
  861. MCDCOMMAND *pCmd = (MCDCOMMAND *)pStart;
  862. MCDCOMMAND *pCmdNext;
  863. DEVRC *pRc = (DEVRC *)pMCDRc->pvUser;
  864. DEVWND *pDevWnd = (DEVWND *)(pMCDSurface->pWnd->pvUser);
  865. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  866. DWORD regtemp;
  867. CHOP_ROUND_ON();
  868. MCDBG_PRINT("MCDrvDraw");
  869. #if TEST_3D_NO_DRAW
  870. CHOP_ROUND_OFF();
  871. return (ULONG)0;
  872. #endif
  873. // Make sure we have both a valid RC and window structure:
  874. if (!pRc || !pDevWnd)
  875. goto DrawExit;
  876. pRc->ppdev = ppdev;
  877. #if FAIL_ALL_DRAWING
  878. goto DrawExit;
  879. #endif
  880. //
  881. // If the resolution has changed and we have not yet updated our
  882. // buffers, fail the call gracefully since the client won't be
  883. // able to perform any software simulations at this point either.
  884. // This applies to any of the other drawing functions as well (such
  885. // as spans and clears).
  886. //
  887. if (pDevWnd->dispUnique != GetDisplayUniqueness(pRc->ppdev)) {
  888. MCDBG_PRINT("MCDrvDraw: invalid (changed) resolution");
  889. CHOP_ROUND_OFF();
  890. return (ULONG)0;
  891. }
  892. if (pRc != (DEVRC *)ppdev->pLastDevRC) ContextSwitch(pRc);
  893. if ((pRc->zBufEnabled && !pDevWnd->bValidZBuffer) ||
  894. (pRc->backBufEnabled && !pDevWnd->bValidBackBuffer)) {
  895. MCDBG_PRINT("MCDrvDraw has invalid buffers");
  896. goto DrawExit;
  897. }
  898. if (pRc->pickNeeded) {
  899. __MCDPickRenderingFuncs(pRc, pDevWnd);
  900. __MCDPickClipFuncs(pRc);
  901. pRc->pickNeeded = FALSE;
  902. }
  903. // If we're completely clipped, return success:
  904. pRc->pEnumClip = pMCDSurface->pWnd->pClip;
  905. if (!pRc->pEnumClip->c) {
  906. CHOP_ROUND_OFF();
  907. if (ppdev->LL_State.pDL->pdwNext != ppdev->LL_State.pDL->pdwStartOutPtr)
  908. {
  909. // Make sure all buffered data sent
  910. //(__MCDPickRenderingFuncs may have buffered control reg writes)
  911. _RunLaguna(ppdev,ppdev->LL_State.pDL->pdwNext);
  912. }
  913. return (ULONG)0;
  914. }
  915. // return here if we can't draw any primitives:
  916. if (pRc->allPrimFail) {
  917. goto DrawExit;
  918. }
  919. // Set these up in the device's RC so we can just pass a single pointer
  920. // to do everything:
  921. pRc->pMCDSurface = pMCDSurface;
  922. pRc->pMCDRc = pMCDRc;
  923. if ((pMCDSurface->pWnd->clientRect.left < 0) ||
  924. (pMCDSurface->pWnd->clientRect.top < 0))
  925. {
  926. // primitive x or y might be negative - hw can't handle, so fail all
  927. goto DrawExit;
  928. }
  929. else
  930. {
  931. int winrelative = FALSE;
  932. pRc->xOffset = -pRc->viewportXAdjust;
  933. pRc->yOffset = -pRc->viewportYAdjust;
  934. // if draw to back buffer, and back buffer is window-sized (not full screen)
  935. // then coordinates to hardware must be relative to window origin, not
  936. // relative to screen. Clip rectangles given are always relative to screen origin,
  937. // so may need to adjust.
  938. if ((pRc->MCDState.drawBuffer == GL_BACK) &&
  939. (pRc->ppdev->pohBackBuffer != pDevWnd->pohBackBuffer))
  940. {
  941. pRc->AdjClip.left = -pMCDSurface->pWnd->clientRect.left;
  942. pRc->AdjClip.right = -pMCDSurface->pWnd->clientRect.left;
  943. pRc->AdjClip.top = -pMCDSurface->pWnd->clientRect.top;
  944. pRc->AdjClip.bottom= -pMCDSurface->pWnd->clientRect.top;
  945. winrelative = TRUE;
  946. }
  947. else
  948. {
  949. pRc->AdjClip.left = 0;
  950. pRc->AdjClip.right = 0;
  951. pRc->AdjClip.top = 0;
  952. pRc->AdjClip.bottom= 0;
  953. // coordinates to hardware will be screen relative, so add window offset
  954. pRc->xOffset += pMCDSurface->pWnd->clientRect.left;
  955. pRc->yOffset += pMCDSurface->pWnd->clientRect.top;
  956. }
  957. // floating pt versions
  958. pRc->fxOffset = (float)((LONG)pRc->xOffset);
  959. pRc->fyOffset = (float)((LONG)pRc->yOffset);
  960. // Subtract of .5(almost) from y's before triangle
  961. // setup make triangles match MSFT SW exactly.
  962. // Can't just subtract .5 since coords could then be made
  963. // negative - so add 1, the subtract .5. Starting
  964. // Y in triangle setup code will have 1 subtracted to offset
  965. pRc->fyOffset += (float)MCD_CONFORM_ADJUST - __MCD_ALMOST_HALF;
  966. }
  967. // increment the time stamp
  968. pRc->fNumDraws+=(float)1.0;
  969. pRc->pMemMin = pStart;
  970. pRc->pvProvoking = (MCDVERTEX *)pStart; // bulletproofing
  971. pRc->pMemMax = pEnd - sizeof(MCDVERTEX);
  972. // warm up the hardware for drawing primitives:
  973. HW_INIT_DRAWING_STATE(pMCDSurface, pMCDSurface->pWnd, pRc);
  974. // If we have a single clipping rectangle, set it up in the hardware once
  975. // for this batch:
  976. if (pRc->pEnumClip->c == 1)
  977. (*pRc->HWSetupClipRect)(pRc, &pRc->pEnumClip->arcl[0]);
  978. // Now, loop through the commands and process the batch:
  979. try {
  980. if (!(pRc->privateEnables & (__MCDENABLE_PG_STIPPLE|__MCDENABLE_LINE_STIPPLE)))
  981. {
  982. // polygon stipple and line stipple both off
  983. if ((ppdev->LL_State.pattern_ram_state != DITHER_LOADED) &&
  984. (pRc->privateEnables & __MCDENABLE_DITHER))
  985. {
  986. DWORD *pdwNext = ppdev->LL_State.pDL->pdwNext;
  987. int i;
  988. *pdwNext++ = write_register( PATTERN_RAM_0_3D, 8 );
  989. for( i=0; i<8; i++ )
  990. *pdwNext++ = ppdev->LL_State.dither_array.pat[i];
  991. ppdev->LL_State.pDL->pdwNext = pdwNext;
  992. ppdev->LL_State.pattern_ram_state = DITHER_LOADED;
  993. }
  994. while (pCmd && (UCHAR *)pCmd < pEnd) {
  995. volatile ULONG command = pCmd->command;
  996. //MCDBG_PRINT("MCDrvDraw: command = %x ",command);
  997. // Make sure we can read at least the command header:
  998. if ((pEnd - (UCHAR *)pCmd) < sizeof(MCDCOMMAND))
  999. goto DrawExit;
  1000. if (command <= GL_POLYGON) { // simple bounds check - GL_POLYGON is max command
  1001. if (pCmd->flags & MCDCOMMAND_RENDER_PRIMITIVE)
  1002. {
  1003. if (pRc->privateEnables & __MCDENABLE_TEXTURE)
  1004. {
  1005. if (pCmd->textureKey == TEXTURE_NOT_LOADED)
  1006. {
  1007. MCDBG_PRINT("MCDrvDraw: texturing, but texture not loaded - PUNT...");
  1008. MCDFREE_PRINT("MCDrvDraw: texturing, but texture not loaded - PUNT...");
  1009. goto DrawExit;
  1010. }
  1011. else
  1012. {
  1013. // if texture different than last time, or if texture not loaded
  1014. // (could have been updated since last MCDrvDraw which would have force it
  1015. // to be unloaded)
  1016. if ( (pRc->pLastTexture != (LL_Texture *)pCmd->textureKey) ||
  1017. !pRc->pLastTexture->pohTextureMap)
  1018. {
  1019. pRc->pLastTexture = (LL_Texture *)pCmd->textureKey;
  1020. TIME_STAMP_TEXTURE(pRc,pRc->pLastTexture); // time stamp before load
  1021. if (!__MCDTextureSetup(ppdev, pRc)) goto DrawExit;
  1022. }
  1023. else
  1024. {
  1025. TIME_STAMP_TEXTURE(pRc,pRc->pLastTexture);
  1026. }
  1027. }
  1028. }
  1029. // MCDBG_PRINT("MCDrvDraw: non-stippled path... rendering....");
  1030. pCmdNext = (*pRc->primFunc[command])(pRc, pCmd);
  1031. }
  1032. else
  1033. {
  1034. // MCDBG_PRINT("MCDrvDraw: non-stippled path... not rendering....");
  1035. pCmdNext = pCmd->pNextCmd;
  1036. }
  1037. if (pCmdNext == pCmd)
  1038. {
  1039. MCDFREE_PRINT("MCDrvDraw: pCmdNext == pCmd-punt");
  1040. goto DrawExit; // primitive failed
  1041. }
  1042. if (!(pCmd = pCmdNext)) { // we're done with the batch
  1043. CHOP_ROUND_OFF();
  1044. if (ppdev->LL_State.pDL->pdwNext != ppdev->LL_State.pDL->pdwStartOutPtr)
  1045. {
  1046. // we should rarely get here - only for case of lots of
  1047. // consecutive stuffed culled or clipped causing no primitives to
  1048. // be sent to HW - in such case, setup info, clip, context
  1049. // switch etc. could stack up and overflow buffer unless
  1050. // we make sure all is dumped here...
  1051. // Recall primitive render procs will dump whole queue before they return
  1052. _RunLaguna(ppdev,ppdev->LL_State.pDL->pdwNext);
  1053. }
  1054. #if FORCE_SYNC
  1055. HW_WAIT_DRAWING_DONE(pRc);
  1056. #endif
  1057. return (ULONG)0;
  1058. }
  1059. }
  1060. }
  1061. }
  1062. else
  1063. {
  1064. // polygon stipple AND/OR line stipple on - may need to reload pattern ram between primitives
  1065. while (pCmd && (UCHAR *)pCmd < pEnd) {
  1066. volatile ULONG command = pCmd->command;
  1067. //MCDBG_PRINT("MCDrvDraw: command = %x ",command);
  1068. // Make sure we can read at least the command header:
  1069. if ((pEnd - (UCHAR *)pCmd) < sizeof(MCDCOMMAND))
  1070. goto DrawExit;
  1071. if (command <= GL_POLYGON) { // simple bounds check - GL_POLYGON is max command
  1072. if (pCmd->flags & MCDCOMMAND_RENDER_PRIMITIVE)
  1073. {
  1074. // FUTURE: move all this pattern toggle to routine that is called indirectly
  1075. // FUTURE: with ptr to proc being reset by prior pattern ram load, etc.
  1076. LL_Pattern *Pattern=0;
  1077. int pat_inc = 1;
  1078. int pattern_bytes = 0;
  1079. if (command >= GL_TRIANGLES)
  1080. {
  1081. // area primitive - if stippled, may need to reload pattern
  1082. if (pRc->privateEnables & __MCDENABLE_PG_STIPPLE)
  1083. {
  1084. pattern_bytes = 8;
  1085. if (ppdev->LL_State.pattern_ram_state != AREA_PATTERN_LOADED)
  1086. {
  1087. ppdev->LL_State.pattern_ram_state = AREA_PATTERN_LOADED;
  1088. Pattern = &(pRc->fill_pattern);
  1089. // pat_inc remains 1;
  1090. }
  1091. }
  1092. }
  1093. else
  1094. {
  1095. // line primitive - if stippled, may need to reload pattern (OK for points though don't care)
  1096. if ( (pRc->privateEnables & __MCDENABLE_LINE_STIPPLE) &&
  1097. (command != GL_POINTS) )
  1098. {
  1099. // fill 8 word ram with same word so we get right pattern regardless
  1100. // of pattern_y_offset that may be set in base0 reg for proper pg stipple
  1101. pattern_bytes = 8;
  1102. if (ppdev->LL_State.pattern_ram_state != LINE_PATTERN_LOADED)
  1103. {
  1104. ppdev->LL_State.pattern_ram_state = LINE_PATTERN_LOADED;
  1105. Pattern = &(pRc->line_style);
  1106. pat_inc = 0; // don't increment through source pattern
  1107. }
  1108. }
  1109. }
  1110. if ((ppdev->LL_State.pattern_ram_state != DITHER_LOADED) &&
  1111. !pattern_bytes && (pRc->privateEnables & __MCDENABLE_DITHER))
  1112. {
  1113. ppdev->LL_State.pattern_ram_state = DITHER_LOADED;
  1114. Pattern = &(ppdev->LL_State.dither_array);
  1115. pattern_bytes = 8;
  1116. // pat_inc remains 1;
  1117. }
  1118. if (Pattern)
  1119. {
  1120. DWORD *pdwNext = ppdev->LL_State.pDL->pdwNext;
  1121. int i;
  1122. *pdwNext++ = write_register( PATTERN_RAM_0_3D, pattern_bytes );
  1123. for( i=0; pattern_bytes>0; i+=pat_inc, pattern_bytes-- )
  1124. *pdwNext++ = Pattern->pat[ i ];
  1125. // leave data queued for now, primitive render procs will send
  1126. ppdev->LL_State.pDL->pdwNext = pdwNext;
  1127. }
  1128. if (pRc->privateEnables & __MCDENABLE_TEXTURE)
  1129. {
  1130. if (pCmd->textureKey == TEXTURE_NOT_LOADED)
  1131. {
  1132. MCDBG_PRINT("MCDrvDraw: texturing, but texture not loaded - PUNT...");
  1133. goto DrawExit;
  1134. }
  1135. else
  1136. {
  1137. // if texture different than last time, or if texture not loaded
  1138. // (could have been updated since last MCDrvDraw which would have force it
  1139. // to be unloaded)
  1140. if ( (pRc->pLastTexture != (LL_Texture *)pCmd->textureKey) ||
  1141. !pRc->pLastTexture->pohTextureMap)
  1142. {
  1143. pRc->pLastTexture = (LL_Texture *)pCmd->textureKey;
  1144. TIME_STAMP_TEXTURE(pRc,pRc->pLastTexture); // time stamp before load
  1145. if (!__MCDTextureSetup(ppdev, pRc)) goto DrawExit;
  1146. }
  1147. else
  1148. {
  1149. TIME_STAMP_TEXTURE(pRc,pRc->pLastTexture);
  1150. }
  1151. }
  1152. }
  1153. // MCDBG_PRINT("MCDrvDraw: stippled path... rendering....");
  1154. pCmdNext = (*pRc->primFunc[command])(pRc, pCmd);
  1155. }
  1156. else
  1157. {
  1158. // MCDBG_PRINT("MCDrvDraw: stippled path... not rendering....");
  1159. pCmdNext = pCmd->pNextCmd;
  1160. }
  1161. if (pCmdNext == pCmd)
  1162. goto DrawExit; // primitive failed
  1163. if (!(pCmd = pCmdNext)) { // we're done with the batch
  1164. CHOP_ROUND_OFF();
  1165. if (ppdev->LL_State.pDL->pdwNext != ppdev->LL_State.pDL->pdwStartOutPtr)
  1166. {
  1167. // we should rarely get here - only for case of lots of
  1168. // consecutive stuffed culled or clipped causing no primitives to
  1169. // be sent to HW - in such case, setup info, clip, context
  1170. // switch etc. could stack up and overflow buffer unless
  1171. // we make sure all is dumped here...
  1172. // Recall primitive render procs will dump whole queue before they return
  1173. _RunLaguna(ppdev,ppdev->LL_State.pDL->pdwNext);
  1174. }
  1175. #if FORCE_SYNC
  1176. HW_WAIT_DRAWING_DONE(pRc);
  1177. #endif
  1178. return (ULONG)0;
  1179. }
  1180. }
  1181. }
  1182. }
  1183. } except (EXCEPTION_EXECUTE_HANDLER) {
  1184. MCDBG_PRINT("!!Exception in MCDrvDraw!!");
  1185. // will fall through to DrawExit condition below...
  1186. }
  1187. // ERROR (or Punt) CONDITION
  1188. DrawExit:
  1189. MCDFREE_PRINT("*****************************************************");
  1190. MCDFREE_PRINT("************* PUNTING in MCDrvDraw ******************");
  1191. MCDFREE_PRINT("*****************************************************");
  1192. if (ppdev->LL_State.pDL->pdwNext != ppdev->LL_State.pDL->pdwStartOutPtr)
  1193. {
  1194. // we should rarely get here - only for case of lots of
  1195. // consecutive stuff culls or clips causing no primitives to
  1196. // be sent to HW - in such case, setup info, clip, context
  1197. // switch etc. could stack up and overflow buffer unless
  1198. // we make sure all is dumped here...
  1199. _RunLaguna(ppdev,ppdev->LL_State.pDL->pdwNext);
  1200. }
  1201. // restore the hardware state:
  1202. CHOP_ROUND_OFF();
  1203. HW_WAIT_DRAWING_DONE(pRc);
  1204. return (ULONG)pCmd; // some sort of overrun has occurred
  1205. }
  1206. #else // NULL MCDrvDraw
  1207. ULONG MCDrvDraw(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc, MCDMEM *prxExecMem,
  1208. UCHAR *pStart, UCHAR *pEnd)
  1209. {
  1210. MCDCOMMAND *pCmd = (MCDCOMMAND *)pStart;
  1211. MCDCOMMAND *pCmdNext;
  1212. try {
  1213. // Now, loop through the commands and process the batch:
  1214. while (pCmd && (UCHAR *)pCmd < pEnd) {
  1215. pCmdNext = pCmd->pNextCmd;
  1216. if (!(pCmd = pCmdNext)) { // we're done with the batch
  1217. return (ULONG)0;
  1218. }
  1219. }
  1220. } except (EXCEPTION_EXECUTE_HANDLER) {
  1221. MCDBG_PRINT("!!Exception in NULL Version of MCDrvDraw!!");
  1222. }
  1223. return (ULONG)pCmd; // some sort of overrun has occurred
  1224. }
  1225. #endif // NULL MCDrvDraw
  1226. ULONG MCDrvClear(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc, ULONG buffers)
  1227. {
  1228. DEVRC *pRc = (DEVRC *)pMCDRc->pvUser;
  1229. MCDWINDOW *pWnd;
  1230. ULONG cClip;
  1231. RECTL *pClip;
  1232. MCDBG_PRINT("MCDrvClear");
  1233. MCD_CHECK_RC(pRc);
  1234. pWnd = pMCDSurface->pWnd;
  1235. MCD_CHECK_BUFFERS_VALID(pMCDSurface, pRc, TRUE);
  1236. pRc->ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  1237. #if FAIL_ALL_DRAWING
  1238. return TRUE;
  1239. #endif
  1240. if (buffers & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
  1241. GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) {
  1242. MCDBG_PRINT("MCDrvClear: attempted to clear buffer of unknown type");
  1243. return FALSE;
  1244. }
  1245. if ((buffers & GL_DEPTH_BUFFER_BIT) && (!pRc->zBufEnabled))
  1246. {
  1247. MCDBG_PRINT("MCDrvClear: clear z requested with z-buffer disabled.");
  1248. HW_WAIT_DRAWING_DONE(pRc);
  1249. return FALSE;
  1250. }
  1251. if (buffers & (GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) {
  1252. MCDBG_PRINT("MCDrvClear: attempted to clear accum or stencil buffer");
  1253. return FALSE;
  1254. }
  1255. // Return if we have nothing to clear:
  1256. if (!(cClip = pWnd->pClip->c))
  1257. return TRUE;
  1258. // We have to protect against bad clear colors since this can
  1259. // potentially cause an FP exception:
  1260. try {
  1261. for (pClip = &pWnd->pClip->arcl[0]; cClip; cClip--,
  1262. pClip++)
  1263. {
  1264. // Do the fill:
  1265. HW_FILL_RECT(pMCDSurface, pRc, pClip, buffers);
  1266. }
  1267. } except (EXCEPTION_EXECUTE_HANDLER) {
  1268. MCDBG_PRINT("!!Exception in MCDrvClear!!");
  1269. return FALSE;
  1270. }
  1271. #if FORCE_SYNC
  1272. HW_WAIT_DRAWING_DONE(pRc);
  1273. #endif
  1274. return (ULONG)TRUE;
  1275. }
  1276. ULONG MCDrvSpan(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc, MCDMEM *pMCDMem,
  1277. MCDSPAN *pMCDSpan, BOOL bRead)
  1278. {
  1279. DEVRC *pRc = (DEVRC *)pMCDRc->pvUser;
  1280. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  1281. UCHAR *pScreen;
  1282. UCHAR *pPixels;
  1283. MCDWINDOW *pWnd;
  1284. DEVWND *pDevWnd;
  1285. LONG xLeftOrg, xLeft, xRight, y;
  1286. LONG bufferYBias;
  1287. ULONG bytesNeeded;
  1288. ULONG cjHwPel;
  1289. int winoffset = FALSE;
  1290. MCD_CHECK_RC(pRc);
  1291. pWnd = pMCDSurface->pWnd;
  1292. // Return if we have nothing to clip:
  1293. if (!pWnd->pClip->c)
  1294. return TRUE;
  1295. // Fail if number of pixels is negative:
  1296. if (pMCDSpan->numPixels < 0) {
  1297. MCDBG_PRINT("MCDrvSpan: numPixels < 0");
  1298. return FALSE;
  1299. }
  1300. MCD_CHECK_BUFFERS_VALID(pMCDSurface, pRc, TRUE);
  1301. pDevWnd = (DEVWND *)pWnd->pvUser;
  1302. xLeft = xLeftOrg = (pMCDSpan->x + pWnd->clientRect.left);
  1303. xRight = (xLeft + pMCDSpan->numPixels);
  1304. y = pMCDSpan->y + pWnd->clientRect.top;
  1305. // Early-out spans which are not visible:
  1306. if ((y < pWnd->clipBoundsRect.top) ||
  1307. (y >= pWnd->clipBoundsRect.bottom))
  1308. return TRUE;
  1309. xLeft = max(xLeft, pWnd->clipBoundsRect.left);
  1310. xRight = min(xRight, pWnd->clipBoundsRect.right);
  1311. // Return if empty:
  1312. if (xLeft >= xRight)
  1313. return TRUE;
  1314. cjHwPel = ppdev->iBytesPerPixel;
  1315. pScreen = ppdev->pjScreen;
  1316. switch (pMCDSpan->type) {
  1317. case MCDSPAN_FRONT:
  1318. // pScreen remains the same
  1319. break;
  1320. case MCDSPAN_BACK:
  1321. pScreen += pDevWnd->backBufferOffset;
  1322. if (ppdev->pohBackBuffer != pDevWnd->pohBackBuffer) winoffset = TRUE;
  1323. break;
  1324. case MCDSPAN_DEPTH:
  1325. cjHwPel = 2;
  1326. pScreen += pDevWnd->zBufferOffset;
  1327. if (ppdev->pohZBuffer != pDevWnd->pohZBuffer) winoffset = TRUE;
  1328. break;
  1329. default:
  1330. MCDBG_PRINT("MCDrvReadSpan: Unrecognized buffer %d", pMCDSpan->type);
  1331. return FALSE;
  1332. }
  1333. if (winoffset)
  1334. {
  1335. // offset from window origin, remove client rectangle offsets applied above
  1336. y -= pWnd->clientRect.top;
  1337. xLeft -= pWnd->clientRect.left;
  1338. xLeftOrg -= pWnd->clientRect.left;
  1339. xRight-= pWnd->clientRect.left;
  1340. }
  1341. // add offset to top of framebuffer, and offset within selected buffer
  1342. pScreen += (y * ppdev->lDeltaScreen) + (xLeft * cjHwPel);
  1343. bytesNeeded = pMCDSpan->numPixels * cjHwPel;
  1344. // Make sure we don't read past the end of the buffer:
  1345. if (((char *)pMCDSpan->pPixels + bytesNeeded) >
  1346. ((char *)pMCDMem->pMemBase + pMCDMem->memSize)) {
  1347. MCDBG_PRINT("MCDrvSpan: Buffer too small");
  1348. return FALSE;
  1349. }
  1350. WAIT_HW_IDLE(ppdev);
  1351. pPixels = pMCDSpan->pPixels;
  1352. //MCDBG_PRINT("MCDrvSpan: read %d, (%d, %d) type %d *ppix=%x, bytes=%d", bRead, pMCDSpan->x, pMCDSpan->y, pMCDSpan->type, *pPixels, bytesNeeded);
  1353. if (bRead) {
  1354. if (xLeftOrg != xLeft) // compensate for clip rectangle
  1355. pPixels = (UCHAR *)pMCDSpan->pPixels + ((xLeft - xLeftOrg) * cjHwPel);
  1356. RtlCopyMemory(pPixels, pScreen, (xRight - xLeft) * cjHwPel);
  1357. } else {
  1358. LONG xLeftClip, xRightClip, yClip;
  1359. RECTL *pClip;
  1360. RECTL AdjClip;
  1361. ULONG cClip;
  1362. for (pClip = &pWnd->pClip->arcl[0], cClip = pWnd->pClip->c; cClip;
  1363. cClip--, pClip++)
  1364. {
  1365. UCHAR *pScreenClip;
  1366. if (winoffset)
  1367. {
  1368. AdjClip.left = pClip->left - pWnd->clientRect.left;
  1369. AdjClip.right = pClip->right - pWnd->clientRect.left;
  1370. AdjClip.top = pClip->top - pWnd->clientRect.top;
  1371. AdjClip.bottom = pClip->bottom - pWnd->clientRect.top;
  1372. }
  1373. else
  1374. {
  1375. AdjClip.left = pClip->left;
  1376. AdjClip.right = pClip->right;
  1377. AdjClip.top = pClip->top;
  1378. AdjClip.bottom = pClip->bottom;
  1379. }
  1380. // Test for trivial cases:
  1381. if (y < AdjClip.top)
  1382. break;
  1383. // Determine trivial rejection for just this span
  1384. if ((xLeft >= AdjClip.right) ||
  1385. (y >= AdjClip.bottom) ||
  1386. (xRight <= AdjClip.left))
  1387. continue;
  1388. // Intersect current clip rect with the span:
  1389. xLeftClip = max(xLeft, AdjClip.left);
  1390. xRightClip = min(xRight, AdjClip.right);
  1391. if (xLeftClip >= xRightClip)
  1392. continue;
  1393. if (xLeftOrg != xLeftClip)
  1394. pPixels = (UCHAR *)pMCDSpan->pPixels +
  1395. ((xLeftClip - xLeftOrg) * cjHwPel);
  1396. pScreenClip = pScreen + ((xLeftClip - xLeft) * cjHwPel);
  1397. // Write the span:
  1398. RtlCopyMemory(pScreenClip, pPixels, (xRightClip - xLeftClip) * cjHwPel);
  1399. }
  1400. }
  1401. return (ULONG)TRUE;
  1402. }
  1403. ULONG MCDrvSync (MCDSURFACE *pMCDSurface, MCDRC *pRc)
  1404. {
  1405. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  1406. MCDBG_PRINT( "MCDrvSync\n");
  1407. WAIT_HW_IDLE(ppdev);
  1408. return FALSE;
  1409. }
  1410. ULONG /* FASTCALL */ MCDrvDummyDrvDrawPixels (MCDSURFACE *pMcdSurface, MCDRC *pRc,
  1411. ULONG width, ULONG height, ULONG format,
  1412. ULONG type, VOID *pPixels, BOOL packed)
  1413. {
  1414. MCDBG_PRINT( "MCDrvDummyDrvDrawPixels\n");
  1415. return FALSE;
  1416. }
  1417. ULONG /* FASTCALL */ MCDrvDummyDrvReadPixels (MCDSURFACE *pMcdSurface, MCDRC *pRc,
  1418. LONG x, LONG y, ULONG width, ULONG height, ULONG format,
  1419. ULONG type, VOID *pPixels)
  1420. {
  1421. MCDBG_PRINT( "MCDrvDummyDrvReadPixels\n");
  1422. return FALSE;
  1423. }
  1424. ULONG /* FASTCALL */ MCDrvDummyDrvCopyPixels (MCDSURFACE *pMcdSurface, MCDRC *pRc,
  1425. LONG x, LONG y, ULONG width, ULONG height, ULONG type)
  1426. {
  1427. MCDBG_PRINT( "MCDrvDummyDrvCopyPixels\n");
  1428. return FALSE;
  1429. }
  1430. ULONG /* FASTCALL */ MCDrvDummyDrvPixelMap (MCDSURFACE *pMcdSurface, MCDRC *pRc,
  1431. ULONG mapType, ULONG mapSize, VOID *pMap)
  1432. {
  1433. MCDBG_PRINT( "MCDrvDummyDrvPixelMap\n");
  1434. return FALSE;
  1435. }
  1436. #define RECORD_TEXTURE_STATE(pTexCtlBlk,pTexState) \
  1437. { \
  1438. pTexCtlBlk->dwTxCtlBits |= (pTexState->sWrapMode==GL_CLAMP) ? CLMCD_TEX_U_SATURATE : 0; \
  1439. pTexCtlBlk->dwTxCtlBits |= (pTexState->tWrapMode==GL_CLAMP) ? CLMCD_TEX_V_SATURATE : 0; \
  1440. /* caller verifies we're not mipmapping and sets up to punt if we are*/ \
  1441. /* MCD_NOTE: only 1 filter on Laguna, not min/mag, so set filter on if either on */ \
  1442. /* MCD_NOTE: may need to punt in case min!=mag for 100% compliance */ \
  1443. /* MCD_NOTE: MSFT said using LINEAR for both OK if 1 LINEAR, 1 NEAREST */ \
  1444. pTexCtlBlk->dwTxCtlBits |= (pTexState->minFilter==GL_LINEAR) ? CLMCD_TEX_FILTER : 0; \
  1445. pTexCtlBlk->dwTxCtlBits |= (pTexState->magFilter==GL_LINEAR) ? CLMCD_TEX_FILTER : 0; \
  1446. }
  1447. ULONG MCDrvCreateTexture(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc, MCDTEXTURE *pTex)
  1448. {
  1449. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  1450. DEVRC *pRc = (DEVRC *)pMCDRc->pvUser;
  1451. MCDMIPMAPLEVEL *level;
  1452. MCDTEXTURESTATE *pTexState;
  1453. LL_Texture *pTexCtlBlk;
  1454. SIZEL mapsize;
  1455. MCDFREE_PRINT("MCDrvCreateTexture");
  1456. // initialize to FAIL condition
  1457. pTex->textureKey = TEXTURE_NOT_LOADED;
  1458. VERIFY_TEXTUREDATA_ACCESSIBLE(pTex);
  1459. pTexState= (MCDTEXTURESTATE *)&pTex->pMCDTextureData->textureState;
  1460. VERIFY_TEXTURELEVEL_ACCESSIBLE(pTex);
  1461. level = pTex->pMCDTextureData->level;
  1462. if ((level[0].width != 0) && (level[0].height != 0) &&
  1463. (level[0].border == 0) && // punt if bordered
  1464. (level[0].widthImage <= 512) && (level[0].heightImage <= 512)) // punt if too big
  1465. {
  1466. MCDBG_PRINT_TEX("width, height = %ld %ld", level[0].width, level[0].height);
  1467. MCDBG_PRINT_TEX("internalFormat = 0x%08lx", level[0].internalFormat );
  1468. MCDBG_PRINT_TEX("\t%s",
  1469. (level[0].internalFormat == GL_ALPHA ) ? "GL_ALPHA " :
  1470. (level[0].internalFormat == GL_RGB ) ? "GL_RGB " :
  1471. (level[0].internalFormat == GL_RGBA ) ? "GL_RGBA " :
  1472. (level[0].internalFormat == GL_LUMINANCE ) ? "GL_LUMINANCE " :
  1473. (level[0].internalFormat == GL_LUMINANCE_ALPHA ) ? "GL_LUMINANCE_ALPHA " :
  1474. (level[0].internalFormat == GL_INTENSITY ) ? "GL_INTENSITY " :
  1475. (level[0].internalFormat == GL_BGR_EXT ) ? "GL_BGR_EXT " :
  1476. (level[0].internalFormat == GL_BGRA_EXT ) ? "GL_BGRA_EXT " :
  1477. (level[0].internalFormat == GL_COLOR_INDEX8_EXT ) ? "GL_COLOR_INDEX8_EXT " :
  1478. (level[0].internalFormat == GL_COLOR_INDEX16_EXT) ? "GL_COLOR_INDEX16_EXT" :
  1479. "unknown");
  1480. if ( !(pTexCtlBlk = (LL_Texture *)MCDAlloc(sizeof(LL_Texture))) )
  1481. {
  1482. MCDBG_PRINT(" create texture failed -> MCDAlloc of LL_Texture failed ");
  1483. return FALSE;
  1484. }
  1485. // add new texture control block to global list (visible to all contexts)
  1486. ppdev->pLastTexture->next = pTexCtlBlk;
  1487. pTexCtlBlk->prev = ppdev->pLastTexture;
  1488. pTexCtlBlk->next = NULL;
  1489. ppdev->pLastTexture = pTexCtlBlk;
  1490. pTexCtlBlk->pohTextureMap = NULL; // texture not loaded yet
  1491. pTexCtlBlk->bNegativeMap = FALSE; // set TRUE to load 1-R,1-G,1-B
  1492. pTexCtlBlk->bMasking = FALSE; // set TRUE to load in 1555 or 1888 mode for alphatest (masking)
  1493. pTexCtlBlk->pTex = pTex; // ptr to user's texture description
  1494. // give new texture highest priority
  1495. TIME_STAMP_TEXTURE(pRc,pTexCtlBlk);
  1496. // scale by priority - 1.0 is max, 0.0 is min
  1497. pTexCtlBlk->fLastDrvDraw *= pTex->pMCDTextureData->textureObjState.priority;
  1498. // set key MCD will use in MCDrvDraw to select this texture
  1499. pTex->textureKey = (ULONG)pTexCtlBlk;
  1500. pTexCtlBlk->dwTxCtlBits = 0;
  1501. RECORD_TEXTURE_STATE(pTexCtlBlk,pTexState)
  1502. // Store the texture properties in the fields
  1503. //
  1504. pTexCtlBlk->fWidth = (float)level[0].widthImage;
  1505. pTexCtlBlk->fHeight = (float)level[0].heightImage;
  1506. //pTexCtlBlk->bLookupOffset = 0;
  1507. // if texture has alpha, it needs to be used in alpha equation, as well as
  1508. // in generation of original source color - so really 2 levels of alpha equations
  1509. // HW only has 1 level, so must punt if blending on
  1510. if ( (level[0].internalFormat == GL_BGRA_EXT) ||
  1511. (level[0].internalFormat == GL_RGBA) ||
  1512. (level[0].internalFormat == GL_ALPHA) ||
  1513. (level[0].internalFormat == GL_INTENSITY) ||
  1514. (level[0].internalFormat == GL_LUMINANCE_ALPHA) )
  1515. pTexCtlBlk->bAlphaInTexture = TRUE;
  1516. else
  1517. pTexCtlBlk->bAlphaInTexture = FALSE;
  1518. if (level[0].widthImage >= 16)
  1519. {
  1520. pTexCtlBlk->bSizeMask = level[0].widthLog2-4; // convert 16->0, 32->1, etc...
  1521. mapsize.cx = level[0].widthImage;
  1522. }
  1523. else
  1524. {
  1525. // width < 16 - set it to 16 anyway, will stretch to 16 at end of this routine
  1526. pTexCtlBlk->bSizeMask = 0;
  1527. mapsize.cx = 16;
  1528. pTexCtlBlk->fWidth = (float)16.0;
  1529. }
  1530. if (level[0].heightImage >= 16)
  1531. {
  1532. pTexCtlBlk->bSizeMask |= (level[0].heightLog2-4)<<4; // convert 16->0, 32->1, etc...
  1533. mapsize.cy = level[0].heightImage;
  1534. }
  1535. else
  1536. {
  1537. // height < 16 - set it to 16 anyway, will stretch to 16 at end of this routine
  1538. // pTexCtlBlk->bSizeMask remains the same
  1539. mapsize.cy = 16;
  1540. pTexCtlBlk->fHeight = (float)16.0;
  1541. }
  1542. }
  1543. else
  1544. {
  1545. MCDBG_PRINT_TEX(" create texture failed -> some parm beyond hw caps, no attempt to alloc ");
  1546. MCDBG_PRINT_TEX(" width, height = %ld %ld", level[0].width, level[0].height);
  1547. MCDBG_PRINT_TEX(" border = %ld", level[0].border );
  1548. MCDBG_PRINT_TEX(" WILL ALLOC CTL BLOCK AND TAG AS BOGUS");
  1549. // allocate control block, but tag as bogus to force all MCDrvDraw's with this
  1550. // texture to punt.
  1551. // Apparently, failing CreateTexture can lead to a bug in MCD above the driver.
  1552. // It looks like when CreateTexture fails, MCD may send a key for a texture
  1553. // that was earlier deleted.
  1554. // Will fix this by never failing CreateTexture, but setting bogus condition
  1555. // so that we never render with it.
  1556. if ( !(pTexCtlBlk = (LL_Texture *)MCDAlloc(sizeof(LL_Texture))) )
  1557. {
  1558. MCDBG_PRINT(" create texture failed -> MCDAlloc of LL_Texture failed ");
  1559. return FALSE;
  1560. }
  1561. // add new texture control block to global list (visible to all contexts)
  1562. ppdev->pLastTexture->next = pTexCtlBlk;
  1563. pTexCtlBlk->prev = ppdev->pLastTexture;
  1564. pTexCtlBlk->next = NULL;
  1565. ppdev->pLastTexture = pTexCtlBlk;
  1566. pTexCtlBlk->dwTxCtlBits = CLMCD_TEX_BOGUS;
  1567. pTexCtlBlk->pohTextureMap = NULL; // texture not loaded yet
  1568. pTexCtlBlk->pTex = pTex; // ptr to user's texture description
  1569. // set key MCD will use in MCDrvDraw to select this texture
  1570. pTex->textureKey = (ULONG)pTexCtlBlk;
  1571. }
  1572. return TRUE;
  1573. }
  1574. ULONG MCDrvUpdateSubTexture(MCDSURFACE *pMCDSurface, MCDRC *pRc,
  1575. MCDTEXTURE *pTex, ULONG lod, RECTL *pRect)
  1576. {
  1577. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  1578. LL_Texture *pTexCtlBlk;
  1579. MCDBG_PRINT_TEX("MCDrvUpdateSubTexture");
  1580. CHK_TEX_KEY(pTex);
  1581. // simply free texture map - will force it to be reloaded before next use
  1582. //
  1583. if (pTex->textureKey != TEXTURE_NOT_LOADED)
  1584. {
  1585. pTexCtlBlk = (LL_Texture *)pTex->textureKey;
  1586. // free off screen memory allocated for texture, if texture currently loaded
  1587. if (pTexCtlBlk->pohTextureMap)
  1588. {
  1589. ppdev->pFreeOffScnMem(ppdev, pTexCtlBlk->pohTextureMap);
  1590. pTexCtlBlk->pohTextureMap = NULL;
  1591. }
  1592. }
  1593. return TRUE;
  1594. }
  1595. ULONG MCDrvUpdateTexturePalette(MCDSURFACE *pMCDSurface, MCDRC *pRc,
  1596. MCDTEXTURE *pTex, ULONG start,
  1597. ULONG numEntries)
  1598. {
  1599. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  1600. LL_Texture *pTexCtlBlk;
  1601. MCDBG_PRINT_TEX("MCDrvUpdateTexturePalette");
  1602. CHK_TEX_KEY(pTex);
  1603. VERIFY_TEXTUREDATA_ACCESSIBLE(pTex);
  1604. VERIFY_TEXTURELEVEL_ACCESSIBLE(pTex);
  1605. // make sure palette will be used before we trouble ourselves to take action
  1606. if ((pTex->pMCDTextureData->level->internalFormat==GL_COLOR_INDEX8_EXT) ||
  1607. (pTex->pMCDTextureData->level->internalFormat==GL_COLOR_INDEX16_EXT))
  1608. {
  1609. // simply free texture map - will force it to be reloaded before next use
  1610. // when reloaded, new palette will be used
  1611. if (pTex->textureKey != TEXTURE_NOT_LOADED)
  1612. {
  1613. pTexCtlBlk = (LL_Texture *)pTex->textureKey;
  1614. // free off screen memory allocated for texture, if texture currently loaded
  1615. if (pTexCtlBlk->pohTextureMap)
  1616. {
  1617. ppdev->pFreeOffScnMem(ppdev, pTexCtlBlk->pohTextureMap);
  1618. pTexCtlBlk->pohTextureMap = NULL;
  1619. }
  1620. }
  1621. }
  1622. return TRUE;
  1623. }
  1624. ULONG MCDrvUpdateTexturePriority(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc,
  1625. MCDTEXTURE *pTex)
  1626. {
  1627. LL_Texture *pTexCtlBlk;
  1628. DEVRC *pRc = pMCDRc->pvUser;
  1629. MCDBG_PRINT_TEX("MCDrvUpdateTexturePriority");
  1630. CHK_TEX_KEY(pTex);
  1631. VERIFY_TEXTUREDATA_ACCESSIBLE(pTex);
  1632. pTexCtlBlk = (LL_Texture *)pTex->textureKey;
  1633. // give new texture highest priority...
  1634. TIME_STAMP_TEXTURE(pRc,pTexCtlBlk);
  1635. // ....then scale by new priority - 1.0 is max, 0.0 is min
  1636. pTexCtlBlk->fLastDrvDraw *= pTex->pMCDTextureData->textureObjState.priority;
  1637. return TRUE;
  1638. }
  1639. ULONG MCDrvUpdateTextureState(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc,
  1640. MCDTEXTURE *pTex)
  1641. {
  1642. DEVRC *pRc = (DEVRC *)pMCDRc->pvUser;
  1643. LL_Texture *pTexCtlBlk;
  1644. MCDTEXTURESTATE *pTexState;
  1645. MCDBG_PRINT_TEX("MCDrvUpdateTextureState");
  1646. CHK_TEX_KEY(pTex);
  1647. VERIFY_TEXTUREDATA_ACCESSIBLE(pTex);
  1648. pTexCtlBlk = (LL_Texture *)pTex->textureKey;
  1649. pTexState = (MCDTEXTURESTATE *)&pTex->pMCDTextureData->textureState;
  1650. // turn off all control bits - while preserving the "bogus" indicator
  1651. pTexCtlBlk->dwTxCtlBits &= CLMCD_TEX_BOGUS;
  1652. RECORD_TEXTURE_STATE(pTexCtlBlk,pTexState)
  1653. // if last texture was this one, reset so next use will force regs to be reloaded
  1654. if ( pRc->pLastTexture==pTexCtlBlk ) pRc->pLastTexture=NULL;
  1655. return TRUE;
  1656. }
  1657. ULONG MCDrvTextureStatus(MCDSURFACE *pMCDSurface, MCDRC *pRc,
  1658. MCDTEXTURE *pTex)
  1659. {
  1660. MCDBG_PRINT_TEX("MCDrvTextureStatus");
  1661. CHK_TEX_KEY(pTex);
  1662. if (pTex->textureKey == TEXTURE_NOT_LOADED)
  1663. {
  1664. return FALSE;
  1665. }
  1666. else
  1667. {
  1668. return MCDRV_TEXTURE_RESIDENT;
  1669. }
  1670. }
  1671. ULONG MCDrvDeleteTexture(MCDTEXTURE *pTex, DHPDEV dhpdev)
  1672. {
  1673. PDEV *ppdev = (PDEV *)dhpdev;
  1674. LL_Texture *pTexCtlBlk;
  1675. MCDBG_PRINT_TEX("MCDrvDeleteTexture");
  1676. CHK_TEX_KEY(pTex);
  1677. MCDBG_PRINT(" key = %x " , pTex->textureKey);
  1678. if (pTex->textureKey != TEXTURE_NOT_LOADED)
  1679. {
  1680. pTexCtlBlk = (LL_Texture *)pTex->textureKey;
  1681. // free off screen memory allocated for texture, if texture currently loaded
  1682. if (pTexCtlBlk->pohTextureMap)
  1683. {
  1684. MCDFREE_PRINT(" MCDrvDeleteTexture, FREEING....size = %x by %x",
  1685. (LONG)pTexCtlBlk->fHeight,
  1686. (LONG)pTexCtlBlk->fWidth);
  1687. ppdev->pFreeOffScnMem(ppdev, pTexCtlBlk->pohTextureMap);
  1688. pTexCtlBlk->pohTextureMap = NULL;
  1689. }
  1690. // Remove from global list of texture control blocks...
  1691. //
  1692. // if there's not a next link, this is last one
  1693. if ( !pTexCtlBlk->next )
  1694. {
  1695. // this was last block, so now "prev" is last block
  1696. ppdev->pLastTexture = pTexCtlBlk->prev;
  1697. pTexCtlBlk->prev->next = NULL;
  1698. }
  1699. else
  1700. {
  1701. // there will always be a prev link for this block, and we now know
  1702. // there is a next block, so make "prev's" next point to what was
  1703. // this block's next;
  1704. pTexCtlBlk->prev->next = pTexCtlBlk->next;
  1705. // "next's" prev ptr pointed to this block, which is going away
  1706. // so make it point to this block's prev
  1707. pTexCtlBlk->next->prev = pTexCtlBlk->prev;
  1708. }
  1709. // set "bogus" bit before freeing, in case MCD tries to use key after delete
  1710. pTexCtlBlk->dwTxCtlBits = CLMCD_TEX_BOGUS;
  1711. // now discard the block
  1712. MCDFree((UCHAR *)pTexCtlBlk);
  1713. return TRUE;
  1714. }
  1715. else
  1716. {
  1717. return FALSE;
  1718. }
  1719. }
  1720. BOOL MCDrvGetEntryPoints(MCDSURFACE *pMCDSurface, MCDDRIVER *pMCDDriver)
  1721. {
  1722. MCDBG_PRINT( "MCDrvGetEntryPoints\n");
  1723. if (pMCDDriver->ulSize < sizeof(MCDDRIVER))
  1724. return FALSE;
  1725. // Required functions (always)
  1726. pMCDDriver->pMCDrvInfo = MCDrvInfo;
  1727. pMCDDriver->pMCDrvDescribePixelFormat = MCDrvDescribePixelFormat;
  1728. pMCDDriver->pMCDrvCreateContext = MCDrvCreateContext;
  1729. pMCDDriver->pMCDrvDeleteContext = MCDrvDeleteContext;
  1730. pMCDDriver->pMCDrvBindContext = MCDrvBindContext;
  1731. pMCDDriver->pMCDrvDraw = MCDrvDraw;
  1732. pMCDDriver->pMCDrvClear = MCDrvClear;
  1733. pMCDDriver->pMCDrvState = MCDrvState;
  1734. pMCDDriver->pMCDrvSpan = MCDrvSpan;
  1735. pMCDDriver->pMCDrvTrackWindow = MCDrvTrackWindow;
  1736. pMCDDriver->pMCDrvAllocBuffers = MCDrvAllocBuffers;
  1737. // Required for NT only
  1738. pMCDDriver->pMCDrvGetHdev = MCDrvGetHdev;
  1739. // Required functions (conditionally)
  1740. // required for double-buffered pixel formats
  1741. pMCDDriver->pMCDrvSwap = MCDrvSwap;
  1742. // required for clipping
  1743. pMCDDriver->pMCDrvViewport = MCDrvViewport;
  1744. // Optional functions
  1745. // if no entry for MCDrvDescribeLayerPlane, MCD will not call driver for layer plane stuff
  1746. // pMCDDriver->pMCDrvSetLayerPalette = MCDrvSetLayerPalette;
  1747. // pMCDDriver->pMCDrvDescribeLayerPlane = MCDrvDescribeLayerPlane;
  1748. pMCDDriver->pMCDrvCreateMem = MCDrvCreateMem;
  1749. pMCDDriver->pMCDrvDeleteMem = MCDrvDeleteMem;
  1750. pMCDDriver->pMCDrvGetBuffers = MCDrvGetBuffers;
  1751. pMCDDriver->pMCDrvSync = MCDrvSync;
  1752. pMCDDriver->pMCDrvCreateTexture = MCDrvCreateTexture;
  1753. pMCDDriver->pMCDrvDeleteTexture = MCDrvDeleteTexture;
  1754. pMCDDriver->pMCDrvUpdateSubTexture = MCDrvUpdateSubTexture;
  1755. pMCDDriver->pMCDrvUpdateTexturePalette = MCDrvUpdateTexturePalette;
  1756. pMCDDriver->pMCDrvUpdateTexturePriority = MCDrvUpdateTexturePriority;
  1757. pMCDDriver->pMCDrvUpdateTextureState = MCDrvUpdateTextureState;
  1758. pMCDDriver->pMCDrvTextureStatus = MCDrvTextureStatus;
  1759. // pMCDDriver->pMCDrvDrawPixels = MCDrvDummyDrvDrawPixels;
  1760. // pMCDDriver->pMCDrvReadPixels = MCDrvDummyDrvReadPixels;
  1761. // pMCDDriver->pMCDrvCopyPixels = MCDrvDummyDrvCopyPixels;
  1762. // pMCDDriver->pMCDrvPixelMap = MCDrvDummyDrvPixelMap;
  1763. return TRUE;
  1764. }