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.

814 lines
27 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: beginend.c
  6. * Content: Begin/End implementation
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "drawprim.hpp"
  12. #include "d3dfei.h"
  13. // This should be moved with other DP flags so that no one uses this bit
  14. #define __NON_FVF_INPUT 0x80000000
  15. //---------------------------------------------------------------------
  16. #undef DPF_MODNAME
  17. #define DPF_MODNAME "MoveData"
  18. _inline void MoveData(LPVOID lpData, DWORD destOffset, DWORD srcOffset,
  19. DWORD size)
  20. {
  21. memcpy((char*)lpData + destOffset, (char*)lpData + srcOffset, size);
  22. }
  23. //---------------------------------------------------------------------
  24. void CleanupBeginEnd(LPDIRECT3DDEVICEI lpDevI)
  25. {
  26. lpDevI->lpVertexIndices = NULL;
  27. lpDevI->lpvVertexData = NULL;
  28. lpDevI->dwBENumVertices = 0;
  29. lpDevI->dwBENumIndices = 0;
  30. lpDevI->dwHintFlags &= ~D3DDEVBOOL_HINTFLAGS_INBEGIN_ALL;
  31. }
  32. //---------------------------------------------------------------------
  33. HRESULT
  34. DoFlushBeginEnd(LPDIRECT3DDEVICEI lpDevI)
  35. {
  36. HRESULT ret;
  37. lpDevI->lpwIndices = NULL;
  38. lpDevI->dwNumIndices = 0;
  39. lpDevI->lpClipFlags = (D3DFE_CLIPCODE*)lpDevI->HVbuf.GetAddress();
  40. lpDevI->position.lpvData = lpDevI->lpvVertexData;
  41. ret = lpDevI->ProcessPrimitive();
  42. return ret;
  43. }
  44. //---------------------------------------------------------------------
  45. __inline void Dereference(LPDIRECT3DDEVICEI lpDevI, DWORD indexStart, DWORD numVer)
  46. {
  47. char *dst_vptr = (char*)lpDevI->lpvVertexBatch;
  48. char *src_vptr = (char*)lpDevI->lpvVertexData;
  49. WORD *iptr = &lpDevI->lpVertexIndices[indexStart];
  50. DWORD size = lpDevI->position.dwStride;
  51. for (DWORD i=0; i < numVer; i++)
  52. {
  53. memcpy(dst_vptr, &src_vptr[iptr[i]*size], size);
  54. dst_vptr += size;
  55. }
  56. }
  57. //---------------------------------------------------------------------
  58. HRESULT
  59. DoFlushBeginIndexedEnd(LPDIRECT3DDEVICEI lpDevI)
  60. {
  61. HRESULT ret;
  62. DWORD i;
  63. static BOOL offScreen; // all vertices are off screen
  64. lpDevI->dwNumVertices = lpDevI->dwBENumVertices;
  65. lpDevI->lpwIndices = lpDevI->lpVertexIndices;
  66. lpDevI->lpClipFlags = (D3DFE_CLIPCODE*)lpDevI->HVbuf.GetAddress();
  67. lpDevI->position.lpvData = lpDevI->lpvVertexData;
  68. if ( (lpDevI->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN) &&
  69. (!(lpDevI->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN_FIRST_FLUSH)) )
  70. { // if this is the first flush
  71. lpDevI->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_INBEGIN_FIRST_FLUSH;
  72. offScreen = 0;
  73. if (lpDevI->dwBENumIndices < lpDevI->dwMaxIndexCount)
  74. { // single flush case
  75. /*
  76. If the user is using a large vertex array for relatively few prims
  77. we need to dereference the indexed prims into another array. Otherwise
  78. we waste too much time transforming and lighting vertices that we never use.
  79. Since BeginIndexed requires that the user pass in an array of vertices we
  80. know that this->lpvVertexBatch is not being used. So derefernce into it.
  81. We know it's there because the index space gets created at the same time.
  82. Also note that since the max size fo the index array is bigger than
  83. the vertex array we may have to do this in several small batches.
  84. */
  85. if (!FVF_TRANSFORMED(lpDevI->dwVIDIn))
  86. {
  87. if (lpDevI->dwBENumIndices*INDEX_BATCH_SCALE < lpDevI->dwBENumVertices)
  88. {
  89. WORD *iptr;
  90. DWORD indexStart = 0;
  91. DWORD numPrims;
  92. DWORD numIndices = lpDevI->dwBENumIndices;
  93. switch (lpDevI->primType)
  94. {
  95. case D3DPT_LINELIST :
  96. {
  97. do
  98. {
  99. numPrims = min(numIndices/2, lpDevI->dwMaxVertexCount/2);
  100. DWORD numVer = numPrims << 1;
  101. Dereference(lpDevI, indexStart, numVer);
  102. lpDevI->dwNumVertices = numVer;
  103. lpDevI->dwNumPrimitives = numPrims;
  104. lpDevI->position.lpvData = lpDevI->lpvVertexBatch;
  105. ret = lpDevI->ProcessPrimitive();
  106. if (ret != D3D_OK)
  107. {
  108. return ret;
  109. }
  110. indexStart += numVer;
  111. numIndices -= numVer;
  112. } while (numIndices > 1);
  113. break;
  114. }
  115. case D3DPT_LINESTRIP :
  116. do
  117. {
  118. numPrims = min(numIndices-1, lpDevI->dwMaxVertexCount-1);
  119. DWORD numVer = numPrims + 1;
  120. Dereference(lpDevI, indexStart, numVer);
  121. lpDevI->dwNumVertices = numPrims+1;
  122. lpDevI->dwNumPrimitives = numPrims;
  123. lpDevI->position.lpvData = lpDevI->lpvVertexBatch;
  124. ret = lpDevI->ProcessPrimitive();
  125. if (ret != D3D_OK)
  126. {
  127. return ret;
  128. }
  129. indexStart += numPrims;
  130. numIndices -= numPrims;
  131. } while (numIndices > 1);
  132. break;
  133. case D3DPT_TRIANGLELIST :
  134. do
  135. {
  136. numPrims = min(numIndices/3, lpDevI->dwMaxVertexCount/3);
  137. DWORD numVer = numPrims*3;
  138. Dereference(lpDevI, indexStart, numVer);
  139. lpDevI->dwNumVertices = numVer;
  140. lpDevI->dwNumPrimitives = numPrims;
  141. lpDevI->position.lpvData = lpDevI->lpvVertexBatch;
  142. ret = lpDevI->ProcessPrimitive();
  143. if (ret != D3D_OK)
  144. {
  145. return ret;
  146. }
  147. indexStart += numVer;
  148. numIndices -= numVer;
  149. } while (numIndices > 2);
  150. break;
  151. case D3DPT_TRIANGLESTRIP :
  152. do
  153. {
  154. numPrims = min(numIndices-2, lpDevI->dwMaxVertexCount-2);
  155. DWORD numVer = numPrims + 2;
  156. Dereference(lpDevI, indexStart, numVer);
  157. lpDevI->dwNumVertices = numVer;
  158. lpDevI->dwNumPrimitives = numPrims;
  159. lpDevI->position.lpvData = lpDevI->lpvVertexBatch;
  160. ret = lpDevI->ProcessPrimitive();
  161. if (ret != D3D_OK)
  162. {
  163. return ret;
  164. }
  165. indexStart += numPrims;
  166. numIndices -= numPrims;
  167. } while (numIndices > 2);
  168. break;
  169. case D3DPT_TRIANGLEFAN :
  170. // lock in center of fan
  171. char *tmp = (char*)lpDevI->lpvVertexBatch;
  172. char *src = (char*)lpDevI->lpvVertexData;
  173. DWORD size = lpDevI->position.dwStride;
  174. memcpy(lpDevI->lpvVertexBatch,
  175. &src[lpDevI->lpVertexIndices[0]*size], size);
  176. lpDevI->lpvVertexBatch = tmp + size;
  177. indexStart = 1;
  178. do
  179. {
  180. numPrims = min(numIndices-2, lpDevI->dwMaxVertexCount-2);
  181. Dereference(lpDevI, indexStart, numPrims + 1);
  182. lpDevI->dwNumVertices = numPrims+2;
  183. lpDevI->dwNumPrimitives = numPrims;
  184. lpDevI->position.lpvData = tmp;
  185. ret = lpDevI->ProcessPrimitive();
  186. if (ret != D3D_OK)
  187. {
  188. return ret;
  189. }
  190. indexStart += numPrims;
  191. numIndices -= numPrims;
  192. } while (numIndices > 2);
  193. lpDevI->lpvVertexBatch = tmp; // Restore
  194. break;
  195. } // end of prim type switch
  196. return D3D_OK;
  197. }
  198. // else fall through to the no batching case
  199. }
  200. // no batching case
  201. ret = lpDevI->ProcessPrimitive(__PROCPRIMOP_INDEXEDPRIM);
  202. return ret;
  203. }
  204. else
  205. {
  206. // this is the first of n possible batches so t&l all vertices just once
  207. ret = lpDevI->ProcessPrimitive(__PROCPRIMOP_PROCVERONLY);
  208. if (ret != D3D_OK)
  209. {
  210. return ret;
  211. }
  212. // This flag is cleared in CleanupBeginEnd
  213. lpDevI->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_INBEGIN_BIG_PRIM;
  214. if (lpDevI->dwClipIntersection)
  215. {
  216. // all vertices are off screen so we can just bail
  217. offScreen = 1; // so we can early out next flush
  218. return D3D_OK;
  219. }
  220. }
  221. } // end if if first flush
  222. // for secondary flushes don't bother to draw if we don't need to
  223. if (!offScreen)
  224. ret = DoDrawIndexedPrimitive(lpDevI);
  225. return ret;
  226. } // end of DoFlushBeginIndexedEnd()
  227. //---------------------------------------------------------------------
  228. // Computes the number of primitives
  229. // Input: lpDevI->primType
  230. // dwNumVertices
  231. // Output: lpDevI->dwNumPrimitives
  232. // lpDevI->D3DStats
  233. // return value = "Real" number of vertices (indices)
  234. #undef DPF_MODNAME
  235. #define DPF_MODNAME "GetNumPrimBE"
  236. inline DWORD GetNumPrimBE(LPDIRECT3DDEVICEI lpDevI, DWORD dwNumVertices)
  237. {
  238. lpDevI->dwNumPrimitives = 0;
  239. switch (lpDevI->primType)
  240. {
  241. case D3DPT_POINTLIST:
  242. lpDevI->D3DStats.dwPointsDrawn += dwNumVertices;
  243. lpDevI->dwNumPrimitives = dwNumVertices;
  244. return dwNumVertices;
  245. case D3DPT_LINELIST:
  246. lpDevI->dwNumPrimitives = dwNumVertices >> 1;
  247. lpDevI->D3DStats.dwLinesDrawn += lpDevI->dwNumPrimitives;
  248. return lpDevI->dwNumPrimitives << 1;
  249. case D3DPT_LINESTRIP:
  250. if (dwNumVertices < 2)
  251. return 0;
  252. lpDevI->dwNumPrimitives = dwNumVertices - 1;
  253. lpDevI->D3DStats.dwLinesDrawn += lpDevI->dwNumPrimitives;
  254. return dwNumVertices;
  255. case D3DPT_TRIANGLEFAN:
  256. case D3DPT_TRIANGLESTRIP:
  257. if (dwNumVertices < 3)
  258. return 0;
  259. lpDevI->dwNumPrimitives = dwNumVertices - 2;
  260. lpDevI->D3DStats.dwTrianglesDrawn += lpDevI->dwNumPrimitives;
  261. return dwNumVertices;
  262. case D3DPT_TRIANGLELIST:
  263. lpDevI->dwNumPrimitives = dwNumVertices / 3;
  264. lpDevI->D3DStats.dwTrianglesDrawn += lpDevI->dwNumPrimitives;
  265. return lpDevI->dwNumPrimitives * 3;
  266. }
  267. return 0;
  268. }
  269. //---------------------------------------------------------------------
  270. #undef DPF_MODNAME
  271. #define DPF_MODNAME "BeginEnd"
  272. HRESULT FlushBeginEndBatch(LPDIRECT3DDEVICEI lpDevI, BOOL leaving)
  273. {
  274. HRESULT ret;
  275. #ifdef _X86_
  276. unsigned short fpsave, fptemp;
  277. #endif
  278. if (lpDevI->dwBENumIndices == 0xFFFFFFFF)
  279. lpDevI->dwNumVertices = GetNumPrimBE(lpDevI, lpDevI->dwBENumVertices);
  280. else
  281. lpDevI->dwNumIndices = GetNumPrimBE(lpDevI, lpDevI->dwBENumIndices);
  282. if (lpDevI->dwNumPrimitives < 1)
  283. {
  284. return DDERR_INVALIDPARAMS;
  285. }
  286. ret = (*lpDevI->pfnDoFlushBeginEnd)(lpDevI);
  287. /*
  288. * ReInit the device Begin/End states
  289. */
  290. if (!leaving)
  291. /*
  292. * Figure out how many and which vertices to keep for next batch.
  293. */
  294. {
  295. DWORD *dataCountPtr;
  296. DWORD vertexSize; // size in bytes
  297. DWORD offset; // start offset
  298. lpDevI->wFlushed = TRUE;
  299. if (lpDevI->lpVertexIndices)
  300. {
  301. dataCountPtr = &(lpDevI->dwBENumIndices);
  302. lpDevI->lpcCurrentPtr = (char*)lpDevI->lpVertexIndices;
  303. vertexSize = 2;
  304. offset = lpDevI->dwBENumIndices * 2;
  305. }
  306. else
  307. {
  308. dataCountPtr = &(lpDevI->dwBENumVertices);
  309. lpDevI->lpcCurrentPtr = (char*)lpDevI->lpvVertexData;
  310. vertexSize = lpDevI->position.dwStride;
  311. offset = lpDevI->dwBENumVertices * lpDevI->position.dwStride;
  312. }
  313. switch (lpDevI->primType)
  314. {
  315. case D3DPT_LINELIST:
  316. if (*dataCountPtr & 1)
  317. {
  318. MoveData(lpDevI->lpcCurrentPtr, 0, offset - vertexSize,
  319. vertexSize);
  320. *dataCountPtr = 1;
  321. lpDevI->lpcCurrentPtr += vertexSize;
  322. } else
  323. *dataCountPtr = 0;
  324. break;
  325. case D3DPT_LINESTRIP:
  326. MoveData(lpDevI->lpcCurrentPtr, 0, offset - vertexSize, vertexSize);
  327. *dataCountPtr = 1;
  328. lpDevI->lpcCurrentPtr += vertexSize;
  329. break;
  330. case D3DPT_TRIANGLEFAN:
  331. MoveData(lpDevI->lpcCurrentPtr, vertexSize, offset - vertexSize,
  332. vertexSize);
  333. *dataCountPtr = 2;
  334. lpDevI->lpcCurrentPtr += (vertexSize << 1);
  335. break;
  336. case D3DPT_TRIANGLESTRIP:
  337. {
  338. DWORD size = vertexSize << 1;
  339. MoveData(lpDevI->lpcCurrentPtr, 0, offset - size, size);
  340. *dataCountPtr = 2;
  341. lpDevI->lpcCurrentPtr += size;
  342. break;
  343. }
  344. case D3DPT_POINTLIST:
  345. *dataCountPtr = 0;
  346. break;
  347. case D3DPT_TRIANGLELIST:
  348. {
  349. DWORD rem = (*dataCountPtr % 3);
  350. if ( rem != 0 )
  351. {
  352. DWORD size = rem * vertexSize;
  353. MoveData(lpDevI->lpcCurrentPtr, 0, offset - size, size);
  354. }
  355. *dataCountPtr = rem;
  356. lpDevI->lpcCurrentPtr += rem * vertexSize;
  357. }
  358. break;
  359. default:
  360. D3D_ERR( "Unknown or unsupported primitive type requested in BeginEnd" );
  361. ret = D3DERR_INVALIDPRIMITIVETYPE;
  362. }
  363. }
  364. return ret;
  365. }
  366. //---------------------------------------------------------------------
  367. #undef DPF_MODNAME
  368. #define DPF_MODNAME "CheckBegin"
  369. HRESULT CheckBegin(LPDIRECT3DDEVICEI lpDevI,
  370. D3DPRIMITIVETYPE ptPrimitiveType,
  371. DWORD dwVertexType,
  372. DWORD dwFlags)
  373. {
  374. lpDevI->dwFlags = 0;
  375. #if DBG
  376. switch (ptPrimitiveType)
  377. {
  378. case D3DPT_POINTLIST:
  379. case D3DPT_LINELIST:
  380. case D3DPT_LINESTRIP:
  381. case D3DPT_TRIANGLELIST:
  382. case D3DPT_TRIANGLESTRIP:
  383. case D3DPT_TRIANGLEFAN:
  384. break;
  385. default:
  386. D3D_ERR( "Invalid primitive type given to Begin" );
  387. return DDERR_INVALIDPARAMS;
  388. }
  389. if (dwFlags & __NON_FVF_INPUT)
  390. {
  391. switch ((D3DVERTEXTYPE)dwVertexType)
  392. {
  393. case D3DVT_TLVERTEX:
  394. case D3DVT_LVERTEX:
  395. case D3DVT_VERTEX:
  396. break;
  397. default:
  398. D3D_ERR( "Invalid vertex type given to Begin" );
  399. return DDERR_INVALIDPARAMS;
  400. }
  401. if (!IsDPFlagsValid(dwFlags & ~__NON_FVF_INPUT))
  402. return DDERR_INVALIDPARAMS;
  403. lpDevI->dwVIDIn = d3dVertexToFVF[dwVertexType];
  404. dwFlags &= ~__NON_FVF_INPUT;
  405. }
  406. else
  407. {
  408. if (ValidateFVF(dwVertexType) != D3D_OK)
  409. return DDERR_INVALIDPARAMS;
  410. lpDevI->dwVIDIn = dwVertexType;
  411. }
  412. /*
  413. * validate parms
  414. */
  415. TRY
  416. {
  417. if (!VALID_DIRECT3DDEVICE3_PTR(lpDevI))
  418. {
  419. D3D_ERR( "Invalid Direct3DDevice pointer" );
  420. return DDERR_INVALIDOBJECT;
  421. }
  422. }
  423. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  424. {
  425. D3D_ERR( "Exception encountered validating parameters" );
  426. return DDERR_INVALIDPARAMS;
  427. }
  428. #else
  429. lpDevI->dwVIDIn = dwVertexType;
  430. #endif
  431. HRESULT err = CheckDeviceSettings(lpDevI);
  432. if (err != D3D_OK)
  433. return err;
  434. err = CheckVertexBatch(lpDevI);
  435. if (err != D3D_OK)
  436. return err;
  437. // acts as boolean
  438. lpDevI->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_INBEGIN;
  439. // indicates first flush
  440. lpDevI->dwHintFlags &= ~D3DDEVBOOL_HINTFLAGS_INBEGIN_FIRST_FLUSH;
  441. lpDevI->primType = ptPrimitiveType;
  442. lpDevI->position.dwStride = GetVertexSizeFVF(lpDevI->dwVIDIn);
  443. lpDevI->dwBENumVertices = 0;
  444. ComputeOutputFVF(lpDevI);
  445. // dwMaxVertexCount should be even to properly break a primitive when
  446. // flushing
  447. lpDevI->dwMaxVertexCount = (BEGIN_DATA_BLOCK_MEM_SIZE /
  448. lpDevI->position.dwStride) & ~1;
  449. lpDevI->dwMaxIndexCount = BEGIN_DATA_BLOCK_SIZE * 16;
  450. lpDevI->dwBENumIndices = 0;
  451. lpDevI->lpvVertexData = NULL;
  452. lpDevI->lpVertexIndices = NULL;
  453. lpDevI->dwFlags |= dwFlags;
  454. lpDevI->wFlushed = FALSE;
  455. if (lpDevI->dwVIDIn & D3DFVF_NORMAL)
  456. lpDevI->dwFlags |= D3DPV_LIGHTING;
  457. return D3D_OK;
  458. }
  459. //*********************************************************************
  460. // API calls
  461. //*********************************************************************
  462. #undef DPF_MODNAME
  463. #define DPF_MODNAME "Begin"
  464. HRESULT D3DAPI
  465. DIRECT3DDEVICEI::Begin(D3DPRIMITIVETYPE ptPrimitiveType,
  466. DWORD dwVertexType,
  467. DWORD dwFlags)
  468. {
  469. HRESULT ret;
  470. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  471. // Release in the destructor
  472. /*
  473. * Check/validate parameters, initialize related fields in the device.
  474. */
  475. if ((ret = CheckBegin(this, ptPrimitiveType, dwVertexType, dwFlags)) != D3D_OK)
  476. {
  477. return ret;
  478. }
  479. Profile(PROF_BEGIN,ptPrimitiveType,dwVertexType);
  480. this->dwBENumIndices = 0xffffffff; // mark as being in Begin rather
  481. // than BeginIndexed
  482. lpvVertexData = lpvVertexBatch;
  483. lpcCurrentPtr = (char*)lpvVertexBatch;
  484. pfnDoFlushBeginEnd = DoFlushBeginEnd;
  485. if ( IS_MT_DEVICE(this) )
  486. EnterCriticalSection(&BeginEndCSect);
  487. return D3D_OK;
  488. }
  489. //---------------------------------------------------------------------
  490. #undef DPF_MODNAME
  491. #define DPF_MODNAME "BeginIndexed"
  492. HRESULT D3DAPI
  493. DIRECT3DDEVICEI::BeginIndexed(D3DPRIMITIVETYPE ptPrimitiveType,
  494. DWORD vtVertexType,
  495. LPVOID lpvVertices,
  496. DWORD dwNumVertices,
  497. DWORD dwFlags)
  498. {
  499. HRESULT ret;
  500. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  501. // Release in the destructor
  502. #if DBG
  503. if (ptPrimitiveType == D3DPT_POINTLIST)
  504. {
  505. D3D_ERR( "BeginIndexed does not support D3DPT_POINTLIST" );
  506. return DDERR_INVALIDPARAMS;
  507. }
  508. /*
  509. * validate lpvVertices & dwNumVertices
  510. */
  511. if ( dwNumVertices > 65535ul )
  512. {
  513. D3D_ERR( "BeginIndexed vertex array > 64K" );
  514. return DDERR_INVALIDPARAMS;
  515. }
  516. if ( dwNumVertices == 0ul )
  517. {
  518. D3D_ERR( "Number of vertices for BeginIndexed is zero" );
  519. return DDERR_INVALIDPARAMS;
  520. }
  521. TRY
  522. {
  523. if (!VALID_PTR(lpvVertices, sizeof(D3DVERTEX)*dwNumVertices))
  524. {
  525. D3D_ERR( "Invalid vertex pointer" );
  526. return DDERR_INVALIDPARAMS;
  527. }
  528. }
  529. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  530. {
  531. D3D_ERR( "Exception encountered validating parameters" );
  532. return DDERR_INVALIDPARAMS;
  533. }
  534. #endif
  535. /*
  536. * Check/validate parameters, initialize related fields in the device.
  537. */
  538. if ((ret = CheckBegin(this, ptPrimitiveType, vtVertexType, dwFlags)) != D3D_OK)
  539. return ret;
  540. Profile(PROF_BEGININDEXED,ptPrimitiveType,vtVertexType);
  541. this->dwBENumVertices = dwNumVertices;
  542. this->lpvVertexData = lpvVertices;
  543. this->pfnDoFlushBeginEnd = DoFlushBeginIndexedEnd;
  544. this->lpVertexIndices = this->lpIndexBatch;
  545. this->lpcCurrentPtr = (char*)this->lpIndexBatch;
  546. if ( IS_MT_DEVICE(this) )
  547. EnterCriticalSection(&this->BeginEndCSect);
  548. return D3D_OK;
  549. }
  550. //---------------------------------------------------------------------
  551. #undef DPF_MODNAME
  552. #define DPF_MODNAME "Begin(D3DVERTEXTYPE)"
  553. HRESULT D3DAPI
  554. DIRECT3DDEVICEI::Begin(D3DPRIMITIVETYPE ptPrimitiveType,
  555. D3DVERTEXTYPE vertexType,
  556. DWORD dwFlags)
  557. {
  558. #if DBG
  559. dwFlags |= __NON_FVF_INPUT;
  560. return Begin(ptPrimitiveType, (DWORD)vertexType, dwFlags);
  561. #else
  562. return Begin(ptPrimitiveType, (DWORD)d3dVertexToFVF[vertexType], dwFlags);
  563. #endif
  564. }
  565. //---------------------------------------------------------------------
  566. #undef DPF_MODNAME
  567. #define DPF_MODNAME "BeginIndexed(D3DVERTEXTYPE)"
  568. HRESULT D3DAPI
  569. DIRECT3DDEVICEI::BeginIndexed(D3DPRIMITIVETYPE ptPrimitiveType,
  570. D3DVERTEXTYPE vertexType,
  571. LPVOID lpvVertices,
  572. DWORD dwNumVertices,
  573. DWORD dwFlags)
  574. {
  575. #if DBG
  576. dwFlags |= __NON_FVF_INPUT;
  577. return BeginIndexed(ptPrimitiveType, (DWORD) vertexType, lpvVertices,
  578. dwNumVertices, dwFlags);
  579. #else
  580. return BeginIndexed(ptPrimitiveType, (DWORD) d3dVertexToFVF[vertexType], lpvVertices,
  581. dwNumVertices, dwFlags);
  582. #endif
  583. }
  584. //---------------------------------------------------------------------
  585. #undef DPF_MODNAME
  586. #define DPF_MODNAME "Vertex"
  587. HRESULT D3DAPI
  588. DIRECT3DDEVICEI::Vertex(LPVOID lpVertex)
  589. {
  590. D3DVERTEX *dataPtr;
  591. HRESULT ret = D3D_OK;
  592. #if DBG
  593. // validate parms
  594. TRY
  595. {
  596. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  597. {
  598. D3D_ERR( "Invalid Direct3DDevice pointer in Vertex" );
  599. return DDERR_INVALIDOBJECT;
  600. }
  601. if (lpVertex == NULL || (! VALID_PTR(lpVertex, 32)) )
  602. {
  603. D3D_ERR( "Invalid vertex pointer in Vertex" );
  604. return DDERR_INVALIDPARAMS;
  605. }
  606. }
  607. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  608. {
  609. D3D_ERR( "Exception encountered validating parameters in Vertex" );
  610. CleanupBeginEnd(this);
  611. return DDERR_INVALIDPARAMS;
  612. }
  613. if (!(this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN))
  614. {
  615. D3D_ERR( "Vertex call not in Begin" );
  616. CleanupBeginEnd(this);
  617. return D3DERR_NOTINBEGIN;
  618. }
  619. #endif
  620. // store the data
  621. if (dwBENumVertices >= dwMaxVertexCount)
  622. {
  623. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  624. // Release in the destructor
  625. if ((ret = FlushBeginEndBatch(this, FALSE)) != D3D_OK)
  626. {
  627. CleanupBeginEnd(this);
  628. return ret;
  629. }
  630. }
  631. memcpy(lpcCurrentPtr, lpVertex, this->position.dwStride);
  632. lpcCurrentPtr += this->position.dwStride;
  633. dwBENumVertices++;
  634. return D3D_OK;
  635. }
  636. //---------------------------------------------------------------------
  637. #undef DPF_MODNAME
  638. #define DPF_MODNAME "Index"
  639. HRESULT D3DAPI
  640. DIRECT3DDEVICEI::Index(WORD dwIndex)
  641. {
  642. WORD *dataPtr;
  643. DWORD *dataCountPtr;
  644. HRESULT ret = D3D_OK;
  645. #if DBG
  646. // validate parms
  647. TRY
  648. {
  649. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  650. {
  651. D3D_ERR( "Invalid Direct3DDevice pointer in Index" );
  652. return DDERR_INVALIDOBJECT;
  653. }
  654. }
  655. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  656. {
  657. D3D_ERR( "Exception encountered validating parameters in Index" );
  658. CleanupBeginEnd(this);
  659. return DDERR_INVALIDPARAMS;
  660. }
  661. if (!(this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN))
  662. {
  663. D3D_ERR( "Index call not in Begin" );
  664. CleanupBeginEnd(this);
  665. return D3DERR_NOTINBEGIN;
  666. }
  667. // check if data valid
  668. if (this->dwBENumVertices < dwIndex)
  669. {
  670. D3D_ERR( "Invalid index value passed to Index" );
  671. CleanupBeginEnd(this);
  672. return DDERR_INVALIDPARAMS;
  673. }
  674. #endif
  675. // store the data
  676. if (dwBENumIndices >= dwMaxIndexCount)
  677. {
  678. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  679. // Release in the destructor
  680. if ((ret = FlushBeginEndBatch(this, FALSE)) != D3D_OK)
  681. {
  682. CleanupBeginEnd(this);
  683. return ret;
  684. }
  685. }
  686. *(WORD*)lpcCurrentPtr = dwIndex;
  687. dwBENumIndices++;
  688. lpcCurrentPtr += 2;
  689. return D3D_OK;
  690. } // end of D3DDev2_Index()
  691. //---------------------------------------------------------------------
  692. #undef DPF_MODNAME
  693. #define DPF_MODNAME "End"
  694. HRESULT D3DAPI
  695. DIRECT3DDEVICEI::End(DWORD dwFlags)
  696. {
  697. HRESULT ret;
  698. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  699. // Release in the destructor
  700. #if DBG
  701. /*
  702. * validate parms
  703. */
  704. TRY
  705. {
  706. if (!VALID_DIRECT3DDEVICE3_PTR(this))
  707. {
  708. D3D_ERR( "Invalid Direct3DDevice pointer" );
  709. return DDERR_INVALIDOBJECT;
  710. }
  711. }
  712. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  713. {
  714. D3D_ERR( "Exception encountered validating parameters" );
  715. return DDERR_INVALIDPARAMS;
  716. }
  717. if ( !(this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN))
  718. {
  719. D3D_ERR( "End not in Begin/BeginIndex" );
  720. return D3DERR_NOTINBEGIN;
  721. }
  722. #endif
  723. if ( IS_MT_DEVICE(this) )
  724. LeaveCriticalSection(&this->BeginEndCSect);
  725. /*
  726. * Draw the primitives
  727. */
  728. ret = FlushBeginEndBatch(this, TRUE);
  729. if (IS_DP2HAL_DEVICE(this) &&
  730. this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN_BIG_PRIM)
  731. {
  732. CDirect3DDeviceIDP2 *dev = static_cast<CDirect3DDeviceIDP2*>(this);
  733. ret = dev->EndPrim(this->dwNumVertices * this->dwOutputSize);
  734. }
  735. CleanupBeginEnd(this);
  736. return ret;
  737. }