//---------------------------------------------------------------------------- // // surfman.cpp // // Reference rasterizer callback functions for D3DIM. // // Copyright (C) Microsoft Corporation, 1997. // //---------------------------------------------------------------------------- #include "pch.cpp" #pragma hdrstop // Global Surface Manager, one per process RDSurfaceManager g_SurfMgr; /////////////////////////////////////////////////////////////////////////////// // // Helper functions // /////////////////////////////////////////////////////////////////////////////// HRESULT CreateAppropriateSurface( LPDDRAWI_DDRAWSURFACE_LCL pDDSLcl, DWORD* pHandle, RDSurface** ppSurf ) { HRESULT hr = S_OK; *ppSurf = NULL; *pHandle = 0; // Obtain the Handle DWORD dwHandle = pDDSLcl->lpSurfMore->dwSurfaceHandle; *pHandle = dwHandle; // Figure out if we care for this surface. Currently, // we care only for: // 1) Textures (MipMaps and Cubemaps) // 2) RenderTargets & DepthBuffers if( pDDSLcl->ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER | DDSCAPS_3DDEVICE) ) { RDSurface2D* pSurf2D = new RDSurface2D(); if( pSurf2D == NULL ) { DPFERR("New RDSurface2D failed, out of memory" ); return DDERR_OUTOFMEMORY; } *ppSurf = pSurf2D; } else if( pDDSLcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER ) { // Strictly speaking, RDVertexBuffer should be // called RDLinearBuffer (it could be vertex, index or command) // For the time being, there is no need to distinguish between // the three. There is not harm in recognizing it for the Index // and Command buffer case. In case in the future, we do need to // make a distinction between Vertex and Index buffers, we need // to make the following tests: // For VB: // (pDDSLcl->pDDSLcl->lpSurfMore->ddsCapsEx.dwCaps2 & // DDSCAPS2_VERTEXBUFFER)) // For IB: // (pDDSLcl->pDDSLcl->lpSurfMore->ddsCapsEx.dwCaps2 & // DDSCAPS2_INDEXBUFFER)) RDVertexBuffer* pVB = new RDVertexBuffer(); if( pVB == NULL ) { DPFERR("New RDVertexBuffer failed, out of memory" ); return DDERR_OUTOFMEMORY; } *ppSurf = pVB; } else { DPFM(2, DRV, ("RefCreateSurfaceEx w/o " "DDSCAPS_TEXTURE/3DDEVICE/ZBUFFER Ignored" "dwCaps=%08lx dwSurfaceHandle=%08lx", pDDSLcl->ddsCaps.dwCaps, pDDSLcl->lpSurfMore->dwSurfaceHandle)); return hr; } if( FAILED( hr = (*ppSurf)->Initialize( pDDSLcl ) ) ) { DPFERR( "Initialize failed" ); delete (*ppSurf); return hr; } return hr; } /////////////////////////////////////////////////////////////////////////////// // // RDVertexBuffer implementation // /////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- // RDVertexBuffer::Initialize // Initializer. //----------------------------------------------------------------------------- HRESULT RDVertexBuffer::Initialize( LPDDRAWI_DDRAWSURFACE_LCL pSLcl ) { HRESULT hr = S_OK; SetInitialized(); m_SurfType = RR_ST_VERTEXBUFFER; if( pSLcl->lpGbl->dwReserved1 ) { RDCREATESURFPRIVATE* pPriv = (RDCREATESURFPRIVATE *)pSLcl->lpGbl->dwReserved1; m_pBits = pPriv->pBits; m_cbSize = (int)pPriv->dwVBSize; SetRefCreated(); } else { m_pBits = (LPBYTE)SURFACE_MEMORY(pSLcl); m_cbSize = pSLcl->lpGbl->dwLinearSize; } return S_OK; } /////////////////////////////////////////////////////////////////////////////// // // RDSurfaceArrayNode implementation // /////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- // RDSurfaceArrayNode::RDSurfaceArrayNode // Constructor. //----------------------------------------------------------------------------- RDSurfaceArrayNode::RDSurfaceArrayNode(LPDDRAWI_DIRECTDRAW_LCL pDDLcl) : RDListEntry(), m_SurfHandleArray() { m_pDDLcl = pDDLcl; } //----------------------------------------------------------------------------- // RDSurfaceArrayNode::~RDSurfaceArrayNode // Destructor. //----------------------------------------------------------------------------- RDSurfaceArrayNode::~RDSurfaceArrayNode() { // Release all the allocated surfaces for( DWORD i=0; im_pDDLcl ) return pCurrNode; pCurrNode = pCurrNode->m_pNext; } // This means that we didnt find an existing node, create a // new one. RDSurfaceArrayNode* pTmpNode = m_pFirstNode; m_pFirstNode = new RDSurfaceArrayNode( pDDLcl ); if( m_pFirstNode == NULL ) { DPFERR("New Failed allocating a new RDSurfaceArrayNode\n"); m_pFirstNode = pTmpNode; return NULL; } m_pFirstNode->m_pNext = pTmpNode; return m_pFirstNode; } //----------------------------------------------------------------------------- // RDSurfaceManager::GetLclNode // Gets a node with the given DDLcl from the list if present. //----------------------------------------------------------------------------- RDSurfaceArrayNode* RDSurfaceManager::GetLclNode( LPDDRAWI_DIRECTDRAW_LCL pDDLcl ) { RDSurfaceArrayNode* pCurrNode = m_pFirstNode; while( pCurrNode ) { if( pDDLcl == pCurrNode->m_pDDLcl ) break; pCurrNode = pCurrNode->m_pNext; } return pCurrNode; } //----------------------------------------------------------------------------- // RDSurfaceManager::AddSurfToList // Adds a surface to the node with a matching DDLcl. If the node // is not present it is created. The ppSurf param can be NULL. //----------------------------------------------------------------------------- HRESULT RDSurfaceManager::AddSurfToList( LPDDRAWI_DIRECTDRAW_LCL pDDLcl, LPDDRAWI_DDRAWSURFACE_LCL pDDSLcl, RDSurface** ppSurf ) { HRESULT hr = S_OK; RDSurface* pSurf = NULL; RDSurfaceArrayNode* pCurrNode = AddLclNode( pDDLcl ); if( pCurrNode ) { hr = pCurrNode->AddSurface( pDDSLcl, &pSurf ); if( ppSurf ) *ppSurf = pSurf; return hr; } return DDERR_OUTOFMEMORY; } //----------------------------------------------------------------------------- // RDSurfaceManager::GetSurfFromList // Gets a surface with the matching handle from the node with a // matching DDLcl, if the node and the surface is present. //----------------------------------------------------------------------------- RDSurface* RDSurfaceManager::GetSurfFromList( LPDDRAWI_DIRECTDRAW_LCL pDDLcl, DWORD dwHandle ) { RDSurfaceArrayNode* pCurrNode = GetLclNode( pDDLcl ); if( pCurrNode ) return pCurrNode->GetSurface( dwHandle ); return NULL; } //----------------------------------------------------------------------------- // RDSurfaceManager::RemoveSurfFromList // Deletes the surface handle. //----------------------------------------------------------------------------- HRESULT RDSurfaceManager::RemoveSurfFromList( LPDDRAWI_DIRECTDRAW_LCL pDDLcl, DWORD dwHandle ) { RDSurfaceArrayNode* pCurrNode = GetLclNode( pDDLcl ); if( pCurrNode ) return pCurrNode->RemoveSurface( dwHandle ); DPFERR("The DrawLcl is unrecognized\n"); return DDERR_INVALIDPARAMS; } HRESULT RDSurfaceManager::RemoveSurfFromList( LPDDRAWI_DIRECTDRAW_LCL pDDLcl, LPDDRAWI_DDRAWSURFACE_LCL pDDSLcl ) { RDSurfaceArrayNode* pCurrNode = GetLclNode( pDDLcl ); if( pCurrNode ) return pCurrNode->RemoveSurface( pDDSLcl->lpSurfMore->dwSurfaceHandle ); DPFERR("The DrawLcl is unrecognized\n"); return DDERR_INVALIDPARAMS; }