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.

988 lines
42 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: mcdutil.h
  3. *
  4. * Include file which indirects all of the hardware-dependent functionality
  5. * in the MCD driver code.
  6. *
  7. * Copyright (c) 1996 Microsoft Corporation
  8. * Copyright (c) 1997 Cirrus Logic, Inc.
  9. \**************************************************************************/
  10. #ifndef _MCDUTIL_H
  11. #define _MCDUTIL_H
  12. #include <gl\gl.h>
  13. VOID MCDrvDebugPrint(char *, ...);
  14. #if DBG // this is defined in \ddk\inc\makefile.def
  15. UCHAR *MCDDbgAlloc(UINT);
  16. VOID MCDDbgFree(UCHAR *);
  17. #define MCDAlloc MCDDbgAlloc
  18. #define MCDFree MCDDbgFree
  19. #define MCDBG_PRINT MCDrvDebugPrint
  20. //#define MCDBG_PRINT
  21. #define MCDFREE_PRINT MCDrvDebugPrint
  22. //#define MCDFREE_PRINT
  23. #else
  24. UCHAR *MCDAlloc(UINT);
  25. VOID MCDFree(UCHAR *);
  26. #define MCDBG_PRINT
  27. //#define MCDFREE_PRINT MCDrvDebugPrint
  28. #define MCDFREE_PRINT
  29. #endif
  30. //#define MCDFORCE_PRINT MCDrvDebugPrint
  31. #define MCDFORCE_PRINT
  32. #define MCD_CHECK_RC(pRc)\
  33. if (pRc == NULL) {\
  34. MCDBG_PRINT("NULL device RC");\
  35. return FALSE;\
  36. }
  37. #define MCD_CHECK_BUFFERS_VALID(pMCDSurface, pRc, resChangedRet)\
  38. {\
  39. DEVWND *pDevWnd = (DEVWND *)pMCDSurface->pWnd->pvUser;\
  40. \
  41. if (!pDevWnd) {\
  42. MCDBG_PRINT("HW_CHECK_BUFFERS_VALID: NULL buffers");\
  43. return FALSE;\
  44. }\
  45. \
  46. if ((pRc->backBufEnabled) &&\
  47. (!pDevWnd->bValidBackBuffer)) {\
  48. MCDBG_PRINT("HW_CHECK_BUFFERS_VALID: back buffer invalid");\
  49. return FALSE;\
  50. }\
  51. \
  52. if ((pRc->zBufEnabled) &&\
  53. (!pDevWnd->bValidZBuffer)) {\
  54. MCDBG_PRINT("HW_CHECK_BUFFERS_VALID: z buffer invalid");\
  55. return FALSE;\
  56. }\
  57. \
  58. if (pDevWnd->dispUnique != GetDisplayUniqueness((PDEV *)pMCDSurface->pso->dhpdev)) {\
  59. MCDBG_PRINT("HW_CHECK_BUFFERS_VALID: resolution changed but not updated");\
  60. return resChangedRet;\
  61. }\
  62. }
  63. #define CHK_TEX_KEY(pTex); \
  64. if(pTex == NULL) { \
  65. MCDBG_PRINT("CHK_TEX_KEY:Attempted to update a null texture"); \
  66. return FALSE; \
  67. } \
  68. \
  69. if(pTex->textureKey == 0) { \
  70. MCDBG_PRINT("CHK_TEX_KEY:Attempted to update a null device texture");\
  71. return FALSE; \
  72. }
  73. BOOL HWAllocResources(MCDWINDOW *pMCDWnd, SURFOBJ *pso, BOOL zEnabled,
  74. BOOL backBufferEnabled);
  75. VOID HWFreeResources(MCDWINDOW *pMCDWnd, SURFOBJ *pso);
  76. VOID HWUpdateBufferPos(MCDWINDOW *pMCDWnd, SURFOBJ *pso, BOOL bForce);
  77. ULONG __MCDLoadTexture(PDEV *ppdev, DEVRC *pRc);
  78. POFMHDL __MCDForceTexture (PDEV *ppdev, SIZEL *mapsize, int alignflag, float priority);
  79. VOID ContextSwitch(DEVRC *pRc);
  80. // simple wait added for 546x
  81. __inline void WAIT_HW_IDLE(PDEV *ppdev)
  82. {
  83. int status;
  84. volatile int wait_count=0;
  85. do
  86. {
  87. status = (*((volatile *)((DWORD *)(ppdev->pLgREGS) + PF_STATUS_3D)) & 0x3FF) ^ 0x3E0;
  88. // do something to give bus a breather
  89. wait_count++;
  90. } while((status & 0x3e0) != 0x3e0);
  91. }
  92. // From Tim McDonald concerning bits in status register, and checking that 2D is idle
  93. // execution engine - 3d only, says poly is being assembled
  94. // cmd fifo - could have 2d command about to be sent to 2d engine, so must be empty
  95. // 2d engine - must be idle
  96. // see include\laguna.h for MACRO display driver uses to make sure 3D idle before starting 2D
  97. //#define WAIT_2D_STATUS_MASK 0x3e0 // wait for everything to stop
  98. #define WAIT_2D_STATUS_MASK 0x300 // wait for 2D(BLT) engine to idle and CMD fifo to drain
  99. // wait for 2D operations to end
  100. __inline void WAIT_2D_IDLE(PDEV *ppdev)
  101. {
  102. int status;
  103. volatile int wait_count=0;
  104. do
  105. {
  106. status = (*((volatile *)((DWORD *)(ppdev->pLgREGS) + PF_STATUS_3D)) & 0x3FF) ^ WAIT_2D_STATUS_MASK;
  107. // do something to give bus a breather
  108. wait_count++;
  109. } while((status & WAIT_2D_STATUS_MASK) != WAIT_2D_STATUS_MASK);
  110. }
  111. __inline void HW_WAIT_DRAWING_DONE(DEVRC *pRc)
  112. {
  113. // MCD_NOTE just waits for all engines to stop...need to change for displists
  114. WAIT_HW_IDLE (pRc->ppdev);
  115. }
  116. __inline void HW_INIT_DRAWING_STATE(MCDSURFACE *pMCDSurface, MCDWINDOW *pMCDWnd,
  117. DEVRC *pRc)
  118. {
  119. DEVWND *pDevWnd = (DEVWND *)pMCDWnd->pvUser;
  120. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  121. DWORD *pdwNext= ppdev->LL_State.pDL->pdwNext;
  122. union {
  123. TBase0Reg Base0;
  124. DWORD dwBase0;
  125. }b0;
  126. union {
  127. TBase1Reg Base1;
  128. DWORD dwBase1;
  129. }b1;
  130. b0.dwBase0 = pDevWnd->dwBase0;
  131. b1.dwBase1 = pDevWnd->dwBase1;
  132. // if window changed, or if double buffered, but drawing to front,
  133. // set base addresses for current window
  134. /* since can have case of GL_FRONT, followed by GL_BACK, may need to reset for either case
  135. * instead of testing, just set regs since tests as expensive as blind set (?) */
  136. /*
  137. if (pRc->pLastDevWnd != pDevWnd ||
  138. ((pRc->MCDState.drawBuffer == GL_FRONT) && pDevWnd->pohBackBuffer) )
  139. */
  140. {
  141. if ((pRc->MCDState.drawBuffer == GL_FRONT) && pDevWnd->pohBackBuffer)
  142. {
  143. // if double buffered window, pDevWnd->base0 and base1 always set for
  144. // draw to back - override that here
  145. b1.Base1.Color_Buffer_Y_Offset = 0;
  146. b0.Base0.Color_Buffer_X_Offset = 0;
  147. }
  148. *pdwNext++ = write_register( BASE0_ADDR_3D, 2 );
  149. *pdwNext++ = b0.dwBase0;
  150. *pdwNext++ = b1.dwBase1;
  151. ppdev->LL_State.pDL->pdwNext = pdwNext;
  152. pRc->pLastDevWnd = pDevWnd;
  153. }
  154. // adjust pattern offset if stipple active and window has moved
  155. if (pRc->privateEnables & __MCDENABLE_PG_STIPPLE)
  156. {
  157. if ((b0.Base0.Pattern_Y_Offset != (DWORD)(16-(pMCDSurface->pWnd->clientRect.top & 0xf) & 0xf)) ||
  158. (b0.Base0.Pattern_X_Offset != (DWORD)(16-(pMCDSurface->pWnd->clientRect.left & 0xf) & 0xf)) )
  159. {
  160. b0.Base0.Pattern_Y_Offset = 16-(pMCDSurface->pWnd->clientRect.top & 0xf) & 0xf;
  161. b0.Base0.Pattern_X_Offset = 16-(pMCDSurface->pWnd->clientRect.left & 0xf) & 0xf;
  162. *pdwNext++ = write_register( BASE0_ADDR_3D, 1 );
  163. *pdwNext++ = b0.dwBase0;
  164. ppdev->LL_State.pDL->pdwNext = pdwNext;
  165. }
  166. }
  167. if (!(pRc->privateEnables & (__MCDENABLE_PG_STIPPLE|__MCDENABLE_LINE_STIPPLE)) &&
  168. (pRc->privateEnables & __MCDENABLE_DITHER))
  169. {
  170. // dither active - check if dither pattern needs to be adjusted
  171. // Must keep pattern relative to x mod 4 = 0, y mod 4 = 0 for consistency
  172. // Windowed draw buffers start at x=y=0. FullScreen buffers start at arbitrary
  173. // window offset - so must adjust dither pattern for these cases
  174. // (which means we may need to "un-adjust" for windowed buffer)
  175. int windowed_buffer =
  176. ((pRc->MCDState.drawBuffer==GL_BACK) && (ppdev->pohBackBuffer!=pDevWnd->pohBackBuffer)) ? TRUE : FALSE;
  177. if ( (!windowed_buffer && // need to adjust???
  178. ((pMCDSurface->pWnd->clientRect.left & 0x3) != ppdev->LL_State.dither_x_offset) ||
  179. ((pMCDSurface->pWnd->clientRect.top & 0x3) != ppdev->LL_State.dither_y_offset) )
  180. ||
  181. (windowed_buffer && // need to un-adjust???
  182. (ppdev->LL_State.dither_x_offset || ppdev->LL_State.dither_y_offset))
  183. )
  184. {
  185. if (windowed_buffer)
  186. {
  187. // load default dither pattern
  188. ppdev->LL_State.dither_array.pat[0] = ppdev->LL_State.dither_array.pat[4] = 0x04150415;
  189. ppdev->LL_State.dither_array.pat[1] = ppdev->LL_State.dither_array.pat[5] = 0x62736273;
  190. ppdev->LL_State.dither_array.pat[2] = ppdev->LL_State.dither_array.pat[6] = 0x15041504;
  191. ppdev->LL_State.dither_array.pat[3] = ppdev->LL_State.dither_array.pat[7] = 0x73627362;
  192. ppdev->LL_State.dither_x_offset = ppdev->LL_State.dither_y_offset = 0;
  193. }
  194. else
  195. {
  196. // adjustment required
  197. int offset;
  198. // adjust columns for X first...
  199. offset = pMCDSurface->pWnd->clientRect.left & 0x3; // number of x positions
  200. offset *= 4; // 4 bits per x position
  201. ppdev->LL_State.dither_array.pat[0] = (0x04150415)>>offset;
  202. ppdev->LL_State.dither_array.pat[0] |= ((0x0415) & (0xFFFF>>(16-offset))) << (32 - offset);
  203. ppdev->LL_State.dither_array.pat[1] = (0x62736273)>>offset;
  204. ppdev->LL_State.dither_array.pat[1] |= ((0x6273) & (0xFFFF>>(16-offset))) << (32 - offset);
  205. ppdev->LL_State.dither_array.pat[2] = (0x15041504)>>offset;
  206. ppdev->LL_State.dither_array.pat[2] |= ((0x1504) & (0xFFFF>>(16-offset))) << (32 - offset);
  207. ppdev->LL_State.dither_array.pat[3] = (0x73627362)>>offset;
  208. ppdev->LL_State.dither_array.pat[3] |= ((0x7362) & (0xFFFF>>(16-offset))) << (32 - offset);
  209. // now adjust rows for y
  210. // copy adjusted row to second half of pattern (which HW sees as repeat of first half)
  211. switch (pMCDSurface->pWnd->clientRect.top & 0x3)
  212. {
  213. case 0:
  214. ppdev->LL_State.dither_array.pat[4] = ppdev->LL_State.dither_array.pat[0];
  215. ppdev->LL_State.dither_array.pat[5] = ppdev->LL_State.dither_array.pat[1];
  216. ppdev->LL_State.dither_array.pat[6] = ppdev->LL_State.dither_array.pat[2];
  217. ppdev->LL_State.dither_array.pat[7] = ppdev->LL_State.dither_array.pat[3];
  218. break;
  219. case 1:
  220. ppdev->LL_State.dither_array.pat[4] = ppdev->LL_State.dither_array.pat[3];
  221. ppdev->LL_State.dither_array.pat[5] = ppdev->LL_State.dither_array.pat[0];
  222. ppdev->LL_State.dither_array.pat[6] = ppdev->LL_State.dither_array.pat[1];
  223. ppdev->LL_State.dither_array.pat[7] = ppdev->LL_State.dither_array.pat[2];
  224. break;
  225. case 2:
  226. ppdev->LL_State.dither_array.pat[4] = ppdev->LL_State.dither_array.pat[2];
  227. ppdev->LL_State.dither_array.pat[5] = ppdev->LL_State.dither_array.pat[3];
  228. ppdev->LL_State.dither_array.pat[6] = ppdev->LL_State.dither_array.pat[0];
  229. ppdev->LL_State.dither_array.pat[7] = ppdev->LL_State.dither_array.pat[1];
  230. break;
  231. case 3:
  232. ppdev->LL_State.dither_array.pat[4] = ppdev->LL_State.dither_array.pat[1];
  233. ppdev->LL_State.dither_array.pat[5] = ppdev->LL_State.dither_array.pat[2];
  234. ppdev->LL_State.dither_array.pat[6] = ppdev->LL_State.dither_array.pat[3];
  235. ppdev->LL_State.dither_array.pat[7] = ppdev->LL_State.dither_array.pat[0];
  236. break;
  237. }
  238. // copied adjusted pattern back to first 4 row
  239. ppdev->LL_State.dither_array.pat[0] = ppdev->LL_State.dither_array.pat[4];
  240. ppdev->LL_State.dither_array.pat[1] = ppdev->LL_State.dither_array.pat[5];
  241. ppdev->LL_State.dither_array.pat[2] = ppdev->LL_State.dither_array.pat[6];
  242. ppdev->LL_State.dither_array.pat[3] = ppdev->LL_State.dither_array.pat[7];
  243. ppdev->LL_State.dither_x_offset = pMCDSurface->pWnd->clientRect.left & 0x3;
  244. ppdev->LL_State.dither_y_offset = pMCDSurface->pWnd->clientRect.top & 0x3;
  245. }
  246. // force adjusted pattern to be loaded before use
  247. ppdev->LL_State.pattern_ram_state = PATTERN_RAM_INVALID;
  248. }
  249. }
  250. // Make sure 2D engine idle before continuing w/ 3D operations
  251. WAIT_2D_IDLE(ppdev);
  252. }
  253. __inline void HW_FILL_RECT(MCDSURFACE *pMCDSurface, DEVRC *pRc, RECTL *pRecl, ULONG buffers)
  254. {
  255. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  256. WORD FillValue;
  257. DEVWND *pDevWnd = (DEVWND *)(pMCDSurface->pWnd->pvUser);
  258. DWORD *pdwNext = ppdev->LL_State.pDL->pdwNext;
  259. DWORD bltdef = 0x1070;
  260. DWORD drawdef = 0x00cc;
  261. DWORD blt_x;
  262. DWORD blt_y;
  263. DWORD ext_x;
  264. DWORD ext_y;
  265. WORD color_l;
  266. WORD color_h;
  267. MCDBG_PRINT("fill rect = %d, %d, %d, %d", pRecl->left,
  268. pRecl->top,
  269. pRecl->right,
  270. pRecl->bottom);
  271. // Since not much setup per blit, all work done here, rather than some in HW_START_FILL_RECT
  272. if ((buffers & GL_DEPTH_BUFFER_BIT) && pRc->MCDState.depthWritemask)
  273. {
  274. MCDBG_PRINT("Z fill rect");
  275. // calculate blt info in the y-dimension, which is constant regardless of pixel-depth
  276. // see mcd.c near line 525 for more hints on z buffer location
  277. blt_y = pRecl->top + pDevWnd->pohZBuffer->aligned_y;
  278. ext_y = pRecl->bottom - pRecl->top + 1;
  279. // QST: always 16bits (2 bytes) per pixel for z?? - z fill macro assumes so
  280. // Z buffer always starts at 0 x offset
  281. blt_x = pRecl->left * 2;
  282. ext_x = (pRecl->right - pRecl->left + 1) * 2;
  283. if (ppdev->pohZBuffer != pDevWnd->pohZBuffer)
  284. {
  285. // Z buffer is window size only, so remove client rectangle origin
  286. blt_y -= pMCDSurface->pWnd->clientRect.top;
  287. blt_x -= pMCDSurface->pWnd->clientRect.left*2;
  288. }
  289. FillValue = (WORD)(pRc->MCDState.depthClearValue);
  290. *pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
  291. *pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
  292. // check for blackness fill: don't need to set bg color
  293. if (FillValue == 0)
  294. {
  295. bltdef = 0x1101;
  296. drawdef = 0x0000;
  297. *pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 4, 0);
  298. }
  299. else
  300. {
  301. // break bg color into low and high for stuffing command register
  302. color_h = FillValue;
  303. color_l = FillValue;
  304. // set up to write the 2d command register
  305. *pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 6, 0);
  306. *pdwNext++ = C_BG_L << 16 | color_l; // bgcolor l
  307. *pdwNext++ = C_BG_H << 16 | color_h; // bgcolor h
  308. ppdev->shadowBGCOLOR = 0xDEADBEEF;
  309. }
  310. // burst the blt data to the 2d command register
  311. *pdwNext++ = C_BLTDEF << 16 | bltdef; // set bltdef register
  312. *pdwNext++ = C_DRWDEF << 16 | drawdef; // set drawdef register
  313. ppdev->shadowDRAWBLTDEF = 0xDEADBEEF;
  314. *pdwNext++ = C_MRX_0 << 16 | blt_x; // x location: use byte pointer
  315. *pdwNext++ = C_MRY_0 << 16 | blt_y; // y location: use byte pointer
  316. // launch the blt by writing the extents
  317. *pdwNext++ = write_dev_regs(DEV_ENG2D, 0, L2D_MBLTEXT_EX, 1, 0); // note pixel ptr
  318. *pdwNext++ = ext_y << 16 | ext_x;
  319. *pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
  320. } // end Z clear
  321. if (buffers & GL_COLOR_BUFFER_BIT)
  322. {
  323. RGBACOLOR scaledcolor;
  324. DWORD color;
  325. MCDBG_PRINT("colorbuf fill rect");
  326. // calculate blt info in the y-dimension, which is constant regardless of pixel-depth
  327. blt_y = pRecl->top;
  328. if ((pRc->MCDState.drawBuffer != GL_FRONT) && pRc->backBufEnabled)
  329. blt_y += pDevWnd->pohBackBuffer->aligned_y;
  330. ext_y = pRecl->bottom - pRecl->top + 1;
  331. // these are x y coordinates - hw converts to proper byte-equivalent locations
  332. blt_x = pRecl->left;
  333. ext_x = (pRecl->right - pRecl->left + 1);
  334. if ((pRc->MCDState.drawBuffer != GL_FRONT) && pRc->backBufEnabled)
  335. {
  336. // back buffer not necessarily at 0 x offset
  337. blt_x += pDevWnd->pohBackBuffer->aligned_x / ppdev->iBytesPerPixel;
  338. if (ppdev->pohBackBuffer != pDevWnd->pohBackBuffer)
  339. {
  340. // Back buffer is window size only, so remove client rectangle origin
  341. blt_y -= pMCDSurface->pWnd->clientRect.top;
  342. blt_x -= pMCDSurface->pWnd->clientRect.left;
  343. }
  344. }
  345. *pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
  346. *pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
  347. // macro converts components to 8.16 format
  348. MCDFIXEDRGB(scaledcolor, pRc->MCDState.colorClearValue);
  349. switch( ppdev->iBitmapFormat )
  350. {
  351. case BMF_8BPP:
  352. color =((scaledcolor.r & 0xe00000) >> 16) | // 3 significant bits, shifted to bits 7 6 5
  353. ((scaledcolor.g & 0xe00000) >> 16+3) | // 3 significant bits, shifted to bits 4 3 2
  354. ((scaledcolor.b & 0xc00000) >> 16+3+3); // 2 significant bits, shifted to bits 1 0
  355. // duplicate the 8-bit color value as a full 32-bit dword
  356. color = color | (color << 8) | (color << 16) | (color << 24);
  357. break;
  358. case BMF_16BPP:
  359. color =((scaledcolor.r & 0xf80000) >> 8) | // 5 significant bits, shifted to bits 15 - 11
  360. ((scaledcolor.g & 0xfc0000) >> 8+5) | // 6 significant bits, shifted to bits 10 - 5
  361. ((scaledcolor.b & 0xf80000) >> 8+5+6); // 5 significant bits, shifted to bits 4 - 0
  362. // duplicate the 16-bit color value as a full 32-bit dword
  363. color = color | (color << 16);
  364. break;
  365. case BMF_24BPP:
  366. case BMF_32BPP:
  367. color = (scaledcolor.r & 0xff0000) | // 8 significant bits
  368. ((scaledcolor.g & 0xff0000) >> 8) | // 8 significant bits, shifted to bits 15 - 8
  369. ((scaledcolor.b & 0xff0000) >> 16); // 8 significant bits, shifted to bits 7 - 0
  370. break;
  371. }
  372. // break bg color into low and high for stuffing command register
  373. color_h = (0xffff0000 & color) >> 16;
  374. color_l = (WORD)(0x0000ffff & color);
  375. *pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 2, 0);
  376. *pdwNext++ = C_BG_L << 16 | color_l; // bgcolor l
  377. *pdwNext++ = C_BG_H << 16 | color_h; // bgcolor h
  378. ppdev->shadowBGCOLOR = 0xDEADBEEF;
  379. // burst blt data to 2d command register
  380. *pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 4, 0);
  381. *pdwNext++ = C_BLTDEF << 16 | bltdef;
  382. *pdwNext++ = C_DRWDEF << 16 | drawdef;
  383. ppdev->shadowDRAWBLTDEF = 0xDEADBEEF;
  384. *pdwNext++ = C_RX_0 << 16 | blt_x; // x location
  385. *pdwNext++ = C_RY_0 << 16 | blt_y; // y location
  386. // launch the blt by writing the extents
  387. *pdwNext++ = write_dev_regs(DEV_ENG2D, 0, L2D_BLTEXT_EX, 1, 0);
  388. *pdwNext++ = ext_y << 16 | ext_x;
  389. // wait for everything to quit
  390. *pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
  391. }
  392. // send data to hardware
  393. if (pdwNext != ppdev->LL_State.pDL->pdwNext) _RunLaguna(ppdev,pdwNext);
  394. }
  395. __inline void HW_COPY_RECT(MCDSURFACE *pMCDSurface, RECTL *pRecl)
  396. {
  397. PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
  398. ULONG FillValue;
  399. DEVWND *pDevWnd = (DEVWND *)(pMCDSurface->pWnd->pvUser);
  400. DWORD *pdwNext = ppdev->LL_State.pDL->pdwNext;
  401. DWORD src_x=0, src_y=0;
  402. DWORD dst_x=0, dst_y=0;
  403. DWORD ext_x=0, ext_y=0;
  404. DWORD bltdef=0;
  405. MCDBG_PRINT("copy rect = %d, %d, %d, %d", pRecl->left,
  406. pRecl->top,
  407. pRecl->right,
  408. pRecl->bottom);
  409. {
  410. RGBACOLOR scaledcolor;
  411. DWORD color;
  412. // calculate blt info in the y-dimension, which is constant regardless of pixel-depth
  413. dst_y = pRecl->top;
  414. src_y = dst_y + pDevWnd->pohBackBuffer->aligned_y;
  415. ext_y = pRecl->bottom - pRecl->top;
  416. // these are x y coordinates - hw converts to proper byte-equivalent locations
  417. dst_x = pRecl->left;
  418. // back buffer may be at same y loc's as front, but offset to right
  419. src_x = dst_x + (pDevWnd->pohBackBuffer->aligned_x / ppdev->iBytesPerPixel);
  420. ext_x = pRecl->right - pRecl->left;
  421. if (ppdev->pohBackBuffer != pDevWnd->pohBackBuffer)
  422. {
  423. // back buffer is window size only, so remove client rectangle origin
  424. // front buffer is always relative to screen origin, so leave dest alone
  425. src_y -= pMCDSurface->pWnd->clientRect.top;
  426. src_x -= pMCDSurface->pWnd->clientRect.left;
  427. }
  428. *pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
  429. *pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
  430. // program frame->frame blt
  431. bltdef |= 0x1010;
  432. // set up blitter: check for display list
  433. #if DRIVER_5465 // C_BLTX moved between 64 and 65, so converted to write extents more like fill proc
  434. // leaving old code for 5464 - even though never enable on real product
  435. *pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 6, 0);
  436. *pdwNext++ = C_BLTDEF << 16 | bltdef; // set bltdef register
  437. *pdwNext++ = C_DRWDEF << 16 | 0x00cc; // set drawdef register
  438. ppdev->shadowDRAWBLTDEF = 0xDEADBEEF;
  439. *pdwNext++ = C_RX_1 << 16 | src_x; // use PIXEL pointer for source x
  440. *pdwNext++ = C_RY_1 << 16 | src_y; // use PIXEL pointer for source y
  441. *pdwNext++ = C_RX_0 << 16 | dst_x; // set dest x always as pixel ptr
  442. *pdwNext++ = C_RY_0 << 16 | dst_y; // set dest y always as pixel ptr
  443. // launch the blt by writing the extents
  444. *pdwNext++ = write_dev_regs(DEV_ENG2D, 0, L2D_BLTEXT_EX, 1, 0);
  445. *pdwNext++ = ext_y << 16 | ext_x;
  446. #else
  447. *pdwNext++ = write_dev_regs(DEV_ENG2D, 0, COMMAND_2D, 9, 0);
  448. *pdwNext++ = C_BLTDEF << 16 | bltdef; // set bltdef register
  449. *pdwNext++ = C_DRWDEF << 16 | 0x00cc; // set drawdef register
  450. ppdev->shadowDRAWBLTDEF = 0xDEADBEEF;
  451. *pdwNext++ = C_RX_1 << 16 | src_x; // use PIXEL pointer for source x
  452. *pdwNext++ = C_RY_1 << 16 | src_y; // use PIXEL pointer for source y
  453. *pdwNext++ = C_RX_0 << 16 | dst_x; // set dest x always as pixel ptr
  454. *pdwNext++ = C_RY_0 << 16 | dst_y; // set dest y always as pixel ptr
  455. *pdwNext++ = C_BLTX << 16 | ext_x; // set x extent
  456. *pdwNext++ = C_BLTY << 16 | ext_y; // set y extent
  457. *pdwNext++ = C_EX_BLT << 16 | 0; // execute the blt
  458. #endif
  459. // wait for everything to quit
  460. *pdwNext++ = 0x720003e0; // wait_3d(0x3e0, 0);
  461. }
  462. // send data to hardware
  463. _RunLaguna(ppdev,pdwNext);
  464. }
  465. __inline int __MCDSetTextureRegisters(DEVRC *pRc)
  466. {
  467. PDEV *ppdev = pRc->ppdev;
  468. unsigned int *pdwNext = ppdev->LL_State.pDL->pdwNext;
  469. LL_Texture *pTex;
  470. int control0_set=FALSE;
  471. union {
  472. TTxCtl0Reg TxControl0; // Tx_Ctl0_3D temp register
  473. DWORD dwTxControl0;
  474. } Tx;
  475. // Set the texture control register with the texture information - start
  476. // with the cleared register and build up info as needed
  477. //
  478. Tx.dwTxControl0 = pRc->dwTxControl0 & ~0x00640FFF;
  479. pTex = pRc->pLastTexture;
  480. // punt if clamp and linear filtering - in this case, BorderColor should be
  481. // used for blend with portion where clamp is in effect, but 5465/5466/5468 has no
  482. // support for border colors
  483. if ( ((pTex->dwTxCtlBits & (CLMCD_TEX_U_SATURATE|CLMCD_TEX_FILTER)) == (CLMCD_TEX_U_SATURATE|CLMCD_TEX_FILTER)) ||
  484. ((pTex->dwTxCtlBits & (CLMCD_TEX_V_SATURATE|CLMCD_TEX_FILTER)) == (CLMCD_TEX_V_SATURATE|CLMCD_TEX_FILTER)) )
  485. {
  486. return (FALSE);
  487. }
  488. //MCD_NOTE2: for true Compliance, don't define TREAT_DECAL_LIKE_REPLACE and DONT_PUNT_MODULATE_W_BLEND
  489. //MCD_NOTE2: below. However, without DONT_PUNT_MODULATE_W_BLEND defined, GLQuake
  490. //MCD_NOTE2: punts the "sparkly chaff" textures.
  491. // When DECAL with RGBA texture and BLEND active, theoretically, we should punt,
  492. // but recall Microsoft's behavior on tlogo:
  493. // - it looked like they treat DECAL like REPLACE in case of RGBA textures,
  494. // so let's do same
  495. //#define TREAT_DECAL_LIKE_REPLACE
  496. // GLQuake using GL_MODULATE, with RGBA textures, with lots of blending
  497. #define DONT_PUNT_MODULATE_W_BLEND
  498. // determine if texture format requires blend capability hw doesn't have
  499. if ( (pRc->privateEnables & (__MCDENABLE_BLEND|__MCDENABLE_FOG)) &&
  500. pTex->bAlphaInTexture &&
  501. #ifndef TREAT_DECAL_LIKE_REPLACE
  502. #ifndef DONT_PUNT_MODULATE_W_BLEND
  503. (pRc->MCDTexEnvState.texEnvMode != GL_REPLACE) )
  504. #else // ndef DONT_PUNT_MODULATE_W_BLEND
  505. (pRc->MCDTexEnvState.texEnvMode != GL_REPLACE) &&
  506. (pRc->MCDTexEnvState.texEnvMode != GL_MODULATE) )
  507. #endif // DONT_PUNT_MODULATE_W_BLEND
  508. #else
  509. (pRc->MCDTexEnvState.texEnvMode != GL_REPLACE) &&
  510. #ifdef DONT_PUNT_MODULATE_W_BLEND
  511. (pRc->MCDTexEnvState.texEnvMode != GL_MODULATE) &&
  512. #endif // ndef DONT_PUNT_MODULATE_W_BLEND
  513. (pRc->MCDTexEnvState.texEnvMode != GL_DECAL) )
  514. #endif
  515. {
  516. return (FALSE);
  517. }
  518. #ifndef TREAT_DECAL_LIKE_REPLACE
  519. if ((pRc->MCDTexEnvState.texEnvMode == GL_DECAL) && pTex->bAlphaInTexture )
  520. {
  521. // decal mode and texture has RGBA or BGRA
  522. // will use alpha circuit for blending texel with polyeng, using alpha in texture
  523. if( pRc->Control0.Alpha_Mode != LL_ALPHA_TEXTURE )
  524. {
  525. pRc->Control0.Alpha_Mode = LL_ALPHA_TEXTURE;
  526. control0_set=TRUE;
  527. }
  528. if( pRc->Control0.Alpha_Dest_Color_Sel != LL_ALPHA_DEST_INTERP )
  529. {
  530. pRc->Control0.Alpha_Dest_Color_Sel = LL_ALPHA_DEST_INTERP;
  531. control0_set=TRUE;
  532. }
  533. if (!pRc->Control0.Alpha_Blending_Enable)
  534. {
  535. pRc->Control0.Alpha_Blending_Enable = TRUE;
  536. control0_set=TRUE;
  537. }
  538. }
  539. #endif
  540. // decal mode without alpha in texture, or replace mode - set alpha regs back for "normal" use
  541. // (previous primitive may have used alpha regs for decal w/ alpha)
  542. #ifndef TREAT_DECAL_LIKE_REPLACE
  543. if ( ((pRc->MCDTexEnvState.texEnvMode == GL_DECAL) && !pTex->bAlphaInTexture) ||
  544. #else
  545. if ( ((pRc->MCDTexEnvState.texEnvMode == GL_DECAL)) ||
  546. #endif
  547. #ifdef DONT_PUNT_MODULATE_W_BLEND
  548. (pRc->MCDTexEnvState.texEnvMode == GL_MODULATE) ||
  549. #endif // DONT_PUNT_MODULATE_W_BLEND
  550. (pRc->MCDTexEnvState.texEnvMode == GL_REPLACE))
  551. {
  552. // alpha circuit will be set as required for normal (blend|fog)
  553. // note that __MCDPickRenderingFuncs will have set up for punt if current
  554. // blend/fog mode not supported in hw
  555. if (pRc->privateEnables & (__MCDENABLE_BLEND|__MCDENABLE_FOG))
  556. {
  557. if ((pRc->privateEnables & __MCDENABLE_BLEND) &&
  558. pTex->bAlphaInTexture)
  559. {
  560. // case of GL_REPLACE and texture has alpha - use texture's alpha
  561. if( pRc->Control0.Alpha_Mode != LL_ALPHA_TEXTURE )
  562. {
  563. pRc->Control0.Alpha_Mode = LL_ALPHA_TEXTURE;
  564. control0_set=TRUE;
  565. }
  566. }
  567. else
  568. {
  569. if( pRc->Control0.Alpha_Mode != LL_ALPHA_INTERP )
  570. {
  571. pRc->Control0.Alpha_Mode = LL_ALPHA_INTERP;
  572. control0_set=TRUE;
  573. }
  574. }
  575. if (pRc->privateEnables & __MCDENABLE_BLEND)
  576. {
  577. if( pRc->Control0.Alpha_Dest_Color_Sel != LL_ALPHA_DEST_FRAME )
  578. {
  579. pRc->Control0.Alpha_Dest_Color_Sel = LL_ALPHA_DEST_FRAME;
  580. control0_set=TRUE;
  581. }
  582. }
  583. else
  584. {
  585. // for fog dest_color is const and alpha values are coord's "fog" value
  586. if( pRc->Control0.Alpha_Dest_Color_Sel != LL_ALPHA_DEST_CONST )
  587. {
  588. pRc->Control0.Alpha_Dest_Color_Sel = LL_ALPHA_DEST_CONST;
  589. control0_set=TRUE;
  590. }
  591. // fog color already loaded into color0 register by __MCDPickRenderingFuncs
  592. }
  593. if (!pRc->Control0.Alpha_Blending_Enable)
  594. {
  595. pRc->Control0.Alpha_Blending_Enable = TRUE;
  596. control0_set=TRUE;
  597. }
  598. }
  599. else
  600. {
  601. // alpha blend not used, so turn off if currently on
  602. if (pRc->Control0.Alpha_Blending_Enable)
  603. {
  604. pRc->Control0.Alpha_Blending_Enable = FALSE;
  605. control0_set=TRUE;
  606. }
  607. }
  608. }
  609. pRc->texture_width = pTex->fWidth;
  610. if (pRc->privateEnables & __MCDENABLE_1D_TEXTURE)
  611. {
  612. // set factors to make v always 0 in parameterization code
  613. pRc->texture_height = (float)0.0;
  614. }
  615. else
  616. {
  617. pRc->texture_height = pTex->fHeight;
  618. }
  619. if (pTex->dwTxCtlBits & CLMCD_TEX_FILTER)
  620. {
  621. pRc->texture_bias = (float)-0.5;
  622. }
  623. else
  624. {
  625. pRc->texture_bias = (float)0.0;
  626. }
  627. // MCD_NOTE: allowing filtering with Decal - broke on 5464, fixed on 5465(?)
  628. Tx.dwTxControl0 |= pTex->dwTxCtlBits &
  629. ( CLMCD_TEX_FILTER
  630. | CLMCD_TEX_U_SATURATE|CLMCD_TEX_V_SATURATE
  631. | CLMCD_TEX_DECAL|CLMCD_TEX_DECAL_POL
  632. //QST: MCD doesn't use CLMCD_TEX_DECAL_INTERP? (currently disabled)
  633. /*| CLMCD_TEX_DECAL_INTERP*/ );
  634. Tx.TxControl0.Texel_Mode = pTex->bType;
  635. Tx.TxControl0.Tex_U_Address_Mask = pTex->bSizeMask & 0xF;
  636. Tx.TxControl0.Tex_V_Address_Mask = pTex->bSizeMask >> 4;
  637. #if 0 // QST: support texture palette???
  638. Tx.TxControl0.Texel_Lookup_En = pTex->fIndexed;
  639. Tx.TxControl0.CLUT_Offset = pTex->bLookupOffset;
  640. #endif //
  641. // masking only meaningful if texture has alpha
  642. if ((pRc->privateEnables & __MCDENABLE_TEXTUREMASKING) && pTex->bAlphaInTexture)
  643. {
  644. Tx.TxControl0.Tex_Mask_Enable=1;
  645. // polarity set to 1 in MCDrvCreateContext and stays that way
  646. }
  647. // Two kinds of textures: those residing in the video memory and
  648. // those rendered from the system memory. They need different setup.
  649. //
  650. #ifdef MCD_SUPPORTS_HOST_TEXTURES
  651. if( pTex->dwFlags & TEX_IN_SYSTEM )
  652. {
  653. DWORD dwOffset;
  654. printf(" Polys.c - tex in system id=%d\n",pBatch->wBuf);
  655. // Texture is in the system memory, so set the location
  656. //
  657. if( LL_State.Base0.Texture_Location != 1 )
  658. {
  659. LL_State.Base0.Texture_Location = 1;
  660. *pdwNext++ = write_register( BASE0_ADDR_3D, 1 );
  661. *pdwNext++ = LL_State.dwBase0;
  662. }
  663. // Set the host access base address and texture map offset
  664. //
  665. dwOffset = (DWORD)pTex->dwAddress - (DWORD)LL_State.Tex.Mem[pTex->bMem].dwAddress;
  666. if( LL_State.dwHXY_Base1_Address_Ptr != LL_State.Tex.Mem[pTex->bMem].dwPhyPtr ||
  667. LL_State.dwHXY_Base1_Offset0 != dwOffset )
  668. {
  669. // Check if only the offset must be reloaded (this is most likely)
  670. //
  671. if( LL_State.dwHXY_Base1_Address_Ptr == LL_State.Tex.Mem[pTex->bMem].dwPhyPtr )
  672. {
  673. *pdwNext++ = write_dev_register( HOST_XY, HXY_BASE1_OFFSET0_3D, 1 );
  674. *pdwNext++ = LL_State.dwHXY_Base1_Offset0 = dwOffset;
  675. }
  676. else
  677. {
  678. *pdwNext++ = write_dev_register( HOST_XY, HXY_BASE1_ADDRESS_PTR_3D, 2 );
  679. *pdwNext++ = LL_State.dwHXY_Base1_Address_Ptr = LL_State.Tex.Mem[pTex->bMem].dwPhyPtr;
  680. *pdwNext++ = LL_State.dwHXY_Base1_Offset0 = dwOffset;
  681. }
  682. }
  683. // Set host control enable bit if necessary
  684. //
  685. if( LL_State.HXYHostControl.HostXYEnable != 1 )
  686. {
  687. LL_State.HXYHostControl.HostXYEnable = 1;
  688. *pdwNext++ = write_dev_register( HOST_XY, HXY_HOST_CTRL_3D, 1 );
  689. *pdwNext++ = LL_State.dwHXYHostControl;
  690. }
  691. *pdwNext++ = write_register( TX_CTL0_3D, 1 );
  692. *pdwNext++ = LL_State.dwTxControl0 = Tx.dwTxControl0 & TX_CTL0_MASK;
  693. }
  694. else
  695. #endif // def MCD_SUPPORTS_HOST_TEXTURES
  696. {
  697. // Texture is in the video memory, so set the location
  698. //
  699. // texture base init'd to RDRAM in LL_InitLib
  700. #ifdef MCD_SUPPORTS_HOST_TEXTURES
  701. if( ppdev->LL_State.Base0.Texture_Location != 0 )
  702. {
  703. ppdev->LL_State.Base0.Texture_Location = 0;
  704. *pdwNext++ = write_register( BASE0_ADDR_3D, 1 );
  705. *pdwNext++ = ppdev->LL_State.dwBase0;
  706. }
  707. #endif
  708. // Set the coordinates of the texture
  709. if( pRc->TxXYBase.Tex_Y_Base_Addr != pTex->wYloc ||
  710. pRc->TxXYBase.Tex_X_Base_Addr != pTex->wXloc )
  711. {
  712. // New location, need to reload tx_xybase_3d register and perhaps control register
  713. //
  714. *pdwNext++ = write_register( TX_CTL0_3D, 2 );
  715. *pdwNext++ = pRc->dwTxControl0 = Tx.dwTxControl0 & TX_CTL0_MASK;
  716. *pdwNext++ = (pTex->wYloc << 16) | pTex->wXloc;
  717. pRc->TxXYBase.Tex_Y_Base_Addr = pTex->wYloc;
  718. pRc->TxXYBase.Tex_X_Base_Addr = pTex->wXloc;
  719. }
  720. else
  721. {
  722. *pdwNext++ = write_register( TX_CTL0_3D, 1 );
  723. *pdwNext++ = pRc->dwTxControl0 = Tx.dwTxControl0 & TX_CTL0_MASK;
  724. }
  725. }
  726. if (control0_set)
  727. {
  728. *pdwNext++ = write_register( CONTROL0_3D, 1 );
  729. *pdwNext++ = pRc->dwControl0;
  730. }
  731. ppdev->LL_State.pDL->pdwNext = pdwNext;
  732. return(TRUE);
  733. }
  734. __inline ULONG GetDisplayUniqueness(PDEV *ppdev)
  735. {
  736. return (ppdev->iUniqueness);
  737. }
  738. #define SET_HW_CLIP_REGS(pRc,pdwNext) { \
  739. *pdwNext++ = write_register( X_CLIP_3D, 2 ); \
  740. *pdwNext++ = ((pClip->right +pRc->AdjClip.right) <<16) | (pClip->left+pRc->AdjClip.left)| 0x80008000; \
  741. *pdwNext++ = ((pClip->bottom+pRc->AdjClip.bottom)<<16) | (pClip->top +pRc->AdjClip.top) | 0x80008000; \
  742. }
  743. // verify MCDTextureData in client space is accessible
  744. #define VERIFY_TEXTUREDATA_ACCESSIBLE(pTex){ \
  745. try { \
  746. EngProbeForRead(pTex->pMCDTextureData, sizeof(MCDTEXTUREDATA), 4); \
  747. } except (EXCEPTION_EXECUTE_HANDLER) { \
  748. MCDBG_PRINT("!!Exception accessing MCDTextureData in client address space!!"); \
  749. return FALSE; \
  750. } \
  751. }
  752. // verify struct addressed by MCDTextureData->level in client space is accessible
  753. #define VERIFY_TEXTURELEVEL_ACCESSIBLE(pTex){ \
  754. try { \
  755. EngProbeForRead(pTex->pMCDTextureData->level, sizeof(MCDMIPMAPLEVEL), 4); \
  756. } except (EXCEPTION_EXECUTE_HANDLER) { \
  757. MCDBG_PRINT("!!Exception accessing MCDTextureData->level in client address space!!"); \
  758. return FALSE; \
  759. } \
  760. }
  761. // verify struct addressed by MCDTextureData->paletteData in client space is accessible
  762. #define VERIFY_TEXTUREPALETTE8_ACCESSIBLE(pTex){ \
  763. try { \
  764. EngProbeForRead(pTex->pMCDTextureData->paletteData, 256*4, 4);/* 256 bytes for 8 bit indices */ \
  765. } except (EXCEPTION_EXECUTE_HANDLER) { \
  766. MCDBG_PRINT("!!Exception accessing MCDTextureData->paletteData in client address space!!"); \
  767. return FALSE; \
  768. } \
  769. }
  770. // verify struct addressed by MCDTextureData->paletteData in client space is accessible
  771. #define VERIFY_TEXTUREPALETTE16_ACCESSIBLE(pTex){ \
  772. try { \
  773. EngProbeForRead(pTex->pMCDTextureData->paletteData, 65536*4, 4);/* 16K bytes for 16 bit indices */ \
  774. } except (EXCEPTION_EXECUTE_HANDLER) { \
  775. MCDBG_PRINT("!!Exception accessing MCDTextureData->paletteData in client address space!!"); \
  776. return FALSE; \
  777. } \
  778. }
  779. #define ENGPROBE_ALIGN_BYTE 1
  780. #define ENGPROBE_ALIGN_WORD 2
  781. #define ENGPROBE_ALIGN_DWORD 4
  782. // verify struct addressed by MCDTextureData->paletteData in client space is accessible
  783. #define VERIFY_TEXELS_ACCESSIBLE(pTexels,nBytes,Align){ \
  784. try { \
  785. EngProbeForRead(pTexels, nBytes, Align); \
  786. } except (EXCEPTION_EXECUTE_HANDLER) { \
  787. MCDBG_PRINT("!!Exception accessing MCDTextureData->level->pTexels in client address space!!"); \
  788. return FALSE; \
  789. } \
  790. }
  791. #define _3D_ENGINE_NOT_READY_FOR_MORE 0x040 // wait for execution engine idle
  792. #define USB_TIMEOUT_FIX(ppdev) \
  793. { \
  794. if (ppdev->dwDataStreaming) \
  795. { \
  796. int status; \
  797. volatile int wait_count=0; \
  798. do \
  799. { \
  800. status = *((volatile *)((DWORD *)(ppdev->pLgREGS) + PF_STATUS_3D)); \
  801. wait_count++; /* do something to give bus a breather */ \
  802. wait_count++; /* do something to give bus a breather */ \
  803. wait_count++; /* do something to give bus a breather */ \
  804. } while(status & _3D_ENGINE_NOT_READY_FOR_MORE); \
  805. } \
  806. }
  807. #endif /* _MCDUTIL_H */