Source code of Windows XP (NT5)
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.

208 lines
7.5 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dphal.c
  6. * Content: DrawPrimitive implementation for DrawPrimitive HALs
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "drawprim.hpp"
  12. #include "clipfunc.h"
  13. //-----------------------------------------------------------------------------
  14. #undef DPF_MODNAME
  15. #define DPF_MODNAME "CD3DHal::ProcessVertices"
  16. HRESULT D3DAPI
  17. CD3DHal::ProcessVertices(UINT SrcStartIndex, UINT DestIndex, UINT VertexCount,
  18. IDirect3DVertexBuffer8 *DestBuffer,
  19. DWORD dwFlags)
  20. {
  21. API_ENTER(this); // Takes D3D Lock if necessary
  22. HRESULT hr = D3D_OK;
  23. CVertexBuffer* pVB = static_cast<CVertexBuffer*>(DestBuffer);
  24. const D3DBUFFER_DESC* pDesc = pVB->GetBufferDesc();
  25. UINT vbVertexSize = pVB->GetVertexSize();
  26. UINT vbNumVertices = pVB->GetNumVertices();
  27. #if DBG
  28. if (pVB->Device() != this)
  29. {
  30. D3D_ERR("VertexBuffer not created with this device. ProcessVertices failed.");
  31. return D3DERR_INVALIDCALL;
  32. }
  33. if (m_dwCurrentShaderHandle == 0)
  34. {
  35. D3D_ERR("Current vertex shader is not set. ProcessVertices failed.");
  36. return D3DERR_INVALIDCALL;
  37. }
  38. if (D3DVSD_ISLEGACY(m_dwCurrentShaderHandle) &&
  39. FVF_TRANSFORMED(m_dwCurrentShaderHandle))
  40. {
  41. D3D_ERR("Invalid vertex shader for ProcessVertices. ProcessVertices failed.");
  42. return D3DERR_INVALIDCALL;
  43. }
  44. if (!(m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING))
  45. {
  46. D3D_ERR("D3D Device should be in software mode for ProcessVertices. ProcessVertices failed.");
  47. return D3DERR_INVALIDCALL;
  48. }
  49. if (dwFlags & ~D3DPV_DONOTCOPYDATA)
  50. {
  51. D3D_ERR( "Invalid dwFlags set. ProcessVertices failed." );
  52. return D3DERR_INVALIDCALL;
  53. }
  54. if (pDesc->Usage & D3DUSAGE_DONOTCLIP &&
  55. !(m_pv->dwDeviceFlags & D3DDEV_DONOTCLIP))
  56. {
  57. D3D_ERR("Vertex buffer has D3D_DONOTCLIP usage, but clipping is enabled. ProcessVertices failed.");
  58. return D3DERR_INVALIDCALL;
  59. }
  60. if (pVB->GetFVF() == 0)
  61. {
  62. D3D_ERR("Destination buffer has no FVF associated with it. ProcessVertices failed.");
  63. return D3DERR_INVALIDCALL;
  64. }
  65. if ((pVB->GetFVF() & D3DFVF_POSITION_MASK) != D3DFVF_XYZRHW)
  66. {
  67. D3D_ERR("Destination vertex buffer should have D3DFVF_XYZRHW position. ProcessVertices failed.");
  68. return D3DERR_INVALIDCALL;
  69. }
  70. if (VertexCount + DestIndex > vbNumVertices)
  71. {
  72. D3D_ERR("Destination vertex buffer has not enough space. ProcessVertices failed.");
  73. return D3DERR_INVALIDCALL;
  74. }
  75. #endif
  76. try
  77. {
  78. DWORD vbFVF = pVB->GetFVF();
  79. m_pv->dwNumVertices = VertexCount;
  80. m_pv->dwFlags = D3DPV_VBCALL;
  81. #if DBG
  82. ValidateDraw2(D3DPT_TRIANGLELIST, SrcStartIndex, 1, VertexCount, FALSE);
  83. #endif
  84. // Internal flags and output vertex offsets could be different for
  85. // ProcessVertices
  86. ForceFVFRecompute();
  87. (this->*m_pfnPrepareToDraw)(SrcStartIndex);
  88. if (!(m_pv->dwDeviceFlags & D3DDEV_DONOTCLIP))
  89. {
  90. if (pVB->GetClipCodes() == NULL)
  91. {
  92. pVB->AllocateClipCodes();
  93. }
  94. m_pv->lpClipFlags = pVB->GetClipCodes();
  95. #if DBG
  96. if (m_pv->lpClipFlags == NULL)
  97. {
  98. D3D_THROW_FAIL("Failed to allocate clip code for the dest VB");
  99. }
  100. #endif
  101. m_pv->lpClipFlags += DestIndex;
  102. }
  103. // Check number of texture coordinates and texture formats in the
  104. // destination VB are the same as in the computed FVF
  105. DWORD dwComputedTexFormats = m_pv->dwVIDOut & 0xFFFF0000;
  106. DWORD dwNumTexCoordVB = FVF_TEXCOORD_NUMBER(vbFVF);
  107. if (m_pv->nOutTexCoord > dwNumTexCoordVB ||
  108. ((vbFVF & dwComputedTexFormats) != dwComputedTexFormats))
  109. {
  110. D3D_ERR("Number of output texture coordinates and their format should be");
  111. D3D_ERR("the same in the destination vertex buffer and as computed for current D3D settings.");
  112. D3D_ERR("Computed output FVF is 0x%08X", m_pv->dwVIDOut);
  113. D3D_THROW_FAIL("");
  114. }
  115. // Check if the computed output FVF is a subset of the VB's FVF.
  116. // Number of texture coordinates should be cleared.
  117. DWORD dwComputedFVF = m_pv->dwVIDOut & 0x000000FF;
  118. // Specularand diffuse colors could be omitted, as well as psize
  119. dwComputedFVF &= ~(D3DFVF_PSIZE | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_FOG);
  120. if((dwComputedFVF & vbFVF) != dwComputedFVF)
  121. {
  122. D3D_ERR("Dest vertex buffer's FVF should be a superset of the FVF, computed for");
  123. D3D_ERR("the current D3D settings");
  124. D3D_ERR("Computed output FVF is 0x%08X", m_pv->dwVIDOut);
  125. D3D_THROW_FAIL("");
  126. }
  127. BYTE* p;
  128. hr = pVB->Lock(0, pDesc->Size, &p, D3DLOCK_NOSYSLOCK);
  129. if (FAILED(hr))
  130. {
  131. D3D_THROW_FAIL("Cannot lock destination buffer");
  132. }
  133. if (this->dwFEFlags & D3DFE_FRONTEND_DIRTY)
  134. DoUpdateState(this);
  135. // Replace output FVF and vertex size
  136. m_pv->dwOutputSize = vbVertexSize;
  137. m_pv->dwVIDOut = vbFVF;
  138. m_pv->lpvOut = p + DestIndex * vbVertexSize;
  139. // Vertex shaders don't write to the output unless shader writes to it
  140. // explicitely. So we do not bother setting any flags
  141. if (dwFlags & D3DPV_DONOTCOPYDATA)
  142. {
  143. if (m_pv->dwDeviceFlags & D3DDEV_VERTEXSHADERS)
  144. {
  145. m_pv->dwFlags |= D3DPV_DONOTCOPYDIFFUSE |
  146. D3DPV_DONOTCOPYSPECULAR |
  147. D3DPV_DONOTCOPYTEXTURE;
  148. }
  149. else
  150. {
  151. m_pv->dwFlags |= D3DPV_DONOTCOPYDIFFUSE |
  152. D3DPV_DONOTCOPYSPECULAR |
  153. D3DPV_DONOTCOPYTEXTURE;
  154. // If D3DIM generates colors or texture, we should clear
  155. // DONOTCOPY bits
  156. if (m_pv->dwFlags & D3DPV_LIGHTING)
  157. {
  158. m_pv->dwFlags &= ~D3DPV_DONOTCOPYDIFFUSE;
  159. if (m_pv->dwDeviceFlags & D3DDEV_SPECULARENABLE)
  160. m_pv->dwFlags &= ~D3DPV_DONOTCOPYSPECULAR;
  161. }
  162. if (m_pv->dwFlags & D3DPV_FOG)
  163. m_pv->dwFlags &= ~D3DPV_DONOTCOPYSPECULAR;
  164. // If front-end is asked to do something with texture
  165. // coordinates we disable DONOTCOPYTEXTURE
  166. if (__TEXTURETRANSFORMENABLED(m_pv) ||
  167. m_pv->dwFlags2 & __FLAGS2_TEXGEN)
  168. {
  169. m_pv->dwFlags &= ~D3DPV_DONOTCOPYTEXTURE;
  170. }
  171. }
  172. }
  173. // Compute flags based on the vertex buffer FVF
  174. UpdateFlagsForOutputFVF(m_pv);
  175. // Update output vertex offsets for the new FVF
  176. ComputeOutputVertexOffsets(m_pv);
  177. m_pv->pGeometryFuncs->ProcessVertices(m_pv);
  178. if (!(m_pv->dwDeviceFlags & D3DDEV_DONOTCLIP))
  179. UpdateClipStatus(this);
  180. // When ProcessVertices is used, user must re-program texture
  181. // stage indices and wrap modes himself
  182. m_pv->dwDeviceFlags &= ~D3DDEV_REMAPTEXTUREINDICES;
  183. }
  184. catch(HRESULT ret)
  185. {
  186. D3D_ERR("ProcessVertices failed.");
  187. hr = ret;
  188. }
  189. ForceFVFRecompute();
  190. pVB->Unlock();
  191. return hr;
  192. }