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.

340 lines
12 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. #ifdef WIN95
  12. #include "drawprim.hpp"
  13. #include "clipfunc.h"
  14. #include "d3dfei.h"
  15. #define LOWVERTICESNUMBERDP 20
  16. extern void SetDebugRenderState(DWORD value);
  17. #define ALIGN32(x) x = ((DWORD)(x + 31)) & (~31);
  18. //---------------------------------------------------------------------
  19. #undef DPF_MODNAME
  20. #define DPF_MODNAME "MapFVFtoTLVertex1"
  21. inline void MapFVFtoTLVertex1(LPDIRECT3DDEVICEI lpDevI, D3DTLVERTEX *pOut,
  22. DWORD *pIn)
  23. {
  24. // Copy position
  25. pOut->sx = *(D3DVALUE*)pIn++;
  26. pOut->sy = *(D3DVALUE*)pIn++;
  27. pOut->sz = *(D3DVALUE*)pIn++;
  28. pOut->rhw = *(D3DVALUE*)pIn++;
  29. // Other fields: diffuse, specular, texture
  30. if (lpDevI->dwVIDOut & D3DFVF_DIFFUSE)
  31. pOut->color = *pIn++;
  32. else
  33. {
  34. pOut->color = __DEFAULT_DIFFUSE;
  35. }
  36. if (lpDevI->dwVIDOut & D3DFVF_SPECULAR)
  37. pOut->specular = *pIn++;
  38. else
  39. {
  40. pOut->specular= __DEFAULT_SPECULAR;
  41. }
  42. if (lpDevI->nOutTexCoord)
  43. {
  44. pIn = &pIn[lpDevI->dwTextureIndexToCopy << 1];
  45. pOut->tu = *(D3DVALUE*)&pIn[0];
  46. pOut->tv = *(D3DVALUE*)&pIn[1];
  47. }
  48. else
  49. {
  50. pOut->tu = 0;
  51. pOut->tv = 0;
  52. }
  53. }
  54. //---------------------------------------------------------------------
  55. // All vertices from lpDevI->lpVout are copied to the output buffer, expanding
  56. // to D3DTLVERTEX.
  57. // The output buffer is lpAddress if it is not NULL, otherwise it is TLVbuf
  58. //
  59. #undef DPF_MODNAME
  60. #define DPF_MODNAME "MapFVFtoTLVertex"
  61. HRESULT CDirect3DDeviceIHW::MapFVFtoTLVertex(LPVOID lpAddress)
  62. {
  63. int i;
  64. DWORD size = this->dwNumVertices * sizeof(D3DTLVERTEX);
  65. D3DTLVERTEX *pOut;
  66. if (lpAddress)
  67. pOut = (D3DTLVERTEX*)lpAddress;
  68. else
  69. {
  70. // See if TL buffer has sufficient space
  71. if (size > this->TLVbuf.GetSize())
  72. {
  73. if (this->TLVbuf.Grow(this, size) != D3D_OK)
  74. {
  75. D3D_ERR( "Could not grow TL vertex buffer" );
  76. return DDERR_OUTOFMEMORY;
  77. }
  78. }
  79. pOut = (D3DTLVERTEX*)this->TLVbuf.GetAddress();
  80. }
  81. // Map vertices
  82. DWORD *pIn = (DWORD*)this->lpvOut;
  83. for (i=this->dwNumVertices; i; i--)
  84. {
  85. MapFVFtoTLVertex1(this, pOut, pIn);
  86. pOut++;
  87. pIn = (DWORD*)((char*)pIn + this->dwOutputSize);
  88. }
  89. return D3D_OK;
  90. }
  91. //---------------------------------------------------------------------
  92. // Vertices, corresponding to the primitive's indices, are converted to D3DTLVERTEX
  93. // and copied to the TL buffer
  94. //
  95. #undef DPF_MODNAME
  96. #define DPF_MODNAME "MapFVFtoTLVertexIndexed"
  97. HRESULT CDirect3DDeviceIHW::MapFVFtoTLVertexIndexed()
  98. {
  99. DWORD size = this->dwNumVertices * sizeof(D3DTLVERTEX);
  100. D3DTLVERTEX *pOut;
  101. // See if TL buffer has sufficient space
  102. if (size > this->TLVbuf.GetSize())
  103. {
  104. if (this->TLVbuf.Grow(this, size) != D3D_OK)
  105. {
  106. D3D_ERR( "Could not grow TL vertex buffer" );
  107. return DDERR_OUTOFMEMORY;
  108. }
  109. }
  110. pOut = (D3DTLVERTEX*)this->TLVbuf.GetAddress();
  111. // Map vertices
  112. DWORD *pIn = (DWORD*)this->lpvOut;
  113. for (DWORD i = 0; i < this->dwNumIndices; i++)
  114. {
  115. DWORD *pInpVertex = (DWORD*)((BYTE*)pIn + this->lpwIndices[i] * this->dwOutputSize);
  116. MapFVFtoTLVertex1(this, &pOut[this->lpwIndices[i]], pInpVertex);
  117. }
  118. return D3D_OK;
  119. }
  120. //---------------------------------------------------------------------
  121. // Draws non-indexed primitives which do not require clipping
  122. //
  123. #undef DPF_MODNAME
  124. #define DPF_MODNAME "DrawPrim"
  125. #define __DRAWPRIMFUNC
  126. #include "dpgen.h"
  127. //---------------------------------------------------------------------
  128. // Draws indexed primitives which do not require clipping
  129. //
  130. #undef DPF_MODNAME
  131. #define DPF_MODNAME "DrawIndexedPrim"
  132. #define __DRAWPRIMFUNC
  133. #define __DRAWPRIMINDEX
  134. #include "dpgen.h"
  135. //---------------------------------------------------------------------
  136. #undef DPF_MODNAME
  137. #define DPF_MODNAME "CDirect3DDeviceIDP::Init"
  138. HRESULT CDirect3DDeviceIDP::Init(REFCLSID riid, LPDIRECT3DI lpD3DI,
  139. LPDIRECTDRAWSURFACE lpDDS,
  140. IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice)
  141. {
  142. HRESULT ret;
  143. ret = CDirect3DDeviceIHW::Init(riid, lpD3DI, lpDDS, pUnkOuter, lplpD3DDevice);
  144. if (ret != D3D_OK)
  145. return ret;
  146. return D3D_OK;
  147. }
  148. //---------------------------------------------------------------------
  149. // ATTENTION - These two functions should be combined into one as soon
  150. // as ContextCreate has the new private data mechanism built in.
  151. #undef DPF_MODNAME
  152. #define DPF_MODNAME "CDirect3DDeviceIDP::halCreateContext"
  153. HRESULT CDirect3DDeviceIDP::halCreateContext()
  154. {
  155. HRESULT ret;
  156. ret = DIRECT3DDEVICEI::halCreateContext();
  157. if (ret != D3D_OK)
  158. return ret;
  159. this->lpDPPrimCounts = (LPD3DHAL_DRAWPRIMCOUNTS)this->lpwDPBuffer;
  160. memset( (char *)this->lpwDPBuffer, 0, sizeof(D3DHAL_DRAWPRIMCOUNTS));
  161. this->dwDPOffset = sizeof(D3DHAL_DRAWPRIMCOUNTS);
  162. this->dwDPMaxOffset = dwD3DTriBatchSize * sizeof(D3DTRIANGLE)-sizeof(D3DTLVERTEX);
  163. return (D3D_OK);
  164. }
  165. //---------------------------------------------------------------------
  166. #undef DPF_MODNAME
  167. #define DPF_MODNAME "FlushStatesDP"
  168. HRESULT
  169. CDirect3DDeviceIDP::FlushStates(bool bWithinPrimitive)
  170. {
  171. HRESULT dwRet=D3D_OK;
  172. if (this->dwDPOffset>sizeof(D3DHAL_DRAWPRIMCOUNTS))
  173. {
  174. ++m_qwBatch;
  175. // So that currently bound textures get rebatched
  176. for (DWORD dwStage = 0; dwStage < this->dwMaxTextureBlendStages; dwStage++)
  177. {
  178. LPDIRECT3DTEXTUREI lpTexI = this->lpD3DMappedTexI[dwStage];
  179. if (NULL != lpTexI)
  180. {
  181. if(lpTexI->lpDDS != NULL)
  182. {
  183. BatchTexture(((LPDDRAWI_DDRAWSURFACE_INT)(lpTexI->lpDDS))->lpLcl);
  184. }
  185. }
  186. }
  187. if ((dwRet=CheckSurfaces()) != D3D_OK)
  188. {
  189. this->dwDPOffset = sizeof(D3DHAL_DRAWPRIMCOUNTS);
  190. this->lpDPPrimCounts = (LPD3DHAL_DRAWPRIMCOUNTS)this->lpwDPBuffer;
  191. memset( (char *)this->lpwDPBuffer,0,sizeof(D3DHAL_DRAWPRIMCOUNTS)); //Clear header also
  192. if (dwRet == DDERR_SURFACELOST)
  193. {
  194. this->dwFEFlags |= D3DFE_LOSTSURFACES;
  195. return D3D_OK;
  196. }
  197. return dwRet;
  198. }
  199. D3DHAL_DRAWPRIMITIVESDATA dpData;
  200. DWORD dwDPOffset;
  201. if (this->lpDPPrimCounts->wNumVertices) //this->lpDPPrimCounts->wNumVertices==0 means the end
  202. { //force it if not
  203. memset(((LPBYTE)this->lpwDPBuffer+this->dwDPOffset),0,sizeof(D3DHAL_DRAWPRIMCOUNTS));
  204. }
  205. dpData.dwhContext = this->dwhContext;
  206. dpData.dwFlags = 0;
  207. dpData.lpvData = this->lpwDPBuffer;
  208. if (FVF_DRIVERSUPPORTED(this))
  209. dpData.dwFVFControl = this->dwCurrentBatchVID;
  210. else
  211. {
  212. if (this->dwDebugFlags & D3DDEBUG_DISABLEFVF)
  213. dpData.dwFVFControl = D3DFVF_TLVERTEX;
  214. else
  215. dpData.dwFVFControl = 0; //always zero for non-FVF drivers
  216. }
  217. dpData.ddrval = 0;
  218. dwDPOffset=this->dwDPOffset; //save it in case Flush returns prematurely
  219. #if 0
  220. if (D3DRENDERSTATE_TEXTUREHANDLE==*((DWORD*)this->lpwDPBuffer+2))
  221. DPF(0,"Flushing dwDPOffset=%08lx ddihandle=%08lx",dwDPOffset,*((DWORD*)this->lpwDPBuffer+3));
  222. #endif //0
  223. //we clear this to break re-entering as SW rasterizer needs to lock DDRAWSURFACE
  224. this->dwDPOffset = sizeof(D3DHAL_DRAWPRIMCOUNTS);
  225. // Spin waiting on the driver if wait requested
  226. #if _D3D_FORCEDOUBLE
  227. CD3DForceFPUDouble ForceFPUDouble(this);
  228. #endif //_D3D_FORCEDOUBLE
  229. do {
  230. #ifndef WIN95
  231. if((dwRet = CheckContextSurface(this)) != D3D_OK)
  232. {
  233. this->dwDPOffset = dwDPOffset;
  234. return (dwRet);
  235. }
  236. #endif //WIN95
  237. CALL_HAL2ONLY(dwRet, this, DrawPrimitives, &dpData);
  238. if (dwRet != DDHAL_DRIVER_HANDLED)
  239. {
  240. D3D_ERR ( "Driver call for DrawOnePrimitive failed" );
  241. // Need sensible return value in this case,
  242. // currently we return whatever the driver stuck in here.
  243. }
  244. } while (dpData.ddrval == DDERR_WASSTILLDRAWING);
  245. this->lpDPPrimCounts = (LPD3DHAL_DRAWPRIMCOUNTS)this->lpwDPBuffer;
  246. memset( (char *)this->lpwDPBuffer,0,sizeof(D3DHAL_DRAWPRIMCOUNTS)); //Clear header also
  247. dwRet= dpData.ddrval;
  248. this->dwCurrentBatchVID = this->dwVIDOut;
  249. }
  250. return dwRet;
  251. }
  252. //---------------------------------------------------------------------
  253. #undef DPF_MODNAME
  254. #define DPF_MODNAME "CDirect3DDeviceIDP::SetRenderStateI"
  255. HRESULT
  256. CDirect3DDeviceIDP::SetRenderStateI(D3DRENDERSTATETYPE dwStateType,
  257. DWORD value)
  258. {
  259. LPD3DHAL_DRAWPRIMCOUNTS lpPC;
  260. LPDWORD lpStateChange;
  261. HRESULT ret;
  262. // map WRAP0 into legacy renderstate
  263. if (D3DRENDERSTATE_WRAP0 == dwStateType)
  264. {
  265. BOOLEAN ustate = (value & D3DWRAP_U) ? TRUE : FALSE;
  266. BOOLEAN vstate = (value & D3DWRAP_V) ? TRUE : FALSE;
  267. SetRenderStateI(D3DRENDERSTATE_WRAPU, ustate);
  268. SetRenderStateI(D3DRENDERSTATE_WRAPV, vstate);
  269. return D3D_OK;
  270. }
  271. if (dwStateType > D3DRENDERSTATE_STIPPLEPATTERN31)
  272. {
  273. D3D_WARN(4,"Trying to send invalid state %d to legacy driver",dwStateType);
  274. return D3D_OK;
  275. }
  276. if (dwStateType > D3DRENDERSTATE_FLUSHBATCH && dwStateType < D3DRENDERSTATE_STIPPLEPATTERN00)
  277. {
  278. D3D_WARN(4,"Trying to send invalid state %d to legacy driver",dwStateType);
  279. return D3D_OK;
  280. }
  281. lpPC = this->lpDPPrimCounts;
  282. if (lpPC->wNumVertices) //Do we already have Vertices filled in for this count ?
  283. { //Yes, then Increment count
  284. lpPC=this->lpDPPrimCounts=(LPD3DHAL_DRAWPRIMCOUNTS)((LPBYTE)this->lpwDPBuffer+this->dwDPOffset);
  285. memset( (char *)lpPC,0,sizeof(D3DHAL_DRAWPRIMCOUNTS));
  286. this->dwDPOffset += sizeof(D3DHAL_DRAWPRIMCOUNTS);
  287. }
  288. if (this->dwDPOffset + 2*sizeof(DWORD) > this->dwDPMaxOffset )
  289. {
  290. CLockD3DST lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (ST only).
  291. ret = FlushStates();
  292. if (ret != D3D_OK)
  293. {
  294. D3D_ERR("Error trying to render batched commands in SetRenderStateI");
  295. return ret;
  296. }
  297. }
  298. lpStateChange=(LPDWORD)((char *)this->lpwDPBuffer + this->dwDPOffset);
  299. *lpStateChange=dwStateType;
  300. lpStateChange ++;
  301. *lpStateChange=value;
  302. this->lpDPPrimCounts->wNumStateChanges ++;
  303. this->dwDPOffset += 2*sizeof(DWORD);
  304. #if 0
  305. if (dwStateType == D3DRENDERSTATE_TEXTUREHANDLE && this->dwDPOffset== 0x10){
  306. DPF(0,"SRdwDPOffset=%08lx, dwStateType=%08lx value=%08lx ddihandle=%08lx lpStateChange=%08lx lpDPPrimCounts=%08lx",
  307. this->dwDPOffset,dwStateType,value,*lpStateChange,lpStateChange,this->lpDPPrimCounts);
  308. _asm int 3
  309. }
  310. #endif //0
  311. return D3D_OK;
  312. }
  313. #endif // WIN95