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.

2675 lines
109 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * D3D SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: d3ddx6.c
  8. *
  9. * Content: Direct3D DX6 Callback function interface
  10. *
  11. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "precomp.h"
  15. #include "d3dhw.h"
  16. #include "d3dcntxt.h"
  17. #include "dd.h"
  18. #include "d3dtxman.h"
  19. #define ALLOC_TAG ALLOC_TAG_6D2P
  20. //-----------------------------------------------------------------------------
  21. //
  22. // DX6 allows driver-level acceleration of the new vertex-buffer API. It
  23. // allows data and commands, indices and statechanges to be contained in
  24. // two separate DirectDraw surfaces. The DirectDraw surfaces can reside
  25. // in system, AGP, or video memory depending on the type of allocation
  26. // requested by the user The interface is designed to accomodate legacy
  27. // ExecuteBuffer applications with no driver impact. This allows higher
  28. // performance on both legacy applications as well as the highest
  29. // possible performance through the vertex buffer API.
  30. //
  31. //-----------------------------------------------------------------------------
  32. #define STARTVERTEXSIZE (sizeof(D3DHAL_DP2STARTVERTEX))
  33. // Macros for updating properly our instruction pointer to our next instruction
  34. // in the command buffer
  35. #define NEXTINSTRUCTION(ptr, type, num, extrabytes) \
  36. NEXTINSTRUCTION_S(ptr, sizeof(type), num, extrabytes)
  37. #define NEXTINSTRUCTION_S(ptr, typesize, num, extrabytes) \
  38. ptr = (LPD3DHAL_DP2COMMAND)((LPBYTE)ptr + sizeof(D3DHAL_DP2COMMAND) + \
  39. ((num) * (typesize)) + (extrabytes))
  40. // Error reporting macro , sets up error code and exits DrawPrimitives2
  41. #define PARSE_ERROR_AND_EXIT( pDP2Data, pIns, pStartIns, ddrvalue) \
  42. { \
  43. pDP2Data->dwErrorOffset = (DWORD)((LPBYTE)pIns-(LPBYTE)pStartIns); \
  44. pDP2Data->ddrval = ddrvalue; \
  45. goto Exit_DrawPrimitives2; \
  46. }
  47. // Macros for verifying validity of the command and vertex buffers. This MUST
  48. // be done by the driver even on free builds as the runtime avoids this check
  49. // in order to not parse the command buffer too.
  50. #define CHECK_CMDBUF_LIMITS( pDP2Data, pBuf, type, num, extrabytes) \
  51. CHECK_CMDBUF_LIMITS_S( pDP2Data, pBuf, sizeof(type), num, extrabytes)
  52. #define CHECK_CMDBUF_LIMITS_S( pDP2Data, pBuf, typesize, num, extrabytes) \
  53. { \
  54. LPBYTE pBase,pEnd,pBufEnd; \
  55. pBase = (LPBYTE)(pDP2Data->lpDDCommands->lpGbl->fpVidMem + \
  56. pDP2Data->dwCommandOffset); \
  57. pEnd = pBase + pDP2Data->dwCommandLength; \
  58. pBufEnd = ((LPBYTE)pBuf + ((num) * (typesize)) + (extrabytes) - 1); \
  59. if (! ((LPBYTE)pBufEnd < pEnd) && ( pBase <= (LPBYTE)pBuf)) \
  60. { \
  61. DBG_D3D((0,"DX6 D3D: Trying to read past Command Buffer limits " \
  62. "%x %x %x %x",pBase ,(LPBYTE)pBuf, pBufEnd, pEnd )); \
  63. PARSE_ERROR_AND_EXIT( pDP2Data, lpIns, lpInsStart, \
  64. D3DERR_COMMAND_UNPARSED ); \
  65. } \
  66. }
  67. #define CHECK_DATABUF_LIMITS( pDP2Data, iIndex) \
  68. { \
  69. if (! (((LONG)iIndex >= 0) && \
  70. ((LONG)iIndex <(LONG)pDP2Data->dwVertexLength))) \
  71. { \
  72. DBG_D3D((0,"DX6 D3D: Trying to read past Vertex Buffer limits " \
  73. "%d limit= %d ",(LONG)iIndex, (LONG)pDP2Data->dwVertexLength));\
  74. PARSE_ERROR_AND_EXIT( pDP2Data, lpIns, lpInsStart, \
  75. D3DERR_COMMAND_UNPARSED ); \
  76. } \
  77. }
  78. // Macros for accessing vertexes in the vertex buffer based on an index or on
  79. // a previous accessed vertex
  80. #define LP_FVF_VERTEX(lpBaseAddr, wIndex, P2FVFOffs) \
  81. (LPD3DTLVERTEX)((LPBYTE)(lpBaseAddr) + (wIndex) * (P2FVFOffs).dwStride)
  82. #define LP_FVF_NXT_VTX(lpVtx, P2FVFOffs ) \
  83. (LPD3DTLVERTEX)((LPBYTE)(lpVtx) + (P2FVFOffs).dwStride)
  84. // Forward declaration of utility functions
  85. DWORD __CheckFVFRequest(DWORD dwFVF, LPP2FVFOFFSETS lpP2FVFOff);
  86. D3DFVFDRAWTRIFUNCPTR __HWSetTriangleFunc(PERMEDIA_D3DCONTEXT *pContext);
  87. HRESULT __Clear( PERMEDIA_D3DCONTEXT* pContext,
  88. DWORD dwFlags,
  89. DWORD dwFillColor,
  90. D3DVALUE dvFillDepth,
  91. DWORD dwFillStencil,
  92. LPD3DRECT lpRects,
  93. DWORD dwNumRects);
  94. HRESULT __TextureBlt(PERMEDIA_D3DCONTEXT* pContext,
  95. D3DHAL_DP2TEXBLT* lpdp2texblt);
  96. HRESULT __SetRenderTarget(PERMEDIA_D3DCONTEXT* pContext,
  97. DWORD hRenderTarget,
  98. DWORD hZBuffer);
  99. HRESULT __PaletteUpdate(PERMEDIA_D3DCONTEXT* pContext,
  100. DWORD dwPaletteHandle,
  101. WORD wStartIndex,
  102. WORD wNumEntries,
  103. BYTE * pPaletteData);
  104. HRESULT __PaletteSet(PERMEDIA_D3DCONTEXT* pContext,
  105. DWORD dwSurfaceHandle,
  106. DWORD dwPaletteHandle,
  107. DWORD dwPaletteFlags);
  108. void __BeginStateSet(PERMEDIA_D3DCONTEXT*, DWORD);
  109. void __EndStateSet(PERMEDIA_D3DCONTEXT*);
  110. void __DeleteStateSet(PERMEDIA_D3DCONTEXT*, DWORD);
  111. void __ExecuteStateSet(PERMEDIA_D3DCONTEXT*, DWORD);
  112. void __CaptureStateSet(PERMEDIA_D3DCONTEXT*, DWORD);
  113. void __RestoreD3DContext(PPDev ppdev, PERMEDIA_D3DCONTEXT* pContext);
  114. //-----------------------------Public Routine----------------------------------
  115. //
  116. // DWORD D3DDrawPrimitives2
  117. //
  118. // The D3DDrawPrimitives2 callback is filled in by drivers which directly
  119. // support the rendering primitives using the new DDI. If this entry is
  120. // left as NULL, the API will be emulated through DX5-level HAL interfaces.
  121. //
  122. // PARAMETERS
  123. //
  124. // lpdp2d This structure is used when D3DDrawPrimitives2 is called
  125. // to draw a set of primitives using a vertex buffer. The
  126. // surface specified by the lpDDCommands in
  127. // D3DHAL_DRAWPRIMITIVES2DATA contains a sequence of
  128. // D3DHAL_DP2COMMAND structures. Each D3DHAL_DP2COMMAND
  129. // specifies either a primitive to draw, a state change to
  130. // process, or a re-base command.
  131. //
  132. //-----------------------------------------------------------------------------
  133. DWORD CALLBACK
  134. D3DDrawPrimitives2_P2( LPD3DHAL_DRAWPRIMITIVES2DATA lpdp2d );
  135. DWORD CALLBACK
  136. D3DDrawPrimitives2( LPD3DHAL_DRAWPRIMITIVES2DATA lpdp2d )
  137. {
  138. // User memory might become invalid under some circumstances,
  139. // exception handler is used for protection
  140. __try
  141. {
  142. return (D3DDrawPrimitives2_P2(lpdp2d));
  143. }
  144. __except(EXCEPTION_EXECUTE_HANDLER)
  145. {
  146. // On Perm2 driver, no special handling is done
  147. DBG_D3D((0, "D3DDrawPrimitives2 : exception happened."));
  148. lpdp2d->ddrval = DDERR_EXCEPTION;
  149. return (DDHAL_DRIVER_HANDLED);
  150. }
  151. }
  152. DWORD CALLBACK
  153. D3DDrawPrimitives2_P2( LPD3DHAL_DRAWPRIMITIVES2DATA lpdp2d )
  154. {
  155. LPDDRAWI_DDRAWSURFACE_LCL lpCmdLcl, lpDataLcl;
  156. LPD3DHAL_DP2COMMAND lpIns, lpResumeIns;
  157. LPD3DTLVERTEX lpVertices=NULL, lpV0, lpV1, lpV2, lpV3;
  158. LPBYTE lpInsStart, lpPrim;
  159. PERMEDIA_D3DCONTEXT *pContext;
  160. UINT i,j;
  161. WORD wCount, wIndex, wIndex1, wIndex2, wIndex3,
  162. wFlags, wIndxBase;
  163. HRESULT ddrval;
  164. P2FVFOFFSETS P2FVFOff;
  165. D3DHAL_DP2TEXTURESTAGESTATE *lpRState;
  166. D3DFVFDRAWTRIFUNCPTR pTriangle;
  167. D3DFVFDRAWPNTFUNCPTR pPoint;
  168. DWORD dwEdgeFlags;
  169. DBG_D3D((6,"Entering D3DDrawPrimitives2"));
  170. DBG_D3D((8," dwhContext = %x",lpdp2d->dwhContext));
  171. DBG_D3D((8," dwFlags = %x",lpdp2d->dwFlags));
  172. DBG_D3D((8," dwVertexType = %d",lpdp2d->dwVertexType));
  173. DBG_D3D((8," dwCommandOffset = %d",lpdp2d->dwCommandOffset));
  174. DBG_D3D((8," dwCommandLength = %d",lpdp2d->dwCommandLength));
  175. DBG_D3D((8," dwVertexOffset = %d",lpdp2d->dwVertexOffset));
  176. DBG_D3D((8," dwVertexLength = %d",lpdp2d->dwVertexLength));
  177. // Retrieve permedia d3d context from context handle
  178. pContext = (PERMEDIA_D3DCONTEXT*)ContextSlots[lpdp2d->dwhContext];
  179. // Check if we got a valid context
  180. CHK_CONTEXT(pContext, lpdp2d->ddrval, "DrawPrimitives2");
  181. PPDev ppdev = pContext->ppdev;
  182. PERMEDIA_DEFS(ppdev);
  183. __P2RegsSoftwareCopy* pSoftPermedia = &pContext->Hdr.SoftCopyP2Regs;
  184. // Switch hw context, and force the next switch to wait for the Permedia
  185. SET_CURRENT_D3D_CONTEXT(pContext->hPermediaContext);
  186. // Restore our D3D rendering context
  187. __RestoreD3DContext(ppdev, pContext);
  188. // Get appropriate pointers to command buffer
  189. lpInsStart = (LPBYTE)(lpdp2d->lpDDCommands->lpGbl->fpVidMem);
  190. if (lpInsStart == NULL)
  191. {
  192. DBG_D3D((0,"DX6 Command Buffer pointer is null"));
  193. lpdp2d->ddrval = DDERR_INVALIDPARAMS;
  194. goto Exit_DrawPrimitives2;
  195. }
  196. lpIns = (LPD3DHAL_DP2COMMAND)(lpInsStart + lpdp2d->dwCommandOffset);
  197. // Check if the FVF format being passed is valid.
  198. if (__CheckFVFRequest(lpdp2d->dwVertexType, &P2FVFOff) != DD_OK)
  199. {
  200. DBG_D3D((0,"DrawPrimitives2 cannot handle "
  201. "Flexible Vertex Format requested"));
  202. PARSE_ERROR_AND_EXIT(lpdp2d, lpIns, lpInsStart,
  203. D3DERR_COMMAND_UNPARSED);
  204. }
  205. // Check if vertex size calculated from dwVertexType is the same as
  206. // dwVertexSize, this is to make sure that CHECK_DATABUF_LIMITS's index
  207. // checking is done using the correct step size
  208. if (lpdp2d->dwVertexSize != P2FVFOff.dwStride)
  209. {
  210. DBG_D3D((0,"DrawPrimitives2 : invalid vertex size from runtime."));
  211. PARSE_ERROR_AND_EXIT(lpdp2d, lpIns, lpInsStart,
  212. D3DERR_COMMAND_UNPARSED);
  213. }
  214. // Process commands while we haven't exhausted the command buffer
  215. while ((LPBYTE)lpIns <
  216. (lpInsStart + lpdp2d->dwCommandLength + lpdp2d->dwCommandOffset))
  217. {
  218. // Get pointer to first primitive structure past the D3DHAL_DP2COMMAND
  219. lpPrim = (LPBYTE)lpIns + sizeof(D3DHAL_DP2COMMAND);
  220. DBG_D3D((4,"D3DDrawPrimitive2: parsing instruction %d count = %d @ %x",
  221. lpIns->bCommand, lpIns->wPrimitiveCount, lpIns));
  222. // If our next command involves some actual rendering, we have to make
  223. // sure that our rendering context is realized
  224. switch( lpIns->bCommand )
  225. {
  226. case D3DDP2OP_POINTS:
  227. case D3DDP2OP_LINELIST:
  228. case D3DDP2OP_INDEXEDLINELIST:
  229. case D3DDP2OP_INDEXEDLINELIST2:
  230. case D3DDP2OP_LINESTRIP:
  231. case D3DDP2OP_INDEXEDLINESTRIP:
  232. case D3DDP2OP_TRIANGLELIST:
  233. case D3DDP2OP_INDEXEDTRIANGLELIST:
  234. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  235. case D3DDP2OP_TRIANGLESTRIP:
  236. case D3DDP2OP_INDEXEDTRIANGLESTRIP:
  237. case D3DDP2OP_TRIANGLEFAN:
  238. case D3DDP2OP_INDEXEDTRIANGLEFAN:
  239. // Check if vertex buffer resides in user memory or in a DDraw surface
  240. if (NULL == lpVertices)
  241. {
  242. if (NULL == lpdp2d->lpVertices)
  243. {
  244. DBG_D3D((0,"DX6 Vertex Buffer pointer is null"));
  245. lpdp2d->ddrval = DDERR_INVALIDPARAMS;
  246. goto Exit_DrawPrimitives2;
  247. }
  248. if (lpdp2d->dwFlags & D3DHALDP2_USERMEMVERTICES)
  249. {
  250. // Get appropriate pointer to vertices , memory is already secured
  251. lpVertices = (LPD3DTLVERTEX)((LPBYTE)lpdp2d->lpVertices +
  252. lpdp2d->dwVertexOffset);
  253. }
  254. else
  255. {
  256. // Get appropriate pointer to vertices
  257. lpVertices =
  258. (LPD3DTLVERTEX)((LPBYTE)lpdp2d->lpDDVertex->lpGbl->fpVidMem
  259. + lpdp2d->dwVertexOffset);
  260. }
  261. if (NULL == lpVertices)
  262. {
  263. DBG_D3D((0,"DX6 Vertex Buffer pointer is null"));
  264. lpdp2d->ddrval = DDERR_INVALIDPARAMS;
  265. goto Exit_DrawPrimitives2;
  266. }
  267. }
  268. // fall through intentionally, no break here
  269. case D3DDP2OP_LINELIST_IMM:
  270. case D3DDP2OP_TRIANGLEFAN_IMM:
  271. // Update triangle rendering function
  272. pTriangle = __HWSetTriangleFunc(pContext);
  273. pPoint = __HWSetPointFunc(pContext, &P2FVFOff);
  274. // Handle State changes that may need to update the chip
  275. if (pContext->dwDirtyFlags)
  276. {
  277. // Handle the dirty states
  278. __HandleDirtyPermediaState(ppdev, pContext, &P2FVFOff);
  279. }
  280. break;
  281. }
  282. // Execute the current command buffer command
  283. switch( lpIns->bCommand )
  284. {
  285. case D3DDP2OP_RENDERSTATE:
  286. // Specifies a render state change that requires processing.
  287. // The rendering state to change is specified by one or more
  288. // D3DHAL_DP2RENDERSTATE structures following D3DHAL_DP2COMMAND.
  289. DBG_D3D((8,"D3DDP2OP_RENDERSTATE "
  290. "state count = %d", lpIns->wStateCount));
  291. // Check we are in valid buffer memory
  292. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  293. D3DHAL_DP2RENDERSTATE, lpIns->wStateCount, 0);
  294. lpdp2d->ddrval = __ProcessPermediaStates(pContext,
  295. lpIns->wStateCount,
  296. (LPD3DSTATE) (lpPrim),
  297. lpdp2d->lpdwRStates);
  298. if ( FAILED(lpdp2d->ddrval) )
  299. {
  300. DBG_D3D((2,"Error processing D3DDP2OP_RENDERSTATE"));
  301. PARSE_ERROR_AND_EXIT(lpdp2d, lpIns, lpInsStart, ddrval);
  302. }
  303. NEXTINSTRUCTION(lpIns, D3DHAL_DP2RENDERSTATE,
  304. lpIns->wStateCount, 0);
  305. break;
  306. case D3DDP2OP_TEXTURESTAGESTATE:
  307. // Specifies texture stage state changes, having wStateCount
  308. // D3DNTHAL_DP2TEXTURESTAGESTATE structures follow the command
  309. // buffer. For each, the driver should update its internal
  310. // texture state associated with the texture at dwStage to
  311. // reflect the new value based on TSState.
  312. DBG_D3D((8,"D3DDP2OP_TEXTURESTAGESTATE"));
  313. // Verify the command buffer validity
  314. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  315. D3DHAL_DP2TEXTURESTAGESTATE, lpIns->wStateCount, 0);
  316. lpRState = (D3DHAL_DP2TEXTURESTAGESTATE *)(lpPrim);
  317. for (i = 0; i < lpIns->wStateCount; i++)
  318. {
  319. if (0 == lpRState->wStage)
  320. {
  321. // Tell __HWSetupPrimitive to look at stage state data
  322. DIRTY_MULTITEXTURE;
  323. if ((lpRState->TSState >= D3DTSS_TEXTUREMAP) &&
  324. (lpRState->TSState <= D3DTSS_TEXTURETRANSFORMFLAGS))
  325. {
  326. #if D3D_STATEBLOCKS
  327. if (!pContext->bStateRecMode)
  328. {
  329. #endif //D3D_STATEBLOCKS
  330. if (pContext->TssStates[lpRState->TSState] !=
  331. lpRState->dwValue)
  332. {
  333. // Store value associated to this stage state
  334. pContext->TssStates[lpRState->TSState] =
  335. lpRState->dwValue;
  336. // Perform any necessary preprocessing of it
  337. __HWPreProcessTSS(pContext,
  338. 0,
  339. lpRState->TSState,
  340. lpRState->dwValue);
  341. DBG_D3D((8,"TSS State Chg , Stage %d, "
  342. "State %d, Value %d",
  343. (LONG)lpRState->wStage,
  344. (LONG)lpRState->TSState,
  345. (LONG)lpRState->dwValue));
  346. DIRTY_TEXTURE; //AZN5
  347. }
  348. #if D3D_STATEBLOCKS
  349. }
  350. else
  351. {
  352. if (pContext->pCurrSS != NULL)
  353. {
  354. DBG_D3D((6,"Recording RS %x = %x",
  355. lpRState->TSState, lpRState->dwValue));
  356. // Recording the state in a stateblock
  357. pContext->pCurrSS->u.uc.TssStates[lpRState->TSState] =
  358. lpRState->dwValue;
  359. FLAG_SET(pContext->pCurrSS->u.uc.bStoredTSS,
  360. lpRState->TSState);
  361. }
  362. }
  363. #endif //D3D_STATEBLOCKS
  364. }
  365. else
  366. {
  367. DBG_D3D((2,"Unhandled texture stage state %d value %d",
  368. (LONG)lpRState->TSState, (LONG)lpRState->dwValue));
  369. }
  370. }
  371. else
  372. {
  373. DBG_D3D((0,"Texture Stage other than 0 received,"
  374. " not supported in hw"));
  375. }
  376. lpRState ++;
  377. }
  378. NEXTINSTRUCTION(lpIns, D3DHAL_DP2TEXTURESTAGESTATE,
  379. lpIns->wStateCount, 0);
  380. break;
  381. case D3DNTDP2OP_VIEWPORTINFO:
  382. // Specifies the clipping rectangle used for guard-band
  383. // clipping by guard-band aware drivers. The clipping
  384. // rectangle (i.e. the viewing rectangle) is specified
  385. // by the D3DHAL_DP2 VIEWPORTINFO structures following
  386. // D3DHAL_DP2COMMAND
  387. // Verify the command buffer validity
  388. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  389. D3DHAL_DP2VIEWPORTINFO, lpIns->wStateCount, 0);
  390. // We don't implement guard band clipping in this driver so
  391. // we just skip any of this data that might be sent to us
  392. NEXTINSTRUCTION(lpIns, D3DHAL_DP2VIEWPORTINFO,
  393. lpIns->wStateCount, 0);
  394. break;
  395. case D3DNTDP2OP_WINFO:
  396. // Specifies the w-range for W buffering. It is specified
  397. // by one or more D3DHAL_DP2WINFO structures following
  398. // D3DHAL_DP2COMMAND.
  399. // Verify the command buffer validity
  400. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  401. D3DHAL_DP2WINFO, lpIns->wStateCount, 0);
  402. // We dont implement a w-buffer in this driver so we just
  403. // skip any of this data that might be sent to us
  404. NEXTINSTRUCTION(lpIns, D3DHAL_DP2WINFO,
  405. lpIns->wStateCount, 0);
  406. break;
  407. case D3DDP2OP_POINTS:
  408. DBG_D3D((8,"D3DDP2OP_POINTS"));
  409. // Point primitives in vertex buffers are defined by the
  410. // D3DHAL_DP2POINTS structure. The driver should render
  411. // wCount points starting at the initial vertex specified
  412. // by wFirst. Then for each D3DHAL_DP2POINTS, the points
  413. // rendered will be (wFirst),(wFirst+1),...,
  414. // (wFirst+(wCount-1)). The number of D3DHAL_DP2POINTS
  415. // structures to process is specified by the wPrimitiveCount
  416. // field of D3DHAL_DP2COMMAND.
  417. // Verify the command buffer validity
  418. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  419. D3DHAL_DP2POINTS, lpIns->wPrimitiveCount, 0);
  420. for (i = lpIns->wPrimitiveCount; i > 0; i--)
  421. {
  422. wIndex = ((D3DHAL_DP2POINTS*)lpPrim)->wVStart;
  423. wCount = ((D3DHAL_DP2POINTS*)lpPrim)->wCount;
  424. lpV0 = LP_FVF_VERTEX(lpVertices, wIndex, P2FVFOff);
  425. // Check first & last vertex
  426. CHECK_DATABUF_LIMITS(lpdp2d, wIndex);
  427. CHECK_DATABUF_LIMITS(lpdp2d, ((LONG)wIndex + wCount - 1));
  428. for (j = 0; j < wCount; j++)
  429. {
  430. (*pPoint)(pContext, lpV0, &P2FVFOff);
  431. lpV0 = LP_FVF_NXT_VTX(lpV0, P2FVFOff);
  432. }
  433. lpPrim += sizeof(D3DHAL_DP2POINTS);
  434. }
  435. NEXTINSTRUCTION(lpIns, D3DHAL_DP2POINTS,
  436. lpIns->wPrimitiveCount, 0);
  437. break;
  438. case D3DDP2OP_LINELIST:
  439. DBG_D3D((8,"D3DDP2OP_LINELIST"));
  440. // Non-indexed vertex-buffer line lists are defined by the
  441. // D3DHAL_DP2LINELIST structure. Given an initial vertex,
  442. // the driver will render a sequence of independent lines,
  443. // processing two new vertices with each line. The number
  444. // of lines to render is specified by the wPrimitiveCount
  445. // field of D3DHAL_DP2COMMAND. The sequence of lines
  446. // rendered will be
  447. // (wVStart, wVStart+1),(wVStart+2, wVStart+3),...,
  448. // (wVStart+(wPrimitiveCount-1)*2), wVStart+wPrimitiveCount*2 - 1).
  449. // Verify the command buffer validity
  450. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim, D3DHAL_DP2LINELIST, 1, 0);
  451. wIndex = ((D3DHAL_DP2LINELIST*)lpPrim)->wVStart;
  452. lpV0 = LP_FVF_VERTEX(lpVertices, wIndex, P2FVFOff);
  453. lpV1 = LP_FVF_NXT_VTX(lpV0, P2FVFOff);
  454. // Check first & last vertex
  455. CHECK_DATABUF_LIMITS(lpdp2d, wIndex);
  456. CHECK_DATABUF_LIMITS(lpdp2d,
  457. ((LONG)wIndex + 2*lpIns->wPrimitiveCount - 1) );
  458. for (i = lpIns->wPrimitiveCount; i > 0; i--)
  459. {
  460. P2_Draw_FVF_Line(pContext, lpV0, lpV1, lpV0, &P2FVFOff);
  461. lpV0 = LP_FVF_NXT_VTX(lpV1, P2FVFOff);
  462. lpV1 = LP_FVF_NXT_VTX(lpV0, P2FVFOff);
  463. }
  464. NEXTINSTRUCTION(lpIns, D3DHAL_DP2LINELIST, 1, 0);
  465. break;
  466. case D3DDP2OP_INDEXEDLINELIST:
  467. DBG_D3D((8,"D3DDP2OP_INDEXEDLINELIST"));
  468. // The D3DHAL_DP2INDEXEDLINELIST structure specifies
  469. // unconnected lines to render using vertex indices.
  470. // The line endpoints for each line are specified by wV1
  471. // and wV2. The number of lines to render using this
  472. // structure is specified by the wPrimitiveCount field of
  473. // D3DHAL_DP2COMMAND. The sequence of lines
  474. // rendered will be (wV[0], wV[1]), (wV[2], wV[3]),...
  475. // (wVStart[(wPrimitiveCount-1)*2], wVStart[wPrimitiveCount*2-1]).
  476. // Verify the command buffer validity
  477. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  478. D3DHAL_DP2INDEXEDLINELIST, lpIns->wPrimitiveCount, 0);
  479. for (i = lpIns->wPrimitiveCount; i > 0; i--)
  480. {
  481. wIndex1 = ((D3DHAL_DP2INDEXEDLINELIST*)lpPrim)->wV1;
  482. wIndex2 = ((D3DHAL_DP2INDEXEDLINELIST*)lpPrim)->wV2;
  483. lpV1 = LP_FVF_VERTEX(lpVertices, wIndex1, P2FVFOff);
  484. lpV2 = LP_FVF_VERTEX(lpVertices, wIndex2, P2FVFOff);
  485. // Must check each new vertex
  486. CHECK_DATABUF_LIMITS(lpdp2d, wIndex1);
  487. CHECK_DATABUF_LIMITS(lpdp2d, wIndex2);
  488. P2_Draw_FVF_Line(pContext, lpV1, lpV2, lpV1, &P2FVFOff);
  489. lpPrim += sizeof(D3DHAL_DP2INDEXEDLINELIST);
  490. }
  491. NEXTINSTRUCTION(lpIns, D3DHAL_DP2INDEXEDLINELIST,
  492. lpIns->wPrimitiveCount, 0);
  493. break;
  494. case D3DDP2OP_INDEXEDLINELIST2:
  495. DBG_D3D((8,"D3DDP2OP_INDEXEDLINELIST2"));
  496. // The D3DHAL_DP2INDEXEDLINELIST structure specifies
  497. // unconnected lines to render using vertex indices.
  498. // The line endpoints for each line are specified by wV1
  499. // and wV2. The number of lines to render using this
  500. // structure is specified by the wPrimitiveCount field of
  501. // D3DHAL_DP2COMMAND. The sequence of lines
  502. // rendered will be (wV[0], wV[1]), (wV[2], wV[3]),
  503. // (wVStart[(wPrimitiveCount-1)*2], wVStart[wPrimitiveCount*2-1]).
  504. // The indexes are relative to a base index value that
  505. // immediately follows the command
  506. // Verify the command buffer validity
  507. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  508. D3DHAL_DP2INDEXEDLINELIST, lpIns->wPrimitiveCount,
  509. STARTVERTEXSIZE);
  510. // Access base index
  511. wIndxBase = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
  512. lpPrim = lpPrim + sizeof(D3DHAL_DP2STARTVERTEX);
  513. for (i = lpIns->wPrimitiveCount; i > 0; i--)
  514. {
  515. wIndex1 = ((D3DHAL_DP2INDEXEDLINELIST*)lpPrim)->wV1;
  516. wIndex2 = ((D3DHAL_DP2INDEXEDLINELIST*)lpPrim)->wV2;
  517. lpV1 = LP_FVF_VERTEX(lpVertices, (wIndex1+wIndxBase), P2FVFOff);
  518. lpV2 = LP_FVF_VERTEX(lpVertices, (wIndex2+wIndxBase), P2FVFOff);
  519. // Must check each new vertex
  520. CHECK_DATABUF_LIMITS(lpdp2d, wIndex1 + wIndxBase);
  521. CHECK_DATABUF_LIMITS(lpdp2d, wIndex2 + wIndxBase);
  522. P2_Draw_FVF_Line(pContext, lpV1, lpV2, lpV1, &P2FVFOff);
  523. lpPrim += sizeof(D3DHAL_DP2INDEXEDLINELIST);
  524. }
  525. NEXTINSTRUCTION(lpIns, D3DHAL_DP2INDEXEDLINELIST,
  526. lpIns->wPrimitiveCount, STARTVERTEXSIZE);
  527. break;
  528. case D3DDP2OP_LINESTRIP:
  529. DBG_D3D((8,"D3DDP2OP_LINESTRIP"));
  530. // Non-index line strips rendered with vertex buffers are
  531. // specified using D3DHAL_DP2LINESTRIP. The first vertex
  532. // in the line strip is specified by wVStart. The
  533. // number of lines to process is specified by the
  534. // wPrimitiveCount field of D3DHAL_DP2COMMAND. The sequence
  535. // of lines rendered will be (wVStart, wVStart+1),
  536. // (wVStart+1, wVStart+2),(wVStart+2, wVStart+3),...,
  537. // (wVStart+wPrimitiveCount, wVStart+wPrimitiveCount+1).
  538. // Verify the command buffer validity
  539. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim, D3DHAL_DP2LINESTRIP, 1, 0);
  540. wIndex = ((D3DHAL_DP2LINESTRIP*)lpPrim)->wVStart;
  541. lpV0 = LP_FVF_VERTEX(lpVertices, wIndex, P2FVFOff);
  542. lpV1 = LP_FVF_NXT_VTX(lpV0, P2FVFOff);
  543. // Check first & last vertex
  544. CHECK_DATABUF_LIMITS(lpdp2d, wIndex);
  545. CHECK_DATABUF_LIMITS(lpdp2d, wIndex + lpIns->wPrimitiveCount);
  546. for (i = lpIns->wPrimitiveCount; i > 0; i--)
  547. {
  548. P2_Draw_FVF_Line(pContext, lpV0, lpV1, lpV0, &P2FVFOff);
  549. lpV0 = lpV1;
  550. lpV1 = LP_FVF_NXT_VTX(lpV1, P2FVFOff);
  551. }
  552. NEXTINSTRUCTION(lpIns, D3DHAL_DP2LINESTRIP, 1, 0);
  553. break;
  554. case D3DDP2OP_INDEXEDLINESTRIP:
  555. DBG_D3D((8,"D3DDP2OP_INDEXEDLINESTRIP"));
  556. // Indexed line strips rendered with vertex buffers are
  557. // specified using D3DHAL_DP2INDEXEDLINESTRIP. The number
  558. // of lines to process is specified by the wPrimitiveCount
  559. // field of D3DHAL_DP2COMMAND. The sequence of lines
  560. // rendered will be (wV[0], wV[1]), (wV[1], wV[2]),
  561. // (wV[2], wV[3]), ...
  562. // (wVStart[wPrimitiveCount-1], wVStart[wPrimitiveCount]).
  563. // Although the D3DHAL_DP2INDEXEDLINESTRIP structure only
  564. // has enough space allocated for a single line, the wV
  565. // array of indices should be treated as a variable-sized
  566. // array with wPrimitiveCount+1 elements.
  567. // The indexes are relative to a base index value that
  568. // immediately follows the command
  569. // Verify the command buffer validity
  570. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  571. WORD, lpIns->wPrimitiveCount + 1, STARTVERTEXSIZE);
  572. wIndxBase = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
  573. lpPrim = lpPrim + sizeof(D3DHAL_DP2STARTVERTEX);
  574. // guard defensively against pathological commands
  575. if ( lpIns->wPrimitiveCount > 0 )
  576. {
  577. wIndex1 = ((D3DHAL_DP2INDEXEDLINESTRIP*)lpPrim)->wV[0];
  578. wIndex2 = ((D3DHAL_DP2INDEXEDLINESTRIP*)lpPrim)->wV[1];
  579. lpV1 =
  580. lpV2 = LP_FVF_VERTEX(lpVertices, wIndex1+wIndxBase, P2FVFOff);
  581. //We need to check each vertex separately
  582. CHECK_DATABUF_LIMITS(lpdp2d, wIndex1 + wIndxBase);
  583. }
  584. for (i = 0; i < lpIns->wPrimitiveCount; i++)
  585. {
  586. lpV1 = lpV2;
  587. lpV2 = LP_FVF_VERTEX(lpVertices, wIndex2 + wIndxBase, P2FVFOff);
  588. CHECK_DATABUF_LIMITS(lpdp2d, wIndex2 + wIndxBase);
  589. P2_Draw_FVF_Line(pContext, lpV1, lpV2, lpV1, &P2FVFOff);
  590. if ( i % 2 )
  591. {
  592. wIndex2 = ((D3DHAL_DP2INDEXEDLINESTRIP*)lpPrim)->wV[1];
  593. }
  594. else if ( (i+1) < lpIns->wPrimitiveCount )
  595. {
  596. // advance to the next element only if we're not done yet
  597. lpPrim += sizeof(D3DHAL_DP2INDEXEDLINESTRIP);
  598. wIndex2 = ((D3DHAL_DP2INDEXEDLINESTRIP*)lpPrim)->wV[0];
  599. }
  600. }
  601. // Point to next D3DHAL_DP2COMMAND in the command buffer
  602. // Advance only as many vertex indices there are, with no padding!
  603. NEXTINSTRUCTION(lpIns, WORD,
  604. lpIns->wPrimitiveCount + 1, STARTVERTEXSIZE);
  605. break;
  606. case D3DDP2OP_TRIANGLELIST:
  607. DBG_D3D((8,"D3DDP2OP_TRIANGLELIST"));
  608. // Non-indexed vertex buffer triangle lists are defined by
  609. // the D3DHAL_DP2TRIANGLELIST structure. Given an initial
  610. // vertex, the driver will render independent triangles,
  611. // processing three new vertices with each triangle. The
  612. // number of triangles to render is specified by the
  613. // wPrimitveCount field of D3DHAL_DP2COMMAND. The sequence
  614. // of vertices processed will be (wVStart, wVStart+1,
  615. // vVStart+2), (wVStart+3, wVStart+4, vVStart+5),...,
  616. // (wVStart+(wPrimitiveCount-1)*3), wVStart+wPrimitiveCount*3-2,
  617. // vStart+wPrimitiveCount*3-1).
  618. // Verify the command buffer validity
  619. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim, D3DHAL_DP2TRIANGLELIST, 1, 0);
  620. wIndex = ((D3DHAL_DP2TRIANGLELIST*)lpPrim)->wVStart;
  621. lpV0 = LP_FVF_VERTEX(lpVertices, wIndex, P2FVFOff);
  622. lpV1 = LP_FVF_NXT_VTX(lpV0, P2FVFOff);
  623. lpV2 = LP_FVF_NXT_VTX(lpV1, P2FVFOff);
  624. // Check first & last vertex
  625. CHECK_DATABUF_LIMITS(lpdp2d, wIndex);
  626. CHECK_DATABUF_LIMITS(lpdp2d,
  627. ((LONG)wIndex + 3*lpIns->wPrimitiveCount - 1) );
  628. for (i = lpIns->wPrimitiveCount; i > 0; i--)
  629. {
  630. if (!CULL_TRI(pContext,lpV0,lpV1,lpV2))
  631. (*pTriangle)(pContext, lpV0, lpV1, lpV2, &P2FVFOff);
  632. lpV0 = LP_FVF_NXT_VTX(lpV2, P2FVFOff);
  633. lpV1 = LP_FVF_NXT_VTX(lpV0, P2FVFOff);
  634. lpV2 = LP_FVF_NXT_VTX(lpV1, P2FVFOff);
  635. }
  636. NEXTINSTRUCTION(lpIns, D3DHAL_DP2TRIANGLELIST, 1, 0);
  637. break;
  638. case D3DDP2OP_INDEXEDTRIANGLELIST:
  639. DBG_D3D((8,"D3DDP2OP_INDEXEDTRIANGLELIST"));
  640. // The D3DHAL_DP2INDEXEDTRIANGLELIST structure specifies
  641. // unconnected triangles to render with a vertex buffer.
  642. // The vertex indices are specified by wV1, wV2 and wV3.
  643. // The wFlags field allows specifying edge flags identical
  644. // to those specified by D3DOP_TRIANGLE. The number of
  645. // triangles to render (that is, number of
  646. // D3DHAL_DP2INDEXEDTRIANGLELIST structures to process)
  647. // is specified by the wPrimitiveCount field of
  648. // D3DHAL_DP2COMMAND.
  649. // This is the only indexed primitive where we don't get
  650. // an offset into the vertex buffer in order to maintain
  651. // DX3 compatibility. A new primitive
  652. // (D3DDP2OP_INDEXEDTRIANGLELIST2) has been added to handle
  653. // the corresponding DX6 primitive.
  654. // Verify the command buffer validity
  655. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  656. D3DHAL_DP2INDEXEDTRIANGLELIST, lpIns->wPrimitiveCount, 0);
  657. for (i = lpIns->wPrimitiveCount; i > 0; i--)
  658. {
  659. wIndex1 = ((D3DHAL_DP2INDEXEDTRIANGLELIST*)lpPrim)->wV1;
  660. wIndex2 = ((D3DHAL_DP2INDEXEDTRIANGLELIST*)lpPrim)->wV2;
  661. wIndex3 = ((D3DHAL_DP2INDEXEDTRIANGLELIST*)lpPrim)->wV3;
  662. wFlags = ((D3DHAL_DP2INDEXEDTRIANGLELIST*)lpPrim)->wFlags;
  663. lpV1 = LP_FVF_VERTEX(lpVertices, wIndex1, P2FVFOff);
  664. lpV2 = LP_FVF_VERTEX(lpVertices, wIndex2, P2FVFOff);
  665. lpV3 = LP_FVF_VERTEX(lpVertices, wIndex3, P2FVFOff);
  666. // Must check each new vertex
  667. CHECK_DATABUF_LIMITS(lpdp2d, wIndex1);
  668. CHECK_DATABUF_LIMITS(lpdp2d, wIndex2);
  669. CHECK_DATABUF_LIMITS(lpdp2d, wIndex3);
  670. if (!CULL_TRI(pContext,lpV1,lpV2,lpV3))
  671. {
  672. if (pContext->Hdr.FillMode == D3DFILL_POINT)
  673. {
  674. (*pPoint)( pContext, lpV1, &P2FVFOff);
  675. (*pPoint)( pContext, lpV2, &P2FVFOff);
  676. (*pPoint)( pContext, lpV3, &P2FVFOff);
  677. }
  678. else if (pContext->Hdr.FillMode == D3DFILL_WIREFRAME)
  679. {
  680. if ( wFlags & D3DTRIFLAG_EDGEENABLE1 )
  681. P2_Draw_FVF_Line( pContext,
  682. lpV1, lpV2, lpV1, &P2FVFOff);
  683. if ( wFlags & D3DTRIFLAG_EDGEENABLE2 )
  684. P2_Draw_FVF_Line( pContext,
  685. lpV2, lpV3, lpV1, &P2FVFOff);
  686. if ( wFlags & D3DTRIFLAG_EDGEENABLE3 )
  687. P2_Draw_FVF_Line( pContext,
  688. lpV3, lpV1, lpV1, &P2FVFOff);
  689. }
  690. else
  691. (*pTriangle)(pContext, lpV1, lpV2, lpV3, &P2FVFOff);
  692. }
  693. lpPrim += sizeof(D3DHAL_DP2INDEXEDTRIANGLELIST);
  694. }
  695. NEXTINSTRUCTION(lpIns, D3DHAL_DP2INDEXEDTRIANGLELIST,
  696. lpIns->wPrimitiveCount, 0);
  697. break;
  698. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  699. DBG_D3D((8,"D3DDP2OP_INDEXEDTRIANGLELIST2 "));
  700. // The D3DHAL_DP2INDEXEDTRIANGLELIST2 structure specifies
  701. // unconnected triangles to render with a vertex buffer.
  702. // The vertex indices are specified by wV1, wV2 and wV3.
  703. // The wFlags field allows specifying edge flags identical
  704. // to those specified by D3DOP_TRIANGLE. The number of
  705. // triangles to render (that is, number of
  706. // D3DHAL_DP2INDEXEDTRIANGLELIST structures to process)
  707. // is specified by the wPrimitiveCount field of
  708. // D3DHAL_DP2COMMAND.
  709. // The indexes are relative to a base index value that
  710. // immediately follows the command
  711. // Verify the command buffer validity
  712. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  713. D3DHAL_DP2INDEXEDTRIANGLELIST2, lpIns->wPrimitiveCount,
  714. STARTVERTEXSIZE);
  715. // Access base index here
  716. wIndxBase = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
  717. lpPrim = lpPrim + sizeof(D3DHAL_DP2STARTVERTEX);
  718. for (i = lpIns->wPrimitiveCount; i > 0; i--)
  719. {
  720. wIndex1 = ((D3DHAL_DP2INDEXEDTRIANGLELIST2*)lpPrim)->wV1;
  721. wIndex2 = ((D3DHAL_DP2INDEXEDTRIANGLELIST2*)lpPrim)->wV2;
  722. wIndex3 = ((D3DHAL_DP2INDEXEDTRIANGLELIST2*)lpPrim)->wV3;
  723. lpV1 = LP_FVF_VERTEX(lpVertices, wIndex1+wIndxBase, P2FVFOff);
  724. lpV2 = LP_FVF_VERTEX(lpVertices, wIndex2+wIndxBase, P2FVFOff);
  725. lpV3 = LP_FVF_VERTEX(lpVertices, wIndex3+wIndxBase, P2FVFOff);
  726. // Must check each new vertex
  727. CHECK_DATABUF_LIMITS(lpdp2d, wIndex1 + wIndxBase);
  728. CHECK_DATABUF_LIMITS(lpdp2d, wIndex2 + wIndxBase);
  729. CHECK_DATABUF_LIMITS(lpdp2d, wIndex3 + wIndxBase);
  730. if (!CULL_TRI(pContext,lpV1,lpV2,lpV3))
  731. {
  732. if (pContext->Hdr.FillMode == D3DFILL_POINT)
  733. {
  734. (*pPoint)( pContext, lpV1, &P2FVFOff);
  735. (*pPoint)( pContext, lpV2, &P2FVFOff);
  736. (*pPoint)( pContext, lpV3, &P2FVFOff);
  737. }
  738. else if (pContext->Hdr.FillMode == D3DFILL_WIREFRAME)
  739. {
  740. P2_Draw_FVF_Line( pContext,
  741. lpV1, lpV2, lpV1, &P2FVFOff);
  742. P2_Draw_FVF_Line( pContext,
  743. lpV2, lpV3, lpV1, &P2FVFOff);
  744. P2_Draw_FVF_Line( pContext,
  745. lpV3, lpV1, lpV1, &P2FVFOff);
  746. }
  747. else
  748. (*pTriangle)(pContext, lpV1, lpV2, lpV3, &P2FVFOff);
  749. }
  750. lpPrim += sizeof(D3DHAL_DP2INDEXEDTRIANGLELIST2);
  751. }
  752. NEXTINSTRUCTION(lpIns, D3DHAL_DP2INDEXEDTRIANGLELIST2,
  753. lpIns->wPrimitiveCount, STARTVERTEXSIZE);
  754. break;
  755. case D3DDP2OP_TRIANGLESTRIP:
  756. DBG_D3D((8,"D3DDP2OP_TRIANGLESTRIP"));
  757. // Non-index triangle strips rendered with vertex buffers
  758. // are specified using D3DHAL_DP2TRIANGLESTRIP. The first
  759. // vertex in the triangle strip is specified by wVStart.
  760. // The number of triangles to process is specified by the
  761. // wPrimitiveCount field of D3DHAL_DP2COMMAND. The sequence
  762. // of triangles rendered for the odd-triangles case will
  763. // be (wVStart, wVStart+1, vVStart+2), (wVStart+1,
  764. // wVStart+3, vVStart+2),.(wVStart+2, wVStart+3,
  765. // vVStart+4),.., (wVStart+wPrimitiveCount-1),
  766. // wVStart+wPrimitiveCount, vStart+wPrimitiveCount+1). For an
  767. // even number of , the last triangle will be .,
  768. // (wVStart+wPrimitiveCount-1, vStart+wPrimitiveCount+1,
  769. // wVStart+wPrimitiveCount).
  770. // Verify the command buffer validity
  771. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim, D3DHAL_DP2TRIANGLESTRIP, 1, 0);
  772. // guard defensively against pathological commands
  773. if ( lpIns->wPrimitiveCount > 0 )
  774. {
  775. wIndex = ((D3DHAL_DP2TRIANGLESTRIP*)lpPrim)->wVStart;
  776. lpV2 = LP_FVF_VERTEX(lpVertices, wIndex, P2FVFOff);
  777. lpV1 = LP_FVF_NXT_VTX(lpV2, P2FVFOff);
  778. // Check first and last vertex
  779. CHECK_DATABUF_LIMITS(lpdp2d, wIndex);
  780. CHECK_DATABUF_LIMITS(lpdp2d,
  781. wIndex + lpIns->wPrimitiveCount + 1);
  782. }
  783. for (i = 0; i < lpIns->wPrimitiveCount; i++)
  784. {
  785. if ( i % 2 )
  786. {
  787. lpV0 = lpV1;
  788. lpV1 = LP_FVF_NXT_VTX(lpV2, P2FVFOff);
  789. }
  790. else
  791. {
  792. lpV0 = lpV2;
  793. lpV2 = LP_FVF_NXT_VTX(lpV1, P2FVFOff);
  794. }
  795. if (!CULL_TRI(pContext,lpV0,lpV1,lpV2))
  796. (*pTriangle)(pContext, lpV0, lpV1, lpV2, &P2FVFOff);
  797. }
  798. // Point to next D3DHAL_DP2COMMAND in the command buffer
  799. NEXTINSTRUCTION(lpIns, D3DHAL_DP2TRIANGLESTRIP, 1, 0);
  800. break;
  801. case D3DDP2OP_INDEXEDTRIANGLESTRIP:
  802. DBG_D3D((8,"D3DDP2OP_INDEXEDTRIANGLESTRIP"));
  803. // Indexed triangle strips rendered with vertex buffers are
  804. // specified using D3DHAL_DP2INDEXEDTRIANGLESTRIP. The number
  805. // of triangles to process is specified by the wPrimitiveCount
  806. // field of D3DHAL_DP2COMMAND. The sequence of triangles
  807. // rendered for the odd-triangles case will be
  808. // (wV[0],wV[1],wV[2]),(wV[1],wV[3],wV[2]),
  809. // (wV[2],wV[3],wV[4]),...,(wV[wPrimitiveCount-1],
  810. // wV[wPrimitiveCount],wV[wPrimitiveCount+1]). For an even
  811. // number of triangles, the last triangle will be
  812. // (wV[wPrimitiveCount-1],wV[wPrimitiveCount+1],
  813. // wV[wPrimitiveCount]).Although the
  814. // D3DHAL_DP2INDEXEDTRIANGLESTRIP structure only has
  815. // enough space allocated for a single line, the wV
  816. // array of indices should be treated as a variable-sized
  817. // array with wPrimitiveCount+2 elements.
  818. // The indexes are relative to a base index value that
  819. // immediately follows the command
  820. // Verify the command buffer validity
  821. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  822. WORD, lpIns->wPrimitiveCount + 2, STARTVERTEXSIZE);
  823. // Access base index
  824. wIndxBase = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
  825. lpPrim = lpPrim + sizeof(D3DHAL_DP2STARTVERTEX);
  826. // guard defensively against pathological commands
  827. if ( lpIns->wPrimitiveCount > 0 )
  828. {
  829. wIndex = ((D3DHAL_DP2INDEXEDTRIANGLESTRIP*)lpPrim)->wV[0];
  830. wIndex1 = ((D3DHAL_DP2INDEXEDTRIANGLESTRIP*)lpPrim)->wV[1];
  831. // We need to check each vertex
  832. CHECK_DATABUF_LIMITS(lpdp2d, wIndex + wIndxBase);
  833. CHECK_DATABUF_LIMITS(lpdp2d, wIndex1 + wIndxBase);
  834. lpV2 = LP_FVF_VERTEX(lpVertices, wIndex + wIndxBase, P2FVFOff);
  835. lpV1 = LP_FVF_VERTEX(lpVertices, wIndex1 + wIndxBase, P2FVFOff);
  836. }
  837. for (i = 0; i < lpIns->wPrimitiveCount; i++)
  838. {
  839. wIndex2 = ((D3DHAL_DP2INDEXEDTRIANGLESTRIP*)lpPrim)->wV[2];
  840. // We need to check each new vertex
  841. CHECK_DATABUF_LIMITS(lpdp2d, wIndex2+wIndxBase);
  842. if ( i % 2 )
  843. {
  844. lpV0 = lpV1;
  845. lpV1 = LP_FVF_VERTEX(lpVertices, wIndex2+wIndxBase, P2FVFOff);
  846. }
  847. else
  848. {
  849. lpV0 = lpV2;
  850. lpV2 = LP_FVF_VERTEX(lpVertices, wIndex2+wIndxBase, P2FVFOff);
  851. }
  852. if (!CULL_TRI(pContext,lpV0,lpV1,lpV2))
  853. (*pTriangle)(pContext, lpV0, lpV1, lpV2, &P2FVFOff);
  854. // We will advance our pointer only one WORD in order
  855. // to fetch the next index
  856. lpPrim += sizeof(WORD);
  857. }
  858. // Point to next D3DHAL_DP2COMMAND in the command buffer
  859. NEXTINSTRUCTION(lpIns, WORD ,
  860. lpIns->wPrimitiveCount + 2, STARTVERTEXSIZE);
  861. break;
  862. case D3DDP2OP_TRIANGLEFAN:
  863. DBG_D3D((8,"D3DDP2OP_TRIANGLEFAN"));
  864. // The D3DHAL_DP2TRIANGLEFAN structure is used to draw
  865. // non-indexed triangle fans. The sequence of triangles
  866. // rendered will be (wVstart+1, wVStart+2, wVStart),
  867. // (wVStart+2,wVStart+3,wVStart), (wVStart+3,wVStart+4
  868. // wVStart),...,(wVStart+wPrimitiveCount,
  869. // wVStart+wPrimitiveCount+1,wVStart).
  870. // Verify the command buffer validity
  871. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim, D3DHAL_DP2TRIANGLEFAN, 1, 0);
  872. wIndex = ((D3DHAL_DP2TRIANGLEFAN*)lpPrim)->wVStart;
  873. lpV0 = LP_FVF_VERTEX(lpVertices, wIndex, P2FVFOff);
  874. lpV1 = LP_FVF_NXT_VTX(lpV0, P2FVFOff);
  875. lpV2 = LP_FVF_NXT_VTX(lpV1, P2FVFOff);
  876. // Check first & last vertex
  877. CHECK_DATABUF_LIMITS(lpdp2d, wIndex);
  878. CHECK_DATABUF_LIMITS(lpdp2d, wIndex + lpIns->wPrimitiveCount + 1);
  879. for (i = 0; i < lpIns->wPrimitiveCount; i++)
  880. {
  881. if (!CULL_TRI(pContext,lpV0,lpV1,lpV2))
  882. (*pTriangle)(pContext, lpV1, lpV2, lpV0, &P2FVFOff);
  883. lpV1 = lpV2;
  884. lpV2 = LP_FVF_NXT_VTX(lpV2, P2FVFOff);
  885. }
  886. NEXTINSTRUCTION(lpIns, D3DHAL_DP2TRIANGLEFAN, 1, 0);
  887. break;
  888. case D3DDP2OP_INDEXEDTRIANGLEFAN:
  889. DBG_D3D((8,"D3DDP2OP_INDEXEDTRIANGLEFAN"));
  890. // The D3DHAL_DP2INDEXEDTRIANGLEFAN structure is used to
  891. // draw indexed triangle fans. The sequence of triangles
  892. // rendered will be (wV[1], wV[2],wV[0]), (wV[2], wV[3],
  893. // wV[0]), (wV[3], wV[4], wV[0]),...,
  894. // (wV[wPrimitiveCount], wV[wPrimitiveCount+1],wV[0]).
  895. // The indexes are relative to a base index value that
  896. // immediately follows the command
  897. // Verify the command buffer validity
  898. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  899. WORD, lpIns->wPrimitiveCount + 2, STARTVERTEXSIZE);
  900. wIndxBase = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
  901. lpPrim = lpPrim + sizeof(D3DHAL_DP2STARTVERTEX);
  902. // guard defensively against pathological commands
  903. if ( lpIns->wPrimitiveCount > 0 )
  904. {
  905. wIndex = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[0];
  906. wIndex1 = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[1];
  907. lpV0 = LP_FVF_VERTEX(lpVertices, wIndex + wIndxBase, P2FVFOff);
  908. lpV1 =
  909. lpV2 = LP_FVF_VERTEX(lpVertices, wIndex1 + wIndxBase, P2FVFOff);
  910. // We need to check each vertex
  911. CHECK_DATABUF_LIMITS(lpdp2d, wIndex + wIndxBase);
  912. CHECK_DATABUF_LIMITS(lpdp2d, wIndex1 + wIndxBase);
  913. }
  914. for (i = 0; i < lpIns->wPrimitiveCount; i++)
  915. {
  916. wIndex2 = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[2];
  917. lpV1 = lpV2;
  918. lpV2 = LP_FVF_VERTEX(lpVertices, wIndex2 + wIndxBase, P2FVFOff);
  919. // We need to check each vertex
  920. CHECK_DATABUF_LIMITS(lpdp2d, wIndex2 + wIndxBase);
  921. if (!CULL_TRI(pContext,lpV0,lpV1,lpV2))
  922. (*pTriangle)(pContext, lpV1, lpV2, lpV0, &P2FVFOff);
  923. // We will advance our pointer only one WORD in order
  924. // to fetch the next index
  925. lpPrim += sizeof(WORD);
  926. }
  927. // Point to next D3DHAL_DP2COMMAND in the command buffer
  928. NEXTINSTRUCTION(lpIns, WORD ,
  929. lpIns->wPrimitiveCount + 2, STARTVERTEXSIZE);
  930. break;
  931. case D3DDP2OP_LINELIST_IMM:
  932. DBG_D3D((8,"D3DDP2OP_LINELIST_IMM"));
  933. // Draw a set of lines specified by pairs of vertices
  934. // that immediately follow this instruction in the
  935. // command stream. The wPrimitiveCount member of the
  936. // D3DHAL_DP2COMMAND structure specifies the number
  937. // of lines that follow. The type and size of the
  938. // vertices are determined by the dwVertexType member
  939. // of the D3DHAL_DRAWPRIMITIVES2DATA structure.
  940. // Primitives in an IMM instruction are stored in the
  941. // command buffer and are DWORD aligned
  942. lpPrim = (LPBYTE)((ULONG_PTR)(lpPrim + 3 ) & ~3 );
  943. // Verify the command buffer validity
  944. CHECK_CMDBUF_LIMITS_S(lpdp2d, lpPrim,
  945. P2FVFOff.dwStride, lpIns->wPrimitiveCount + 1, 0);
  946. // Get vertex pointers
  947. lpV0 = (LPD3DTLVERTEX)lpPrim;
  948. lpV1 = LP_FVF_NXT_VTX(lpV0, P2FVFOff);
  949. for (i = 0; i < lpIns->wPrimitiveCount; i++)
  950. {
  951. P2_Draw_FVF_Line(pContext, lpV0, lpV1, lpV0, &P2FVFOff);
  952. lpV0 = lpV1;
  953. lpV1 = LP_FVF_NXT_VTX(lpV1, P2FVFOff);
  954. }
  955. // Realign next command since vertices are dword aligned
  956. // and store # of primitives before affecting the pointer
  957. wCount = lpIns->wPrimitiveCount;
  958. lpIns = (LPD3DHAL_DP2COMMAND)(( ((ULONG_PTR)lpIns) + 3 ) & ~ 3);
  959. NEXTINSTRUCTION_S(lpIns, P2FVFOff.dwStride, wCount + 1, 0);
  960. break;
  961. case D3DDP2OP_TRIANGLEFAN_IMM:
  962. DBG_D3D((8,"D3DDP2OP_TRIANGLEFAN_IMM"));
  963. // Draw a triangle fan specified by pairs of vertices
  964. // that immediately follow this instruction in the
  965. // command stream. The wPrimitiveCount member of the
  966. // D3DHAL_DP2COMMAND structure specifies the number
  967. // of triangles that follow. The type and size of the
  968. // vertices are determined by the dwVertexType member
  969. // of the D3DHAL_DRAWPRIMITIVES2DATA structure.
  970. // Verify the command buffer validity for the first structure
  971. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  972. BYTE , 0 , sizeof(D3DHAL_DP2TRIANGLEFAN_IMM));
  973. // Get Edge flags (we still have to process them)
  974. dwEdgeFlags = ((D3DHAL_DP2TRIANGLEFAN_IMM *)lpPrim)->dwEdgeFlags;
  975. lpPrim = (LPBYTE)lpPrim + sizeof(D3DHAL_DP2TRIANGLEFAN_IMM);
  976. // Vertices in an IMM instruction are stored in the
  977. // command buffer and are DWORD aligned
  978. lpPrim = (LPBYTE)((ULONG_PTR)(lpPrim + 3 ) & ~3 );
  979. // Verify the rest of the command buffer
  980. CHECK_CMDBUF_LIMITS_S(lpdp2d, lpPrim,
  981. P2FVFOff.dwStride, lpIns->wPrimitiveCount + 2, 0);
  982. // Get vertex pointers
  983. lpV0 = (LPD3DTLVERTEX)lpPrim;
  984. lpV1 = LP_FVF_NXT_VTX(lpV0, P2FVFOff);
  985. lpV2 = LP_FVF_NXT_VTX(lpV1, P2FVFOff);
  986. for (i = 0 ; i < lpIns->wPrimitiveCount ; i++)
  987. {
  988. if (!CULL_TRI(pContext,lpV0,lpV1,lpV2))
  989. {
  990. if (pContext->Hdr.FillMode == D3DFILL_POINT)
  991. {
  992. if (0 == i)
  993. {
  994. (*pPoint)( pContext, lpV0, &P2FVFOff);
  995. (*pPoint)( pContext, lpV1, &P2FVFOff);
  996. }
  997. (*pPoint)( pContext, lpV2, &P2FVFOff);
  998. }
  999. else if (pContext->Hdr.FillMode == D3DFILL_WIREFRAME)
  1000. {
  1001. // dwEdgeFlags is a bit sequence representing the edge
  1002. // flag for each one of the outer edges of the
  1003. // triangle fan
  1004. if (0 == i)
  1005. {
  1006. if (dwEdgeFlags & 0x0001)
  1007. P2_Draw_FVF_Line( pContext, lpV0, lpV1, lpV0,
  1008. &P2FVFOff);
  1009. dwEdgeFlags >>= 1;
  1010. }
  1011. if (dwEdgeFlags & 0x0001)
  1012. P2_Draw_FVF_Line( pContext, lpV1, lpV2, lpV0,
  1013. &P2FVFOff);
  1014. dwEdgeFlags >>= 1;
  1015. if (i == (UINT)lpIns->wPrimitiveCount - 1)
  1016. {
  1017. // last triangle fan edge
  1018. if (dwEdgeFlags & 0x0001)
  1019. P2_Draw_FVF_Line( pContext, lpV2, lpV0, lpV0,
  1020. &P2FVFOff);
  1021. }
  1022. }
  1023. else
  1024. (*pTriangle)(pContext, lpV1, lpV2, lpV0, &P2FVFOff);
  1025. }
  1026. lpV1 = lpV2;
  1027. lpV2 = LP_FVF_NXT_VTX(lpV2, P2FVFOff);
  1028. }
  1029. // Realign next command since vertices are dword aligned
  1030. // and store # of primitives before affecting the pointer
  1031. wCount = lpIns->wPrimitiveCount;
  1032. lpIns = (LPD3DHAL_DP2COMMAND)(( ((ULONG_PTR)lpIns) + 3 ) & ~ 3);
  1033. NEXTINSTRUCTION_S(lpIns, P2FVFOff.dwStride,
  1034. wCount + 2, sizeof(D3DHAL_DP2TRIANGLEFAN_IMM));
  1035. break;
  1036. case D3DDP2OP_TEXBLT:
  1037. // Inform the drivers to perform a BitBlt operation from a source
  1038. // texture to a destination texture. A texture can also be cubic
  1039. // environment map. The driver should copy a rectangle specified
  1040. // by rSrc in the source texture to the location specified by pDest
  1041. // in the destination texture. The destination and source textures
  1042. // are identified by handles that the driver was notified with
  1043. // during texture creation time. If the driver is capable of
  1044. // managing textures, then it is possible that the destination
  1045. // handle is 0. This indicates to the driver that it should preload
  1046. // the texture into video memory (or wherever the hardware
  1047. // efficiently textures from). In this case, it can ignore rSrc and
  1048. // pDest. Note that for mipmapped textures, only one D3DDP2OP_TEXBLT
  1049. // instruction is inserted into the D3dDrawPrimitives2 command stream.
  1050. // In this case, the driver is expected to BitBlt all the mipmap
  1051. // levels present in the texture.
  1052. // Verify the command buffer validity
  1053. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  1054. D3DHAL_DP2TEXBLT, lpIns->wStateCount, 0);
  1055. DBG_D3D((8,"D3DDP2OP_TEXBLT"));
  1056. for ( i = 0; i < lpIns->wStateCount; i++)
  1057. {
  1058. __TextureBlt(pContext, (D3DHAL_DP2TEXBLT*)(lpPrim));
  1059. lpPrim += sizeof(D3DHAL_DP2TEXBLT);
  1060. }
  1061. //need to restore following registers
  1062. RESERVEDMAPTR(15);
  1063. SEND_PERMEDIA_DATA(FBReadPixel, pSoftPermedia->FBReadPixel);
  1064. COPY_PERMEDIA_DATA(FBReadMode, pSoftPermedia->FBReadMode);
  1065. SEND_PERMEDIA_DATA(FBSourceOffset, 0x0);
  1066. SEND_PERMEDIA_DATA(FBPixelOffset, pContext->PixelOffset);
  1067. SEND_PERMEDIA_DATA(FBWindowBase,0);
  1068. COPY_PERMEDIA_DATA(Window, pSoftPermedia->Window);
  1069. COPY_PERMEDIA_DATA(AlphaBlendMode, pSoftPermedia->AlphaBlendMode);
  1070. COPY_PERMEDIA_DATA(DitherMode, pSoftPermedia->DitherMode);
  1071. COPY_PERMEDIA_DATA(ColorDDAMode, pSoftPermedia->ColorDDAMode);
  1072. COPY_PERMEDIA_DATA(TextureColorMode,
  1073. pSoftPermedia->TextureColorMode);
  1074. COPY_PERMEDIA_DATA(TextureReadMode,
  1075. pSoftPermedia->TextureReadMode);
  1076. COPY_PERMEDIA_DATA(TextureAddressMode,
  1077. pSoftPermedia->TextureAddressMode);
  1078. COPY_PERMEDIA_DATA(TextureDataFormat,
  1079. pSoftPermedia->TextureDataFormat);
  1080. COPY_PERMEDIA_DATA(TextureMapFormat,
  1081. pSoftPermedia->TextureMapFormat);
  1082. if (pContext->CurrentTextureHandle)
  1083. {
  1084. PERMEDIA_D3DTEXTURE* pTexture;
  1085. pTexture = TextureHandleToPtr(pContext->CurrentTextureHandle,
  1086. pContext);
  1087. if (NULL != pTexture)
  1088. {
  1089. SEND_PERMEDIA_DATA(TextureBaseAddress,
  1090. pTexture->MipLevels[0].PixelOffset);
  1091. }
  1092. }
  1093. COMMITDMAPTR();
  1094. NEXTINSTRUCTION(lpIns, D3DHAL_DP2TEXBLT, lpIns->wStateCount, 0);
  1095. break;
  1096. case D3DDP2OP_STATESET:
  1097. {
  1098. P2D3DHAL_DP2STATESET *pStateSetOp = (P2D3DHAL_DP2STATESET*)(lpPrim);
  1099. DBG_D3D((8,"D3DDP2OP_STATESET"));
  1100. #if D3D_STATEBLOCKS
  1101. for (i = 0; i < lpIns->wStateCount; i++, pStateSetOp++)
  1102. {
  1103. switch (pStateSetOp->dwOperation)
  1104. {
  1105. case D3DHAL_STATESETBEGIN :
  1106. __BeginStateSet(pContext,pStateSetOp->dwParam);
  1107. break;
  1108. case D3DHAL_STATESETEND :
  1109. __EndStateSet(pContext);
  1110. break;
  1111. case D3DHAL_STATESETDELETE :
  1112. __DeleteStateSet(pContext,pStateSetOp->dwParam);
  1113. break;
  1114. case D3DHAL_STATESETEXECUTE:
  1115. __ExecuteStateSet(pContext,pStateSetOp->dwParam);
  1116. break;
  1117. case D3DHAL_STATESETCAPTURE:
  1118. __CaptureStateSet(pContext,pStateSetOp->dwParam);
  1119. break;
  1120. default :
  1121. DBG_D3D((0,"D3DDP2OP_STATESET has invalid"
  1122. "dwOperation %08lx",pStateSetOp->dwOperation));
  1123. }
  1124. }
  1125. #endif //D3D_STATEBLOCKS
  1126. // Update the command buffer pointer
  1127. NEXTINSTRUCTION(lpIns, P2D3DHAL_DP2STATESET,
  1128. lpIns->wStateCount, 0);
  1129. }
  1130. break;
  1131. case D3DDP2OP_SETPALETTE:
  1132. // Attach a palette to a texture, that is , map an association
  1133. // between a palette handle and a surface handle, and specify
  1134. // the characteristics of the palette. The number of
  1135. // D3DNTHAL_DP2SETPALETTE structures to follow is specified by
  1136. // the wStateCount member of the D3DNTHAL_DP2COMMAND structure
  1137. {
  1138. D3DHAL_DP2SETPALETTE* lpSetPal =
  1139. (D3DHAL_DP2SETPALETTE*)(lpPrim);
  1140. DBG_D3D((8,"D3DDP2OP_SETPALETTE"));
  1141. // Verify the command buffer validity
  1142. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  1143. D3DHAL_DP2SETPALETTE, lpIns->wStateCount, 0);
  1144. for (i = 0; i < lpIns->wStateCount; i++, lpSetPal++)
  1145. {
  1146. __PaletteSet(pContext,
  1147. lpSetPal->dwSurfaceHandle,
  1148. lpSetPal->dwPaletteHandle,
  1149. lpSetPal->dwPaletteFlags );
  1150. }
  1151. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETPALETTE,
  1152. lpIns->wStateCount, 0);
  1153. }
  1154. break;
  1155. case D3DDP2OP_UPDATEPALETTE:
  1156. // Perform modifications to the palette that is used for palettized
  1157. // textures. The palette handle attached to a surface is updated
  1158. // with wNumEntries PALETTEENTRYs starting at a specific wStartIndex
  1159. // member of the palette. (A PALETTENTRY (defined in wingdi.h and
  1160. // wtypes.h) is actually a DWORD with an ARGB color for each byte.)
  1161. // After the D3DNTHAL_DP2UPDATEPALETTE structure in the command
  1162. // stream the actual palette data will follow (without any padding),
  1163. // comprising one DWORD per palette entry. There will only be one
  1164. // D3DNTHAL_DP2UPDATEPALETTE structure (plus palette data) following
  1165. // the D3DNTHAL_DP2COMMAND structure regardless of the value of
  1166. // wStateCount.
  1167. {
  1168. D3DHAL_DP2UPDATEPALETTE* lpUpdatePal =
  1169. (D3DHAL_DP2UPDATEPALETTE*)(lpPrim);
  1170. PERMEDIA_D3DPALETTE* pPalette;
  1171. DBG_D3D((8,"D3DDP2OP_UPDATEPALETTE"));
  1172. // Verify the command buffer validity
  1173. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  1174. D3DHAL_DP2UPDATEPALETTE, 1,
  1175. lpUpdatePal->wNumEntries * sizeof(PALETTEENTRY));
  1176. // We will ALWAYS have only 1 palette update structure + palette
  1177. // following the D3DDP2OP_UPDATEPALETTE token
  1178. ASSERTDD(1 == lpIns->wStateCount,
  1179. "1 != wStateCount in D3DDP2OP_UPDATEPALETTE");
  1180. __PaletteUpdate(pContext,
  1181. lpUpdatePal->dwPaletteHandle,
  1182. lpUpdatePal->wStartIndex,
  1183. lpUpdatePal->wNumEntries,
  1184. (BYTE*)(lpUpdatePal+1) );
  1185. NEXTINSTRUCTION(lpIns, D3DHAL_DP2UPDATEPALETTE,
  1186. 1,
  1187. (DWORD)lpUpdatePal->wNumEntries *
  1188. sizeof(PALETTEENTRY));
  1189. }
  1190. break;
  1191. case D3DDP2OP_SETRENDERTARGET:
  1192. // Map a new rendering target surface and depth buffer in
  1193. // the current context. This replaces the old D3dSetRenderTarget
  1194. // callback.
  1195. {
  1196. D3DHAL_DP2SETRENDERTARGET* pSRTData;
  1197. // Verify the command buffer validity
  1198. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  1199. D3DHAL_DP2SETRENDERTARGET, lpIns->wStateCount, 0);
  1200. // Get new data by ignoring all but the last structure
  1201. pSRTData = (D3DHAL_DP2SETRENDERTARGET*)lpPrim +
  1202. (lpIns->wStateCount - 1);
  1203. __SetRenderTarget(pContext,
  1204. pSRTData->hRenderTarget,
  1205. pSRTData->hZBuffer);
  1206. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETRENDERTARGET,
  1207. lpIns->wStateCount, 0);
  1208. }
  1209. break;
  1210. case D3DDP2OP_CLEAR:
  1211. // Perform hardware-assisted clearing on the rendering target,
  1212. // depth buffer or stencil buffer. This replaces the old D3dClear
  1213. // and D3dClear2 callbacks.
  1214. {
  1215. D3DHAL_DP2CLEAR* pClear;
  1216. // Verify the command buffer validity
  1217. CHECK_CMDBUF_LIMITS(lpdp2d, lpPrim,
  1218. RECT, lpIns->wStateCount,
  1219. (sizeof(D3DHAL_DP2CLEAR) - sizeof(RECT)));
  1220. // Get new data by ignoring all but the last structure
  1221. pClear = (D3DHAL_DP2CLEAR*)lpPrim;
  1222. DBG_D3D((8,"D3DDP2OP_CLEAR dwFlags=%08lx dwColor=%08lx "
  1223. "dvZ=%08lx dwStencil=%08lx",
  1224. pClear->dwFlags,
  1225. pClear->dwFillColor,
  1226. (DWORD)(pClear->dvFillDepth*0x0000FFFF),
  1227. pClear->dwFillStencil));
  1228. __Clear(pContext,
  1229. pClear->dwFlags, // in: surfaces to clear
  1230. pClear->dwFillColor, // in: Color value for rtarget
  1231. pClear->dvFillDepth, // in: Depth value for
  1232. // Z-buffer (0.0-1.0)
  1233. pClear->dwFillStencil, // in: value used to clear stencil
  1234. // in: Rectangles to clear
  1235. (LPD3DRECT)((LPBYTE)pClear +
  1236. sizeof(D3DHAL_DP2CLEAR) -
  1237. sizeof(RECT)),
  1238. (DWORD)lpIns->wStateCount); // in: Number of rectangles
  1239. //need to restore following registers
  1240. RESERVEDMAPTR(4);
  1241. SEND_PERMEDIA_DATA(FBReadPixel, pSoftPermedia->FBReadPixel);
  1242. COPY_PERMEDIA_DATA(FBReadMode, pSoftPermedia->FBReadMode);
  1243. SEND_PERMEDIA_DATA(FBPixelOffset, pContext->PixelOffset);
  1244. SEND_PERMEDIA_DATA(FBWindowBase,0);
  1245. COMMITDMAPTR();
  1246. NEXTINSTRUCTION(lpIns, RECT, lpIns->wStateCount,
  1247. (sizeof(D3DHAL_DP2CLEAR) - sizeof(RECT)));
  1248. }
  1249. break;
  1250. #if D3DDX7_TL
  1251. case D3DDP2OP_SETMATERIAL:
  1252. // We don't support T&L in this driver so we only skip this data
  1253. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETMATERIAL,
  1254. lpIns->wStateCount, 0);
  1255. break;
  1256. case D3DDP2OP_SETLIGHT:
  1257. // We don't support T&L in this driver so we only skip this data
  1258. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETLIGHT,
  1259. lpIns->wStateCount, 0);
  1260. break;
  1261. case D3DDP2OP_CREATELIGHT:
  1262. // We don't support T&L in this driver so we only skip this data
  1263. NEXTINSTRUCTION(lpIns, D3DHAL_DP2CREATELIGHT,
  1264. lpIns->wStateCount, 0);
  1265. break;
  1266. case D3DDP2OP_SETTRANSFORM:
  1267. // We don't support T&L in this driver so we only skip this data
  1268. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETTRANSFORM,
  1269. lpIns->wStateCount, 0);
  1270. break;
  1271. case D3DDP2OP_ZRANGE:
  1272. // We don't support T&L in this driver so we only skip this data
  1273. NEXTINSTRUCTION(lpIns, D3DHAL_DP2ZRANGE,
  1274. lpIns->wStateCount, 0);
  1275. break;
  1276. #endif //D3DDX7_TL
  1277. default:
  1278. ASSERTDD((pContext->ppdev->pD3DParseUnknownCommand),
  1279. "D3D DX6 ParseUnknownCommand callback == NULL");
  1280. // Call the ParseUnknown callback to process
  1281. // any unidentifiable token
  1282. ddrval = (pContext->ppdev->pD3DParseUnknownCommand)
  1283. ( (VOID **) lpIns , (VOID **) &lpResumeIns);
  1284. if ( SUCCEEDED(ddrval) )
  1285. {
  1286. // Resume buffer processing after D3DParseUnknownCommand
  1287. // was succesful in processing an unknown command
  1288. lpIns = lpResumeIns;
  1289. break;
  1290. }
  1291. DBG_D3D((2,"unhandled opcode (%d)- returning "
  1292. "D3DERR_COMMAND_UNPARSED @ addr %x",
  1293. lpIns->bCommand,lpIns));
  1294. PARSE_ERROR_AND_EXIT( lpdp2d, lpIns, lpInsStart, ddrval);
  1295. } // switch
  1296. } //while
  1297. lpdp2d->ddrval = DD_OK;
  1298. Exit_DrawPrimitives2:
  1299. // any necessary housekeeping can be done here before leaving
  1300. DBG_D3D((6,"Exiting D3DDrawPrimitives2"));
  1301. return DDHAL_DRIVER_HANDLED;
  1302. } // D3DDrawPrimitives2
  1303. //-----------------------------Public Routine----------------------------------
  1304. //
  1305. // DWORD D3DValidateTextureStageState
  1306. //
  1307. // ValidateTextureStageState evaluates the current state for blending
  1308. // operations (including multitexture) and returns the number of passes the
  1309. // hardware can do it in. This is a mechanism to query the driver about
  1310. // whether it is able to handle the current stage state setup that has been
  1311. // set up in hardware. For example, some hardware cannot do two simultaneous
  1312. // modulate operations because they have only one multiplication unit and one
  1313. // addition unit.
  1314. //
  1315. // The other reason for this function is that some hardware may not map
  1316. // directly onto the Direct3D state architecture. This is a mechanism to map
  1317. // the hardware's capabilities onto what the Direct3D DDI expects.
  1318. //
  1319. // Parameters
  1320. //
  1321. // lpvtssd
  1322. //
  1323. // .dwhContext
  1324. // Context handle
  1325. // .dwFlags
  1326. // Flags, currently set to 0
  1327. // .dwReserved
  1328. // Reserved
  1329. // .dwNumPasses
  1330. // Number of passes the hardware can perform the operation in
  1331. // .ddrval
  1332. // return value
  1333. //
  1334. //-----------------------------------------------------------------------------
  1335. DWORD CALLBACK
  1336. D3DValidateTextureStageState( LPD3DHAL_VALIDATETEXTURESTAGESTATEDATA lpvtssd )
  1337. {
  1338. PERMEDIA_D3DTEXTURE *lpTexture;
  1339. PERMEDIA_D3DCONTEXT *pContext;
  1340. DWORD mag, min, cop, ca1, ca2, aop, aa1, aa2;
  1341. DBG_D3D((6,"Entering D3DValidateTextureStageState"));
  1342. pContext = (PERMEDIA_D3DCONTEXT*)ContextSlots[lpvtssd->dwhContext];
  1343. // Check if we got a valid context handle.
  1344. CHK_CONTEXT(pContext, lpvtssd->ddrval, "D3DValidateTextureStageState");
  1345. lpvtssd->dwNumPasses = 0;
  1346. lpvtssd->ddrval = DD_OK;
  1347. mag = pContext->TssStates[D3DTSS_MAGFILTER];
  1348. min = pContext->TssStates[D3DTSS_MINFILTER];
  1349. cop = pContext->TssStates[D3DTSS_COLOROP];
  1350. ca1 = pContext->TssStates[D3DTSS_COLORARG1];
  1351. ca2 = pContext->TssStates[D3DTSS_COLORARG2];
  1352. aop = pContext->TssStates[D3DTSS_ALPHAOP];
  1353. aa1 = pContext->TssStates[D3DTSS_ALPHAARG1];
  1354. aa2 = pContext->TssStates[D3DTSS_ALPHAARG2];
  1355. if (!pContext->TssStates[D3DTSS_TEXTUREMAP])
  1356. {
  1357. lpvtssd->dwNumPasses = 1;
  1358. // Current is the same as diffuse in stage 0
  1359. if (ca2 == D3DTA_CURRENT)
  1360. ca2 = D3DTA_DIFFUSE;
  1361. if (aa2 == D3DTA_CURRENT)
  1362. aa2 = D3DTA_DIFFUSE;
  1363. // Check TSS even with texture handle = 0 since
  1364. // certain operations with the fragments colors might
  1365. // be possible. Here we only allow plain "classic" rendering
  1366. if ((ca1 == D3DTA_DIFFUSE ) &&
  1367. (cop == D3DTOP_SELECTARG1) &&
  1368. (aa1 == D3DTA_DIFFUSE ) &&
  1369. (aop == D3DTOP_SELECTARG1))
  1370. {
  1371. }
  1372. else if ((ca2 == D3DTA_DIFFUSE ) &&
  1373. (cop == D3DTOP_SELECTARG2) &&
  1374. (aa2 == D3DTA_DIFFUSE) &&
  1375. (aop == D3DTOP_SELECTARG2))
  1376. {
  1377. }
  1378. // Default modulation
  1379. else if ((ca2 == D3DTA_DIFFUSE) &&
  1380. (ca1 == D3DTA_TEXTURE) &&
  1381. (cop == D3DTOP_MODULATE) &&
  1382. (aa1 == D3DTA_TEXTURE) &&
  1383. (aop == D3DTOP_SELECTARG1))
  1384. {
  1385. }
  1386. // Check disable
  1387. else if (cop == D3DTOP_DISABLE)
  1388. {
  1389. }
  1390. else
  1391. goto Fail_Validate;
  1392. }
  1393. else
  1394. if ((mag != D3DTFG_POINT && mag != D3DTFG_LINEAR) ||
  1395. (min != D3DTFG_POINT && min != D3DTFG_LINEAR)
  1396. )
  1397. {
  1398. lpvtssd->ddrval = D3DERR_CONFLICTINGTEXTUREFILTER;
  1399. DBG_D3D((2,"D3DERR_CONFLICTINGTEXTUREFILTER"));
  1400. }
  1401. else
  1402. {
  1403. lpvtssd->dwNumPasses = 1;
  1404. // Current is the same as diffuse in stage 0
  1405. if (ca2 == D3DTA_CURRENT)
  1406. ca2 = D3DTA_DIFFUSE;
  1407. if (aa2 == D3DTA_CURRENT)
  1408. aa2 = D3DTA_DIFFUSE;
  1409. // Check decal
  1410. if ((ca1 == D3DTA_TEXTURE ) &&
  1411. (cop == D3DTOP_SELECTARG1) &&
  1412. (aa1 == D3DTA_TEXTURE) &&
  1413. (aop == D3DTOP_SELECTARG1))
  1414. {
  1415. }
  1416. // Check all modulate variations
  1417. else if ((ca2 == D3DTA_DIFFUSE) &&
  1418. (ca1 == D3DTA_TEXTURE) &&
  1419. (cop == D3DTOP_MODULATE))
  1420. {
  1421. if (
  1422. // legacy (DX5) mode
  1423. ((aa1 == D3DTA_TEXTURE) &&
  1424. (aop == D3DTOP_LEGACY_ALPHAOVR)) ||
  1425. // modulate color & pass diffuse alpha
  1426. ((aa2 == D3DTA_DIFFUSE) &&
  1427. (aop == D3DTOP_SELECTARG2))
  1428. )
  1429. {
  1430. PermediaSurfaceData* pPrivateData;
  1431. // Get Texture for current stage (0) to verify properties
  1432. lpTexture = TextureHandleToPtr(
  1433. pContext->TssStates[D3DTSS_TEXTUREMAP],
  1434. pContext);
  1435. if (!CHECK_D3DSURFACE_VALIDITY(lpTexture))
  1436. {
  1437. // we're lacking key information about the texture
  1438. DBG_D3D((0,"D3DValidateTextureStageState gets "
  1439. "NULL == lpTexture"));
  1440. lpvtssd->ddrval = D3DERR_WRONGTEXTUREFORMAT;
  1441. lpvtssd->dwNumPasses = 0;
  1442. goto Exit_ValidateTSS;
  1443. }
  1444. pPrivateData = lpTexture->pTextureSurface;
  1445. if (NULL == pPrivateData)
  1446. {
  1447. // we're lacking key information about the texture
  1448. DBG_D3D((0,"D3DValidateTextureStageState gets "
  1449. "NULL == lpTexture->pTextureSurface"));
  1450. lpvtssd->ddrval = D3DERR_WRONGTEXTUREFORMAT;
  1451. lpvtssd->dwNumPasses = 0;
  1452. goto Exit_ValidateTSS;
  1453. }
  1454. // legacy texture modulation must have texture alpha
  1455. if (!pPrivateData->SurfaceFormat.bAlpha &&
  1456. (aop == D3DTOP_LEGACY_ALPHAOVR))
  1457. {
  1458. lpvtssd->ddrval = D3DERR_WRONGTEXTUREFORMAT;
  1459. lpvtssd->dwNumPasses = 0;
  1460. DBG_D3D((2,"D3DERR_WRONGTEXTUREFORMAT a format "
  1461. "with alpha must be used"));
  1462. goto Exit_ValidateTSS;
  1463. }
  1464. // modulation w diffuse alpha channel must lack texture
  1465. // alpha channel due to Permedia2 limitations on
  1466. // texture blending operations
  1467. if (pPrivateData->SurfaceFormat.bAlpha &&
  1468. (aop == D3DTOP_SELECTARG2))
  1469. {
  1470. lpvtssd->ddrval = D3DERR_WRONGTEXTUREFORMAT;
  1471. lpvtssd->dwNumPasses = 0;
  1472. DBG_D3D((2,"D3DERR_WRONGTEXTUREFORMAT a format "
  1473. "with alpha must be used"));
  1474. goto Exit_ValidateTSS;
  1475. }
  1476. }
  1477. // modulate alpha
  1478. else if ((aa2 == D3DTA_DIFFUSE) &&
  1479. (aa1 == D3DTA_TEXTURE) &&
  1480. (aop == D3DTOP_MODULATE))
  1481. {
  1482. }
  1483. // modulate color & pass texture alpha
  1484. else if ((aa1 == D3DTA_TEXTURE) &&
  1485. (aop == D3DTOP_SELECTARG1))
  1486. {
  1487. }
  1488. else
  1489. {
  1490. goto Fail_Validate;
  1491. }
  1492. }
  1493. // Check decal alpha
  1494. else if ((ca2 == D3DTA_DIFFUSE) &&
  1495. (ca1 == D3DTA_TEXTURE) &&
  1496. (cop == D3DTOP_BLENDTEXTUREALPHA) &&
  1497. (aa2 == D3DTA_DIFFUSE) &&
  1498. (aop == D3DTOP_SELECTARG2))
  1499. {
  1500. }
  1501. // Check add
  1502. else if ((ca2 == D3DTA_DIFFUSE) &&
  1503. (ca1 == D3DTA_TEXTURE) &&
  1504. (cop == D3DTOP_ADD) &&
  1505. (aa2 == D3DTA_DIFFUSE) &&
  1506. (aop == D3DTOP_SELECTARG2))
  1507. {
  1508. }
  1509. // Check disable
  1510. else if ((cop == D3DTOP_DISABLE) ||
  1511. (cop == D3DTOP_SELECTARG2 &&
  1512. ca2 == D3DTA_DIFFUSE &&
  1513. aop == D3DTOP_SELECTARG2 &&
  1514. aa2 == D3DTA_DIFFUSE) )
  1515. {
  1516. }
  1517. // Don't understand
  1518. else {
  1519. Fail_Validate:
  1520. DBG_D3D((4,"Failing with cop=%d ca1=%d ca2=%d aop=%d aa1=%d aa2=%d",
  1521. cop,ca1,ca2,aop,aa1,aa2));
  1522. if (!((cop == D3DTOP_DISABLE) ||
  1523. (cop == D3DTOP_ADD) ||
  1524. (cop == D3DTOP_MODULATE) ||
  1525. (cop == D3DTOP_BLENDTEXTUREALPHA) ||
  1526. (cop == D3DTOP_SELECTARG2) ||
  1527. (cop == D3DTOP_SELECTARG1)))
  1528. lpvtssd->ddrval = D3DERR_UNSUPPORTEDCOLOROPERATION;
  1529. else if (!((aop == D3DTOP_SELECTARG1) ||
  1530. (aop == D3DTOP_SELECTARG2) ||
  1531. (aop == D3DTOP_MODULATE) ||
  1532. (aop == D3DTOP_LEGACY_ALPHAOVR)))
  1533. lpvtssd->ddrval = D3DERR_UNSUPPORTEDALPHAOPERATION;
  1534. else if (!(ca1 == D3DTA_TEXTURE))
  1535. lpvtssd->ddrval = D3DERR_UNSUPPORTEDCOLORARG;
  1536. else if (!(ca2 == D3DTA_DIFFUSE))
  1537. lpvtssd->ddrval = D3DERR_UNSUPPORTEDCOLORARG;
  1538. else if (!(aa1 == D3DTA_TEXTURE))
  1539. lpvtssd->ddrval = D3DERR_UNSUPPORTEDALPHAARG;
  1540. else if (!(aa2 == D3DTA_DIFFUSE))
  1541. lpvtssd->ddrval = D3DERR_UNSUPPORTEDALPHAARG;
  1542. else
  1543. lpvtssd->ddrval = D3DERR_UNSUPPORTEDCOLOROPERATION;
  1544. lpvtssd->dwNumPasses = 0;
  1545. DBG_D3D((2,"D3DERR_UNSUPPORTEDCOLOROPERATION"));
  1546. goto Exit_ValidateTSS;
  1547. }
  1548. }
  1549. Exit_ValidateTSS:
  1550. DBG_D3D((6,"Exiting D3DValidateTextureStageState with dwNumPasses=%d",
  1551. lpvtssd->dwNumPasses));
  1552. return DDHAL_DRIVER_HANDLED;
  1553. } // D3DValidateTextureStageState
  1554. //-----------------------------Public Routine----------------------------------
  1555. //
  1556. // DWORD __CheckFVFRequest
  1557. //
  1558. // This utility function verifies that the requested FVF format makes sense
  1559. // and computes useful offsets into the data and a stride between succesive
  1560. // vertices.
  1561. //
  1562. //-----------------------------------------------------------------------------
  1563. DWORD
  1564. __CheckFVFRequest(DWORD dwFVF, LPP2FVFOFFSETS lpP2FVFOff)
  1565. {
  1566. DWORD stride;
  1567. UINT iTexCount;
  1568. DBG_D3D((10,"Entering __CheckFVFRequest"));
  1569. memset(lpP2FVFOff, 0, sizeof(P2FVFOFFSETS));
  1570. if ( (dwFVF & (D3DFVF_RESERVED0 | D3DFVF_RESERVED1 | D3DFVF_RESERVED2 |
  1571. D3DFVF_NORMAL)) ||
  1572. ((dwFVF & (D3DFVF_XYZ | D3DFVF_XYZRHW)) == 0) )
  1573. {
  1574. // can't set reserved bits, shouldn't have normals in
  1575. // output to rasterizers, and must have coordinates
  1576. return DDERR_INVALIDPARAMS;
  1577. }
  1578. lpP2FVFOff->dwStride = sizeof(D3DVALUE) * 3;
  1579. if (dwFVF & D3DFVF_XYZRHW)
  1580. {
  1581. lpP2FVFOff->dwStride += sizeof(D3DVALUE);
  1582. }
  1583. if (dwFVF & D3DFVF_DIFFUSE)
  1584. {
  1585. lpP2FVFOff->dwColOffset = lpP2FVFOff->dwStride;
  1586. lpP2FVFOff->dwStride += sizeof(D3DCOLOR);
  1587. }
  1588. if (dwFVF & D3DFVF_SPECULAR)
  1589. {
  1590. lpP2FVFOff->dwSpcOffset = lpP2FVFOff->dwStride;
  1591. lpP2FVFOff->dwStride += sizeof(D3DCOLOR);
  1592. }
  1593. //@@BEGIN_DDKSPLIT
  1594. #if D3D_POINTSPRITES
  1595. if (dwFVF & D3DFVF_S)
  1596. {
  1597. lpP2FVFOff->dwPntSizeOffset = lpP2FVFOff->dwStride;
  1598. lpP2FVFOff->dwStride += sizeof(D3DVALUE);
  1599. }
  1600. #endif // D3D_POINTSPRITES
  1601. //@@END_DDKSPLIT
  1602. iTexCount = (dwFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
  1603. if (iTexCount >= 1)
  1604. {
  1605. lpP2FVFOff->dwTexBaseOffset = lpP2FVFOff->dwStride;
  1606. lpP2FVFOff->dwTexOffset = lpP2FVFOff->dwTexBaseOffset;
  1607. if (0xFFFF0000 & dwFVF)
  1608. {
  1609. //expansion of FVF, these 16 bits are designated for up to
  1610. //8 sets of texture coordinates with each set having 2bits
  1611. //Normally a capable driver has to process all coordinates
  1612. //However, code below only show correct parsing w/o really
  1613. //observing all the texture coordinates.In reality,this would
  1614. //result in incorrect result.
  1615. UINT i,numcoord;
  1616. DWORD extrabits;
  1617. for (i = 0; i < iTexCount; i++)
  1618. {
  1619. extrabits= (dwFVF >> (16+2*i)) & 0x0003;
  1620. switch(extrabits)
  1621. {
  1622. case 1:
  1623. // one more D3DVALUE for 3D textures
  1624. numcoord = 3;
  1625. break;
  1626. case 2:
  1627. // two more D3DVALUEs for 4D textures
  1628. numcoord = 4;
  1629. break;
  1630. case 3:
  1631. // one less D3DVALUE for 1D textures
  1632. numcoord = 1;
  1633. break;
  1634. default:
  1635. // i.e. case 0 regular 2 D3DVALUEs
  1636. numcoord = 2;
  1637. break;
  1638. }
  1639. DBG_D3D((0,"Expanded TexCoord set %d has a offset %8lx",
  1640. i,lpP2FVFOff->dwStride));
  1641. lpP2FVFOff->dwStride += sizeof(D3DVALUE) * numcoord;
  1642. }
  1643. DBG_D3D((0,"Expanded dwVertexType=0x%08lx has %d Texture Coords "
  1644. "with total stride=0x%08lx",
  1645. dwFVF, iTexCount, lpP2FVFOff->dwStride));
  1646. }
  1647. else
  1648. lpP2FVFOff->dwStride += iTexCount * sizeof(D3DVALUE) * 2;
  1649. }
  1650. else
  1651. {
  1652. lpP2FVFOff->dwTexBaseOffset = 0;
  1653. lpP2FVFOff->dwTexOffset = 0;
  1654. }
  1655. DBG_D3D((10,"Exiting __CheckFVFRequest"));
  1656. return DD_OK;
  1657. } // __CheckFVFRequest
  1658. //-----------------------------------------------------------------------------
  1659. //
  1660. // D3DFVFDRAWTRIFUNCPTR __HWSetTriangleFunc
  1661. //
  1662. // Select the appropiate triangle rendering function depending on the
  1663. // current fillmode set for the current context
  1664. //
  1665. //-----------------------------------------------------------------------------
  1666. D3DFVFDRAWTRIFUNCPTR
  1667. __HWSetTriangleFunc(PERMEDIA_D3DCONTEXT *pContext)
  1668. {
  1669. if ( pContext->Hdr.FillMode == D3DFILL_SOLID )
  1670. return P2_Draw_FVF_Solid_Tri;
  1671. else
  1672. {
  1673. if ( pContext->Hdr.FillMode == D3DFILL_WIREFRAME )
  1674. return P2_Draw_FVF_Wire_Tri;
  1675. else
  1676. // if it isn't solid nor line it must be a point filled triangle
  1677. return P2_Draw_FVF_Point_Tri;
  1678. }
  1679. }
  1680. //-----------------------------------------------------------------------------
  1681. //
  1682. // D3DFVFDRAWPNTFUNCPTR __HWSetPointFunc
  1683. //
  1684. // Select the appropiate point rendering function depending on the
  1685. // current point sprite mode set for the current context
  1686. //
  1687. //-----------------------------------------------------------------------------
  1688. D3DFVFDRAWPNTFUNCPTR
  1689. __HWSetPointFunc(PERMEDIA_D3DCONTEXT *pContext, LPP2FVFOFFSETS lpP2FVFOff)
  1690. {
  1691. //@@BEGIN_DDKSPLIT
  1692. #if D3D_POINTSPRITES
  1693. // Only if we are not enabling point sprites and the default point size
  1694. // is 1.0f and vertexes don't have their own point size, then use
  1695. // classical points for rendering
  1696. if ( pContext->bPointSpriteEnabled ||
  1697. (pContext->fPointSize != 1.0f) ||
  1698. (lpP2FVFOff->dwPntSizeOffset) )
  1699. return P2_Draw_FVF_Point_Sprite;
  1700. else
  1701. #endif // D3D_POINTSPRITES
  1702. //@@END_DDKSPLIT
  1703. return P2_Draw_FVF_Point;
  1704. }
  1705. //-----------------------------------------------------------------------------
  1706. //
  1707. // void __TextureBlt
  1708. //
  1709. // Transfer a texture from system memory into AGP or video memory
  1710. //-----------------------------------------------------------------------------
  1711. HRESULT
  1712. __TextureBlt(PERMEDIA_D3DCONTEXT* pContext,
  1713. D3DHAL_DP2TEXBLT* lpdp2texblt)
  1714. {
  1715. PPERMEDIA_D3DTEXTURE dsttex,srctex;
  1716. RECTL rDest;
  1717. PPDev ppdev=pContext->ppdev;
  1718. DBG_D3D((10,"Entering __TextureBlt"));
  1719. if (0 == lpdp2texblt->dwDDSrcSurface)
  1720. {
  1721. DBG_D3D((0,"Inavlid handle TexBlt from %08lx to %08lx",
  1722. lpdp2texblt->dwDDSrcSurface,lpdp2texblt->dwDDDestSurface));
  1723. return DDERR_INVALIDPARAMS;
  1724. }
  1725. srctex = TextureHandleToPtr(lpdp2texblt->dwDDSrcSurface,pContext);
  1726. if(!CHECK_D3DSURFACE_VALIDITY(srctex))
  1727. {
  1728. DBG_D3D((0,"D3DDP2OP_TEXBLT: invalid dwDDSrcSurface !"));
  1729. return DDERR_INVALIDPARAMS;
  1730. }
  1731. if (0 == lpdp2texblt->dwDDDestSurface)
  1732. {
  1733. PPERMEDIA_D3DTEXTURE pTexture = srctex;
  1734. PermediaSurfaceData* pPrivateData = pTexture->pTextureSurface;
  1735. if (!(pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
  1736. {
  1737. DBG_D3D((0,"Must be a managed texture to do texture preload"));
  1738. return DDERR_INVALIDPARAMS;
  1739. }
  1740. if (NULL==pPrivateData->fpVidMem)
  1741. {
  1742. TextureCacheManagerAllocNode(pContext,pTexture);
  1743. if (NULL==pPrivateData->fpVidMem)
  1744. {
  1745. DBG_D3D((0,"EnableTexturePermedia unable to "
  1746. "allocate memory from heap"));
  1747. return DDERR_OUTOFVIDEOMEMORY;
  1748. }
  1749. pPrivateData->dwFlags |= P2_SURFACE_NEEDUPDATE;
  1750. }
  1751. if (pPrivateData->dwFlags & P2_SURFACE_NEEDUPDATE)
  1752. {
  1753. RECTL rect;
  1754. rect.left=rect.top=0;
  1755. rect.right=pTexture->wWidth;
  1756. rect.bottom=pTexture->wHeight;
  1757. // texture download
  1758. // Switch to DirectDraw context
  1759. pPrivateData->dwFlags &= ~P2_SURFACE_NEEDUPDATE;
  1760. // .. Convert it to Pixels
  1761. pTexture->MipLevels[0].PixelOffset =
  1762. (ULONG)(pPrivateData->fpVidMem);
  1763. switch(pTexture->pTextureSurface->SurfaceFormat.PixelSize)
  1764. {
  1765. case __PERMEDIA_4BITPIXEL:
  1766. pTexture->MipLevels[0].PixelOffset <<= 1;
  1767. break;
  1768. case __PERMEDIA_8BITPIXEL: /* No Change*/
  1769. break;
  1770. case __PERMEDIA_16BITPIXEL:
  1771. pTexture->MipLevels[0].PixelOffset >>= 1;
  1772. break;
  1773. case __PERMEDIA_24BITPIXEL:
  1774. pTexture->MipLevels[0].PixelOffset /= 3;
  1775. break;
  1776. case __PERMEDIA_32BITPIXEL:
  1777. pTexture->MipLevels[0].PixelOffset >>= 2;
  1778. break;
  1779. default:
  1780. ASSERTDD(0,"Invalid Texture Pixel Size!");
  1781. pTexture->MipLevels[0].PixelOffset >>= 1;
  1782. break;
  1783. }
  1784. PermediaPatchedTextureDownload(pContext->ppdev,
  1785. pPrivateData,
  1786. pTexture->fpVidMem,
  1787. pTexture->lPitch,
  1788. &rect,
  1789. pPrivateData->fpVidMem,
  1790. pTexture->lPitch,
  1791. &rect);
  1792. DBG_D3D((10, "Copy from %08lx to %08lx w=%08lx h=%08lx "
  1793. "p=%08lx b=%08lx",
  1794. pTexture->fpVidMem,pPrivateData->fpVidMem,pTexture->wWidth,
  1795. pTexture->wHeight,pTexture->lPitch,pTexture->dwRGBBitCount));
  1796. }
  1797. return DD_OK;
  1798. }
  1799. else
  1800. {
  1801. dsttex = TextureHandleToPtr(lpdp2texblt->dwDDDestSurface,pContext);
  1802. if(!CHECK_D3DSURFACE_VALIDITY(dsttex))
  1803. {
  1804. DBG_D3D((0,"D3DDP2OP_TEXBLT: invalid dwDDDestSurface !"));
  1805. return DDERR_INVALIDPARAMS;
  1806. }
  1807. }
  1808. if (NULL != dsttex && NULL != srctex)
  1809. {
  1810. rDest.left = lpdp2texblt->pDest.x;
  1811. rDest.top = lpdp2texblt->pDest.y;
  1812. rDest.right = rDest.left + lpdp2texblt->rSrc.right
  1813. - lpdp2texblt->rSrc.left;
  1814. rDest.bottom = rDest.top + lpdp2texblt->rSrc.bottom
  1815. - lpdp2texblt->rSrc.top;
  1816. DBG_D3D((4,"TexBlt from %d %08lx %08lx to %d %08lx %08lx",
  1817. lpdp2texblt->dwDDSrcSurface,srctex->dwCaps,srctex->dwCaps2,
  1818. lpdp2texblt->dwDDDestSurface,dsttex->dwCaps,dsttex->dwCaps2));
  1819. dsttex->dwPaletteHandle = srctex->dwPaletteHandle;
  1820. dsttex->pTextureSurface->dwPaletteHandle = srctex->dwPaletteHandle;
  1821. if ((DDSCAPS_VIDEOMEMORY & srctex->dwCaps) &&
  1822. !(DDSCAPS2_TEXTUREMANAGE & srctex->dwCaps2))
  1823. {
  1824. PermediaSurfaceData* pPrivateDest = dsttex->pTextureSurface;
  1825. PermediaSurfaceData* pPrivateSource = srctex->pTextureSurface;
  1826. // If the surface sizes don't match, then we are stretching.
  1827. // Also the blits from Nonlocal- to Videomemory have to go through
  1828. // the texture unit!
  1829. if (!(DDSCAPS_VIDEOMEMORY & dsttex->dwCaps) ||
  1830. (DDSCAPS2_TEXTUREMANAGE & dsttex->dwCaps2))
  1831. {
  1832. DBG_DD((0,"DDBLT_ROP: NOT ABLE TO BLT FROM "
  1833. "VIDEO TO NON-VIDEO SURFACE"));
  1834. return DDERR_INVALIDPARAMS;
  1835. }
  1836. if ( DDSCAPS_NONLOCALVIDMEM & srctex->dwCaps)
  1837. {
  1838. DBG_DD((3,"DDBLT_ROP: STRETCHCOPYBLT OR "
  1839. "MIRROR OR BOTH OR AGPVIDEO"));
  1840. PermediaStretchCopyBlt( ppdev,
  1841. NULL,
  1842. pPrivateDest,
  1843. pPrivateSource,
  1844. &rDest,
  1845. &lpdp2texblt->rSrc,
  1846. dsttex->MipLevels[0].PixelOffset,
  1847. srctex->MipLevels[0].PixelOffset);
  1848. }
  1849. else
  1850. {
  1851. ULONG ulDestPixelShift=ShiftLookup[dsttex->dwRGBBitCount>>3];
  1852. LONG lPixPitchDest = dsttex->lPitch >> ulDestPixelShift;
  1853. LONG lPixPitchSrc = srctex->lPitch >> ulDestPixelShift;
  1854. LONG srcOffset=(LONG)((srctex->fpVidMem - dsttex->fpVidMem)
  1855. >> ulDestPixelShift);
  1856. DBG_DD((3,"DDBLT_ROP: COPYBLT %08lx %08lx %08lx",
  1857. srctex->fpVidMem, dsttex->fpVidMem, ulDestPixelShift));
  1858. // For some reason, the user might want
  1859. // to do a conversion on the data as it is
  1860. // blitted from VRAM->VRAM by turning on Patching.
  1861. // If Surf1Patch XOR Surf2Patch then
  1862. // do a special blit that isn't packed and does patching.
  1863. if (((pPrivateDest->dwFlags & P2_CANPATCH) ^
  1864. (pPrivateSource->dwFlags & P2_CANPATCH))
  1865. & P2_CANPATCH)
  1866. {
  1867. DBG_DD((4,"Doing Patch-Conversion!"));
  1868. PermediaPatchedCopyBlt( ppdev,
  1869. lPixPitchDest,
  1870. lPixPitchSrc,
  1871. pPrivateDest,
  1872. pPrivateSource,
  1873. &rDest,
  1874. &lpdp2texblt->rSrc,
  1875. dsttex->MipLevels[0].PixelOffset,
  1876. srcOffset);
  1877. }
  1878. else
  1879. {
  1880. DBG_DD((4,"Doing PermediaPackedCopyBlt!"));
  1881. PermediaPackedCopyBlt( ppdev,
  1882. lPixPitchDest,
  1883. lPixPitchSrc,
  1884. pPrivateDest,
  1885. pPrivateSource,
  1886. &rDest,
  1887. &lpdp2texblt->rSrc,
  1888. dsttex->MipLevels[0].PixelOffset,
  1889. srcOffset);
  1890. }
  1891. }
  1892. }
  1893. else
  1894. if (dsttex->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
  1895. {
  1896. // texture download
  1897. if (pContext->CurrentTextureHandle == lpdp2texblt->dwDDDestSurface)
  1898. DIRTY_TEXTURE;
  1899. dsttex->pTextureSurface->dwFlags |= P2_SURFACE_NEEDUPDATE;
  1900. SysMemToSysMemSurfaceCopy(
  1901. srctex->fpVidMem,
  1902. srctex->lPitch,
  1903. srctex->dwRGBBitCount,
  1904. dsttex->fpVidMem,
  1905. dsttex->lPitch,
  1906. dsttex->dwRGBBitCount,
  1907. &lpdp2texblt->rSrc,
  1908. &rDest);
  1909. }
  1910. else
  1911. if (DDSCAPS_NONLOCALVIDMEM & dsttex->dwCaps)
  1912. {
  1913. // Blt from system to AGP memory
  1914. SysMemToSysMemSurfaceCopy(srctex->fpVidMem,
  1915. srctex->lPitch,
  1916. srctex->dwRGBBitCount,
  1917. dsttex->fpVidMem,
  1918. dsttex->lPitch,
  1919. dsttex->dwRGBBitCount,
  1920. &lpdp2texblt->rSrc,
  1921. &rDest);
  1922. }
  1923. else
  1924. if (DDSCAPS_LOCALVIDMEM & dsttex->dwCaps)
  1925. {
  1926. // texture download
  1927. PermediaPatchedTextureDownload(ppdev,
  1928. dsttex->pTextureSurface,
  1929. srctex->fpVidMem,
  1930. srctex->lPitch,
  1931. &lpdp2texblt->rSrc,
  1932. dsttex->fpVidMem,
  1933. dsttex->lPitch,
  1934. &rDest);
  1935. }
  1936. else
  1937. {
  1938. DBG_DD((0,"DDBLT_ROP: NOT ABLE TO BLT FROM "
  1939. "SYSTEM TO NON-VIDEO SURFACE"));
  1940. return DDERR_INVALIDPARAMS;
  1941. }
  1942. }
  1943. DBG_D3D((10,"Exiting __TextureBlt"));
  1944. return DD_OK;
  1945. } //__TextureBlt
  1946. //-----------------------------------------------------------------------------
  1947. //
  1948. // void __SetRenderTarget
  1949. //
  1950. // Set new render and z buffer target surfaces
  1951. //-----------------------------------------------------------------------------
  1952. HRESULT __SetRenderTarget(PERMEDIA_D3DCONTEXT* pContext,
  1953. DWORD hRenderTarget,
  1954. DWORD hZBuffer)
  1955. {
  1956. DBG_D3D((10,"Entering __SetRenderTarget Target=%d Z=%d",
  1957. hRenderTarget,hZBuffer));
  1958. // Call a function to initialise registers that will setup the rendering
  1959. pContext->RenderSurfaceHandle = hRenderTarget;
  1960. pContext->ZBufferHandle = hZBuffer;
  1961. SetupPermediaRenderTarget(pContext);
  1962. // The AlphaBlending may need to be changed.
  1963. DIRTY_ALPHABLEND;
  1964. // Dirty the Z Buffer (the new target may not have one)
  1965. DIRTY_ZBUFFER;
  1966. DBG_D3D((10,"Exiting __SetRenderTarget"));
  1967. return DD_OK;
  1968. } // __SetRenderTarget
  1969. //-----------------------------------------------------------------------------
  1970. //
  1971. // void __Clear
  1972. //
  1973. // Clears selectively the frame buffer, z buffer and stencil buffer for the
  1974. // D3D Clear2 callback and for the D3DDP2OP_CLEAR command token.
  1975. //
  1976. //-----------------------------------------------------------------------------
  1977. HRESULT __Clear( PERMEDIA_D3DCONTEXT* pContext,
  1978. DWORD dwFlags, // in: surfaces to clear
  1979. DWORD dwFillColor, // in: Color value for rtarget
  1980. D3DVALUE dvFillDepth, // in: Depth value for
  1981. // Z-buffer (0.0-1.0)
  1982. DWORD dwFillStencil, // in: value used to clear stencil buffer
  1983. LPD3DRECT lpRects, // in: Rectangles to clear
  1984. DWORD dwNumRects) // in: Number of rectangles
  1985. {
  1986. int i;
  1987. PermediaSurfaceData* pPrivateData;
  1988. RECTL* pRect;
  1989. PPDev ppdev=pContext->ppdev;
  1990. PERMEDIA_DEFS(pContext->ppdev);
  1991. if (D3DCLEAR_TARGET & dwFlags)
  1992. {
  1993. DWORD a,r,g,b;
  1994. PPERMEDIA_D3DTEXTURE pSurfRender =
  1995. TextureHandleToPtr(pContext->RenderSurfaceHandle, pContext);
  1996. if(!CHECK_D3DSURFACE_VALIDITY(pSurfRender))
  1997. {
  1998. DBG_D3D((0,"D3DDP2OP_CLEAR: invalid RenderSurfaceHandle !"));
  1999. return DDERR_INVALIDPARAMS;
  2000. }
  2001. pPrivateData = pSurfRender->pTextureSurface;
  2002. if( NULL == pPrivateData)
  2003. {
  2004. DBG_D3D((0,"D3DDP2OP_CLEAR: NULL == pPrivateData(pSurfRender)!"));
  2005. return DDERR_INVALIDPARAMS;
  2006. }
  2007. // Translate into HW specific format
  2008. a = RGB888ToHWFmt(dwFillColor,
  2009. pPrivateData->SurfaceFormat.AlphaMask, 0x80000000);
  2010. r = RGB888ToHWFmt(dwFillColor,
  2011. pPrivateData->SurfaceFormat.RedMask, 0x00800000);
  2012. g = RGB888ToHWFmt(dwFillColor,
  2013. pPrivateData->SurfaceFormat.GreenMask, 0x00008000);
  2014. b = RGB888ToHWFmt(dwFillColor,
  2015. pPrivateData->SurfaceFormat.BlueMask, 0x00000080);
  2016. dwFillColor = a | r | g | b;
  2017. DBG_D3D((8,"D3DDP2OP_CLEAR convert to %08lx with Mask %8lx %8lx %8lx",
  2018. dwFillColor,
  2019. pPrivateData->SurfaceFormat.RedMask,
  2020. pPrivateData->SurfaceFormat.GreenMask,
  2021. pPrivateData->SurfaceFormat.BlueMask));
  2022. pRect = (RECTL*)lpRects;
  2023. // Do clear for each Rect that we have
  2024. for (i = dwNumRects; i > 0; i--)
  2025. {
  2026. PermediaFastClear(ppdev, pPrivateData,
  2027. pRect, pContext->PixelOffset, dwFillColor);
  2028. pRect++;
  2029. }
  2030. }
  2031. if (((D3DCLEAR_ZBUFFER
  2032. #if D3D_STENCIL
  2033. | D3DCLEAR_STENCIL
  2034. #endif //D3D_STENCIL
  2035. ) & dwFlags)
  2036. && (0 != pContext->ZBufferHandle))
  2037. {
  2038. DWORD dwZbufferClearValue = 0x0000FFFF; //no stencil case
  2039. DWORD dwWriteMask;
  2040. PPERMEDIA_D3DTEXTURE pSurfZBuffer =
  2041. TextureHandleToPtr(pContext->ZBufferHandle, pContext);
  2042. if(!CHECK_D3DSURFACE_VALIDITY(pSurfZBuffer))
  2043. {
  2044. DBG_D3D((0,"D3DDP2OP_CLEAR: invalid ZBufferHandle !"));
  2045. return DDERR_INVALIDPARAMS;
  2046. }
  2047. // get z buffer pixelformat info
  2048. pPrivateData = pSurfZBuffer->pTextureSurface;
  2049. if( NULL == pPrivateData)
  2050. {
  2051. DBG_D3D((0,"D3DDP2OP_CLEAR: NULL == pPrivateData(pSurfZBuffer)!"));
  2052. return DDERR_INVALIDPARAMS;
  2053. }
  2054. #if D3D_STENCIL
  2055. //actually check dwStencilBitMask
  2056. if (0 == pPrivateData->SurfaceFormat.BlueMask)
  2057. {
  2058. dwWriteMask = 0xFFFFFFFF; //all 16bits are for Z
  2059. dwZbufferClearValue = (DWORD)(dvFillDepth*0x0000FFFF);
  2060. }
  2061. else
  2062. {
  2063. dwWriteMask = 0;
  2064. dwZbufferClearValue = (DWORD)(dvFillDepth*0x00007FFF);
  2065. if (D3DCLEAR_ZBUFFER & dwFlags)
  2066. dwWriteMask |= 0x7FFF7FFF;
  2067. if (D3DCLEAR_STENCIL & dwFlags)
  2068. {
  2069. dwWriteMask |= 0x80008000;
  2070. if (0 != dwFillStencil)
  2071. {
  2072. dwZbufferClearValue |= 0x8000; //or stencil bit
  2073. }
  2074. }
  2075. if (0xFFFFFFFF != dwWriteMask)
  2076. {
  2077. RESERVEDMAPTR(1);
  2078. SEND_PERMEDIA_DATA(FBHardwareWriteMask, dwWriteMask);
  2079. COMMITDMAPTR();
  2080. }
  2081. }
  2082. #endif //D3D_STENCIL
  2083. pRect = (RECTL*)lpRects;
  2084. for (i = dwNumRects; i > 0; i--)
  2085. {
  2086. PermediaFastLBClear(ppdev, pPrivateData, pRect,
  2087. (DWORD)((UINT_PTR)pSurfZBuffer->fpVidMem >> P2DEPTH16),
  2088. dwZbufferClearValue);
  2089. pRect++;
  2090. }
  2091. #if D3D_STENCIL
  2092. // Restore the LB write mask is we didn't clear stencil & zbuffer
  2093. if (0xFFFFFFFF != dwWriteMask)
  2094. {
  2095. RESERVEDMAPTR(1);
  2096. SEND_PERMEDIA_DATA(FBHardwareWriteMask, 0xFFFFFFFF); //restore
  2097. COMMITDMAPTR();
  2098. }
  2099. #endif //D3D_STENCIL
  2100. }
  2101. return DD_OK;
  2102. } // __Clear
  2103. //-----------------------------------------------------------------------------
  2104. //
  2105. // void __PaletteSet
  2106. //
  2107. // Attaches a palette handle to a texture in the given context
  2108. // The texture is the one associated to the given surface handle.
  2109. //
  2110. //-----------------------------------------------------------------------------
  2111. HRESULT
  2112. __PaletteSet(PERMEDIA_D3DCONTEXT* pContext,
  2113. DWORD dwSurfaceHandle,
  2114. DWORD dwPaletteHandle,
  2115. DWORD dwPaletteFlags)
  2116. {
  2117. PERMEDIA_D3DTEXTURE * pTexture;
  2118. ASSERTDD(0 != dwSurfaceHandle, "dwSurfaceHandle==0 in D3DDP2OP_SETPALETTE");
  2119. DBG_D3D((8,"SETPALETTE %d to %d", dwPaletteHandle, dwSurfaceHandle));
  2120. pTexture = TextureHandleToPtr(dwSurfaceHandle, pContext);
  2121. if (!CHECK_D3DSURFACE_VALIDITY(pTexture))
  2122. {
  2123. DBG_D3D((0,"__PaletteSet:NULL==pTexture Palette=%08lx Surface=%08lx",
  2124. dwPaletteHandle, dwSurfaceHandle));
  2125. return DDERR_INVALIDPARAMS; // invalid dwSurfaceHandle, skip it
  2126. }
  2127. pTexture->dwPaletteHandle = dwPaletteHandle;
  2128. // need to make it into private data if driver created this surface
  2129. if (NULL != pTexture->pTextureSurface)
  2130. pTexture->pTextureSurface->dwPaletteHandle = dwPaletteHandle;
  2131. if (pContext->CurrentTextureHandle == dwSurfaceHandle)
  2132. DIRTY_TEXTURE;
  2133. if (0 == dwPaletteHandle)
  2134. {
  2135. return D3D_OK; //palette association is OFF
  2136. }
  2137. // Check if we need to grow our palette list for this handle element
  2138. if (NULL == pContext->pHandleList->dwPaletteList ||
  2139. dwPaletteHandle >= PtrToUlong(pContext->pHandleList->dwPaletteList[0]))
  2140. {
  2141. DWORD newsize = ((dwPaletteHandle +
  2142. LISTGROWSIZE)/LISTGROWSIZE)*LISTGROWSIZE;
  2143. PPERMEDIA_D3DPALETTE *newlist = (PPERMEDIA_D3DPALETTE *)
  2144. ENGALLOCMEM( FL_ZERO_MEMORY,
  2145. sizeof(PPERMEDIA_D3DPALETTE)*newsize,
  2146. ALLOC_TAG);
  2147. DBG_D3D((8,"Growing pDDLcl=%x's "
  2148. "PaletteList[%x] size to %08lx",
  2149. pContext->pDDLcl, newlist, newsize));
  2150. if (NULL == newlist)
  2151. {
  2152. DBG_D3D((0,"D3DDP2OP_SETPALETTE Out of memory."));
  2153. return DDERR_OUTOFMEMORY;
  2154. }
  2155. memset(newlist,0,newsize);
  2156. if (NULL != pContext->pHandleList->dwPaletteList)
  2157. {
  2158. memcpy(newlist,pContext->pHandleList->dwPaletteList,
  2159. PtrToUlong(pContext->pHandleList->dwPaletteList[0]) *
  2160. sizeof(PPERMEDIA_D3DPALETTE));
  2161. ENGFREEMEM(pContext->pHandleList->dwPaletteList);
  2162. DBG_D3D((8,"Freeing pDDLcl=%x's old PaletteList[%x]",
  2163. pContext->pDDLcl,
  2164. pContext->pHandleList->dwPaletteList));
  2165. }
  2166. pContext->pHandleList->dwPaletteList = newlist;
  2167. //store size in dwSurfaceList[0]
  2168. *(DWORD*)pContext->pHandleList->dwPaletteList = newsize;
  2169. }
  2170. // If we don't have a palette hanging from this palette list
  2171. // element we have to create one. The actual palette data will
  2172. // come down in the D3DDP2OP_UPDATEPALETTE command token.
  2173. if (NULL == pContext->pHandleList->dwPaletteList[dwPaletteHandle])
  2174. {
  2175. pContext->pHandleList->dwPaletteList[dwPaletteHandle] =
  2176. (PERMEDIA_D3DPALETTE*)ENGALLOCMEM( FL_ZERO_MEMORY,
  2177. sizeof(PERMEDIA_D3DPALETTE),
  2178. ALLOC_TAG);
  2179. if (NULL == pContext->pHandleList->dwPaletteList[dwPaletteHandle])
  2180. {
  2181. DBG_D3D((0,"D3DDP2OP_SETPALETTE Out of memory."));
  2182. return DDERR_OUTOFMEMORY;
  2183. }
  2184. }
  2185. // driver may store this dwFlags to decide whether
  2186. // ALPHA exists in Palette
  2187. pContext->pHandleList->dwPaletteList[dwPaletteHandle]->dwFlags =
  2188. dwPaletteFlags;
  2189. return DD_OK;
  2190. } // PaletteSet
  2191. //-----------------------------------------------------------------------------
  2192. //
  2193. // void __PaletteUpdate
  2194. //
  2195. // Updates the entries of a palette attached to a texture in the given context
  2196. //
  2197. //-----------------------------------------------------------------------------
  2198. HRESULT
  2199. __PaletteUpdate(PERMEDIA_D3DCONTEXT* pContext,
  2200. DWORD dwPaletteHandle,
  2201. WORD wStartIndex,
  2202. WORD wNumEntries,
  2203. BYTE * pPaletteData)
  2204. {
  2205. PERMEDIA_D3DPALETTE* pPalette;
  2206. DBG_D3D((8,"UPDATEPALETTE %d (%d,%d) %d",
  2207. dwPaletteHandle,
  2208. wStartIndex,
  2209. wNumEntries,
  2210. pContext->CurrentTextureHandle));
  2211. pPalette = PaletteHandleToPtr(dwPaletteHandle,pContext);
  2212. if (NULL != pPalette)
  2213. {
  2214. ASSERTDD(256 >= wStartIndex + wNumEntries,
  2215. "wStartIndex+wNumEntries>256 in D3DDP2OP_UPDATEPALETTE");
  2216. // Copy the palette & associated data
  2217. pPalette->wStartIndex = wStartIndex;
  2218. pPalette->wNumEntries = wNumEntries;
  2219. memcpy((LPVOID)&pPalette->ColorTable[wStartIndex],
  2220. (LPVOID)pPaletteData,
  2221. (DWORD)wNumEntries*sizeof(PALETTEENTRY));
  2222. // If we are currently texturing and the texture is using the
  2223. // palette we just updated, dirty the texture flag so that
  2224. // it set up with the right (updated) palette
  2225. if (pContext->CurrentTextureHandle)
  2226. {
  2227. PERMEDIA_D3DTEXTURE * pTexture=
  2228. TextureHandleToPtr(pContext->CurrentTextureHandle,pContext);
  2229. if (pTexture && pTexture->pTextureSurface)
  2230. {
  2231. if (pTexture->dwPaletteHandle == dwPaletteHandle)
  2232. {
  2233. DIRTY_TEXTURE;
  2234. DBG_D3D((8,"UPDATEPALETTE DIRTY_TEXTURE"));
  2235. }
  2236. }
  2237. }
  2238. }
  2239. else
  2240. {
  2241. return DDERR_INVALIDPARAMS;
  2242. }
  2243. return DD_OK;
  2244. } // __PaletteUpdate
  2245. //-----------------------------------------------------------------------------
  2246. //
  2247. // void __RestoreD3DContext
  2248. //
  2249. // Restores the P2 registers to what they were when we last left this D3D context
  2250. //
  2251. //-----------------------------------------------------------------------------
  2252. void __RestoreD3DContext(PPDev ppdev, PERMEDIA_D3DCONTEXT* pContext)
  2253. {
  2254. __P2RegsSoftwareCopy* pSoftPermedia = &pContext->Hdr.SoftCopyP2Regs;
  2255. PERMEDIA_DEFS(ppdev);
  2256. // Dirty everything in order to restore the D3D state
  2257. DIRTY_TEXTURE;
  2258. DIRTY_ZBUFFER;
  2259. DIRTY_ALPHABLEND;
  2260. // Restore the correct surface (render & depth buffer) characteristics
  2261. SetupPermediaRenderTarget(pContext);
  2262. //Bring back manually some registers which we care about
  2263. RESERVEDMAPTR(5);
  2264. COPY_PERMEDIA_DATA(DeltaMode, pSoftPermedia->DeltaMode);
  2265. COPY_PERMEDIA_DATA(ColorDDAMode, pSoftPermedia->ColorDDAMode);
  2266. COPY_PERMEDIA_DATA(FogColor, pSoftPermedia->FogColor);
  2267. SEND_PERMEDIA_DATA(FBHardwareWriteMask, -1 );
  2268. COMMITDMAPTR();
  2269. }