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.
 
 
 
 
 
 

535 lines
18 KiB

/*==========================================================================;
*
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
*
* File: texture.c
* Content: Direct3DTexture interface
*@@BEGIN_MSINTERNAL
*
* $Id$
*
* History:
* Date By Reason
* ==== == ======
* 07/12/95 stevela Merged Colin's changes.
* 10/12/95 stevela Removed AGGREGATE_D3D
* 17/04/96 colinmc Bug 12185: Debug output too aggresive
* 30/04/96 stevela Bug 18898: Wrong error returned on invalid GetHandle
*@@END_MSINTERNAL
*
***************************************************************************/
#include "pch.cpp"
#pragma hdrstop
/*
* Create an api for the Direct3DTexture object
*/
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DTexture"
void D3DI_RemoveTextureHandle(LPD3DI_TEXTUREBLOCK lpBlock)
{
/* check if this block refers to a Texture/Texture2 - this
* needs to handle both texture types for device cleanup
*/
if (lpBlock->hTex)
{
D3DHAL_TextureDestroy(lpBlock);
}
}
DIRECT3DTEXTUREI::DIRECT3DTEXTUREI()
{
m_dwHeapIndex = 0;
m_bInUse = FALSE;
m_dwPriority = 0;
m_dwLOD = 0;
bDirty = FALSE;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTUREI::Initialize"
HRESULT DIRECT3DTEXTUREI::Initialize(LPDIRECT3DI lpDirect3DI, LPDIRECTDRAWSURFACE7 pDDS)
{
LIST_INITIALIZE(&blocks);
this->DDS1Tex.lpVtbl = ((LPDDRAWI_DIRECTDRAW_INT)(lpDirect3DI->lpDD7))->lpLcl->pddSurfaceCallbacks;
this->DDS1Tex.lpLcl = ((LPDDRAWI_DDRAWSURFACE_INT)pDDS)->lpLcl;
this->DDS1Tex.lpLink = NULL;
this->DDS1Tex.dwIntRefCnt = 1;
this->lpDDS = pDDS;
this->lpDDSSys = NULL;
this->m_hTex = ((LPDDRAWI_DDRAWSURFACE_INT)pDDS)->lpLcl->lpSurfMore->dwSurfaceHandle;
this->lpDirect3DI = lpDirect3DI;
this->lpDirect3DI->AddRef(); // Since we hold a pointer to D3DI
// Hook texture into the list
LIST_INSERT_ROOT(&this->lpDirect3DI->textures, this, m_List);
return D3D_OK;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTUREI::Destroy"
void DIRECT3DTEXTUREI::Destroy()
{
// lpDDS or lpDDSSys need to remain alive during the while loop
while (LIST_FIRST(&this->blocks))
{
LPD3DI_TEXTUREBLOCK tBlock = LIST_FIRST(&this->blocks);
D3DI_RemoveTextureHandle(tBlock);
// Remove from device
LIST_DELETE(tBlock, devList);
// Remove from texture
LIST_DELETE(tBlock, list);
D3DFree(tBlock);
}
LIST_DELETE(this, m_List); // Remove ourself from the texture chain
lpDirect3DI->Release(); // Remove the Addref from Create
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTURED3DM::Initialize"
HRESULT DIRECT3DTEXTURED3DM::Initialize(LPDIRECT3DI lpDirect3DI, LPDIRECTDRAWSURFACE7 pDDS)
{
HRESULT ddrval = DIRECT3DTEXTUREI::Initialize(lpDirect3DI, pDDS);
if(ddrval != D3D_OK)
return ddrval;
memset(&this->ddsd, 0, sizeof(DDSURFACEDESC2));
this->ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddrval = pDDS->GetSurfaceDesc(&this->ddsd);
if(ddrval != DD_OK)
{
D3D_ERR("Failed to get surface descriptor for texture");
return ddrval;
}
this->ddsd.dwFlags &= ~DDSD_PITCH; // DDRAW always give that, but we don't want
if(this->ddsd.ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM)
{
this->ddsd.ddsCaps.dwCaps &= ~DDSCAPS_NONLOCALVIDMEM;
this->ddsd.ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
}
else
{
this->ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
this->ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
}
this->ddsd.ddsCaps.dwCaps2 &= ~(DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE);
this->ddsd.ddsCaps.dwCaps2 |= DDSCAPS2_DONOTCREATED3DTEXOBJECT;
if(((LPDDRAWI_DIRECTDRAW_INT)(lpDirect3DI->lpDD7))->lpLcl->lpGbl->lpD3DGlobalDriverData)
{
if(!(((LPDDRAWI_DIRECTDRAW_INT)(lpDirect3DI->lpDD7))->lpLcl->lpGbl->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) ||
!(this->ddsd.dwFlags & DDSD_TEXTURESTAGE) ||
(((LPDDRAWI_DIRECTDRAW_INT)(lpDirect3DI->lpDD7))->lpLcl->lpGbl->lpD3DExtendedCaps->wMaxSimultaneousTextures < 2))
this->ddsd.dwTextureStage = 0;
}
else
{
this->ddsd.dwTextureStage = 0;
}
this->lpDDSSys = pDDS;
this->lpDDS = NULL;
this->m_hTex = 0;
this->m_dwBytes = 0;
this->m_dwVidBytes = 0;
// Next, we need to loop thru and set pointers to the dirty
// bit in the DDraw surfaces
for(CCubemapIter cmit(((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSSys)->lpLcl); cmit != 0; ++cmit)
{
// Set the faces bit so that when the cubemap is eventually created in vidmem, it will get all faces
this->ddsd.ddsCaps.dwCaps2 |= (cmit()->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES);
for(CMipmapIter mmit(cmit()); mmit != 0; ++mmit)
{
mmit()->lpSurfMore->lpbDirty = &(this->bDirty);
if(this->ddsd.dwFlags & DDSD_LINEARSIZE)
m_dwBytes += mmit()->lpGbl->dwLinearSize;
else
m_dwBytes += mmit()->lpGbl->lPitch * mmit()->lpGbl->wHeight;
}
}
#if COLLECTSTATS
this->lpDirect3DI->lpTextureManager->IncTotSz(m_dwBytes);
#endif
return D3D_OK;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTURED3DM::Destroy"
void DIRECT3DTEXTURED3DM::Destroy()
{
DIRECT3DTEXTUREI::Destroy();
if(InVidmem())
{
this->lpDirect3DI->lpTextureManager->RemoveFromHeap(this);
this->lpDirect3DI->lpTextureManager->remove(this);
}
#if COLLECTSTATS
this->lpDirect3DI->lpTextureManager->DecTotSz(m_dwBytes);
#endif
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTUREI::SetPriority"
HRESULT DIRECT3DTEXTUREI::SetPriority(DWORD dwPriority)
{
D3D_ERR( "SetPriority called on unmanaged texture." );
return DDERR_INVALIDPARAMS;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTUREI::GetPriority"
HRESULT DIRECT3DTEXTUREI::GetPriority(LPDWORD lpdwPriority)
{
D3D_ERR( "GetPriority called on unmanaged texture." );
return DDERR_INVALIDPARAMS;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTUREI::SetLOD"
HRESULT DIRECT3DTEXTUREI::SetLOD(DWORD dwLOD)
{
D3D_ERR( "SetLOD called on unmanaged texture." );
return DDERR_INVALIDPARAMS;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTUREI::GetLOD"
HRESULT DIRECT3DTEXTUREI::GetLOD(LPDWORD lpdwLOD)
{
D3D_ERR( "GetLOD called on unmanaged texture." );
return DDERR_INVALIDPARAMS;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTUREM::SetPriority"
HRESULT DIRECT3DTEXTUREM::SetPriority(DWORD dwPriority)
{
try
{
m_dwPriority = dwPriority;
// Look for a hardware device
LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&this->lpDirect3DI->devices);
if(lpDevI == NULL)
{
D3D_WARN(0, "SetPriority called before D3D device was created.");
}
while (lpDevI)
{
if (lpDevI->dwFEFlags & D3DFE_REALHAL)
{
if(this->lpDirect3DI->numDevs > 1)
{
D3D_WARN(2, "Multiple devices used. Calling Flush");
HRESULT hr = this->lpDirect3DI->FlushDevicesExcept(lpDevI); // to avoid sync problems
if(hr != D3D_OK)
{
DPF_ERR("Error flushing devices in SetPriority");
return hr;
}
}
DDASSERT(IS_DX7HAL_DEVICE(lpDevI));
HRESULT hr = static_cast<CDirect3DDevice7*>(lpDevI)->SetPriorityI(((LPDDRAWI_DDRAWSURFACE_INT)(this->lpDDS))->lpLcl, m_dwPriority);
if(hr != D3D_OK)
{
DPF_ERR("Error inserting SetPriority instruction in batch");
return hr;
}
if(this->lpDirect3DI->numDevs > 1)
{
hr = lpDevI->FlushStates(); // to avoid sync problems
if(hr != D3D_OK)
{
DPF_ERR("Error flushing device in SetPriority");
}
}
else
{
// This will ensure that the SetPriority gets to the driver before
// Blting or Locking the (texture) surface. Not sure that this is
// necessary.
lpDevI->BatchTexture(((LPDDRAWI_DDRAWSURFACE_INT)(this->lpDDS))->lpLcl);
}
return hr;
}
lpDevI = LIST_NEXT(lpDevI,list);
}
return D3D_OK;
}
catch (HRESULT ret)
{
return ret;
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTUREM::GetPriority"
HRESULT DIRECT3DTEXTUREM::GetPriority(LPDWORD lpdwPriority)
{
*lpdwPriority = m_dwPriority;
return D3D_OK;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTURED3DM::SetPriority"
HRESULT DIRECT3DTEXTURED3DM::SetPriority(DWORD dwPriority)
{
m_dwPriority = dwPriority;
lpDirect3DI->lpTextureManager->UpdatePriority(this);
return D3D_OK;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTUREM::GetLOD"
HRESULT DIRECT3DTEXTUREM::GetLOD(LPDWORD lpdwLOD)
{
*lpdwLOD = m_dwLOD;
return D3D_OK;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTUREM::SetLOD"
HRESULT DIRECT3DTEXTUREM::SetLOD(DWORD dwLOD)
{
try
{
if(dwLOD >= ((LPDDRAWI_DDRAWSURFACE_INT)(this->lpDDS))->lpLcl->lpSurfMore->dwMipMapCount)
{
D3D_ERR( "Texture has insufficient mipmap levels for this LOD" );
return DDERR_INVALIDPARAMS;
}
m_dwLOD = dwLOD;
// Look for a hardware device
LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&this->lpDirect3DI->devices);
if(lpDevI == NULL)
{
D3D_WARN(0, "SetLOD called before D3D device was created.");
}
while (lpDevI)
{
if (lpDevI->dwFEFlags & D3DFE_REALHAL)
{
if(this->lpDirect3DI->numDevs > 1)
{
D3D_WARN(2, "Multiple devices used. Calling Flush");
HRESULT hr = this->lpDirect3DI->FlushDevicesExcept(lpDevI); // to avoid sync problems
if(hr != D3D_OK)
{
DPF_ERR("Error flushing devices in SetLOD");
return hr;
}
}
DDASSERT(IS_DX7HAL_DEVICE(lpDevI));
HRESULT hr = static_cast<CDirect3DDevice7*>(lpDevI)->SetTexLODI(((LPDDRAWI_DDRAWSURFACE_INT)(this->lpDDS))->lpLcl, m_dwLOD);
if(hr != D3D_OK)
{
DPF_ERR("Error inserting SetTexLODI instruction in batch");
return hr;
}
if(this->lpDirect3DI->numDevs > 1)
{
hr = lpDevI->FlushStates(); // to avoid sync problems
if(hr != D3D_OK)
{
DPF_ERR("Error flushing device in SetLODI");
}
}
else
{
// This will ensure that the SetTexLODI gets to the driver before
// Blting or Locking the (texture) surface. Not sure that this is
// necessary.
lpDevI->BatchTexture(((LPDDRAWI_DDRAWSURFACE_INT)(this->lpDDS))->lpLcl);
}
return hr;
}
lpDevI = LIST_NEXT(lpDevI,list);
}
return D3D_OK;
}
catch (HRESULT ret)
{
return ret;
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTURED3DM::SetLOD"
HRESULT DIRECT3DTEXTURED3DM::SetLOD(DWORD dwLOD)
{
if(dwLOD >= ((LPDDRAWI_DDRAWSURFACE_INT)(this->lpDDSSys))->lpLcl->lpSurfMore->dwMipMapCount)
{
D3D_ERR( "Texture has insufficient mipmap levels for this LOD" );
return DDERR_INVALIDPARAMS;
}
if(m_dwLOD != dwLOD)
{
m_dwLOD = dwLOD;
this->ddsd.dwWidth = ((LPDDRAWI_DDRAWSURFACE_INT)(this->lpDDSSys))->lpLcl->lpGbl->wWidth >> m_dwLOD;
if(this->ddsd.dwWidth == 0)
this->ddsd.dwWidth = 1;
this->ddsd.dwHeight = ((LPDDRAWI_DDRAWSURFACE_INT)(this->lpDDSSys))->lpLcl->lpGbl->wHeight >> m_dwLOD;
if(this->ddsd.dwHeight == 0)
this->ddsd.dwHeight = 1;
this->ddsd.dwMipMapCount = ((LPDDRAWI_DDRAWSURFACE_INT)(this->lpDDSSys))->lpLcl->lpSurfMore->dwMipMapCount - m_dwLOD;
if(InVidmem())
{
this->lpDirect3DI->lpTextureManager->RemoveFromHeap(this);
this->lpDirect3DI->lpTextureManager->remove(this);
}
D3DTextureUpdate(static_cast<LPUNKNOWN>(&(this->lpDirect3DI->mD3DUnk)));
}
return D3D_OK;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DTEXTURED3DM::MarkDirtyPointers"
void DIRECT3DTEXTURED3DM::MarkDirtyPointers()
{
// We need to loop thru and set pointers to the dirty
// bit in the DDraw surfaces. The dirty bit will be
// used to properly update vidmem copies after they
// have been lost and restored.
CCubemapIter cmsysmem(((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSSys)->lpLcl);
CCubemapIter cmvidmem(((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDS)->lpLcl);
m_dwVidBytes = 0;
do
{
CMipmapIter mmsysmem(cmsysmem()), mmvidmem(cmvidmem());
do
{
mmvidmem()->lpSurfMore->lpbDirty = &(this->bDirty);
mmvidmem()->lpSurfMore->lpRegionList = mmsysmem()->lpSurfMore->lpRegionList;
// Mark everything dirty since we are going to copy into this surface
// from sysmem
mmvidmem()->lpSurfMore->lpRegionList->rdh.nCount = NUM_RECTS_IN_REGIONLIST;
if(this->ddsd.dwFlags & DDSD_LINEARSIZE)
m_dwVidBytes += mmvidmem()->lpGbl->dwLinearSize;
else
m_dwVidBytes += mmvidmem()->lpGbl->lPitch * mmvidmem()->lpGbl->wHeight;
++mmvidmem;
++mmsysmem;
}
while(mmsysmem != 0 && mmvidmem != 0);
++cmvidmem;
++cmsysmem;
}
while(cmsysmem != 0);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CreateTexture"
extern "C" HRESULT WINAPI CreateTexture(LPDIRECTDRAWSURFACE7 pDDS)
{
LPDIRECT3DTEXTUREI pTex;
LPDDRAWI_DDRAWSURFACE_LCL pLcl = ((LPDDRAWI_DDRAWSURFACE_INT)pDDS)->lpLcl;
// Should this texture be managed by D3D?
if(((DDSCAPS2_TEXTUREMANAGE & pLcl->lpSurfMore->ddsCapsEx.dwCaps2) && !(DDCAPS2_CANMANAGETEXTURE & pLcl->lpSurfMore->lpDD_lcl->lpGbl->ddCaps.dwCaps2))
|| (DDSCAPS2_D3DTEXTUREMANAGE & pLcl->lpSurfMore->ddsCapsEx.dwCaps2))
{
pTex = static_cast<LPDIRECT3DTEXTUREI>(new DIRECT3DTEXTURED3DM);
}
// Should this texture be managed by the driver?
else if((DDSCAPS2_TEXTUREMANAGE & pLcl->lpSurfMore->ddsCapsEx.dwCaps2) && (DDCAPS2_CANMANAGETEXTURE & pLcl->lpSurfMore->lpDD_lcl->lpGbl->ddCaps.dwCaps2))
{
pTex = static_cast<LPDIRECT3DTEXTUREI>(new DIRECT3DTEXTUREM);
}
// This texture is unmanaged
else
{
pTex = static_cast<LPDIRECT3DTEXTUREI>(new DIRECT3DTEXTUREI);
}
if (!pTex)
{
D3D_ERR("failed to allocate space for texture object");
return (DDERR_OUTOFMEMORY);
}
LPDIRECT3DI lpD3D = static_cast<CDirect3DUnk*>(pLcl->lpSurfMore->lpDD_lcl->pD3DIUnknown)->pD3DI;
DDASSERT(lpD3D);
HRESULT ddrval = pTex->Initialize(lpD3D, pDDS);
if(ddrval != D3D_OK)
{
D3D_ERR("Failed to initialize texture.");
delete pTex;
return ddrval;
}
pLcl->lpSurfMore->lpTex = reinterpret_cast<LPVOID>(pTex);
#if COLLECTSTATS
pTex->lpDirect3DI->IncNumTexCreates();
#endif
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DestroyTexture"
extern "C" void WINAPI DestroyTexture(LPVOID pTex)
{
D3D_INFO(3, "Destroying D3D texture");
LPDIRECT3DTEXTUREI lpTexI = reinterpret_cast<LPDIRECT3DTEXTUREI>(pTex);
#if COLLECTSTATS
lpTexI->lpDirect3DI->IncNumTexDestroys();
#endif
lpTexI->Destroy();
delete lpTexI;
}
#undef DPF_MODNAME
#define DPF_MODNAME "SetPriority"
extern "C" HRESULT WINAPI SetPriority(LPVOID lpTexI, DWORD dwPriority)
{
#if COLLECTSTATS
reinterpret_cast<LPDIRECT3DTEXTUREI>(lpTexI)->lpDirect3DI->IncNumSetPris();
#endif
return reinterpret_cast<LPDIRECT3DTEXTUREI>(lpTexI)->SetPriority(dwPriority);
}
#undef DPF_MODNAME
#define DPF_MODNAME "GetPriority"
extern "C" HRESULT WINAPI GetPriority(LPVOID lpTexI, LPDWORD lpdwPriority)
{
return reinterpret_cast<LPDIRECT3DTEXTUREI>(lpTexI)->GetPriority(lpdwPriority);
}
#undef DPF_MODNAME
#define DPF_MODNAME "SetLOD"
extern "C" HRESULT WINAPI SetLOD(LPVOID lpTexI, DWORD dwLOD)
{
#if COLLECTSTATS
reinterpret_cast<LPDIRECT3DTEXTUREI>(lpTexI)->lpDirect3DI->IncNumSetLODs();
#endif
return reinterpret_cast<LPDIRECT3DTEXTUREI>(lpTexI)->SetLOD(dwLOD);
}
#undef DPF_MODNAME
#define DPF_MODNAME "GetLOD"
extern "C" HRESULT WINAPI GetLOD(LPVOID lpTexI, LPDWORD lpdwLOD)
{
return reinterpret_cast<LPDIRECT3DTEXTUREI>(lpTexI)->GetLOD(lpdwLOD);
}