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.

356 lines
11 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // surfman.cpp
  4. //
  5. // Reference rasterizer callback functions for D3DIM.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. // Global Surface Manager, one per process
  13. RDSurfaceManager g_SurfMgr;
  14. ///////////////////////////////////////////////////////////////////////////////
  15. //
  16. // Helper functions
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. HRESULT
  20. CreateAppropriateSurface( LPDDRAWI_DDRAWSURFACE_LCL pDDSLcl,
  21. DWORD* pHandle,
  22. RDSurface** ppSurf )
  23. {
  24. HRESULT hr = S_OK;
  25. *ppSurf = NULL;
  26. *pHandle = 0;
  27. // Obtain the Handle
  28. DWORD dwHandle = pDDSLcl->lpSurfMore->dwSurfaceHandle;
  29. *pHandle = dwHandle;
  30. // Figure out if we care for this surface. Currently,
  31. // we care only for:
  32. // 1) Textures (MipMaps and Cubemaps)
  33. // 2) RenderTargets & DepthBuffers
  34. if( pDDSLcl->ddsCaps.dwCaps &
  35. (DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER | DDSCAPS_3DDEVICE) )
  36. {
  37. RDSurface2D* pSurf2D = new RDSurface2D();
  38. if( pSurf2D == NULL )
  39. {
  40. DPFERR("New RDSurface2D failed, out of memory" );
  41. return DDERR_OUTOFMEMORY;
  42. }
  43. *ppSurf = pSurf2D;
  44. }
  45. else if( pDDSLcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  46. {
  47. // Strictly speaking, RDVertexBuffer should be
  48. // called RDLinearBuffer (it could be vertex, index or command)
  49. // For the time being, there is no need to distinguish between
  50. // the three. There is not harm in recognizing it for the Index
  51. // and Command buffer case. In case in the future, we do need to
  52. // make a distinction between Vertex and Index buffers, we need
  53. // to make the following tests:
  54. // For VB:
  55. // (pDDSLcl->pDDSLcl->lpSurfMore->ddsCapsEx.dwCaps2 &
  56. // DDSCAPS2_VERTEXBUFFER))
  57. // For IB:
  58. // (pDDSLcl->pDDSLcl->lpSurfMore->ddsCapsEx.dwCaps2 &
  59. // DDSCAPS2_INDEXBUFFER))
  60. RDVertexBuffer* pVB = new RDVertexBuffer();
  61. if( pVB == NULL )
  62. {
  63. DPFERR("New RDVertexBuffer failed, out of memory" );
  64. return DDERR_OUTOFMEMORY;
  65. }
  66. *ppSurf = pVB;
  67. }
  68. else
  69. {
  70. DPFM(2, DRV, ("RefCreateSurfaceEx w/o "
  71. "DDSCAPS_TEXTURE/3DDEVICE/ZBUFFER Ignored"
  72. "dwCaps=%08lx dwSurfaceHandle=%08lx",
  73. pDDSLcl->ddsCaps.dwCaps,
  74. pDDSLcl->lpSurfMore->dwSurfaceHandle));
  75. return hr;
  76. }
  77. if( FAILED( hr = (*ppSurf)->Initialize( pDDSLcl ) ) )
  78. {
  79. DPFERR( "Initialize failed" );
  80. delete (*ppSurf);
  81. return hr;
  82. }
  83. return hr;
  84. }
  85. ///////////////////////////////////////////////////////////////////////////////
  86. //
  87. // RDVertexBuffer implementation
  88. //
  89. ///////////////////////////////////////////////////////////////////////////////
  90. //-----------------------------------------------------------------------------
  91. // RDVertexBuffer::Initialize
  92. // Initializer.
  93. //-----------------------------------------------------------------------------
  94. HRESULT
  95. RDVertexBuffer::Initialize( LPDDRAWI_DDRAWSURFACE_LCL pSLcl )
  96. {
  97. HRESULT hr = S_OK;
  98. SetInitialized();
  99. m_SurfType = RR_ST_VERTEXBUFFER;
  100. if( pSLcl->lpGbl->dwReserved1 )
  101. {
  102. RDCREATESURFPRIVATE* pPriv =
  103. (RDCREATESURFPRIVATE *)pSLcl->lpGbl->dwReserved1;
  104. m_pBits = pPriv->pBits;
  105. m_cbSize = (int)pPriv->dwVBSize;
  106. SetRefCreated();
  107. }
  108. else
  109. {
  110. m_pBits = (LPBYTE)SURFACE_MEMORY(pSLcl);
  111. m_cbSize = pSLcl->lpGbl->dwLinearSize;
  112. }
  113. return S_OK;
  114. }
  115. ///////////////////////////////////////////////////////////////////////////////
  116. //
  117. // RDSurfaceArrayNode implementation
  118. //
  119. ///////////////////////////////////////////////////////////////////////////////
  120. //-----------------------------------------------------------------------------
  121. // RDSurfaceArrayNode::RDSurfaceArrayNode
  122. // Constructor.
  123. //-----------------------------------------------------------------------------
  124. RDSurfaceArrayNode::RDSurfaceArrayNode(LPDDRAWI_DIRECTDRAW_LCL pDDLcl)
  125. : RDListEntry(), m_SurfHandleArray()
  126. {
  127. m_pDDLcl = pDDLcl;
  128. }
  129. //-----------------------------------------------------------------------------
  130. // RDSurfaceArrayNode::~RDSurfaceArrayNode
  131. // Destructor.
  132. //-----------------------------------------------------------------------------
  133. RDSurfaceArrayNode::~RDSurfaceArrayNode()
  134. {
  135. // Release all the allocated surfaces
  136. for( DWORD i=0; i<m_SurfHandleArray.GetSize(); i++ )
  137. {
  138. delete m_SurfHandleArray[i].m_pSurf;
  139. }
  140. }
  141. //-----------------------------------------------------------------------------
  142. // RDSurfaceArrayNode::AddSurface
  143. // Adds a surface to its internal growable array if not already
  144. // present. ppSurf can be NULL.
  145. //-----------------------------------------------------------------------------
  146. HRESULT
  147. RDSurfaceArrayNode::AddSurface( LPDDRAWI_DDRAWSURFACE_LCL pDDSLcl,
  148. RDSurface** ppSurf )
  149. {
  150. DWORD dwHandle = 0;
  151. HRESULT hr = S_OK;
  152. RDSurface* pSurf = NULL;
  153. if( FAILED(hr = CreateAppropriateSurface( pDDSLcl, &dwHandle, &pSurf ) ) )
  154. {
  155. return hr;
  156. }
  157. // If it is zero, there was something wrong
  158. if( pSurf == NULL || dwHandle == 0 ) return E_FAIL;
  159. hr = m_SurfHandleArray.Grow( dwHandle );
  160. if (FAILED(hr))
  161. {
  162. return hr;
  163. }
  164. if( m_SurfHandleArray[dwHandle].m_pSurf )
  165. {
  166. #if DBG
  167. _ASSERT( m_SurfHandleArray[dwHandle].m_tag,
  168. "A surface is associated with this handle even though it was never initialized!" );
  169. #endif
  170. delete m_SurfHandleArray[dwHandle].m_pSurf;
  171. }
  172. m_SurfHandleArray[dwHandle].m_pSurf = pSurf;
  173. #if DBG
  174. m_SurfHandleArray[dwHandle].m_tag = 1;
  175. #endif
  176. if( ppSurf ) *ppSurf = pSurf;
  177. return S_OK;
  178. }
  179. //-----------------------------------------------------------------------------
  180. // RDSurfaceArrayNode::GetSurface
  181. // Gets a surface from its internal array if present.
  182. //-----------------------------------------------------------------------------
  183. RDSurface*
  184. RDSurfaceArrayNode::GetSurface( DWORD dwHandle )
  185. {
  186. if( m_SurfHandleArray.IsValidIndex( dwHandle ) )
  187. return m_SurfHandleArray[dwHandle].m_pSurf;
  188. return NULL;
  189. }
  190. //-----------------------------------------------------------------------------
  191. // RDSurfaceArrayNode::RemoveSurface
  192. // Removed the surface with the given handle from the list.
  193. //-----------------------------------------------------------------------------
  194. HRESULT
  195. RDSurfaceArrayNode::RemoveSurface( DWORD dwHandle )
  196. {
  197. if( m_SurfHandleArray.IsValidIndex( dwHandle ) &&
  198. m_SurfHandleArray[dwHandle].m_pSurf )
  199. {
  200. delete m_SurfHandleArray[dwHandle].m_pSurf;
  201. m_SurfHandleArray[dwHandle].m_pSurf = NULL;
  202. return S_OK;
  203. }
  204. DPFERR( "Bad handle passed for delete" );
  205. return DDERR_INVALIDPARAMS;
  206. }
  207. ///////////////////////////////////////////////////////////////////////////////
  208. //
  209. // RDSurfaceManager implementation
  210. //
  211. ///////////////////////////////////////////////////////////////////////////////
  212. //-----------------------------------------------------------------------------
  213. // RDSurfaceManager::AddLclNode
  214. // Adds a node with the given DDLcl to the list if not already
  215. // present.
  216. //-----------------------------------------------------------------------------
  217. RDSurfaceArrayNode*
  218. RDSurfaceManager::AddLclNode( LPDDRAWI_DIRECTDRAW_LCL pDDLcl )
  219. {
  220. RDSurfaceArrayNode* pCurrNode = m_pFirstNode;
  221. while( pCurrNode )
  222. {
  223. if( pDDLcl == pCurrNode->m_pDDLcl ) return pCurrNode;
  224. pCurrNode = pCurrNode->m_pNext;
  225. }
  226. // This means that we didnt find an existing node, create a
  227. // new one.
  228. RDSurfaceArrayNode* pTmpNode = m_pFirstNode;
  229. m_pFirstNode = new RDSurfaceArrayNode( pDDLcl );
  230. if( m_pFirstNode == NULL )
  231. {
  232. DPFERR("New Failed allocating a new RDSurfaceArrayNode\n");
  233. m_pFirstNode = pTmpNode;
  234. return NULL;
  235. }
  236. m_pFirstNode->m_pNext = pTmpNode;
  237. return m_pFirstNode;
  238. }
  239. //-----------------------------------------------------------------------------
  240. // RDSurfaceManager::GetLclNode
  241. // Gets a node with the given DDLcl from the list if present.
  242. //-----------------------------------------------------------------------------
  243. RDSurfaceArrayNode*
  244. RDSurfaceManager::GetLclNode( LPDDRAWI_DIRECTDRAW_LCL pDDLcl )
  245. {
  246. RDSurfaceArrayNode* pCurrNode = m_pFirstNode;
  247. while( pCurrNode )
  248. {
  249. if( pDDLcl == pCurrNode->m_pDDLcl ) break;
  250. pCurrNode = pCurrNode->m_pNext;
  251. }
  252. return pCurrNode;
  253. }
  254. //-----------------------------------------------------------------------------
  255. // RDSurfaceManager::AddSurfToList
  256. // Adds a surface to the node with a matching DDLcl. If the node
  257. // is not present it is created. The ppSurf param can be NULL.
  258. //-----------------------------------------------------------------------------
  259. HRESULT
  260. RDSurfaceManager::AddSurfToList( LPDDRAWI_DIRECTDRAW_LCL pDDLcl,
  261. LPDDRAWI_DDRAWSURFACE_LCL pDDSLcl,
  262. RDSurface** ppSurf )
  263. {
  264. HRESULT hr = S_OK;
  265. RDSurface* pSurf = NULL;
  266. RDSurfaceArrayNode* pCurrNode = AddLclNode( pDDLcl );
  267. if( pCurrNode )
  268. {
  269. hr = pCurrNode->AddSurface( pDDSLcl, &pSurf );
  270. if( ppSurf ) *ppSurf = pSurf;
  271. return hr;
  272. }
  273. return DDERR_OUTOFMEMORY;
  274. }
  275. //-----------------------------------------------------------------------------
  276. // RDSurfaceManager::GetSurfFromList
  277. // Gets a surface with the matching handle from the node with a
  278. // matching DDLcl, if the node and the surface is present.
  279. //-----------------------------------------------------------------------------
  280. RDSurface*
  281. RDSurfaceManager::GetSurfFromList( LPDDRAWI_DIRECTDRAW_LCL pDDLcl,
  282. DWORD dwHandle )
  283. {
  284. RDSurfaceArrayNode* pCurrNode = GetLclNode( pDDLcl );
  285. if( pCurrNode ) return pCurrNode->GetSurface( dwHandle );
  286. return NULL;
  287. }
  288. //-----------------------------------------------------------------------------
  289. // RDSurfaceManager::RemoveSurfFromList
  290. // Deletes the surface handle.
  291. //-----------------------------------------------------------------------------
  292. HRESULT
  293. RDSurfaceManager::RemoveSurfFromList( LPDDRAWI_DIRECTDRAW_LCL pDDLcl,
  294. DWORD dwHandle )
  295. {
  296. RDSurfaceArrayNode* pCurrNode = GetLclNode( pDDLcl );
  297. if( pCurrNode ) return pCurrNode->RemoveSurface( dwHandle );
  298. DPFERR("The DrawLcl is unrecognized\n");
  299. return DDERR_INVALIDPARAMS;
  300. }
  301. HRESULT
  302. RDSurfaceManager::RemoveSurfFromList( LPDDRAWI_DIRECTDRAW_LCL pDDLcl,
  303. LPDDRAWI_DDRAWSURFACE_LCL pDDSLcl )
  304. {
  305. RDSurfaceArrayNode* pCurrNode = GetLclNode( pDDLcl );
  306. if( pCurrNode ) return pCurrNode->RemoveSurface(
  307. pDDSLcl->lpSurfMore->dwSurfaceHandle );
  308. DPFERR("The DrawLcl is unrecognized\n");
  309. return DDERR_INVALIDPARAMS;
  310. }