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.

3111 lines
133 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * D3D SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: d3ddp2p3.c
  8. *
  9. * Content: D3D DrawPrimitives2 callback support
  10. *
  11. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "glint.h"
  15. #include "dma.h"
  16. #include "tag.h"
  17. //-----------------------------------------------------------------------------
  18. // in-the-file nonexported forward declarations
  19. //-----------------------------------------------------------------------------
  20. BOOL __DP2_PrimitiveOpsParser(
  21. P3_D3DCONTEXT *pContext,
  22. LPD3DHAL_DRAWPRIMITIVES2DATA pdp2d,
  23. LPD3DHAL_DP2COMMAND *lplpIns,
  24. LPBYTE insStart,
  25. LPDWORD lpVertices);
  26. //-----------------------------------------------------------------------------
  27. // Macros to access and validate command and vertex buffer data
  28. // These checks need ALWAYS to be made for all builds, free and checked.
  29. //-----------------------------------------------------------------------------
  30. #define STARTVERTEXSIZE (sizeof(D3DHAL_DP2STARTVERTEX))
  31. #define NEXTINSTRUCTION(ptr, type, num, extrabytes) \
  32. ptr = (LPD3DHAL_DP2COMMAND)((LPBYTE)ptr + sizeof(D3DHAL_DP2COMMAND) + \
  33. ((num) * sizeof(type)) + (extrabytes))
  34. #define PARSE_ERROR_AND_EXIT( pDP2Data, pIns, pStartIns, ddrvalue) \
  35. { \
  36. pDP2Data->dwErrorOffset = (DWORD)((LPBYTE)pIns - (LPBYTE)pStartIns);\
  37. pDP2Data->ddrval = ddrvalue; \
  38. bParseError = TRUE; \
  39. break; \
  40. }
  41. #define CHECK_CMDBUF_LIMITS( pDP2Data, pBuf, type, num, extrabytes) \
  42. CHECK_CMDBUF_LIMITS_S( pDP2Data, pBuf, sizeof(type), num, extrabytes)
  43. #define CHECK_CMDBUF_LIMITS_S( pDP2Data, pBuf, typesize, num, extrabytes) \
  44. { \
  45. LPBYTE pBase,pEnd,pBufEnd; \
  46. pBase = (LPBYTE)(pDP2Data->lpDDCommands->lpGbl->fpVidMem + \
  47. pDP2Data->dwCommandOffset); \
  48. pEnd = pBase + pDP2Data->dwCommandLength; \
  49. pBufEnd = ((LPBYTE)pBuf + ((num) * (typesize)) + (extrabytes) - 1); \
  50. if (! ((LPBYTE)pBufEnd < pEnd) && ( pBase <= (LPBYTE)pBuf)) \
  51. { \
  52. DISPDBG((ERRLVL,"Trying to read past Command Buffer limits " \
  53. "%x %x %x %x",pBase ,(LPBYTE)pBuf, pBufEnd, pEnd )); \
  54. PARSE_ERROR_AND_EXIT( pDP2Data, lpIns, lpInsStart, \
  55. D3DERR_COMMAND_UNPARSED ); \
  56. } \
  57. }
  58. #define LP_FVF_VERTEX(lpBaseAddr, wIndex) \
  59. (LPDWORD)((LPBYTE)(lpBaseAddr) + (wIndex) * pContext->FVFData.dwStride)
  60. #define LP_FVF_NXT_VTX(lpVtx) \
  61. (LPDWORD)((LPBYTE)(lpVtx) + pContext->FVFData.dwStride)
  62. //-----------------------------------------------------------------------------
  63. // These defines are derived from the VertexTagList initialisation in stateset.c
  64. #define FVF_TEXCOORD_BASE 6
  65. #define FVF_XYZ (7 << 0)
  66. #define FVF_RHW (1 << 3)
  67. #define FVF_DIFFUSE (1 << 4)
  68. #define FVF_SPECULAR (1 << 5)
  69. #define FVF_TEXCOORD1 (3 << FVF_TEXCOORD_BASE)
  70. #define FVF_TEXCOORD2 (3 << (FVF_TEXCOORD_BASE + 2))
  71. //-----------------------------------------------------------------------------
  72. //
  73. // ReconsiderStateChanges
  74. //
  75. //-----------------------------------------------------------------------------
  76. static D3DSTATE localState[] =
  77. {
  78. { (D3DTRANSFORMSTATETYPE)D3DRENDERSTATE_SHADEMODE, 0 },
  79. { (D3DTRANSFORMSTATETYPE)D3DRENDERSTATE_CULLMODE, 0 }
  80. };
  81. #define NUM_LOCAL_STATES ( sizeof( localState ) / sizeof( D3DSTATE ))
  82. void ReconsiderStateChanges( P3_D3DCONTEXT *pContext )
  83. {
  84. int i;
  85. for( i = 0; i < NUM_LOCAL_STATES; i++ )
  86. {
  87. localState[i].dwArg[0] =
  88. pContext->RenderStates[localState[i].drstRenderStateType];
  89. }
  90. _D3D_ST_ProcessRenderStates(pContext, NUM_LOCAL_STATES, localState, FALSE);
  91. _D3D_ST_RealizeHWStateChanges( pContext );
  92. } // ReconsiderStateChanges
  93. //-----------------------------------------------------------------------------
  94. //
  95. // __CheckFVFRequest
  96. //
  97. // This utility function verifies that the requested FVF format makes sense
  98. // and computes useful offsets into the data and a stride between succesive
  99. // vertices.
  100. //
  101. //-----------------------------------------------------------------------------
  102. #define FVFEQUAL(fvfcode, fvfmask) \
  103. (((DWORD)fvfcode & (DWORD)fvfmask)) == (DWORD)fvfmask)
  104. DWORD __CheckFVFRequest(P3_D3DCONTEXT *pContext, DWORD dwFVF)
  105. {
  106. UINT i, iTexCount;
  107. P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
  108. int nonTexStride, texMask;
  109. FVFOFFSETS KeptFVF;
  110. P3_SOFTWARECOPY* pSoftP3RX = &pContext->SoftCopyGlint;
  111. P3_DMA_DEFS();
  112. DISPDBG((DBGLVL,"Looking at FVF Code %x:",dwFVF));
  113. // Check for bogus fields
  114. if ( (dwFVF & (D3DFVF_RESERVED0 | D3DFVF_RESERVED2)) ||
  115. (!(dwFVF & (D3DFVF_XYZ | D3DFVF_XYZRHW))) ||
  116. (dwFVF & (D3DFVF_NORMAL) ) )
  117. {
  118. DISPDBG((ERRLVL,"ERROR: Invalid FVF Buffer for this hardware!(%x)"
  119. ,dwFVF));
  120. // can't set reserved bits, shouldn't have normals in
  121. // output to rasterizers (since we're not a TnL driver/hw)
  122. // and must have coordinates
  123. return DDERR_INVALIDPARAMS;
  124. }
  125. KeptFVF = pContext->FVFData;
  126. // Ensure the default offsets are setup
  127. ZeroMemory(&pContext->FVFData, sizeof(FVFOFFSETS));
  128. // Minimum FVF coordinate fields
  129. pContext->FVFData.dwStride = sizeof(D3DVALUE) * 3;
  130. pContext->FVFData.vFmat |= FVF_XYZ;
  131. // RHW if present in FVF
  132. if (dwFVF & D3DFVF_XYZRHW)
  133. {
  134. DISPDBG((DBGLVL, " D3DFVF_XYZRHW"));
  135. pContext->FVFData.dwStride += sizeof(D3DVALUE);
  136. pContext->FVFData.vFmat |= FVF_RHW;
  137. }
  138. #if DX8_POINTSPRITES
  139. // Point size offsets for point sprites
  140. if (dwFVF & D3DFVF_PSIZE)
  141. {
  142. pContext->FVFData.dwPntSizeOffset = pContext->FVFData.dwStride;
  143. pContext->FVFData.dwStride += sizeof(D3DVALUE);
  144. }
  145. #else
  146. if (dwFVF & D3DFVF_RESERVED1)
  147. {
  148. DISPDBG((DBGLVL, " D3DFVF_RESERVED1"));
  149. pContext->FVFData.dwStride += sizeof(D3DVALUE);
  150. }
  151. #endif // DX8_POINTSPRITES
  152. // Diffuse color
  153. if (dwFVF & D3DFVF_DIFFUSE)
  154. {
  155. DISPDBG((DBGLVL, " D3DFVF_DIFFUSE"));
  156. pContext->FVFData.dwColOffset = pContext->FVFData.dwStride;
  157. pContext->FVFData.dwStride += sizeof(D3DCOLOR);
  158. pContext->FVFData.vFmat |= FVF_DIFFUSE;
  159. }
  160. // Specular color
  161. if (dwFVF & D3DFVF_SPECULAR)
  162. {
  163. DISPDBG((DBGLVL, " D3DFVF_SPECULAR"));
  164. pContext->FVFData.dwSpcOffset = pContext->FVFData.dwStride;
  165. pContext->FVFData.dwStride += sizeof(D3DCOLOR);
  166. pContext->FVFData.vFmat |= FVF_SPECULAR;
  167. }
  168. // Store some info for later setting up our inline hostin renderers
  169. nonTexStride = pContext->FVFData.dwStride / sizeof(DWORD);
  170. texMask = 0;
  171. pContext->FVFData.dwStrideHostInline = pContext->FVFData.dwStride;
  172. pContext->FVFData.dwNonTexStride = pContext->FVFData.dwStride;
  173. // Up until this point the vertex format is the same for both
  174. pContext->FVFData.vFmatHostInline = pContext->FVFData.vFmat;
  175. // Get number of texture coordinates present in this FVF code
  176. iTexCount = (dwFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
  177. pContext->FVFData.dwTexCount = iTexCount;
  178. for (i=0; i<D3DHAL_TSS_MAXSTAGES;i++)
  179. {
  180. pContext->FVFData.dwTexCoordOffset[i] = 0;
  181. }
  182. // Do we have tex coords in FVF? What kinds?
  183. if (iTexCount >= 1)
  184. {
  185. DISPDBG((DBGLVL,"Texture enabled: %d stages", iTexCount));
  186. // What is the dimensionality of each of our texcoords?
  187. if (0xFFFF0000 & dwFVF)
  188. {
  189. //expansion of FVF, these 16 bits are designated for up to
  190. //8 sets of texture coordinates with each set having 2bits
  191. //Normally a capable driver has to process all coordinates
  192. //Code below shows correct parsing
  193. UINT numcoord;
  194. for (i = 0; i < iTexCount; i++)
  195. {
  196. if (FVFEQUAL(dwFVF,D3DFVF_TEXCOORDSIZE1(i))
  197. {
  198. // one less D3DVALUE for 1D textures
  199. numcoord = 1;
  200. }
  201. else if (FVFEQUAL(dwFVF,D3DFVF_TEXCOORDSIZE3(i))
  202. {
  203. // one more D3DVALUE for 3D textures
  204. numcoord = 3;
  205. }
  206. else if (FVFEQUAL(dwFVF,D3DFVF_TEXCOORDSIZE4(i))
  207. {
  208. // two more D3DVALUEs for 4D textures
  209. numcoord = 4;
  210. }
  211. else
  212. {
  213. // D3DFVF_TEXCOORDSIZE2(i) is always 0
  214. // i.e. case 0 regular 2 D3DVALUEs
  215. numcoord = 2;
  216. }
  217. DISPDBG((DBGLVL,"Expanded TexCoord set %d has a offset %8lx",
  218. i,pContext->FVFData.dwStride));
  219. pContext->FVFData.dwTexCoordOffset[i] =
  220. pContext->FVFData.dwStride;
  221. pContext->FVFData.dwStride += sizeof(D3DVALUE) * numcoord;
  222. }
  223. DISPDBG((DBGLVL,"Expanded dwVertexType=0x%08lx has %d "
  224. "Texture Coords with total stride=0x%08lx",
  225. dwFVF, iTexCount, pContext->FVFData.dwStride));
  226. }
  227. else
  228. {
  229. // If the top FVF bits are not set, the default is to consider all
  230. // text coords to be u.v (2D)
  231. for (i = 0; i < iTexCount; i++)
  232. {
  233. pContext->FVFData.dwTexCoordOffset[i] =
  234. pContext->FVFData.dwStride;
  235. pContext->FVFData.dwStride += sizeof(D3DVALUE) * 2;
  236. }
  237. }
  238. // Update the offsets to our current (2) textures
  239. if( pContext->iTexStage[0] != -1 )
  240. {
  241. DWORD dwTexCoordSet =
  242. pContext->TextureStageState[pContext->iTexStage[0]].
  243. m_dwVal[D3DTSS_TEXCOORDINDEX];
  244. // The texture coordinate index may contain texgen flags
  245. // in the high word. These flags are not interesting here
  246. // so we mask them off.
  247. dwTexCoordSet = dwTexCoordSet & 0x0000FFFFul;
  248. pContext->FVFData.dwTexOffset[0] =
  249. pContext->FVFData.dwTexCoordOffset[dwTexCoordSet];
  250. texMask |= 3 << ( 2 * dwTexCoordSet );
  251. pContext->FVFData.vFmat |= FVF_TEXCOORD1;
  252. }
  253. if( pContext->iTexStage[1] != -1 )
  254. {
  255. DWORD dwTexCoordSet =
  256. pContext->TextureStageState[pContext->iTexStage[1]].
  257. m_dwVal[D3DTSS_TEXCOORDINDEX];
  258. // The texture coordinate index may contain texgen flags
  259. // in the high word. These flags are not interesting here
  260. // so we mask them off.
  261. dwTexCoordSet = dwTexCoordSet & 0x0000FFFFul;
  262. pContext->FVFData.dwTexOffset[1] =
  263. pContext->FVFData.dwTexCoordOffset[dwTexCoordSet];
  264. texMask |= 3 << ( 2 * dwTexCoordSet );
  265. pContext->FVFData.vFmat |= FVF_TEXCOORD2;
  266. }
  267. } // if (iTexCount >= 1)
  268. //---------------------------------------------------------
  269. // Update Permedia 3 hw registers for host inline rendering
  270. //---------------------------------------------------------
  271. // Update the Hostinline renderers with the correct values.
  272. // These usually aren't the same as the Hostin renderer values
  273. if (pContext->FVFData.vFmat & FVF_TEXCOORD1)
  274. {
  275. // Add this texture coordinate into the stride
  276. pContext->FVFData.dwStrideHostInline += (sizeof(D3DVALUE) * 2);
  277. // Set up the vertex format bit
  278. pContext->FVFData.vFmatHostInline |= FVF_TEXCOORD1;
  279. }
  280. if (pContext->FVFData.vFmat & FVF_TEXCOORD2)
  281. {
  282. P3_SURF_INTERNAL* pTexture = pContext->pCurrentTexture[TEXSTAGE_1];
  283. // If the texture coordinates aren't the same, or we are mipmapping,
  284. // then we must send the second set of texture coordinates
  285. if ((pContext->FVFData.dwTexOffset[0] !=
  286. pContext->FVFData.dwTexOffset[1]) ||
  287. ((pTexture != NULL) &&
  288. (pContext->TextureStageState[TEXSTAGE_1].m_dwVal[D3DTSS_MIPFILTER] != D3DTFP_NONE) &&
  289. (pTexture->bMipMap)))
  290. {
  291. pContext->FVFData.dwStrideHostInline += (sizeof(D3DVALUE) * 2);
  292. // Add in the second texture set to the vertex format
  293. pContext->FVFData.vFmatHostInline |= FVF_TEXCOORD2;
  294. }
  295. }
  296. // VertexValid is all 1's for the stride, because we will never want
  297. // to send a gap in the inline hostin triangle renderer
  298. pContext->FVFData.dwVertexValidHostInline =
  299. (1 << (pContext->FVFData.dwStrideHostInline >> 2)) - 1;
  300. // The vertex valid for Hostin renderers is more complex because the chip
  301. // may be required to skip data.
  302. pContext->FVFData.dwVertexValid = ((1 << nonTexStride) - 1) |
  303. (texMask << nonTexStride);
  304. // If the FVF has changed, resend the state. This can be improved because
  305. // you don't always have to send the default stuff (only if that state is
  306. // enabled and the vertex doesn't contain it).
  307. if (memcmp(&KeptFVF, &pContext->FVFData, sizeof(KeptFVF)) != 0)
  308. {
  309. // Update P3 for the changed FVF
  310. P3_DMA_GET_BUFFER_ENTRIES( 12 );
  311. SEND_P3_DATA(V0FloatPackedColour, 0xFFFFFFFF);
  312. SEND_P3_DATA(V1FloatPackedColour, 0xFFFFFFFF);
  313. SEND_P3_DATA(V2FloatPackedColour, 0xFFFFFFFF);
  314. SEND_P3_DATA(V0FloatPackedSpecularFog, 0x0);
  315. SEND_P3_DATA(V1FloatPackedSpecularFog, 0x0);
  316. SEND_P3_DATA(V2FloatPackedSpecularFog, 0x0);
  317. pSoftP3RX->P3RX_P3VertexControl.CacheEnable = 1;
  318. P3_DMA_COMMIT_BUFFER();
  319. }
  320. DISPDBG((DBGLVL,"FVF stride set to %d",pContext->FVFData.dwStride));
  321. return DD_OK;
  322. } // __CheckFVFRequest
  323. //-----------------------------Public Routine----------------------------------
  324. //
  325. // DWORD D3DDrawPrimitives2_P3
  326. //
  327. // Renders primitives and returns the updated render state.
  328. //
  329. // D3dDrawPrimitives2 must be implemented in Direct3D drivers.
  330. //
  331. // The driver must do the following:
  332. //
  333. // -Ensure that the context handle specified by dwhContext is valid.
  334. //
  335. // -Check that a flip to the drawing surface associated with the context is not
  336. // in progress. If the drawing surface is involved in a flip, the driver should
  337. // set ddrval to DDERR_WASSTILLDRAWING and return DDHAL_DRIVER_HANDLED.
  338. //
  339. // -Determine the location at which the first D3DNTHAL_DP2COMMAND structure is
  340. // found by adding dwCommandOffset bytes to the Command Buffer to which
  341. // lpDDCommands points.
  342. //
  343. // -Determine the location in the Vertex Buffer at which the first vertex is found
  344. // This is should only be done if there is data in the Vertex Buffer; that is,
  345. // when a D3DDP2OP_* command token is received (except when the token is
  346. // D3DDP2OP_LINELIST_IMM or D3DDP2OP_TRIANGLEFAN_IMM). These later two opcodes
  347. // indicate that the vertex data is passed immediately in the command stream,
  348. // rather than in a Vertex Buffer. So, assuming there is data in the Vertex
  349. // Buffer, if the Vertex Buffer is in user memory, the first vertex is
  350. // dwVertexOffset bytes into the buffer to which lpVertices points. Otherwise,
  351. // the driver should apply dwVertexOffset to the memory associated with the
  352. // DD_SURFACE_LOCAL structure to which lpDDVertex points.
  353. //
  354. // -Check dwVertexType to ensure that the driver supports the requested FVF. The
  355. // driver should fail the call if any of the following conditions exist:
  356. //
  357. // *Vertex coordinates are not specified; that is, if D3DFVF_XYZRHW is not set.
  358. // *Normals are specified; that is, if D3DFVF_NORMAL is set.
  359. // *Any of the reserved D3DFVF_RESERVEDx bits are set.
  360. //
  361. // -Process all of the commands in the Command Buffer sequentially. For each
  362. // D3DNTHAL_DP2COMMAND structure, the driver should do the following:
  363. //
  364. // *If the command is D3DDP2OP_RENDERSTATE, process the wStateCount
  365. // D3DNTHAL_DP2RENDERSTATE structures that follow in the Command Buffer,
  366. // updating the driver state for each render state structure. When the
  367. // D3DNTHALDP2_EXECUTEBUFFER flag is set, the driver should also reflect the
  368. // state change in the array to which lpdwRStates points.
  369. // *If the command is D3DDP2OP_TEXTURESTAGESTATE, process the wStateCount
  370. // D3DNTHAL_DP2TEXTURESTAGESTATE structures that follow in the Command Buffer,
  371. // updating the driver's texture state associated with the specified texture
  372. // stage for each texture state structure.
  373. // *If the command is D3DDP2OP_VIEWPORTINFO, process the D3DNTHAL_DP2VIEWPORTINFO
  374. // structure that follows in the Command Buffer, updating the viewport
  375. // information stored in the driver's internal rendering context.
  376. // *If the command is D3DDP2OP_WINFO, process the D3DNTHAL_DP2WINFO structure
  377. // that follows in the Command Buffer, updating the w-buffering information
  378. // stored in the driver's internal rendering context.
  379. // *Otherwise, process the D3DNTHAL_DP2Xxx primitive structures that follow the
  380. // D3DDP2OP_Xxx primitive rendering command in the Command Buffer.
  381. // *If the command is unknown, call the runtime's D3dParseUnknownCommand callback
  382. // The runtime provides this callback to the driver's DdGetDriverInfo callback
  383. // with the GUID_D3DPARSEUNKNOWNCOMMANDCALLBACK guid.
  384. //
  385. // The driver doesn't need to probe for readability the memory in which the
  386. // Command and Vertex Buffers are stored. However, the driver is responsible for
  387. // ensuring that it does not exceed the bounds of these buffers; that is, the
  388. // driver must stay within the bounds specified by dwCommandLength and
  389. // dwVertexLength.
  390. //
  391. // If the driver needs to fail D3dDrawPrimitives2, it should fill in
  392. // dwErrorOffset with the offset into Command Buffer at which the first
  393. // unhandled D3DNTHAL_DP2COMMAND can be found.
  394. //
  395. //
  396. // Parameters
  397. //
  398. // pdp2d
  399. // Points to a D3DNTHAL_DRAWPRIMITIVES2DATA structure that contains
  400. // the information required for the driver to render one or more
  401. // primitives.
  402. //
  403. // .dwhContext
  404. // Specifies the context handle of the Direct3D device.
  405. // .dwFlags
  406. // Specifies flags that provide additional instructions to the
  407. // driver or provide information from the driver. This member
  408. // can be a bitwise OR of the following values:
  409. //
  410. // D3DNTHALDP2_USERMEMVERTICES
  411. // The lpVertices member is valid; that is, the driver
  412. // should obtain the vertex data from the user-allocated
  413. // memory to which lpVertices points. This flag is set
  414. // by Direct3D only.
  415. // D3DNTHALDP2_EXECUTEBUFFER
  416. // Indicates that the Command and Vertex Buffers were
  417. // created in system memory. The driver should update
  418. // the state array to which lpdwRStates points. This
  419. // flag is set by Direct3D only.
  420. // D3DNTHALDP2_SWAPVERTEXBUFFER
  421. // Indicates that the driver can swap the buffer to
  422. // which lpDDVertex or lpVertices points with a new
  423. // Vertex Buffer and return immediately, asynchronously
  424. // processing the original buffer while Direct3D fills
  425. // the new Vertex Buffer. Drivers that do not support
  426. // multi-buffering of Vertex Buffers can ignore this
  427. // flag. This flag is set by Direct3D only.
  428. // D3DNTHALDP2_SWAPCOMMANDBUFFER
  429. // Indicates that the driver can swap the buffer to
  430. // which lpDDCommands points with a new Command Buffer
  431. // and return immediately, asynchronously processing
  432. // the original buffer while Direct3D fills the new
  433. // Command Buffer. Drivers that do not support
  434. /// multi-buffering of Command Buffers can ignore this
  435. // flag. This flag is set by Direct3D only.
  436. // D3DNTHALDP2_REQVERTEXBUFSIZE
  437. // Indicates that the driver must be able to allocate
  438. // a Vertex Buffer of at least the size specified in
  439. // dwReqVertexBufSize. Drivers that do not support
  440. // multi-buffering of Vertex Buffers can ignore this
  441. // flag. This flag is set by Direct3D only.
  442. // D3DNTHALDP2_REQCOMMANDBUFSIZE
  443. // Indicates that the driver must be able to allocate
  444. // a Command Buffer of at least the size specified in
  445. // dwReqCommandBufSize. Drivers that do not support
  446. // multi-buffering of Command Buffers can ignore this
  447. // flag. This flag is set by Direct3D only.
  448. // D3DNTHALDP2_VIDMEMVERTEXBUF
  449. // Indicates that the Vertex Buffer allocated by the
  450. // driver as a swap buffer is not in system memory.
  451. // This flag can be set by drivers that support multi-
  452. // buffering of Vertex Buffers.
  453. // D3DNTHALDP2_VIDMEMCOMMANDBUF
  454. // Indicates that the Command Buffer allocated by the
  455. // driver as a swap buffer is not in system memory. This
  456. // flag can be set by drivers that support multi-
  457. // buffering of Command Buffers.
  458. //
  459. // .dwVertexType
  460. // Identifies the FVF of the data in the Vertex Buffer; that is,
  461. // dwVertexType specifies which per-vertex data fields are present
  462. // in the Vertex Buffer to which lpDDVertex or lpVertices points.
  463. // This member can be a bitwise OR of the values in the table that
  464. // follows. Only one of the D3DFVF_TEXx flags will be set.
  465. //
  466. // Value Meaning
  467. // ============== =======
  468. // D3DFVF_XYZRHW Each vertex has an x,y,z, and w.
  469. // This flag is always set.
  470. // D3DFVF_DIFFUSE Each vertex has a diffuse color.
  471. // D3DFVF_SPECULAR Each vertex has a specular color.
  472. // D3DFVF_TEX0 No texture coordinates are provided
  473. // with the vertex data.
  474. // D3DFVF_TEX1 Each vertex has one set of texture
  475. // coordinates.
  476. // D3DFVF_TEX2 Each vertex has two sets of texture
  477. // coordinates.
  478. // D3DFVF_TEX3 Each vertex has three sets of texture
  479. // coordinates.
  480. // D3DFVF_TEX4 Each vertex has four sets of texture
  481. // coordinates.
  482. // D3DFVF_TEX5 Each vertex has five sets of texture
  483. // coordinates.
  484. // D3DFVF_TEX6 Each vertex has six sets of texture
  485. // coordinates.
  486. // D3DFVF_TEX7 Each vertex has seven sets of texture
  487. // coordinates.
  488. // D3DFVF_TEX8 Each vertex has eight sets of texture
  489. // coordinates.
  490. //
  491. // .lpDDCommands
  492. // Points to the DD_SURFACE_LOCAL structure that identifies the
  493. // DirectDraw surface containing the command data. The fpVidMem
  494. // member of the embedded DD_SURFACE_GLOBAL structure points to
  495. // the buffer that contains state change and primitive drawing
  496. // commands for the driver to process. Specifically, this buffer
  497. // contains one or more D3DNTHAL_DP2COMMAND structures, each
  498. // followed by a D3DNTHAL_DP2Xxx structure whose exact type is
  499. // identified by D3DNTHAL_DP2COMMAND's bCommand member.
  500. // .dwCommandOffset
  501. // Specifies the number of bytes into the surface to which
  502. // lpDDCommands points at which the command data starts.
  503. // .dwCommandLength
  504. // Specifies the number of bytes of valid command data in the
  505. // surface to which lpDDCommands points starting at dwCommandOffset.
  506. // .lpDDVertex
  507. // Points to the DD_SURFACE_LOCAL structure that identifies the
  508. // DirectDraw surface containing the vertex data when the
  509. // D3DNTHALDP2_USERMEMVERTICES flag is not set in dwFlags. Union
  510. // with lpVertices.
  511. // .lpVertices
  512. // Points to a user-mode memory block containing vertex data when
  513. // the D3DNTHALDP2_USERMEMVERTICES flag is set in dwFlags.
  514. // .dwVertexOffset
  515. // Specifies the number of bytes into the surface to which
  516. // lpDDVertex or lpVertices points at which the vertex data starts.
  517. // .dwVertexLength
  518. // The number of vertices, for which valid data exists in the
  519. // surface, that lpDDVertex points to (starting at dwVertexOffset).
  520. // Note that dwVertexOffset is specified in bytes.
  521. // .dwReqVertexBufSize
  522. // Specifies the minimum number of bytes that the driver must
  523. // allocate for the swap Vertex Buffer. This member is valid only
  524. // when the D3DNTHALDP2_REQVERTEXBUFSIZE flag is set. Drivers that
  525. // do not support multi-buffering of Vertex Buffers should ignore
  526. // this member.
  527. // .dwReqCommandBufSize
  528. // Specifies the minimum number of bytes that the driver must
  529. // allocate for the swap Command Buffer. This member is valid only
  530. // when the D3DNTHALDP2_REQCOMMANDBUFSIZE flag is set. Drivers that
  531. // do not support multi-buffering of Command Buffers should ignore
  532. // this member.
  533. // .lpdwRStates
  534. // Points to a render state array that the driver should update
  535. // when it parses render state commands from the Command Buffer.
  536. // The driver should update this array only when the
  537. // D3DNTHALDP2_EXECUTEBUFFER flag is set in dwFlags. The driver
  538. // should use the D3DRENDERSTATETYPE enumerated types to update
  539. // the appropriate render state's array element.
  540. // .dwVertexSize
  541. // Used to pass in the size of each vertex in bytes. Union with
  542. // ddrval.
  543. // .ddrval
  544. // Specifies the location in which the driver writes the return
  545. // value of D3dDrawPrimitives2. D3D_OK indicates success;
  546. // otherwise, the driver should return the appropriate
  547. // D3DNTERR_Xxx error code.
  548. // .dwErrorOffset
  549. // Specifies the location in which the driver should write the
  550. // offset into the surface to which lpDDCommands points at which
  551. // the first unhandled D3DNTHAL_DP2COMMAND can be found. The
  552. // driver must set this value when it returns an error condition
  553. // in ddrval.
  554. //
  555. //-----------------------------------------------------------------------------
  556. DWORD WINAPI
  557. D3DDrawPrimitives2_P3(
  558. LPD3DHAL_DRAWPRIMITIVES2DATA pdp2d )
  559. {
  560. P3_THUNKEDDATA* pThisDisplay;
  561. P3_D3DCONTEXT* pContext;
  562. LPDWORD lpVertices;
  563. P3_VERTEXBUFFERINFO* pVertexBufferInfo;
  564. P3_VERTEXBUFFERINFO* pCommandBufferInfo;
  565. LPD3DHAL_DP2COMMAND lpIns;
  566. LPBYTE lpInsStart;
  567. LPBYTE lpPrim;
  568. BOOL bParseError = FALSE;
  569. BOOL bUsedHostIn = FALSE;
  570. HRESULT ddrval;
  571. LPBYTE pUMVtx;
  572. int i;
  573. DBG_CB_ENTRY(D3DDrawPrimitives2_P3);
  574. // Get current context and validate it
  575. pContext = _D3D_CTX_HandleToPtr(pdp2d->dwhContext);
  576. if (!CHECK_D3DCONTEXT_VALIDITY(pContext))
  577. {
  578. pdp2d->ddrval = D3DHAL_CONTEXT_BAD;
  579. DISPDBG((ERRLVL,"ERROR: Context not valid"));
  580. DBG_CB_EXIT(D3DDrawPrimitives2_P3, D3DHAL_CONTEXT_BAD);
  581. return (DDHAL_DRIVER_HANDLED);
  582. }
  583. // Get and validate driver data
  584. pThisDisplay = pContext->pThisDisplay;
  585. VALIDATE_MODE_AND_STATE(pThisDisplay);
  586. // Debugging messages
  587. DISPDBG((DBGLVL, " dwhContext = %x",pdp2d->dwhContext));
  588. DISPDBG((DBGLVL, " dwFlags = %x",pdp2d->dwFlags));
  589. DBGDUMP_D3DDP2FLAGS(DBGLVL, pdp2d->dwFlags);
  590. DISPDBG((DBGLVL, " dwVertexType = %x",pdp2d->dwVertexType));
  591. DISPDBG((DBGLVL, " dwCommandOffset = %d",pdp2d->dwCommandOffset));
  592. DISPDBG((DBGLVL, " dwCommandLength = %d",pdp2d->dwCommandLength));
  593. DISPDBG((DBGLVL, " dwVertexOffset = %d",pdp2d->dwVertexOffset));
  594. DISPDBG((DBGLVL, " dwVertexLength = %d",pdp2d->dwVertexLength));
  595. DISPDBG((DBGLVL, " dwReqVertexBufSize = %d",pdp2d->dwReqVertexBufSize));
  596. DISPDBG((DBGLVL, " dwReqCommandBufSize = %d",pdp2d->dwReqCommandBufSize));
  597. // Get appropriate pointers to commands in command buffer
  598. lpInsStart = (LPBYTE)(pdp2d->lpDDCommands->lpGbl->fpVidMem);
  599. if (lpInsStart == NULL)
  600. {
  601. DISPDBG((ERRLVL, "ERROR: Command Buffer pointer is null"));
  602. pdp2d->ddrval = DDERR_INVALIDPARAMS;
  603. DBG_CB_EXIT(D3DDrawPrimitives2_P3, DDERR_INVALIDPARAMS);
  604. return DDHAL_DRIVER_HANDLED;
  605. }
  606. lpIns = (LPD3DHAL_DP2COMMAND)(lpInsStart + pdp2d->dwCommandOffset);
  607. // Check if vertex buffer resides in user memory or in a DDraw surface
  608. if (pdp2d->dwFlags & D3DHALDP2_USERMEMVERTICES)
  609. {
  610. pUMVtx = (LPBYTE)pdp2d->lpVertices;
  611. // Get appropriate pointer to vertices , memory is already secured
  612. lpVertices = (LPDWORD)((LPBYTE)pdp2d->lpVertices +
  613. pdp2d->dwVertexOffset);
  614. }
  615. else
  616. {
  617. // Get appropriate pointer to vertices
  618. lpVertices = (LPDWORD)((LPBYTE)pdp2d->lpDDVertex->lpGbl->fpVidMem +
  619. pdp2d->dwVertexOffset);
  620. }
  621. if (lpVertices == NULL)
  622. {
  623. DISPDBG((ERRLVL, "ERROR: Vertex Buffer pointer is null"));
  624. pdp2d->ddrval = DDERR_INVALIDPARAMS;
  625. DBG_CB_EXIT(D3DDrawPrimitives2_P3, DDERR_INVALIDPARAMS);
  626. return DDHAL_DRIVER_HANDLED;
  627. }
  628. #if DX8_DDI
  629. // Take notice of the following block of code necessary
  630. // for DX8 drivers to run <= DX7 apps succesfully!
  631. #endif // DX8_DDI
  632. // Take the VB format and address from our header info if we are
  633. // processing a DX7 or earlier context. Otherwise we'll get updates
  634. // through the new DX8 DP2 tokens (D3DDP2OP_SETSTREAMSOURCE &
  635. // D3DDP2OP_SETVERTEXSHADER)
  636. if (IS_DX7_OR_EARLIER_APP(pContext))
  637. {
  638. // Update place from where vertices will be processed for this context
  639. pContext->lpVertices = lpVertices;
  640. // Update the FVF code to be used currently.
  641. pContext->dwVertexType = pdp2d->dwVertexType;
  642. }
  643. // Switch to the chips D3D context and get ready for rendering
  644. STOP_SOFTWARE_CURSOR(pThisDisplay);
  645. D3D_OPERATION(pContext, pThisDisplay);
  646. //@@BEGIN_DDKSPLIT
  647. //AZN This check for flips is here because otherwise DX3 tunnel in FS flickers
  648. //@@END_DDKSPLIT
  649. // Can return if still drawing
  650. pdp2d->ddrval =
  651. _DX_QueryFlipStatus(pThisDisplay,
  652. pContext->pSurfRenderInt->fpVidMem,
  653. TRUE);
  654. if( FAILED( pdp2d->ddrval ) )
  655. {
  656. DISPDBG((DBGLVL,"Returning because flip has not occurred"));
  657. START_SOFTWARE_CURSOR(pThisDisplay);
  658. DBG_CB_EXIT(D3DDrawPrimitives2_P3, 0);
  659. return DDHAL_DRIVER_HANDLED;
  660. }
  661. //@@BEGIN_DDKSPLIT
  662. #if DX7_VERTEXBUFFERS
  663. _D3D_EB_GetAndWaitForBuffers(pThisDisplay,
  664. pdp2d,
  665. &pCommandBufferInfo,
  666. &pVertexBufferInfo);
  667. #endif
  668. //@@END_DDKSPLIT
  669. DISPDBG((DBGLVL,"Command Buffer @ %x Vertex Buffer @ %x",
  670. lpIns, lpVertices));
  671. // Process commands while we haven't exhausted the command buffer
  672. while (!bParseError &&
  673. ((LPBYTE)lpIns <
  674. (lpInsStart + pdp2d->dwCommandLength + pdp2d->dwCommandOffset) )
  675. )
  676. {
  677. // Get pointer to first primitive structure past the D3DHAL_DP2COMMAND
  678. lpPrim = (LPBYTE)lpIns + sizeof(D3DHAL_DP2COMMAND);
  679. DISPDBG((DBGLVL, "DrawPrimitive2: Parsing instruction %d Count = %d @ %x",
  680. lpIns->bCommand, lpIns->wPrimitiveCount, lpIns));
  681. // Look for opcodes that cause rendering - we need to process state
  682. // changes and wait for any pending flip.
  683. switch( lpIns->bCommand )
  684. {
  685. case D3DDP2OP_RENDERSTATE:
  686. case D3DDP2OP_TEXTURESTAGESTATE:
  687. case D3DDP2OP_STATESET:
  688. case D3DDP2OP_VIEWPORTINFO:
  689. case D3DDP2OP_WINFO:
  690. case D3DDP2OP_UPDATEPALETTE:
  691. case D3DDP2OP_SETPALETTE:
  692. #if DX7_TEXMANAGEMENT
  693. case D3DDP2OP_SETTEXLOD:
  694. case D3DDP2OP_SETPRIORITY:
  695. #if DX8_DDI
  696. case D3DDP2OP_ADDDIRTYRECT:
  697. case D3DDP2OP_ADDDIRTYBOX:
  698. #endif // DX8_DDI
  699. #endif
  700. case D3DDP2OP_ZRANGE:
  701. case D3DDP2OP_SETMATERIAL:
  702. case D3DDP2OP_SETLIGHT:
  703. case D3DDP2OP_CREATELIGHT:
  704. case D3DDP2OP_EXT:
  705. case D3DDP2OP_SETTRANSFORM:
  706. case D3DDP2OP_SETRENDERTARGET:
  707. #if DX8_DDI
  708. case D3DDP2OP_CREATEVERTEXSHADER:
  709. case D3DDP2OP_SETVERTEXSHADER:
  710. case D3DDP2OP_DELETEVERTEXSHADER:
  711. case D3DDP2OP_SETVERTEXSHADERCONST:
  712. case D3DDP2OP_CREATEPIXELSHADER:
  713. case D3DDP2OP_SETPIXELSHADER:
  714. case D3DDP2OP_DELETEPIXELSHADER:
  715. case D3DDP2OP_SETPIXELSHADERCONST:
  716. case D3DDP2OP_SETSTREAMSOURCE :
  717. case D3DDP2OP_SETSTREAMSOURCEUM :
  718. case D3DDP2OP_SETINDICES :
  719. #endif // DX8_DDI
  720. // These opcodes don't cause any rendering - do nothing
  721. break;
  722. default:
  723. // The primitive type is not actually important to
  724. // make sure the hw setup changes have been done.
  725. _D3D_ST_RealizeHWStateChanges( pContext );
  726. // Need to reset the FVF data because it
  727. // depends on the texture setup
  728. if (__CheckFVFRequest(pContext,
  729. pContext->dwVertexType) != DD_OK)
  730. {
  731. DISPDBG((ERRLVL, "ERROR: D3DDrawPrimitives2_P3 cannot handle "
  732. "Flexible Vertex Format requested"));
  733. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  734. D3DERR_COMMAND_UNPARSED);
  735. }
  736. // Fall through as we don't need to handle any new state or
  737. // check our FVF formats if we're only clearing or blitting
  738. // surfaces
  739. case D3DDP2OP_CLEAR:
  740. case D3DDP2OP_TEXBLT:
  741. #if DX8_DDI
  742. case D3DDP2OP_VOLUMEBLT:
  743. case D3DDP2OP_BUFFERBLT:
  744. #endif // DX8_DDI
  745. // Check to see if any pending physical flip has occurred
  746. //@@BEGIN_DDKSPLIT
  747. //
  748. // The runtime doesn't expect to see DDERR_WASSTILLDRAWING
  749. // when using DP2 to emulate Execute buffers, so we have to
  750. // spin here. Also, if we have processed any of this command
  751. // buffer we are forced into spinning here because if we
  752. // returned the runtime would not know about the already
  753. // processed commands and we would process them again -
  754. // probably a bad thing. We must do this check here rather
  755. // than earlier because in some cases DP2 gets called when
  756. // the render surface has been freed. This causes an exception
  757. // if we try to check the flip status.
  758. if(( pdp2d->dwFlags & D3DHALDP2_EXECUTEBUFFER ) ||
  759. ( lpIns >
  760. (LPD3DHAL_DP2COMMAND)( lpInsStart +
  761. pdp2d->dwCommandOffset )))
  762. {
  763. while( _DX_QueryFlipStatus(pThisDisplay,
  764. pContext->pSurfRenderInt->fpVidMem,
  765. TRUE) == DDERR_WASSTILLDRAWING )
  766. {
  767. // Waste time - could back off here
  768. }
  769. }
  770. else
  771. //@@END_DDKSPLIT
  772. {
  773. // Can return if still drawing
  774. pdp2d->ddrval =
  775. _DX_QueryFlipStatus(pThisDisplay,
  776. pContext->pSurfRenderInt->fpVidMem,
  777. TRUE);
  778. if( FAILED ( pdp2d->ddrval ) )
  779. {
  780. DISPDBG((DBGLVL,"Returning because flip has not occurred"));
  781. START_SOFTWARE_CURSOR(pThisDisplay);
  782. DBG_CB_EXIT(D3DDrawPrimitives2_P3, 0);
  783. return DDHAL_DRIVER_HANDLED;
  784. }
  785. }
  786. break;
  787. }
  788. switch( lpIns->bCommand )
  789. {
  790. case D3DDP2OP_VIEWPORTINFO:
  791. // Used to inform the guard-band aware drivers, the view
  792. // clipping rectangle. Non-guard-band drivers should ignore
  793. // and skip over these instructions and continue processing
  794. // the rest of the command buffer. The clipping rectangle is
  795. // specified by the members dwX, dwY, dwWidth and dwHeight.
  796. DISPDBG((DBGLVL, "D3DDP2OP_VIEWPORTINFO"));
  797. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  798. D3DHAL_DP2VIEWPORTINFO, lpIns->wStateCount, 0);
  799. for( i = 0; i < lpIns->wStateCount; i++)
  800. {
  801. // There should be only one of these, but we'll pay attention
  802. // to the last one just in case
  803. _D3D_OP_Viewport(pContext, (D3DHAL_DP2VIEWPORTINFO*)lpPrim);
  804. lpPrim += sizeof(D3DHAL_DP2VIEWPORTINFO);
  805. }
  806. NEXTINSTRUCTION(lpIns, D3DHAL_DP2VIEWPORTINFO, lpIns->wStateCount, 0);
  807. break;
  808. case D3DDP2OP_WINFO:
  809. // Record the W Buffering info
  810. DISPDBG((DBGLVL, "D3DDP2OP_WINFO"));
  811. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  812. D3DHAL_DP2WINFO, lpIns->wStateCount, 0);
  813. pContext->WBufferInfo = *((D3DHAL_DP2WINFO*)lpPrim);
  814. DIRTY_WBUFFER(pContext);
  815. lpPrim += sizeof(D3DHAL_DP2WINFO);
  816. NEXTINSTRUCTION(lpIns, D3DHAL_DP2WINFO, lpIns->wStateCount, 0);
  817. break;
  818. case D3DDP2OP_RENDERSTATE:
  819. // Specifies a render state change that requires processing.
  820. // The rendering state to change is specified by one or more
  821. // D3DHAL_DP2RENDERSTATE structures following D3DHAL_DP2COMMAND.
  822. DISPDBG((DBGLVL,"D3DDP2OP_RENDERSTATE: state count = %d",
  823. lpIns->wStateCount));
  824. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  825. D3DHAL_DP2RENDERSTATE, lpIns->wStateCount, 0);
  826. if (pdp2d->dwFlags & D3DHALDP2_EXECUTEBUFFER)
  827. {
  828. _D3D_ST_ProcessRenderStates(pContext,
  829. lpIns->wStateCount,
  830. (LPD3DSTATE)lpPrim,
  831. TRUE);
  832. // As the render states vector lives in user memory, we need to
  833. // access it bracketing it with a try/except block. This
  834. // is because the user memory might under some circumstances
  835. // become invalid while the driver is running and then it
  836. // would AV. Also, the driver might need to do some cleanup
  837. // before returning to the OS.
  838. __try
  839. {
  840. for (i = lpIns->wStateCount; i > 0; i--)
  841. {
  842. pdp2d->lpdwRStates[((D3DHAL_DP2RENDERSTATE*)lpPrim)->RenderState]
  843. = ((D3DHAL_DP2RENDERSTATE*)lpPrim)->dwState;
  844. lpPrim += sizeof(D3DHAL_DP2RENDERSTATE);
  845. }
  846. }
  847. __except(EXCEPTION_EXECUTE_HANDLER)
  848. {
  849. // On this driver we don't need to do anything special
  850. DISPDBG((ERRLVL,"Driver caused exception at "
  851. "line %u of file %s",
  852. __LINE__,__FILE__));
  853. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  854. DDERR_GENERIC);
  855. }
  856. }
  857. else
  858. {
  859. _D3D_ST_ProcessRenderStates(pContext,
  860. lpIns->wStateCount,
  861. (LPD3DSTATE)lpPrim,
  862. FALSE);
  863. lpPrim += (sizeof(D3DHAL_DP2RENDERSTATE) * lpIns->wStateCount);
  864. }
  865. NEXTINSTRUCTION(lpIns, D3DHAL_DP2RENDERSTATE, lpIns->wStateCount, 0);
  866. break;
  867. case D3DDP2OP_TEXTURESTAGESTATE:
  868. DISPDBG((DBGLVL,"D3DDP2OP_TEXTURESTAGESTATE: state count = %d",
  869. lpIns->wStateCount));
  870. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  871. D3DHAL_DP2TEXTURESTAGESTATE,
  872. lpIns->wStateCount , 0);
  873. _D3D_TXT_ParseTextureStageStates(
  874. pContext,
  875. (D3DHAL_DP2TEXTURESTAGESTATE*)lpPrim,
  876. lpIns->wStateCount,
  877. TRUE);
  878. lpPrim += sizeof(D3DHAL_DP2TEXTURESTAGESTATE) *
  879. lpIns->wStateCount;
  880. NEXTINSTRUCTION(lpIns,
  881. D3DHAL_DP2TEXTURESTAGESTATE,
  882. lpIns->wStateCount , 0);
  883. break;
  884. case D3DDP2OP_STATESET:
  885. {
  886. D3DHAL_DP2STATESET *pStateSetOp = (D3DHAL_DP2STATESET*)(lpPrim);
  887. DISPDBG((DBGLVL,"D3DDP2OP_STATESET: state count = %d",
  888. lpIns->wStateCount));
  889. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  890. D3DHAL_DP2STATESET, lpIns->wStateCount, 0);
  891. #if DX7_D3DSTATEBLOCKS
  892. for (i = 0; i < lpIns->wStateCount; i++, pStateSetOp++)
  893. {
  894. switch (pStateSetOp->dwOperation)
  895. {
  896. #if DX8_DDI
  897. case D3DHAL_STATESETCREATE :
  898. // This DDI should be called only for drivers > DX7
  899. // and only for those which support TLHals. It is
  900. // called only when the device created is a pure-device
  901. // On receipt of this request the driver should create
  902. // a state block of the type given in the field sbType
  903. // and capture the current given state into it.
  904. break;
  905. #endif //DX8_DDI
  906. case D3DHAL_STATESETBEGIN :
  907. _D3D_SB_BeginStateSet(pContext,pStateSetOp->dwParam);
  908. break;
  909. case D3DHAL_STATESETEND :
  910. _D3D_SB_EndStateSet(pContext);
  911. break;
  912. case D3DHAL_STATESETDELETE :
  913. _D3D_SB_DeleteStateSet(pContext,pStateSetOp->dwParam);
  914. break;
  915. case D3DHAL_STATESETEXECUTE:
  916. _D3D_SB_ExecuteStateSet(pContext,pStateSetOp->dwParam);
  917. break;
  918. case D3DHAL_STATESETCAPTURE:
  919. _D3D_SB_CaptureStateSet(pContext,pStateSetOp->dwParam);
  920. break;
  921. default :
  922. DISPDBG((ERRLVL,"D3DDP2OP_STATESET has invalid"
  923. "dwOperation %08lx",pStateSetOp->dwOperation));
  924. }
  925. }
  926. #endif //DX7_D3DSTATEBLOCKS
  927. // Update the command buffer pointer
  928. NEXTINSTRUCTION(lpIns, D3DHAL_DP2STATESET,
  929. lpIns->wStateCount, 0);
  930. }
  931. break;
  932. case D3DDP2OP_ZRANGE:
  933. DISPDBG((DBGLVL, "D3DDP2OP_ZRANGE"));
  934. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  935. D3DHAL_DP2ZRANGE, lpIns->wStateCount, 0);
  936. for( i = 0; i < lpIns->wStateCount; i++)
  937. {
  938. // There should be only one of these, but we'll pay attention
  939. // to the last one just in case
  940. _D3D_OP_ZRange(pContext, (D3DHAL_DP2ZRANGE*)lpPrim);
  941. lpPrim += sizeof(D3DHAL_DP2ZRANGE);
  942. }
  943. NEXTINSTRUCTION(lpIns, D3DHAL_DP2ZRANGE, lpIns->wStateCount, 0);
  944. break;
  945. case D3DDP2OP_UPDATEPALETTE:
  946. // Perform modifications to the palette that is used for palettized
  947. // textures. The palette handle attached to a surface is updated
  948. // with wNumEntries PALETTEENTRYs starting at a specific wStartIndex
  949. // member of the palette. (A PALETTENTRY (defined in wingdi.h and
  950. // wtypes.h) is actually a DWORD with an ARGB color for each byte.)
  951. // After the D3DNTHAL_DP2UPDATEPALETTE structure in the command
  952. // stream the actual palette data will follow (without any padding),
  953. // comprising one DWORD per palette entry. There will only be one
  954. // D3DNTHAL_DP2UPDATEPALETTE structure (plus palette data) following
  955. // the D3DNTHAL_DP2COMMAND structure regardless of the value of
  956. // wStateCount.
  957. {
  958. D3DHAL_DP2UPDATEPALETTE* pUpdatePalette;
  959. DISPDBG((DBGLVL, "D3DDP2OP_UPDATEPALETTE"));
  960. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  961. D3DHAL_DP2UPDATEPALETTE, 1, 0);
  962. pUpdatePalette = (D3DHAL_DP2UPDATEPALETTE *)lpPrim;
  963. // Each palette entry is a DWORD ARGB 8:8:8:8
  964. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  965. D3DHAL_DP2UPDATEPALETTE,
  966. 1, pUpdatePalette->wNumEntries * sizeof(DWORD));
  967. ddrval = _D3D_OP_UpdatePalette(pContext,
  968. pUpdatePalette,
  969. (LPDWORD)(pUpdatePalette + 1));
  970. if ( FAILED(ddrval) )
  971. {
  972. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  973. ddrval);
  974. }
  975. lpPrim += (sizeof(D3DHAL_DP2UPDATEPALETTE) +
  976. pUpdatePalette->wNumEntries * 4);
  977. // Each palette entry is a DWORD ARGB 8:8:8:8
  978. NEXTINSTRUCTION(lpIns, D3DHAL_DP2UPDATEPALETTE,
  979. 1, pUpdatePalette->wNumEntries * sizeof(DWORD));
  980. }
  981. break;
  982. case D3DDP2OP_SETPALETTE:
  983. // Attach a palette to a texture, that is , map an association
  984. // between a palette handle and a surface handle, and specify
  985. // the characteristics of the palette. The number of
  986. // D3DNTHAL_DP2SETPALETTE structures to follow is specified by
  987. // the wStateCount member of the D3DNTHAL_DP2COMMAND structure
  988. {
  989. DISPDBG((DBGLVL, "D3DDP2OP_SETPALETTE"));
  990. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  991. D3DHAL_DP2SETPALETTE,
  992. lpIns->wStateCount, 0);
  993. ddrval = _D3D_OP_SetPalettes(pContext,
  994. (D3DHAL_DP2SETPALETTE *)lpPrim,
  995. lpIns->wStateCount);
  996. if ( FAILED(ddrval) )
  997. {
  998. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  999. ddrval);
  1000. }
  1001. lpPrim += sizeof(D3DHAL_DP2SETPALETTE) * lpIns->wStateCount;
  1002. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETPALETTE,
  1003. lpIns->wStateCount, 0);
  1004. }
  1005. break;
  1006. #if DX7_TEXMANAGEMENT
  1007. case D3DDP2OP_SETTEXLOD:
  1008. {
  1009. D3DHAL_DP2SETTEXLOD* pTexLod;
  1010. DISPDBG((DBGLVL, "D3DDP2OP_SETTEXLOD"));
  1011. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1012. D3DHAL_DP2SETTEXLOD, lpIns->wStateCount, 0);
  1013. for( i = 0; i < lpIns->wStateCount; i++)
  1014. {
  1015. // Get the passed material
  1016. pTexLod = ((D3DHAL_DP2SETTEXLOD*)lpPrim);
  1017. lpPrim += sizeof(D3DHAL_DP2SETTEXLOD);
  1018. _D3D_OP_SetTexLod(pContext, pTexLod);
  1019. }
  1020. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETTEXLOD,
  1021. lpIns->wStateCount, 0);
  1022. }
  1023. break;
  1024. case D3DDP2OP_SETPRIORITY:
  1025. {
  1026. D3DHAL_DP2SETPRIORITY* pSetPri;
  1027. DISPDBG((DBGLVL, "D3DDP2OP_SETPRIORITY"));
  1028. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1029. D3DHAL_DP2SETPRIORITY, lpIns->wStateCount, 0);
  1030. for( i = 0; i < lpIns->wStateCount; i++)
  1031. {
  1032. // Get the passed material
  1033. pSetPri = ((D3DHAL_DP2SETPRIORITY*)lpPrim);
  1034. lpPrim += sizeof(D3DHAL_DP2SETPRIORITY);
  1035. _D3D_OP_SetPriority(pContext, pSetPri);
  1036. }
  1037. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETPRIORITY,
  1038. lpIns->wStateCount, 0);
  1039. }
  1040. break;
  1041. #if DX8_DDI
  1042. case D3DDP2OP_ADDDIRTYRECT:
  1043. {
  1044. D3DHAL_DP2ADDDIRTYRECT* pAddRect;
  1045. DISPDBG((DBGLVL, "D3DDP2OP_ADDDIRTYRECT"));
  1046. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1047. D3DDP2OP_ADDDIRTYRECT, lpIns->wStateCount, 0);
  1048. for( i = 0; i < lpIns->wStateCount; i++)
  1049. {
  1050. // Get the dirty rect
  1051. pAddRect = ((D3DHAL_DP2ADDDIRTYRECT*)lpPrim);
  1052. lpPrim += sizeof(D3DHAL_DP2ADDDIRTYRECT);
  1053. _D3D_OP_AddDirtyRect(pContext, pAddRect);
  1054. }
  1055. NEXTINSTRUCTION(lpIns, D3DHAL_DP2ADDDIRTYRECT,
  1056. lpIns->wStateCount, 0);
  1057. }
  1058. break;
  1059. case D3DDP2OP_ADDDIRTYBOX:
  1060. {
  1061. D3DHAL_DP2ADDDIRTYBOX* pAddBox;
  1062. DISPDBG((DBGLVL, "D3DDP2OP_ADDDIRTYBOX"));
  1063. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1064. D3DDP2OP_ADDDIRTYBOX, lpIns->wStateCount, 0);
  1065. for( i = 0; i < lpIns->wStateCount; i++)
  1066. {
  1067. // Get the dirty rect
  1068. pAddBox = ((D3DHAL_DP2ADDDIRTYBOX*)lpPrim);
  1069. lpPrim += sizeof(D3DHAL_DP2ADDDIRTYBOX);
  1070. _D3D_OP_AddDirtyBox(pContext, pAddBox);
  1071. }
  1072. NEXTINSTRUCTION(lpIns, D3DHAL_DP2ADDDIRTYBOX,
  1073. lpIns->wStateCount, 0);
  1074. }
  1075. break;
  1076. #endif // DX8_DDI
  1077. #endif // DX7_TEXMANAGEMENT
  1078. case D3DDP2OP_SETCLIPPLANE:
  1079. {
  1080. D3DHAL_DP2SETCLIPPLANE* pSetPlane;
  1081. DISPDBG((DBGLVL, "D3DDP2OP_SETCLIPPLANE"));
  1082. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1083. D3DHAL_DP2SETCLIPPLANE,
  1084. lpIns->wStateCount, 0);
  1085. for( i = 0; i < lpIns->wStateCount; i++)
  1086. {
  1087. // Get the passed material
  1088. pSetPlane = ((D3DHAL_DP2SETCLIPPLANE*)lpPrim);
  1089. lpPrim += sizeof(D3DHAL_DP2SETCLIPPLANE);
  1090. // (unimplemented OP as we don't support user
  1091. // defined clipping planes)
  1092. // _D3D_OP_SetClipPlane(pContext, pSetPlane);
  1093. }
  1094. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETCLIPPLANE,
  1095. lpIns->wStateCount, 0);
  1096. }
  1097. break;
  1098. case D3DDP2OP_SETMATERIAL:
  1099. {
  1100. D3DHAL_DP2SETMATERIAL* pSetMaterial;
  1101. DISPDBG((DBGLVL, "D3DDP2OP_SETMATERIAL"));
  1102. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1103. D3DHAL_DP2SETMATERIAL, lpIns->wStateCount, 0);
  1104. for( i = 0; i < lpIns->wStateCount; i++)
  1105. {
  1106. // Get the passed material
  1107. pSetMaterial = ((D3DHAL_DP2SETMATERIAL*)lpPrim);
  1108. lpPrim += sizeof(D3DHAL_DP2SETMATERIAL);
  1109. // (unimplemented OP as we are not a TnL driver)
  1110. // _D3D_OP_SetMaterial(pContext, pSetMaterial);
  1111. DIRTY_MATERIAL;
  1112. DBGDUMP_D3DMATERIAL7(DBGLVL, &pSetMaterial);
  1113. }
  1114. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETMATERIAL, lpIns->wStateCount, 0);
  1115. }
  1116. break;
  1117. case D3DDP2OP_SETLIGHT:
  1118. {
  1119. D3DHAL_DP2SETLIGHT* pSetLight;
  1120. DISPDBG((DBGLVL, "D3DDP2OP_SETLIGHT"));
  1121. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1122. D3DHAL_DP2SETLIGHT, lpIns->wStateCount, 0);
  1123. for( i = 0; i < lpIns->wStateCount; i++)
  1124. {
  1125. // Get the passed in light
  1126. pSetLight = (D3DHAL_DP2SETLIGHT*)lpPrim;
  1127. lpPrim += sizeof(D3DHAL_DP2SETLIGHT);
  1128. // (unimplemented OP as we are not a TnL driver)
  1129. // _D3D_OP_SetLight(pContext, pSetLight);
  1130. DIRTY_GAMMA_STATE;
  1131. }
  1132. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETLIGHT, lpIns->wStateCount, 0);
  1133. }
  1134. break;
  1135. case D3DDP2OP_CREATELIGHT:
  1136. {
  1137. D3DHAL_DP2CREATELIGHT* pCreateLight;
  1138. DISPDBG((DBGLVL, "D3DDP2OP_CREATELIGHT"));
  1139. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1140. D3DHAL_DP2CREATELIGHT, 1, 0);
  1141. pCreateLight = (D3DHAL_DP2CREATELIGHT*)lpPrim;
  1142. DISPDBG((DBGLVL,"Creating light, handle: 0x%x",
  1143. pCreateLight->dwIndex));
  1144. DIRTY_GAMMA_STATE;
  1145. lpPrim += sizeof(D3DHAL_DP2CREATELIGHT);
  1146. NEXTINSTRUCTION(lpIns, D3DHAL_DP2CREATELIGHT, 1, 0);
  1147. }
  1148. break;
  1149. case D3DDP2OP_SETTRANSFORM:
  1150. {
  1151. D3DHAL_DP2SETTRANSFORM* pTransform;
  1152. DISPDBG((DBGLVL, "D3DDP2OP_SETTRANSFORM"));
  1153. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1154. D3DHAL_DP2SETTRANSFORM, lpIns->wStateCount, 0);
  1155. for( i = 0; i < lpIns->wStateCount; i++)
  1156. {
  1157. pTransform = (D3DHAL_DP2SETTRANSFORM*)lpPrim;
  1158. switch(pTransform->xfrmType)
  1159. {
  1160. case D3DTRANSFORMSTATE_WORLD:
  1161. DISPDBG((DBGLVL,"D3DTRANSFORMSTATE_WORLD"));
  1162. DIRTY_MODELVIEW;
  1163. break;
  1164. case D3DTRANSFORMSTATE_VIEW:
  1165. DISPDBG((DBGLVL,"D3DTRANSFORMSTATE_VIEW"));
  1166. DIRTY_MODELVIEW;
  1167. break;
  1168. case D3DTRANSFORMSTATE_PROJECTION:
  1169. DISPDBG((DBGLVL,"D3DTRANSFORMSTATE_PROJECTION"));
  1170. DIRTY_PROJECTION;
  1171. break;
  1172. default:
  1173. DISPDBG((ERRLVL,"Texture transform not handled yet!"));
  1174. break;
  1175. }
  1176. // (unimplemented OP as we are not a TnL driver)
  1177. // _D3D_OP_SetTransform(pContext, pTransform);
  1178. // display the matrix in the debugger
  1179. DBGDUMP_D3DMATRIX(DBGLVL, &pTransform->matrix);
  1180. lpPrim += sizeof(D3DHAL_DP2SETTRANSFORM);
  1181. }
  1182. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETTRANSFORM, lpIns->wStateCount, 0);
  1183. }
  1184. break;
  1185. case D3DDP2OP_EXT:
  1186. DISPDBG((ERRLVL, "D3DDP2OP_EXT"));
  1187. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim, DWORD, 1, 0);
  1188. lpPrim += sizeof(DWORD);
  1189. NEXTINSTRUCTION(lpIns, DWORD, 1, 0);
  1190. break;
  1191. case D3DDP2OP_CLEAR:
  1192. {
  1193. D3DHAL_DP2CLEAR* pClear;
  1194. DISPDBG((DBGLVL, "D3DDP2OP_CLEAR"));
  1195. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1196. D3DHAL_DP2CLEAR, 1,
  1197. (lpIns->wStateCount - 1)*sizeof(RECT) );
  1198. pClear = (D3DHAL_DP2CLEAR*)lpPrim;
  1199. // Notice that the interpretation of wStateCount for this
  1200. // operation is special: wStateCount means the number of
  1201. // RECTs following the D3DHAL_DP2CLEAR struct
  1202. _D3D_OP_Clear2(pContext, pClear, lpIns->wStateCount);
  1203. // Return to the 3D state, because the above call
  1204. // will have switched us to a DDRAW hw context
  1205. D3D_OPERATION(pContext, pThisDisplay);
  1206. lpPrim += sizeof(D3DHAL_DP2CLEAR);
  1207. NEXTINSTRUCTION(lpIns, D3DHAL_DP2CLEAR, 1,
  1208. (lpIns->wStateCount - 1)*sizeof(RECT) );
  1209. }
  1210. break;
  1211. case D3DDP2OP_SETRENDERTARGET:
  1212. {
  1213. D3DHAL_DP2SETRENDERTARGET* pSetRenderTarget;
  1214. P3_SURF_INTERNAL* pFrameBuffer;
  1215. P3_SURF_INTERNAL* pZBuffer;
  1216. BOOL bNewAliasBuffers;
  1217. DISPDBG((DBGLVL, "D3DDP2OP_SETRENDERTARGET"));
  1218. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1219. D3DHAL_DP2SETRENDERTARGET, 1, 0);
  1220. pSetRenderTarget = (D3DHAL_DP2SETRENDERTARGET*)lpPrim;
  1221. pFrameBuffer =
  1222. GetSurfaceFromHandle(pContext,
  1223. pSetRenderTarget->hRenderTarget);
  1224. pZBuffer = GetSurfaceFromHandle(pContext,
  1225. pSetRenderTarget->hZBuffer);
  1226. // Check that the Framebuffer is valid
  1227. if (pFrameBuffer == NULL)
  1228. {
  1229. DISPDBG((ERRLVL, "ERROR: "
  1230. "FrameBuffer Surface is invalid!"));
  1231. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  1232. DDERR_GENERIC);
  1233. }
  1234. // Decide whether the render target's size has changed
  1235. bNewAliasBuffers = TRUE;
  1236. if ((pContext->pSurfRenderInt) &&
  1237. (pContext->pSurfRenderInt->wWidth == pFrameBuffer->wWidth) &&
  1238. (pContext->pSurfRenderInt->wHeight == pFrameBuffer->wHeight))
  1239. {
  1240. bNewAliasBuffers = FALSE;
  1241. }
  1242. // Setup in hw the new render target and zbuffer
  1243. if (FAILED(_D3D_OP_SetRenderTarget(pContext,
  1244. pFrameBuffer,
  1245. pZBuffer,
  1246. bNewAliasBuffers) ) )
  1247. {
  1248. DISPDBG((ERRLVL, "ERROR: "
  1249. "FrameBuffer Surface Format is invalid!"));
  1250. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  1251. DDERR_GENERIC);
  1252. }
  1253. // Dirty the renderstate so that the hw setup is reevaluated
  1254. // next time before we render anything
  1255. DIRTY_RENDER_OFFSETS(pContext);
  1256. DIRTY_ALPHABLEND(pContext);
  1257. DIRTY_OPTIMIZE_ALPHA(pContext);
  1258. DIRTY_ZBUFFER(pContext);
  1259. DIRTY_VIEWPORT(pContext);
  1260. lpPrim += sizeof(D3DHAL_DP2SETRENDERTARGET);
  1261. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETRENDERTARGET, 1, 0);
  1262. }
  1263. break;
  1264. case D3DDP2OP_TEXBLT:
  1265. {
  1266. DISPDBG((DBGLVL, "D3DDP2OP_TEXBLT"));
  1267. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1268. D3DHAL_DP2TEXBLT, lpIns->wStateCount, 0);
  1269. for ( i = 0; i < lpIns->wStateCount; i++)
  1270. {
  1271. // As the texture might live in user memory, we need to
  1272. // access it bracketing it with a try/except block. This
  1273. // is because the user memory might under some circumstances
  1274. // become invalid while the driver is running and then it
  1275. // would AV. Also, the driver might need to do some cleanup
  1276. // before returning to the OS.
  1277. __try
  1278. {
  1279. _D3D_OP_TextureBlt(pContext,
  1280. pThisDisplay,
  1281. (D3DHAL_DP2TEXBLT*)(lpPrim));
  1282. }
  1283. __except(EXCEPTION_EXECUTE_HANDLER)
  1284. {
  1285. // On this driver we don't need to do anything special
  1286. DISPDBG((ERRLVL,"Driver caused exception at "
  1287. "line %u of file %s",
  1288. __LINE__,__FILE__));
  1289. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  1290. DDERR_GENERIC);
  1291. }
  1292. lpPrim += sizeof(D3DHAL_DP2TEXBLT);
  1293. }
  1294. NEXTINSTRUCTION(lpIns, D3DHAL_DP2TEXBLT, lpIns->wStateCount, 0);
  1295. }
  1296. break;
  1297. #if DX8_VERTEXSHADERS
  1298. case D3DDP2OP_CREATEVERTEXSHADER:
  1299. {
  1300. D3DHAL_DP2CREATEVERTEXSHADER* pCreateVtxShader;
  1301. DWORD dwExtraBytes = 0;
  1302. DISPDBG((DBGLVL, "D3DDP2OP_CREATEVERTEXSHADER"));
  1303. // iterate through each passed vertex shader creation block
  1304. for (i = 0; i < lpIns->wStateCount; i++)
  1305. {
  1306. // verify that the next vertex shader is readable
  1307. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1308. D3DHAL_DP2CREATEVERTEXSHADER, 1, 0);
  1309. // Get the passed in vertex shader
  1310. pCreateVtxShader = (D3DHAL_DP2CREATEVERTEXSHADER*)lpPrim;
  1311. // Check if the size of the declaration and body of the
  1312. // vertex shader don't exceed the command buffer limits
  1313. CHECK_CMDBUF_LIMITS_S(pdp2d, lpPrim,
  1314. 0, 0,
  1315. pCreateVtxShader->dwDeclSize +
  1316. pCreateVtxShader->dwCodeSize);
  1317. // Advance lpPrim so that it points to the vertex shader's
  1318. // declaration and body
  1319. lpPrim += sizeof(D3DHAL_DP2CREATEVERTEXSHADER);
  1320. // Create this particular shader
  1321. ddrval = _D3D_OP_VertexShader_Create(pContext,
  1322. pCreateVtxShader->dwHandle,
  1323. pCreateVtxShader->dwDeclSize,
  1324. pCreateVtxShader->dwCodeSize,
  1325. lpPrim);
  1326. if ( FAILED(ddrval) )
  1327. {
  1328. DISPDBG((ERRLVL, "ERROR: "
  1329. "Vertex Shader couldn't be created!"));
  1330. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  1331. D3DERR_DRIVERINVALIDCALL);
  1332. }
  1333. // Update lpPrim in order to get to the next vertex
  1334. // shader creation command block.
  1335. dwExtraBytes += pCreateVtxShader->dwDeclSize
  1336. + pCreateVtxShader->dwCodeSize;
  1337. lpPrim += pCreateVtxShader->dwDeclSize
  1338. + pCreateVtxShader->dwCodeSize;
  1339. }
  1340. // Now skip into the next DP2 token in the command buffer
  1341. NEXTINSTRUCTION(lpIns,
  1342. D3DHAL_DP2CREATEVERTEXSHADER,
  1343. lpIns->wStateCount,
  1344. dwExtraBytes);
  1345. }
  1346. break;
  1347. case D3DDP2OP_SETVERTEXSHADER:
  1348. {
  1349. D3DHAL_DP2VERTEXSHADER* pSetVtxShader;
  1350. DISPDBG((DBGLVL, "D3DHAL_DP2SETVERTEXSHADER"));
  1351. // Following the DP2 token there is one and only one
  1352. // set vertex shader block. But lets accomodate if for
  1353. // any reason we receive more than one
  1354. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1355. D3DHAL_DP2VERTEXSHADER,
  1356. lpIns->wStateCount, 0);
  1357. for (i = 0; i < lpIns->wStateCount; i++)
  1358. {
  1359. // Get the passed in vertex shader
  1360. pSetVtxShader = (D3DHAL_DP2VERTEXSHADER*)lpPrim;
  1361. // Setup the given vertex shader.
  1362. _D3D_OP_VertexShader_Set(pContext,
  1363. pSetVtxShader->dwHandle);
  1364. // Now skip into the next DP2 token in the command buffer
  1365. lpPrim += sizeof(D3DHAL_DP2VERTEXSHADER);
  1366. }
  1367. NEXTINSTRUCTION(lpIns, D3DHAL_DP2VERTEXSHADER,
  1368. lpIns->wStateCount, 0);
  1369. }
  1370. break;
  1371. case D3DDP2OP_DELETEVERTEXSHADER:
  1372. {
  1373. D3DHAL_DP2VERTEXSHADER* pDelVtxShader;
  1374. DISPDBG((DBGLVL, "D3DDP2OP_DELETEVERTEXSHADER"));
  1375. // verify that all the following vertex shader
  1376. // delete blocks are readable
  1377. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1378. D3DHAL_DP2VERTEXSHADER,
  1379. lpIns->wStateCount, 0);
  1380. // iterate through each passed vertex shader delete block
  1381. for (i = 0; i < lpIns->wStateCount; i++)
  1382. {
  1383. // Get the passed in vertex shader
  1384. pDelVtxShader = (D3DHAL_DP2VERTEXSHADER*)lpPrim;
  1385. // Destroy the given vertex shader.
  1386. _D3D_OP_VertexShader_Delete(pContext,
  1387. pDelVtxShader->dwHandle);
  1388. // Update lpPrim in order to get to the next vertex
  1389. // shader delete command block.
  1390. lpPrim += sizeof(D3DHAL_DP2VERTEXSHADER);
  1391. }
  1392. // Now skip into the next DP2 token in the command buffer
  1393. NEXTINSTRUCTION(lpIns,
  1394. D3DHAL_DP2VERTEXSHADER,
  1395. lpIns->wStateCount,
  1396. 0);
  1397. }
  1398. break;
  1399. case D3DDP2OP_SETVERTEXSHADERCONST:
  1400. {
  1401. D3DHAL_DP2SETVERTEXSHADERCONST* pVtxShaderConst;
  1402. DWORD dwExtraBytes = 0;
  1403. DISPDBG((DBGLVL, "D3DDP2OP_SETVERTEXSHADERCONST"));
  1404. // verify that all the following vertex shader
  1405. // constant blocks are readable
  1406. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1407. D3DHAL_DP2SETVERTEXSHADERCONST,
  1408. lpIns->wStateCount, 0);
  1409. // iterate through each passed vertex shader constant block
  1410. for (i = 0; i < lpIns->wStateCount; i++)
  1411. {
  1412. // Get the passed in vertex shader constant
  1413. pVtxShaderConst = (D3DHAL_DP2SETVERTEXSHADERCONST*)lpPrim;
  1414. // Advance lpPrim so that it points to the constant
  1415. // values to be loaded
  1416. lpPrim += sizeof(D3DHAL_DP2SETVERTEXSHADERCONST);
  1417. // constant block in order to Set up the constant entries
  1418. _D3D_OP_VertexShader_SetConst(pContext,
  1419. pVtxShaderConst->dwRegister,
  1420. pVtxShaderConst->dwCount,
  1421. (DWORD *)lpPrim);
  1422. // Update lpPrim in order to get to the next vertex
  1423. // shader constants command block. Each register has 4 floats.
  1424. lpPrim += pVtxShaderConst->dwCount * 4 * sizeof(FLOAT);
  1425. dwExtraBytes += pVtxShaderConst->dwCount * 4 * sizeof(FLOAT);
  1426. }
  1427. // Now skip into the next DP2 token in the command buffer
  1428. NEXTINSTRUCTION(lpIns,
  1429. D3DHAL_DP2SETVERTEXSHADERCONST,
  1430. lpIns->wStateCount,
  1431. dwExtraBytes);
  1432. }
  1433. break;
  1434. #endif // DX8_VERTEXSHADERS
  1435. #if DX8_PIXELSHADERS
  1436. case D3DDP2OP_CREATEPIXELSHADER:
  1437. {
  1438. D3DHAL_DP2CREATEPIXELSHADER* pCreatePxlShader;
  1439. DWORD dwExtraBytes = 0;
  1440. DISPDBG((DBGLVL, "D3DDP2OP_CREATEPIXELSHADER"));
  1441. // iterate through each passed pixel shader creation block
  1442. for (i = 0; i < lpIns->wStateCount; i++)
  1443. {
  1444. // verify that the next pixel shader is readable
  1445. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1446. D3DHAL_DP2CREATEPIXELSHADER, 1, 0);
  1447. // Get the passed in pixel shader
  1448. pCreatePxlShader = (D3DHAL_DP2CREATEPIXELSHADER*)lpPrim;
  1449. // Check if the size of the declaration and body of the
  1450. // pixel shader don't exceed the command buffer limits
  1451. CHECK_CMDBUF_LIMITS_S(pdp2d, lpPrim,
  1452. 0, 0,
  1453. pCreatePxlShader->dwCodeSize);
  1454. // Update lpPrim to point to the actual pixel shader code
  1455. lpPrim += sizeof(D3DHAL_DP2CREATEPIXELSHADER);
  1456. // Create the given pixel shader
  1457. ddrval = _D3D_OP_PixelShader_Create(pContext,
  1458. pCreatePxlShader->dwHandle,
  1459. pCreatePxlShader->dwCodeSize,
  1460. lpPrim);
  1461. if ( FAILED(ddrval) )
  1462. {
  1463. DISPDBG((ERRLVL, "ERROR: "
  1464. "Pixel Shader couldn't be created!"));
  1465. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  1466. D3DERR_DRIVERINVALIDCALL);
  1467. }
  1468. // Update lpPrim in order to get to the next vertex
  1469. // shader creation command block.
  1470. lpPrim += pCreatePxlShader->dwCodeSize;
  1471. dwExtraBytes += pCreatePxlShader->dwCodeSize;
  1472. }
  1473. // Now skip into the next DP2 token in the command buffer
  1474. NEXTINSTRUCTION(lpIns,
  1475. D3DHAL_DP2CREATEPIXELSHADER,
  1476. lpIns->wStateCount,
  1477. dwExtraBytes);
  1478. }
  1479. break;
  1480. case D3DDP2OP_SETPIXELSHADER:
  1481. {
  1482. D3DHAL_DP2PIXELSHADER* pSetPxlShader;
  1483. DISPDBG((DBGLVL, "D3DHAL_DP2SETPIXELSHADER"));
  1484. // Following the DP2 token there is one and only one
  1485. // set pixel shader block. But lets accomodate if for
  1486. // any reason we receive more than one
  1487. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1488. D3DHAL_DP2PIXELSHADER,
  1489. lpIns->wStateCount, 0);
  1490. for (i = 0; i < lpIns->wStateCount; i++)
  1491. {
  1492. // Get the passed in pixel shader
  1493. pSetPxlShader = (D3DHAL_DP2PIXELSHADER*)lpPrim;
  1494. // Setup the given pixel shader.
  1495. _D3D_OP_PixelShader_Set(pContext,
  1496. pSetPxlShader->dwHandle);
  1497. // Now skip into the next DP2 token in the command buffer
  1498. lpPrim += sizeof(D3DHAL_DP2PIXELSHADER);
  1499. }
  1500. NEXTINSTRUCTION(lpIns, D3DHAL_DP2PIXELSHADER,
  1501. lpIns->wStateCount, 0);
  1502. }
  1503. break;
  1504. case D3DDP2OP_DELETEPIXELSHADER:
  1505. {
  1506. D3DHAL_DP2PIXELSHADER* pDelPxlShader;
  1507. DISPDBG((DBGLVL, "D3DDP2OP_DELETEPIXELSHADER"));
  1508. // verify that all the following pixel shader
  1509. // delete blocks are readable
  1510. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1511. D3DHAL_DP2PIXELSHADER,
  1512. lpIns->wStateCount, 0);
  1513. // iterate through each passed vertex shader delete block
  1514. for (i = 0; i < lpIns->wStateCount; i++)
  1515. {
  1516. // Get the passed in vertex shader
  1517. pDelPxlShader = (D3DHAL_DP2PIXELSHADER*)lpPrim;
  1518. // Destroy the given pixel shader
  1519. _D3D_OP_PixelShader_Delete(pContext,
  1520. pDelPxlShader->dwHandle);
  1521. // Update lpPrim in order to get to the next vertex
  1522. // shader delete command block.
  1523. lpPrim += sizeof(D3DHAL_DP2PIXELSHADER);
  1524. }
  1525. // Now skip into the next DP2 token in the command buffer
  1526. NEXTINSTRUCTION(lpIns,
  1527. D3DHAL_DP2PIXELSHADER,
  1528. lpIns->wStateCount,
  1529. 0);
  1530. }
  1531. break;
  1532. case D3DDP2OP_SETPIXELSHADERCONST:
  1533. {
  1534. D3DHAL_DP2SETPIXELSHADERCONST* pPxlShaderConst;
  1535. DWORD dwExtraBytes = 0;
  1536. DISPDBG((DBGLVL, "D3DDP2OP_SETPIXELSHADERCONST"));
  1537. // verify that all the following vertex shader
  1538. // constant blocks are readable
  1539. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1540. D3DHAL_DP2SETPIXELSHADERCONST,
  1541. lpIns->wStateCount, 0);
  1542. // iterate through each passed vertex shader constant block
  1543. for (i = 0; i < lpIns->wStateCount; i++)
  1544. {
  1545. // Get the passed in vertex shader constant
  1546. pPxlShaderConst = (D3DHAL_DP2SETPIXELSHADERCONST*)lpPrim;
  1547. // Update lpPrim to point to the const data to setup
  1548. lpPrim += sizeof(D3DHAL_DP2SETPIXELSHADERCONST);
  1549. // Set up the constant entries
  1550. _D3D_OP_PixelShader_SetConst(pContext,
  1551. pPxlShaderConst->dwRegister,
  1552. pPxlShaderConst->dwCount,
  1553. (DWORD *)lpPrim);
  1554. // Update lpPrim in order to get to the next vertex
  1555. // shader delete command block. Each register has 4 floats.
  1556. lpPrim += pPxlShaderConst->dwCount * 4 * sizeof(FLOAT);
  1557. dwExtraBytes += pPxlShaderConst->dwCount * 4 * sizeof(FLOAT);
  1558. }
  1559. // Now skip into the next DP2 token in the command buffer
  1560. NEXTINSTRUCTION(lpIns,
  1561. D3DHAL_DP2SETPIXELSHADERCONST,
  1562. lpIns->wStateCount,
  1563. dwExtraBytes);
  1564. }
  1565. break;
  1566. #endif // DX8_PIXELSHADERS
  1567. #if DX8_MULTSTREAMS
  1568. case D3DDP2OP_SETSTREAMSOURCE :
  1569. {
  1570. D3DHAL_DP2SETSTREAMSOURCE* pSetStreamSrc;
  1571. DISPDBG((DBGLVL, "D3DDP2OP_SETSTREAMSOURCE"));
  1572. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1573. D3DHAL_DP2SETSTREAMSOURCE,
  1574. lpIns->wStateCount, 0);
  1575. // iterate through each
  1576. for ( i = 0; i < lpIns->wStateCount; i++)
  1577. {
  1578. pSetStreamSrc = (D3DHAL_DP2SETSTREAMSOURCE*)lpPrim;
  1579. _D3D_OP_MStream_SetSrc(pContext,
  1580. pSetStreamSrc->dwStream,
  1581. pSetStreamSrc->dwVBHandle,
  1582. pSetStreamSrc->dwStride);
  1583. lpPrim += sizeof(D3DHAL_DP2SETSTREAMSOURCE);
  1584. }
  1585. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETSTREAMSOURCE,
  1586. lpIns->wStateCount, 0);
  1587. }
  1588. break;
  1589. case D3DDP2OP_SETSTREAMSOURCEUM :
  1590. {
  1591. D3DHAL_DP2SETSTREAMSOURCEUM* pSetStreamSrcUM;
  1592. DISPDBG((DBGLVL, "D3DDP2OP_SETSTREAMSOURCEUM"));
  1593. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1594. D3DHAL_DP2SETSTREAMSOURCEUM,
  1595. lpIns->wStateCount, 0);
  1596. // iterate through each
  1597. for ( i = 0; i < lpIns->wStateCount; i++)
  1598. {
  1599. pSetStreamSrcUM = (D3DHAL_DP2SETSTREAMSOURCEUM*)lpPrim;
  1600. _D3D_OP_MStream_SetSrcUM(pContext,
  1601. pSetStreamSrcUM->dwStream,
  1602. pSetStreamSrcUM->dwStride,
  1603. pUMVtx,
  1604. pdp2d->dwVertexLength);
  1605. lpPrim += sizeof(D3DHAL_DP2SETSTREAMSOURCEUM);
  1606. }
  1607. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETSTREAMSOURCEUM,
  1608. lpIns->wStateCount, 0);
  1609. }
  1610. break;
  1611. case D3DDP2OP_SETINDICES :
  1612. {
  1613. D3DHAL_DP2SETINDICES* pSetIndices;
  1614. DISPDBG((DBGLVL, "D3DDP2OP_SETINDICES"));
  1615. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1616. D3DHAL_DP2SETINDICES,
  1617. lpIns->wStateCount, 0);
  1618. // iterate through each
  1619. for ( i = 0; i < lpIns->wStateCount; i++)
  1620. {
  1621. pSetIndices = (D3DHAL_DP2SETINDICES*)lpPrim;
  1622. _D3D_OP_MStream_SetIndices(pContext,
  1623. pSetIndices->dwVBHandle,
  1624. pSetIndices->dwStride);
  1625. lpPrim += sizeof(D3DHAL_DP2SETINDICES);
  1626. }
  1627. NEXTINSTRUCTION(lpIns, D3DHAL_DP2SETINDICES,
  1628. lpIns->wStateCount, 0);
  1629. }
  1630. break;
  1631. #endif // DX8_MULTSTREAMS
  1632. #if DX8_3DTEXTURES
  1633. case D3DDP2OP_VOLUMEBLT:
  1634. {
  1635. DISPDBG((DBGLVL, "D3DDP2OP_VOLUMEBLT"));
  1636. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1637. D3DHAL_DP2VOLUMEBLT,
  1638. lpIns->wStateCount, 0);
  1639. for ( i = 0; i < lpIns->wStateCount; i++)
  1640. {
  1641. // As the texture might live in user memory, we need to
  1642. // access it bracketing it with a try/except block. This
  1643. // is because the user memory might under some circumstances
  1644. // become invalid while the driver is running and then it
  1645. // would AV. Also, the driver might need to do some cleanup
  1646. // before returning to the OS.
  1647. __try
  1648. {
  1649. _D3D_OP_VolumeBlt(pContext,
  1650. pThisDisplay,
  1651. (D3DHAL_DP2VOLUMEBLT*)(lpPrim));
  1652. }
  1653. __except(EXCEPTION_EXECUTE_HANDLER)
  1654. {
  1655. // On this driver we don't need to do anything special
  1656. DISPDBG((ERRLVL,"Driver caused exception at "
  1657. "line %u of file %s",
  1658. __LINE__,__FILE__));
  1659. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  1660. DDERR_GENERIC);
  1661. }
  1662. lpPrim += sizeof(D3DHAL_DP2VOLUMEBLT);
  1663. }
  1664. NEXTINSTRUCTION(lpIns, D3DHAL_DP2VOLUMEBLT,
  1665. lpIns->wStateCount, 0);
  1666. }
  1667. break;
  1668. #endif // DX8_3DTEXTURES
  1669. #if DX8_DDI
  1670. case D3DDP2OP_BUFFERBLT:
  1671. {
  1672. DISPDBG((DBGLVL, "D3DDP2OP_BUFFERBLT"));
  1673. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1674. D3DHAL_DP2BUFFERBLT,
  1675. lpIns->wStateCount, 0);
  1676. for ( i = 0; i < lpIns->wStateCount; i++)
  1677. {
  1678. _D3D_OP_BufferBlt(pContext,
  1679. pThisDisplay,
  1680. (D3DHAL_DP2BUFFERBLT*)(lpPrim));
  1681. lpPrim += sizeof(D3DHAL_DP2BUFFERBLT);
  1682. }
  1683. NEXTINSTRUCTION(lpIns, D3DHAL_DP2BUFFERBLT,
  1684. lpIns->wStateCount, 0);
  1685. }
  1686. break;
  1687. #endif // DX8_DDI
  1688. // This was found to be required for a few D3DRM apps
  1689. case D3DOP_EXIT:
  1690. lpIns = (D3DHAL_DP2COMMAND *)(lpInsStart +
  1691. pdp2d->dwCommandLength +
  1692. pdp2d->dwCommandOffset);
  1693. break;
  1694. default:
  1695. // Pick up the right rasterizers depending on the
  1696. // current rendering state
  1697. _D3D_R3_PickVertexProcessor( pContext );
  1698. // Check if vertex buffer resides in user memory or in a DDraw surface
  1699. if (pdp2d->dwFlags & D3DHALDP2_USERMEMVERTICES)
  1700. {
  1701. // As the vertex buffer lives in user memory, we need to
  1702. // access it bracketing it with a try/except block. This
  1703. // is because the user memory might under some circumstances
  1704. // become invalid while the driver is running and then it
  1705. // would AV. Also, the driver might need to do some cleanup
  1706. // before returning to the OS.
  1707. __try
  1708. {
  1709. // Try to render as a primitive(s) in a separate loop
  1710. // in order not loose performance doing hw setup again
  1711. bParseError = __DP2_PrimitiveOpsParser( pContext,
  1712. pdp2d,
  1713. &lpIns,
  1714. lpInsStart,
  1715. pContext->lpVertices);
  1716. }
  1717. __except(EXCEPTION_EXECUTE_HANDLER)
  1718. {
  1719. // On this driver we don't need to do anything special
  1720. DISPDBG((ERRLVL,"Driver caused exception at "
  1721. "line %u of file %s",
  1722. __LINE__,__FILE__));
  1723. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  1724. DDERR_GENERIC);
  1725. }
  1726. }
  1727. else
  1728. {
  1729. // Try to render as a primitive(s) in a separate loop
  1730. // in order not loose performance doing hw setup again
  1731. bParseError = __DP2_PrimitiveOpsParser( pContext,
  1732. pdp2d,
  1733. &lpIns,
  1734. lpInsStart,
  1735. pContext->lpVertices);
  1736. }
  1737. // We weren't succesful, so we exit with an error code
  1738. if (bParseError)
  1739. {
  1740. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart,
  1741. D3DERR_COMMAND_UNPARSED);
  1742. }
  1743. } // switch
  1744. } // while
  1745. //@@BEGIN_DDKSPLIT
  1746. #if DX7_VERTEXBUFFERS
  1747. if( bUsedHostIn )
  1748. {
  1749. _D3D_EB_UpdateSwapBuffers(pThisDisplay,
  1750. pdp2d ,
  1751. pVertexBufferInfo,
  1752. pCommandBufferInfo);
  1753. }
  1754. #endif
  1755. //@@END_DDKSPLIT
  1756. START_SOFTWARE_CURSOR(pThisDisplay);
  1757. if (!bParseError)
  1758. {
  1759. pdp2d->ddrval = DD_OK;
  1760. }
  1761. DBG_CB_EXIT(D3DDrawPrimitives2_P3, DD_OK);
  1762. return DDHAL_DRIVER_HANDLED;
  1763. } // D3DDrawPrimitives2_P3
  1764. //-----------------------------------------------------------------------------
  1765. //
  1766. // __DP2_PrimitiveOpsParser
  1767. //
  1768. // Render command buffer which contains primitive(s) in a separate loop
  1769. // in order not to loose performance doing hw setup repeatedly. We keep
  1770. // spinning in this loop until we reach an EOB, a non-rendering DP2 command
  1771. // or until an error is detected.
  1772. //
  1773. //-----------------------------------------------------------------------------
  1774. BOOL
  1775. __DP2_PrimitiveOpsParser(
  1776. P3_D3DCONTEXT *pContext,
  1777. LPD3DHAL_DRAWPRIMITIVES2DATA pdp2d,
  1778. LPD3DHAL_DP2COMMAND *lplpIns,
  1779. LPBYTE lpInsStart,
  1780. LPDWORD lpVerts)
  1781. {
  1782. P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
  1783. LPD3DTLVERTEX lpVertices = (LPD3DTLVERTEX) lpVerts;
  1784. LPD3DHAL_DP2COMMAND lpIns;
  1785. LPD3DHAL_DP2COMMAND lpResumeIns;
  1786. LPBYTE lpPrim, lpChkPrim;
  1787. HRESULT ddrval;
  1788. DWORD dwFillMode;
  1789. BOOL bParseError = FALSE;
  1790. DWORD i;
  1791. DBG_ENTRY(__DP2_PrimitiveOpsParser);
  1792. lpIns = *lplpIns;
  1793. // This macro includes all parameters passed to all the specialized
  1794. // rendering functions (since their parameters are all the same)
  1795. // just to save us of some clutter in the actual code
  1796. #define P3_RND_PARAMS \
  1797. pContext, \
  1798. lpIns->wPrimitiveCount, \
  1799. lpPrim, \
  1800. lpVertices, \
  1801. pdp2d->dwVertexLength, \
  1802. &bParseError
  1803. // Ensure the hostin unit is setup for inline vertex data.
  1804. {
  1805. P3_DMA_DEFS();
  1806. P3_DMA_GET_BUFFER_ENTRIES(6);
  1807. pContext->SoftCopyGlint.P3RX_P3VertexControl.Size =
  1808. pContext->FVFData.dwStrideHostInline / sizeof(DWORD);
  1809. COPY_P3_DATA( VertexControl,
  1810. pContext->SoftCopyGlint.P3RX_P3VertexControl );
  1811. SEND_P3_DATA( VertexValid,
  1812. pContext->FVFData.dwVertexValidHostInline);
  1813. SEND_P3_DATA( VertexFormat,
  1814. pContext->FVFData.vFmatHostInline);
  1815. P3_DMA_COMMIT_BUFFER();
  1816. }
  1817. // Process commands while we haven't exhausted the command buffer
  1818. while (!bParseError &&
  1819. ((LPBYTE)lpIns <
  1820. (lpInsStart + pdp2d->dwCommandLength + pdp2d->dwCommandOffset)))
  1821. {
  1822. BOOL bNonRenderingOP;
  1823. // Get pointer to first primitive structure past the D3DHAL_DP2COMMAND
  1824. lpPrim = (LPBYTE)lpIns + sizeof(D3DHAL_DP2COMMAND);
  1825. // Rendering primitive functions called vary according to
  1826. // the fill mode selected ( POINT, WIREFRAME, SOLID );
  1827. dwFillMode = pContext->RenderStates[D3DRENDERSTATE_FILLMODE];
  1828. DISPDBG((DBGLVL, "__DP2_PrimitiveOpsParser: "
  1829. "Parsing instruction %d Count = %d @ %x",
  1830. lpIns->bCommand, lpIns->wPrimitiveCount, lpIns));
  1831. // If we are processing a known, though non-rendering opcode
  1832. // then its time to quit this function
  1833. bNonRenderingOP =
  1834. ( lpIns->bCommand == D3DDP2OP_RENDERSTATE ) ||
  1835. ( lpIns->bCommand == D3DDP2OP_TEXTURESTAGESTATE ) ||
  1836. ( lpIns->bCommand == D3DDP2OP_STATESET ) ||
  1837. ( lpIns->bCommand == D3DDP2OP_VIEWPORTINFO ) ||
  1838. ( lpIns->bCommand == D3DDP2OP_WINFO ) ||
  1839. ( lpIns->bCommand == D3DDP2OP_ZRANGE ) ||
  1840. ( lpIns->bCommand == D3DDP2OP_SETMATERIAL ) ||
  1841. ( lpIns->bCommand == D3DDP2OP_SETLIGHT ) ||
  1842. ( lpIns->bCommand == D3DDP2OP_TEXBLT ) ||
  1843. ( lpIns->bCommand == D3DDP2OP_SETLIGHT ) ||
  1844. ( lpIns->bCommand == D3DDP2OP_TEXBLT ) ||
  1845. ( lpIns->bCommand == D3DDP2OP_CREATELIGHT ) ||
  1846. ( lpIns->bCommand == D3DDP2OP_EXT ) ||
  1847. ( lpIns->bCommand == D3DDP2OP_SETTRANSFORM ) ||
  1848. ( lpIns->bCommand == D3DDP2OP_CLEAR ) ||
  1849. ( lpIns->bCommand == D3DDP2OP_UPDATEPALETTE ) ||
  1850. ( lpIns->bCommand == D3DDP2OP_SETPALETTE ) ||
  1851. #if DX7_TEXMANAGEMENT
  1852. ( lpIns->bCommand == D3DDP2OP_SETTEXLOD ) ||
  1853. ( lpIns->bCommand == D3DDP2OP_SETPRIORITY ) ||
  1854. #endif // DX7_TEXMANAGEMENT
  1855. #if DX8_DDI
  1856. ( lpIns->bCommand == D3DDP2OP_CREATEVERTEXSHADER) ||
  1857. ( lpIns->bCommand == D3DDP2OP_SETVERTEXSHADER) ||
  1858. ( lpIns->bCommand == D3DDP2OP_DELETEVERTEXSHADER) ||
  1859. ( lpIns->bCommand == D3DDP2OP_SETVERTEXSHADERCONST) ||
  1860. ( lpIns->bCommand == D3DDP2OP_CREATEPIXELSHADER) ||
  1861. ( lpIns->bCommand == D3DDP2OP_SETPIXELSHADER) ||
  1862. ( lpIns->bCommand == D3DDP2OP_DELETEPIXELSHADER) ||
  1863. ( lpIns->bCommand == D3DDP2OP_SETPIXELSHADERCONST)||
  1864. ( lpIns->bCommand == D3DDP2OP_SETSTREAMSOURCE ) ||
  1865. ( lpIns->bCommand == D3DDP2OP_SETSTREAMSOURCEUM ) ||
  1866. ( lpIns->bCommand == D3DDP2OP_SETINDICES ) ||
  1867. #endif //DX8_DDI
  1868. ( lpIns->bCommand == D3DDP2OP_SETRENDERTARGET);
  1869. if (bNonRenderingOP)
  1870. {
  1871. break;
  1872. }
  1873. // Main rendering Dp2 opcode switch
  1874. switch( lpIns->bCommand )
  1875. {
  1876. case D3DDP2OP_POINTS:
  1877. DISPDBG((DBGLVL, "D3DDP2OP_POINTS"));
  1878. // Point primitives in vertex buffers are defined by the
  1879. // D3DHAL_DP2POINTS structure. The driver should render
  1880. // wCount points starting at the initial vertex specified
  1881. // by wFirst. Then for each D3DHAL_DP2POINTS, the points
  1882. // rendered will be (wFirst),(wFirst+1),...,
  1883. // (wFirst+(wCount-1)). The number of D3DHAL_DP2POINTS
  1884. // structures to process is specified by the wPrimitiveCount
  1885. // field of D3DHAL_DP2COMMAND.
  1886. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1887. D3DHAL_DP2POINTS, lpIns->wPrimitiveCount, 0);
  1888. _D3D_R3_DP2_Points( P3_RND_PARAMS );
  1889. NEXTINSTRUCTION(lpIns, D3DHAL_DP2POINTS,
  1890. lpIns->wPrimitiveCount, 0);
  1891. break;
  1892. case D3DDP2OP_LINELIST:
  1893. DISPDBG((DBGLVL, "D3DDP2OP_LINELIST"));
  1894. // Non-indexed vertex-buffer line lists are defined by the
  1895. // D3DHAL_DP2LINELIST structure. Given an initial vertex,
  1896. // the driver will render a sequence of independent lines,
  1897. // processing two new vertices with each line. The number
  1898. // of lines to render is specified by the wPrimitiveCount
  1899. // field of D3DHAL_DP2COMMAND. The sequence of lines
  1900. // rendered will be
  1901. // (wVStart, wVStart+1),(wVStart+2, wVStart+3),...,
  1902. // (wVStart+(wPrimitiveCount-1)*2), wVStart+wPrimitiveCount*2 - 1).
  1903. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim, D3DHAL_DP2LINELIST, 1, 0);
  1904. _D3D_R3_DP2_LineList( P3_RND_PARAMS );
  1905. NEXTINSTRUCTION(lpIns, D3DHAL_DP2LINELIST, 1, 0);
  1906. break;
  1907. case D3DDP2OP_INDEXEDLINELIST:
  1908. DISPDBG((DBGLVL, "D3DDP2OP_INDEXEDLINELIST"));
  1909. // The D3DHAL_DP2INDEXEDLINELIST structure specifies
  1910. // unconnected lines to render using vertex indices.
  1911. // The line endpoints for each line are specified by wV1
  1912. // and wV2. The number of lines to render using this
  1913. // structure is specified by the wPrimitiveCount field of
  1914. // D3DHAL_DP2COMMAND. The sequence of lines
  1915. // rendered will be (wV[0], wV[1]), (wV[2], wV[3]),...
  1916. // (wVStart[(wPrimitiveCount-1)*2], wVStart[wPrimitiveCount*2-1]).
  1917. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1918. D3DHAL_DP2INDEXEDLINELIST,
  1919. lpIns->wPrimitiveCount, 0);
  1920. _D3D_R3_DP2_IndexedLineList( P3_RND_PARAMS );
  1921. NEXTINSTRUCTION(lpIns, D3DHAL_DP2INDEXEDLINELIST,
  1922. lpIns->wPrimitiveCount, 0);
  1923. break;
  1924. case D3DDP2OP_INDEXEDLINELIST2:
  1925. DISPDBG((DBGLVL, "D3DDP2OP_INDEXEDLINELIST2"));
  1926. // The D3DHAL_DP2INDEXEDLINELIST structure specifies
  1927. // unconnected lines to render using vertex indices.
  1928. // The line endpoints for each line are specified by wV1
  1929. // and wV2. The number of lines to render using this
  1930. // structure is specified by the wPrimitiveCount field of
  1931. // D3DHAL_DP2COMMAND. The sequence of lines
  1932. // rendered will be (wV[0], wV[1]), (wV[2], wV[3]),
  1933. // (wVStart[(wPrimitiveCount-1)*2], wVStart[wPrimitiveCount*2-1]).
  1934. // The indexes are relative to a base index value that
  1935. // immediately follows the command
  1936. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1937. D3DHAL_DP2INDEXEDLINELIST,
  1938. lpIns->wPrimitiveCount, STARTVERTEXSIZE);
  1939. _D3D_R3_DP2_IndexedLineList2( P3_RND_PARAMS );
  1940. NEXTINSTRUCTION(lpIns, D3DHAL_DP2INDEXEDLINELIST,
  1941. lpIns->wPrimitiveCount, STARTVERTEXSIZE);
  1942. break;
  1943. case D3DDP2OP_LINESTRIP:
  1944. DISPDBG((DBGLVL, "D3DDP2OP_LINESTRIP"));
  1945. // Non-index line strips rendered with vertex buffers are
  1946. // specified using D3DHAL_DP2LINESTRIP. The first vertex
  1947. // in the line strip is specified by wVStart. The
  1948. // number of lines to process is specified by the
  1949. // wPrimitiveCount field of D3DHAL_DP2COMMAND. The sequence
  1950. // of lines rendered will be (wVStart, wVStart+1),
  1951. // (wVStart+1, wVStart+2),(wVStart+2, wVStart+3),...,
  1952. // (wVStart+wPrimitiveCount, wVStart+wPrimitiveCount+1).
  1953. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,D3DHAL_DP2LINESTRIP, 1, 0);
  1954. _D3D_R3_DP2_LineStrip( P3_RND_PARAMS );
  1955. NEXTINSTRUCTION(lpIns, D3DHAL_DP2LINESTRIP, 1, 0);
  1956. break;
  1957. case D3DDP2OP_INDEXEDLINESTRIP:
  1958. DISPDBG((DBGLVL, "D3DDP2OP_INDEXEDLINESTRIP"));
  1959. // Indexed line strips rendered with vertex buffers are
  1960. // specified using D3DHAL_DP2INDEXEDLINESTRIP. The number
  1961. // of lines to process is specified by the wPrimitiveCount
  1962. // field of D3DHAL_DP2COMMAND. The sequence of lines
  1963. // rendered will be (wV[0], wV[1]), (wV[1], wV[2]),
  1964. // (wV[2], wV[3]), ...
  1965. // (wVStart[wPrimitiveCount-1], wVStart[wPrimitiveCount]).
  1966. // Although the D3DHAL_DP2INDEXEDLINESTRIP structure only
  1967. // has enough space allocated for a single line, the wV
  1968. // array of indices should be treated as a variable-sized
  1969. // array with wPrimitiveCount+1 elements.
  1970. // The indexes are relative to a base index value that
  1971. // immediately follows the command
  1972. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1973. WORD,
  1974. lpIns->wPrimitiveCount + 1,
  1975. STARTVERTEXSIZE);
  1976. _D3D_R3_DP2_IndexedLineStrip( P3_RND_PARAMS );
  1977. // Point to next D3DHAL_DP2COMMAND in the command buffer
  1978. // Advance only as many vertex indices there are, with no padding!
  1979. NEXTINSTRUCTION(lpIns, WORD,
  1980. lpIns->wPrimitiveCount + 1, STARTVERTEXSIZE);
  1981. break;
  1982. case D3DDP2OP_TRIANGLELIST:
  1983. DISPDBG((DBGLVL, "D3DDP2OP_TRIANGLELIST"));
  1984. // Non-indexed vertex buffer triangle lists are defined by
  1985. // the D3DHAL_DP2TRIANGLELIST structure. Given an initial
  1986. // vertex, the driver will render independent triangles,
  1987. // processing three new vertices with each triangle. The
  1988. // number of triangles to render is specified by the
  1989. // wPrimitveCount field of D3DHAL_DP2COMMAND. The sequence
  1990. // of vertices processed will be (wVStart, wVStart+1,
  1991. // vVStart+2), (wVStart+3, wVStart+4, vVStart+5),...,
  1992. // (wVStart+(wPrimitiveCount-1)*3), wVStart+wPrimitiveCount*3-2,
  1993. // vStart+wPrimitiveCount*3-1).
  1994. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  1995. D3DHAL_DP2TRIANGLELIST, 1, 0);
  1996. _D3D_R3_DP2_TriangleList( P3_RND_PARAMS );
  1997. NEXTINSTRUCTION(lpIns, D3DHAL_DP2TRIANGLELIST, 1, 0);
  1998. break;
  1999. case D3DDP2OP_INDEXEDTRIANGLELIST:
  2000. DISPDBG((DBGLVL, "D3DDP2OP_INDEXEDTRIANGLELIST"));
  2001. // The D3DHAL_DP2INDEXEDTRIANGLELIST structure specifies
  2002. // unconnected triangles to render with a vertex buffer.
  2003. // The vertex indices are specified by wV1, wV2 and wV3.
  2004. // The wFlags field allows specifying edge flags identical
  2005. // to those specified by D3DOP_TRIANGLE. The number of
  2006. // triangles to render (that is, number of
  2007. // D3DHAL_DP2INDEXEDTRIANGLELIST structures to process)
  2008. // is specified by the wPrimitiveCount field of
  2009. // D3DHAL_DP2COMMAND.
  2010. // This is the only indexed primitive where we don't get
  2011. // an offset into the vertex buffer in order to maintain
  2012. // DX3 compatibility. A new primitive
  2013. // (D3DDP2OP_INDEXEDTRIANGLELIST2) has been added to handle
  2014. // the corresponding D3D primitive.
  2015. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2016. D3DHAL_DP2INDEXEDTRIANGLELIST,
  2017. lpIns->wPrimitiveCount, 0);
  2018. if( lpIns->wPrimitiveCount )
  2019. {
  2020. _D3D_R3_DP2_IndexedTriangleList( P3_RND_PARAMS );
  2021. }
  2022. NEXTINSTRUCTION(lpIns, D3DHAL_DP2INDEXEDTRIANGLELIST,
  2023. lpIns->wPrimitiveCount, 0);
  2024. break;
  2025. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  2026. DISPDBG((DBGLVL, "D3DDP2OP_INDEXEDTRIANGLELIST2 "));
  2027. // The D3DHAL_DP2INDEXEDTRIANGLELIST2 structure specifies
  2028. // unconnected triangles to render with a vertex buffer.
  2029. // The vertex indices are specified by wV1, wV2 and wV3.
  2030. // The wFlags field allows specifying edge flags identical
  2031. // to those specified by D3DOP_TRIANGLE. The number of
  2032. // triangles to render (that is, number of
  2033. // D3DHAL_DP2INDEXEDTRIANGLELIST structures to process)
  2034. // is specified by the wPrimitiveCount field of
  2035. // D3DHAL_DP2COMMAND.
  2036. // The indexes are relative to a base index value that
  2037. // immediately follows the command
  2038. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2039. D3DHAL_DP2INDEXEDTRIANGLELIST2,
  2040. lpIns->wPrimitiveCount, STARTVERTEXSIZE);
  2041. _D3D_R3_DP2_IndexedTriangleList2( P3_RND_PARAMS );
  2042. NEXTINSTRUCTION(lpIns, D3DHAL_DP2INDEXEDTRIANGLELIST2,
  2043. lpIns->wPrimitiveCount, STARTVERTEXSIZE);
  2044. break;
  2045. case D3DDP2OP_TRIANGLESTRIP:
  2046. DISPDBG((DBGLVL, "D3DDP2OP_TRIANGLESTRIP"));
  2047. // Non-index triangle strips rendered with vertex buffers
  2048. // are specified using D3DHAL_DP2TRIANGLESTRIP. The first
  2049. // vertex in the triangle strip is specified by wVStart.
  2050. // The number of triangles to process is specified by the
  2051. // wPrimitiveCount field of D3DHAL_DP2COMMAND. The sequence
  2052. // of triangles rendered for the odd-triangles case will
  2053. // be (wVStart, wVStart+1, vVStart+2), (wVStart+2,
  2054. // wVStart+1, vVStart+3),.(wVStart+2, wVStart+3,
  2055. // vVStart+4),.., (wVStart+wPrimitiveCount-1),
  2056. // wVStart+wPrimitiveCount, vStart+wPrimitiveCount+1). For an
  2057. // even number of , the last triangle will be .,
  2058. // (wVStart+wPrimitiveCount), wVStart+wPrimitiveCount-1,
  2059. // vStart+wPrimitiveCount+1).
  2060. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim, D3DHAL_DP2TRIANGLESTRIP, 1, 0);
  2061. _D3D_R3_DP2_TriangleStrip( P3_RND_PARAMS );
  2062. // Point to next D3DHAL_DP2COMMAND in the command buffer
  2063. NEXTINSTRUCTION(lpIns, D3DHAL_DP2TRIANGLESTRIP, 1, 0);
  2064. break;
  2065. case D3DDP2OP_INDEXEDTRIANGLESTRIP:
  2066. DISPDBG((DBGLVL, "D3DDP2OP_INDEXEDTRIANGLESTRIP"));
  2067. // Indexed triangle strips rendered with vertex buffers are
  2068. // specified using D3DHAL_DP2INDEXEDTRIANGLESTRIP. The number
  2069. // of triangles to process is specified by the wPrimitiveCount
  2070. // field of D3DHAL_DP2COMMAND. The sequence of triangles
  2071. // rendered for the odd-triangles case will be
  2072. // (wV[0],wV[1],wV[2]),(wV[2],wV[1],wV[3]),
  2073. // (wV[3],wV[4],wV[5]),...,(wV[wPrimitiveCount-1],
  2074. // wV[wPrimitiveCount],wV[wPrimitiveCount+1]). For an even
  2075. // number of triangles, the last triangle will be
  2076. // (wV[wPrimitiveCount],wV[wPrimitiveCount-1],
  2077. // wV[wPrimitiveCount+1]).Although the
  2078. // D3DHAL_DP2INDEXEDTRIANGLESTRIP structure only has
  2079. // enough space allocated for a single line, the wV
  2080. // array of indices should be treated as a variable-sized
  2081. // array with wPrimitiveCount+2 elements.
  2082. // The indexes are relative to a base index value that
  2083. // immediately follows the command
  2084. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim, WORD,
  2085. lpIns->wPrimitiveCount + 2, STARTVERTEXSIZE);
  2086. _D3D_R3_DP2_IndexedTriangleStrip( P3_RND_PARAMS );
  2087. // Point to next D3DHAL_DP2COMMAND in the command buffer
  2088. NEXTINSTRUCTION(lpIns, WORD ,
  2089. lpIns->wPrimitiveCount + 2, STARTVERTEXSIZE);
  2090. break;
  2091. case D3DDP2OP_TRIANGLEFAN:
  2092. DISPDBG((DBGLVL, "D3DDP2OP_TRIANGLEFAN"));
  2093. // The D3DHAL_DP2TRIANGLEFAN structure is used to draw
  2094. // non-indexed triangle fans. The sequence of triangles
  2095. // rendered will be (wVStart, wVstart+1, wVStart+2),
  2096. // (wVStart,wVStart+2,wVStart+3), (wVStart,wVStart+3,
  2097. // wVStart+4),...,(wVStart,wVStart+wPrimitiveCount,
  2098. // wVStart+wPrimitiveCount+1).
  2099. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2100. D3DHAL_DP2TRIANGLEFAN, 1, 0);
  2101. _D3D_R3_DP2_TriangleFan( P3_RND_PARAMS );
  2102. NEXTINSTRUCTION(lpIns, D3DHAL_DP2TRIANGLEFAN, 1, 0);
  2103. break;
  2104. case D3DDP2OP_INDEXEDTRIANGLEFAN:
  2105. DISPDBG((DBGLVL,"D3DDP2OP_INDEXEDTRIANGLEFAN"));
  2106. // The D3DHAL_DP2INDEXEDTRIANGLEFAN structure is used to
  2107. // draw indexed triangle fans. The sequence of triangles
  2108. // rendered will be (wV[0], wV[1], wV[2]), (wV[0], wV[2],
  2109. // wV[3]), (wV[0], wV[3], wV[4]),...,(wV[0],
  2110. // wV[wPrimitiveCount], wV[wPrimitiveCount+1]).
  2111. // The indexes are relative to a base index value that
  2112. // immediately follows the command
  2113. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim, WORD,
  2114. lpIns->wPrimitiveCount + 2, STARTVERTEXSIZE);
  2115. _D3D_R3_DP2_IndexedTriangleFan( P3_RND_PARAMS );
  2116. // Point to next D3DHAL_DP2COMMAND in the command buffer
  2117. NEXTINSTRUCTION(lpIns,WORD ,lpIns->wPrimitiveCount + 2,
  2118. STARTVERTEXSIZE);
  2119. break;
  2120. case D3DDP2OP_LINELIST_IMM:
  2121. DISPDBG((DBGLVL, "D3DDP2OP_LINELIST_IMM"));
  2122. // Draw a set of lines specified by pairs of vertices
  2123. // that immediately follow this instruction in the
  2124. // command stream. The wPrimitiveCount member of the
  2125. // D3DHAL_DP2COMMAND structure specifies the number
  2126. // of lines that follow.
  2127. // Primitives in an IMM instruction are stored in the
  2128. // command buffer and are DWORD aligned
  2129. lpPrim = (LPBYTE)((ULONG_PTR)(lpPrim + 3 ) & ~3 );
  2130. // Verify the command buffer validity (data lives in it!)
  2131. CHECK_CMDBUF_LIMITS_S(pdp2d, lpPrim,
  2132. pContext->FVFData.dwStride,
  2133. lpIns->wPrimitiveCount + 1, 0);
  2134. _D3D_R3_DP2_LineListImm( P3_RND_PARAMS );
  2135. // Realign next command since vertices are dword aligned
  2136. // and store # of primitives before affecting the pointer
  2137. NEXTINSTRUCTION(lpIns, BYTE,
  2138. ((lpIns->wPrimitiveCount * 2) *
  2139. pContext->FVFData.dwStride), 0);
  2140. // Realign next command since vertices are dword aligned
  2141. lpIns = (LPD3DHAL_DP2COMMAND)(( ((ULONG_PTR)lpIns) + 3 ) & ~ 3);
  2142. break;
  2143. case D3DDP2OP_TRIANGLEFAN_IMM:
  2144. DISPDBG((DBGLVL, "D3DDP2OP_TRIANGLEFAN_IMM"));
  2145. // Draw a triangle fan specified by pairs of vertices
  2146. // that immediately follow this instruction in the
  2147. // command stream. The wPrimitiveCount member of the
  2148. // D3DHAL_DP2COMMAND structure specifies the number
  2149. // of triangles that follow.
  2150. // Verify the command buffer validity for the first structure
  2151. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2152. BYTE , 0 ,
  2153. sizeof(D3DHAL_DP2TRIANGLEFAN_IMM));
  2154. // Get pointer where data should start
  2155. lpChkPrim = (LPBYTE)((ULONG_PTR)( lpPrim + 3 +
  2156. sizeof(D3DHAL_DP2TRIANGLEFAN_IMM)) & ~3 );
  2157. // Verify the rest of the command buffer
  2158. CHECK_CMDBUF_LIMITS_S(pdp2d, lpChkPrim,
  2159. pContext->FVFData.dwStride,
  2160. lpIns->wPrimitiveCount + 2, 0);
  2161. _D3D_R3_DP2_TriangleFanImm( P3_RND_PARAMS );
  2162. // Realign next command since vertices are dword aligned
  2163. // and store # of primitives before affecting the pointer
  2164. NEXTINSTRUCTION(lpIns, BYTE,
  2165. ((lpIns->wPrimitiveCount + 2) *
  2166. pContext->FVFData.dwStride),
  2167. sizeof(D3DHAL_DP2TRIANGLEFAN_IMM));
  2168. // Realign next command since vertices are dword aligned
  2169. lpIns = (LPD3DHAL_DP2COMMAND)(( ((ULONG_PTR)lpIns) + 3 ) & ~ 3);
  2170. break;
  2171. #if DX8_MULTSTREAMS
  2172. case D3DDP2OP_DRAWPRIMITIVE :
  2173. {
  2174. D3DHAL_DP2DRAWPRIMITIVE* pDrawPrim;
  2175. DISPDBG((DBGLVL, "D3DDP2OP_DRAWPRIMITIVE"));
  2176. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2177. D3DHAL_DP2DRAWPRIMITIVE,
  2178. lpIns->wStateCount, 0);
  2179. // iterate through each
  2180. for ( i = 0; i < lpIns->wStateCount; i++)
  2181. {
  2182. pDrawPrim = (D3DHAL_DP2DRAWPRIMITIVE*)lpPrim;
  2183. _D3D_OP_MStream_DrawPrim(pContext,
  2184. pDrawPrim->primType,
  2185. pDrawPrim->VStart,
  2186. pDrawPrim->PrimitiveCount);
  2187. lpPrim += sizeof(D3DHAL_DP2DRAWPRIMITIVE);
  2188. }
  2189. NEXTINSTRUCTION(lpIns, D3DHAL_DP2DRAWPRIMITIVE,
  2190. lpIns->wStateCount, 0);
  2191. }
  2192. break;
  2193. case D3DDP2OP_DRAWINDEXEDPRIMITIVE :
  2194. {
  2195. D3DHAL_DP2DRAWINDEXEDPRIMITIVE* pDrawIndxPrim;
  2196. DISPDBG((DBGLVL, "D3DDP2OP_DRAWINDEXEDPRIMITIVE"));
  2197. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2198. D3DHAL_DP2DRAWINDEXEDPRIMITIVE,
  2199. lpIns->wStateCount, 0);
  2200. // iterate through each
  2201. for ( i = 0; i < lpIns->wStateCount; i++)
  2202. {
  2203. pDrawIndxPrim = (D3DHAL_DP2DRAWINDEXEDPRIMITIVE*)lpPrim;
  2204. _D3D_OP_MStream_DrawIndxP(pContext,
  2205. pDrawIndxPrim->primType,
  2206. pDrawIndxPrim->BaseVertexIndex,
  2207. pDrawIndxPrim->MinIndex,
  2208. pDrawIndxPrim->NumVertices,
  2209. pDrawIndxPrim->StartIndex,
  2210. pDrawIndxPrim->PrimitiveCount);
  2211. lpPrim += sizeof(D3DHAL_DP2DRAWINDEXEDPRIMITIVE);
  2212. }
  2213. NEXTINSTRUCTION(lpIns, D3DHAL_DP2DRAWINDEXEDPRIMITIVE,
  2214. lpIns->wStateCount, 0);
  2215. }
  2216. break;
  2217. case D3DDP2OP_DRAWPRIMITIVE2 :
  2218. {
  2219. D3DHAL_DP2DRAWPRIMITIVE2* pDrawPrim2;
  2220. DISPDBG((DBGLVL, "D3DDP2OP_DRAWPRIMITIVE2"));
  2221. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2222. D3DHAL_DP2DRAWPRIMITIVE2,
  2223. lpIns->wStateCount, 0);
  2224. // iterate through each
  2225. for ( i = 0; i < lpIns->wStateCount; i++)
  2226. {
  2227. pDrawPrim2 = (D3DHAL_DP2DRAWPRIMITIVE2*)lpPrim;
  2228. _D3D_OP_MStream_DrawPrim2(pContext,
  2229. pDrawPrim2->primType,
  2230. pDrawPrim2->FirstVertexOffset,
  2231. pDrawPrim2->PrimitiveCount);
  2232. lpPrim += sizeof(D3DHAL_DP2DRAWPRIMITIVE2);
  2233. }
  2234. NEXTINSTRUCTION(lpIns, D3DHAL_DP2DRAWPRIMITIVE2,
  2235. lpIns->wStateCount, 0);
  2236. }
  2237. break;
  2238. case D3DDP2OP_DRAWINDEXEDPRIMITIVE2 :
  2239. {
  2240. D3DHAL_DP2DRAWINDEXEDPRIMITIVE2* pDrawIndxPrim2;
  2241. DISPDBG((DBGLVL, "D3DDP2OP_DRAWINDEXEDPRIMITIVE2"));
  2242. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2243. D3DHAL_DP2DRAWINDEXEDPRIMITIVE2,
  2244. lpIns->wStateCount, 0);
  2245. // iterate through each
  2246. for ( i = 0; i < lpIns->wStateCount; i++)
  2247. {
  2248. pDrawIndxPrim2 = (D3DHAL_DP2DRAWINDEXEDPRIMITIVE2*)lpPrim;
  2249. _D3D_OP_MStream_DrawIndxP2(pContext,
  2250. pDrawIndxPrim2->primType,
  2251. pDrawIndxPrim2->BaseVertexOffset,
  2252. pDrawIndxPrim2->MinIndex,
  2253. pDrawIndxPrim2->NumVertices,
  2254. pDrawIndxPrim2->StartIndexOffset,
  2255. pDrawIndxPrim2->PrimitiveCount);
  2256. lpPrim += sizeof(D3DHAL_DP2DRAWINDEXEDPRIMITIVE2);
  2257. }
  2258. NEXTINSTRUCTION(lpIns, D3DHAL_DP2DRAWINDEXEDPRIMITIVE2,
  2259. lpIns->wStateCount, 0);
  2260. }
  2261. break;
  2262. case D3DDP2OP_DRAWRECTPATCH :
  2263. {
  2264. D3DHAL_DP2DRAWRECTPATCH* pRectSurf;
  2265. DWORD dwExtraBytes = 0;
  2266. DISPDBG((DBGLVL, "D3DDP2OP_DRAWRECTPATCH"));
  2267. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2268. D3DHAL_DP2DRAWRECTPATCH,
  2269. lpIns->wStateCount, 0);
  2270. // iterate through each
  2271. for ( i = 0; i < lpIns->wStateCount; i++)
  2272. {
  2273. pRectSurf = (D3DHAL_DP2DRAWRECTPATCH*)lpPrim;
  2274. lpPrim += sizeof(D3DHAL_DP2DRAWRECTPATCH);
  2275. _D3D_OP_MStream_DrawRectSurface(pContext,
  2276. pRectSurf->Handle,
  2277. pRectSurf->Flags,
  2278. lpPrim);
  2279. if (pRectSurf->Flags & RTPATCHFLAG_HASSEGS)
  2280. {
  2281. dwExtraBytes += sizeof(D3DVALUE)* 4;
  2282. }
  2283. if (pRectSurf->Flags & RTPATCHFLAG_HASINFO)
  2284. {
  2285. dwExtraBytes += sizeof(D3DRECTPATCH_INFO);
  2286. }
  2287. lpPrim += dwExtraBytes;
  2288. }
  2289. NEXTINSTRUCTION(lpIns, D3DHAL_DP2DRAWRECTPATCH,
  2290. lpIns->wStateCount, dwExtraBytes);
  2291. }
  2292. break;
  2293. case D3DDP2OP_DRAWTRIPATCH :
  2294. {
  2295. D3DHAL_DP2DRAWTRIPATCH* pTriSurf;
  2296. DWORD dwExtraBytes = 0;
  2297. DISPDBG((DBGLVL, "D3DDP2OP_DRAWTRIPATCH"));
  2298. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2299. D3DHAL_DP2DRAWTRIPATCH,
  2300. lpIns->wStateCount, 0);
  2301. // iterate through each
  2302. for ( i = 0; i < lpIns->wStateCount; i++)
  2303. {
  2304. pTriSurf = (D3DHAL_DP2DRAWTRIPATCH*)lpPrim;
  2305. lpPrim += sizeof(D3DHAL_DP2DRAWTRIPATCH);
  2306. _D3D_OP_MStream_DrawTriSurface(pContext,
  2307. pTriSurf->Handle,
  2308. pTriSurf->Flags,
  2309. lpPrim);
  2310. if (pTriSurf->Flags & RTPATCHFLAG_HASSEGS)
  2311. {
  2312. dwExtraBytes += sizeof(D3DVALUE)* 3;
  2313. }
  2314. if (pTriSurf->Flags & RTPATCHFLAG_HASINFO)
  2315. {
  2316. dwExtraBytes += sizeof(D3DTRIPATCH_INFO);
  2317. }
  2318. lpPrim += dwExtraBytes;
  2319. }
  2320. NEXTINSTRUCTION(lpIns, D3DHAL_DP2DRAWTRIPATCH,
  2321. lpIns->wStateCount, dwExtraBytes);
  2322. }
  2323. break;
  2324. case D3DDP2OP_CLIPPEDTRIANGLEFAN :
  2325. {
  2326. D3DHAL_CLIPPEDTRIANGLEFAN* pClipdTriFan;
  2327. DISPDBG((DBGLVL, "D3DDP2OP_CLIPPEDTRIANGLEFAN"));
  2328. CHECK_CMDBUF_LIMITS(pdp2d, lpPrim,
  2329. D3DHAL_CLIPPEDTRIANGLEFAN,
  2330. lpIns->wStateCount, 0);
  2331. // iterate through each
  2332. for ( i = 0; i < lpIns->wStateCount; i++)
  2333. {
  2334. pClipdTriFan = (D3DHAL_CLIPPEDTRIANGLEFAN*)lpPrim;
  2335. _D3D_OP_MStream_ClipTriFan(pContext,
  2336. pClipdTriFan->FirstVertexOffset,
  2337. pClipdTriFan->dwEdgeFlags,
  2338. pClipdTriFan->PrimitiveCount);
  2339. lpPrim += sizeof(D3DHAL_CLIPPEDTRIANGLEFAN);
  2340. }
  2341. NEXTINSTRUCTION(lpIns, D3DHAL_CLIPPEDTRIANGLEFAN,
  2342. lpIns->wStateCount, 0);
  2343. }
  2344. break;
  2345. #endif // DX8_MULTSTREAMS
  2346. // This was found to be required for a few D3DRM apps
  2347. case D3DOP_EXIT:
  2348. lpIns = (D3DHAL_DP2COMMAND *)(lpInsStart +
  2349. pdp2d->dwCommandLength +
  2350. pdp2d->dwCommandOffset);
  2351. break;
  2352. default:
  2353. ASSERTDD((pThisDisplay->pD3DParseUnknownCommand),
  2354. "D3D ParseUnknownCommand callback == NULL");
  2355. if( SUCCEEDED(ddrval=(pThisDisplay->pD3DParseUnknownCommand)
  2356. ( lpIns ,
  2357. (void**)&lpResumeIns)) )
  2358. {
  2359. // Resume buffer processing after D3DParseUnknownCommand
  2360. // was succesful in processing an unknown command
  2361. lpIns = lpResumeIns;
  2362. break;
  2363. }
  2364. DISPDBG((ERRLVL, "Unhandled opcode (%d)- "
  2365. "returning D3DERR_COMMAND_UNPARSED @ addr %x",
  2366. lpIns->bCommand,
  2367. lpIns));
  2368. PARSE_ERROR_AND_EXIT( pdp2d, lpIns, lpInsStart, ddrval);
  2369. } // switch
  2370. } //while
  2371. *lplpIns = lpIns;
  2372. DBG_EXIT(__DP2_PrimitiveOpsParser, bParseError);
  2373. return bParseError;
  2374. } // __DP2_PrimitiveOpsParser
  2375. //-----------------------------Public Routine----------------------------------
  2376. //
  2377. // D3DValidateDeviceP3
  2378. //
  2379. // Returns the number of passes in which the hardware can perform the blending
  2380. // operations specified in the current state.
  2381. //
  2382. // Direct3D drivers that support texturing must implement
  2383. // D3dValidateTextureStageState.
  2384. //
  2385. // The driver must do the following:
  2386. //
  2387. // Evaluate the current texture state for all texture stages associated with the
  2388. // context. If the driver's hardware can perform the specified blending
  2389. // operations, the driver should return the number of passes on the state data
  2390. // that its hardware requires in order to entirely process the operations. If
  2391. // the hardware is incapable of performing the specified blending operations,
  2392. // the driver should return one of the following error codes in ddrval:
  2393. //
  2394. // D3DERR_CONFLICTINGTEXTUREFILTER
  2395. // The hardware cannot do both trilinear filtering and
  2396. // multi-texturing at the same time.
  2397. // D3DERR_TOOMANYOPERATIONS
  2398. // The hardware cannot handle the specified number of operations.
  2399. // D3DERR_UNSUPPORTEDALPHAARG
  2400. // The hardware does not support a specified alpha argument.
  2401. // D3DERR_UNSUPPORTEDALPHAOPERATION
  2402. // The hardware does not support a specified alpha operation.
  2403. // D3DERR_UNSUPPORTEDCOLORARG
  2404. // The hardware does not support a specified color argument.
  2405. // D3DERR_UNSUPPORTEDCOLOROPERATION
  2406. // The hardware does not support a specified color operation.
  2407. // D3DERR_UNSUPPORTEDFACTORVALUE
  2408. // The hardware does not support a D3DTA_TFACTOR greater than 1.0.
  2409. // D3DERR_WRONGTEXTUREFORMAT
  2410. // The hardware does not support the current state in the selected
  2411. // texture format
  2412. //
  2413. // Direct3D calls D3dValidateTextureStageState in response to an application
  2414. // request through a call to IDirect3DDevice3::ValidateTextureStageState. The
  2415. // number of passes returned by the driver is propagated back to the application
  2416. // , which can then decide whether it wants to proceed with rendering using the
  2417. // current state or if it wants/needs to change the blending operations to
  2418. // render faster or render at all. There are no limits to the number of passes
  2419. // that a driver can return.
  2420. //
  2421. // A driver that returns more than one pass is responsible for properly
  2422. //executing the passes on all state and primitive data when rendering.
  2423. //
  2424. // Parameters
  2425. //
  2426. // pvtssd
  2427. //
  2428. // .dwhContext
  2429. // Specifies the context ID of the Direct3D device.
  2430. // .dwFlags
  2431. // Is currently set to zero and should be ignored by the driver.
  2432. // .dwReserved
  2433. // Is reserved for system use and should be ignored by the driver.
  2434. // .dwNumPasses
  2435. // Specifies the location in which the driver should write the
  2436. // number of passes required by the hardware to perform the
  2437. // blending operations.
  2438. // .ddrval
  2439. // return value
  2440. //
  2441. //-----------------------------------------------------------------------------
  2442. // Taken from the registry variable.
  2443. #define VDOPMODE_IGNORE_NONFATAL 0 // dualtex + trilinear (for examples)
  2444. // not flagged as a bug.
  2445. DWORD CALLBACK
  2446. D3DValidateDeviceP3(
  2447. LPD3DHAL_VALIDATETEXTURESTAGESTATEDATA pvtssd )
  2448. {
  2449. P3_D3DCONTEXT* pContext;
  2450. P3_THUNKEDDATA* pThisDisplay;
  2451. DBG_CB_ENTRY(D3DValidateDeviceP3);
  2452. pContext = _D3D_CTX_HandleToPtr(pvtssd->dwhContext);
  2453. if (!CHECK_D3DCONTEXT_VALIDITY(pContext))
  2454. {
  2455. pvtssd->ddrval = D3DHAL_CONTEXT_BAD;
  2456. DISPDBG((WRNLVL,"ERROR: Context not valid"));
  2457. DBG_CB_EXIT(D3DValidateDeviceP3, pvtssd->ddrval);
  2458. return (DDHAL_DRIVER_HANDLED);
  2459. }
  2460. pThisDisplay = pContext->pThisDisplay;
  2461. STOP_SOFTWARE_CURSOR(pThisDisplay);
  2462. D3D_OPERATION(pContext, pThisDisplay);
  2463. // Re-do all the blend-mode setup from scratch.
  2464. RESET_BLEND_ERROR(pContext);
  2465. DIRTY_EVERYTHING(pContext);
  2466. // The primitive type is not actually important except to keep the
  2467. // rout from asserting various things when it tries to pick the renderer
  2468. // (which of course does not need to be done in this case).
  2469. ReconsiderStateChanges ( pContext );
  2470. START_SOFTWARE_CURSOR(pThisDisplay);
  2471. _D3DDisplayWholeTSSPipe ( pContext, DBGLVL);
  2472. // And see if anything died.
  2473. if (GET_BLEND_ERROR(pContext) == BS_OK )
  2474. {
  2475. // Cool - that worked.
  2476. pvtssd->dwNumPasses = 1;
  2477. pvtssd->ddrval = DD_OK;
  2478. DBG_CB_EXIT(D3DValidateDeviceP3, pvtssd->ddrval);
  2479. return ( DDHAL_DRIVER_HANDLED );
  2480. }
  2481. else
  2482. {
  2483. // Oops. Failed.
  2484. DISPDBG((DBGLVL,"ValidateDevice: failed ValidateDevice()"));
  2485. switch ( GET_BLEND_ERROR(pContext) )
  2486. {
  2487. case BS_OK:
  2488. DISPDBG((ERRLVL,"ValidateDevice: got BS_OK - that's not "
  2489. "an error!"));
  2490. pvtssd->ddrval = DD_OK;
  2491. break;
  2492. case BS_INVALID_FILTER:
  2493. pvtssd->ddrval = D3DERR_CONFLICTINGTEXTUREFILTER;
  2494. break;
  2495. case BSF_CANT_USE_COLOR_OP_HERE:
  2496. case BSF_CANT_USE_COLOR_ARG_HERE:
  2497. case BSF_CANT_USE_ALPHA_OP_HERE:
  2498. case BSF_CANT_USE_ALPHA_ARG_HERE:
  2499. pvtssd->ddrval = D3DERR_CONFLICTINGRENDERSTATE;
  2500. break;
  2501. case BSF_INVALID_TEXTURE:
  2502. case BSF_TEXTURE_NOT_POW2:
  2503. pvtssd->ddrval = D3DERR_WRONGTEXTUREFORMAT;
  2504. break;
  2505. case BSF_UNDEFINED_COLOR_OP:
  2506. case BSF_UNSUPPORTED_COLOR_OP:
  2507. case BSF_UNSUPPORTED_ALPHA_BLEND: // doesn't fit anywhere else.
  2508. case BSF_UNDEFINED_ALPHA_BLEND: // doesn't fit anywhere else.
  2509. case BSF_UNSUPPORTED_STATE: // doesn't fit anywhere else.
  2510. case BSF_UNDEFINED_STATE: // doesn't fit anywhere else.
  2511. case BS_PHONG_SHADING: // doesn't fit anywhere else.
  2512. pvtssd->ddrval = D3DERR_UNSUPPORTEDCOLOROPERATION;
  2513. break;
  2514. case BSF_UNDEFINED_COLOR_ARG:
  2515. case BSF_UNSUPPORTED_COLOR_ARG:
  2516. pvtssd->ddrval = D3DERR_UNSUPPORTEDCOLORARG;
  2517. break;
  2518. case BSF_UNDEFINED_ALPHA_OP:
  2519. case BSF_UNSUPPORTED_ALPHA_OP:
  2520. pvtssd->ddrval = D3DERR_UNSUPPORTEDALPHAOPERATION;
  2521. break;
  2522. case BSF_UNDEFINED_ALPHA_ARG:
  2523. case BSF_UNSUPPORTED_ALPHA_ARG:
  2524. pvtssd->ddrval = D3DERR_UNSUPPORTEDALPHAARG;
  2525. break;
  2526. case BSF_TOO_MANY_TEXTURES:
  2527. case BSF_TOO_MANY_BLEND_STAGES:
  2528. pvtssd->ddrval = D3DERR_TOOMANYOPERATIONS;
  2529. break;
  2530. case BSF_UNDEFINED_FILTER:
  2531. case BSF_UNSUPPORTED_FILTER:
  2532. pvtssd->ddrval = D3DERR_UNSUPPORTEDTEXTUREFILTER;
  2533. break;
  2534. case BSF_TOO_MANY_PALETTES:
  2535. pvtssd->ddrval = D3DERR_CONFLICTINGTEXTUREPALETTE;
  2536. break;
  2537. // Nothing maps to these, but they are valid D3D return
  2538. // codes that be used for future errors.
  2539. // pvtssd->ddrval = D3DERR_UNSUPPORTEDFACTORVALUE;
  2540. // break;
  2541. // pvtssd->ddrval = D3DERR_TOOMANYPRIMITIVES;
  2542. // break;
  2543. // pvtssd->ddrval = D3DERR_INVALIDMATRIX;
  2544. // break;
  2545. // pvtssd->ddrval = D3DERR_TOOMANYVERTICES;
  2546. // break;
  2547. case BSF_UNINITIALISED:
  2548. // Oops.
  2549. DISPDBG((ERRLVL,"ValidateDevice: unitialised error"
  2550. " - logic problem."));
  2551. pvtssd->ddrval = D3DERR_TOOMANYOPERATIONS;
  2552. break;
  2553. default:
  2554. // Unknown.
  2555. DISPDBG((ERRLVL,"ValidateDevice: unknown "
  2556. "blend-mode error."));
  2557. pvtssd->ddrval = D3DERR_TOOMANYOPERATIONS;
  2558. break;
  2559. }
  2560. pvtssd->dwNumPasses = 1;
  2561. DBG_CB_EXIT(D3DValidateDeviceP3, pvtssd->ddrval);
  2562. return ( DDHAL_DRIVER_HANDLED );
  2563. }
  2564. } // D3DValidateDeviceP3