📄 texturedx8.cpp
字号:
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// The dx8 implementation of the texture allocation
//=============================================================================
#include "locald3dtypes.h"
#include "TextureDX8.h"
#include "ShaderAPIDX8_Global.h"
#include "ColorFormatDX8.h"
#include "IShaderUtil.h"
#include "materialsystem/IMaterialSystem.h"
#include "UtlVector.h"
#include "CMaterialSystemStats.h"
#include "recording.h"
#include "ShaderAPI.h"
#include "filesystem.h"
#include "locald3dtypes.h"
#include "tier0/memdbgon.h"
#ifdef _WIN32
#pragma warning (disable:4189 4701)
#endif
static int s_TextureCount = 0;
//-----------------------------------------------------------------------------
// Stats...
//-----------------------------------------------------------------------------
int TextureCount()
{
return s_TextureCount;
}
static HRESULT GetLevelDesc( IDirect3DBaseTexture* pBaseTexture, UINT level, D3DSURFACE_DESC* pDesc )
{
HRESULT hr;
switch( pBaseTexture->GetType() )
{
case D3DRTYPE_TEXTURE:
hr = ( ( IDirect3DTexture * )pBaseTexture )->GetLevelDesc( level, pDesc );
break;
case D3DRTYPE_CUBETEXTURE:
hr = ( ( IDirect3DCubeTexture * )pBaseTexture )->GetLevelDesc( level, pDesc );
break;
default:
return ( HRESULT )-1;
break;
}
return hr;
}
static HRESULT GetSurfaceFromTexture( IDirect3DBaseTexture* pBaseTexture, UINT level,
D3DCUBEMAP_FACES cubeFaceID, IDirect3DSurface** ppSurfLevel )
{
HRESULT hr;
switch( pBaseTexture->GetType() )
{
case D3DRTYPE_TEXTURE:
hr = ( ( IDirect3DTexture * )pBaseTexture )->GetSurfaceLevel( level, ppSurfLevel );
break;
case D3DRTYPE_CUBETEXTURE:
hr = ( ( IDirect3DCubeTexture * )pBaseTexture )->GetCubeMapSurface( cubeFaceID, level, ppSurfLevel );
break;
default:
return ( HRESULT )-1;
break;
}
return hr;
}
//-----------------------------------------------------------------------------
// Gets the image format of a texture
//-----------------------------------------------------------------------------
static ImageFormat GetImageFormat( IDirect3DBaseTexture* pTexture )
{
D3DSURFACE_DESC desc;
HRESULT hr = GetLevelDesc( pTexture, 0, &desc );
if (!FAILED(hr))
{
return D3DFormatToImageFormat( desc.Format );
}
// Bogus baby!
return (ImageFormat)-1;
}
//-----------------------------------------------------------------------------
// Allocates the D3DTexture
//-----------------------------------------------------------------------------
IDirect3DBaseTexture* CreateD3DTexture( int width, int height,
ImageFormat dstFormat, int numLevels, int creationFlags )
{
bool isCubeMap = (creationFlags & TEXTURE_CREATE_CUBEMAP) != 0;
bool isRenderTarget = (creationFlags & TEXTURE_CREATE_RENDERTARGET) != 0;
bool managed = (creationFlags & TEXTURE_CREATE_MANAGED) != 0;
bool isDepthBuffer = (creationFlags & TEXTURE_CREATE_DEPTHBUFFER) != 0;
bool isDynamic = (creationFlags & TEXTURE_CREATE_DYNAMIC) != 0;
bool bAutoMipMap = (creationFlags & TEXTURE_CREATE_AUTOMIPMAP) != 0;
// NOTE: This function shouldn't be used for creating depth buffers!
Assert( !isDepthBuffer );
D3DFORMAT d3dFormat;
// move this up a level?
if (!isRenderTarget)
d3dFormat = ImageFormatToD3DFormat( FindNearestSupportedFormat( dstFormat ) );
else
d3dFormat = ImageFormatToD3DFormat( FindNearestRenderTargetFormat( dstFormat) );
if ( d3dFormat == -1 )
{
Warning("ShaderAPIDX8::CreateD3DTexture: Invalid color format!\n");
return 0;
}
IDirect3DBaseTexture* pBaseTexture = NULL;
IDirect3DTexture* pD3DTexture = NULL;
IDirect3DCubeTexture* pD3DCubeTexture = NULL;
HRESULT hr;
DWORD usage = 0;
if( isRenderTarget )
{
usage |= D3DUSAGE_RENDERTARGET;
}
if ( isDynamic )
{
usage |= D3DUSAGE_DYNAMIC;
}
if( bAutoMipMap )
{
usage |= D3DUSAGE_AUTOGENMIPMAP;
}
if( isCubeMap )
{
hr = D3DDevice()->CreateCubeTexture(
width, numLevels, usage, d3dFormat, managed ? D3DPOOL_MANAGED : D3DPOOL_DEFAULT,
&pD3DCubeTexture,NULL
);
pBaseTexture = pD3DCubeTexture;
}
else
{
hr = D3DDevice()->CreateTexture( width, height, numLevels,
usage, d3dFormat, managed ? D3DPOOL_MANAGED : D3DPOOL_DEFAULT, &pD3DTexture,NULL
);
pBaseTexture = pD3DTexture;
}
if ( FAILED(hr) )
{
switch( hr )
{
case D3DERR_INVALIDCALL:
Warning( "ShaderAPIDX8::CreateD3DTexture: D3DERR_INVALIDCALL\n" );
break;
case D3DERR_OUTOFVIDEOMEMORY:
// This conditional is here so that we don't complain when testing
// how much video memory we have. . this is kinda gross.
if (managed)
Warning( "ShaderAPIDX8::CreateD3DTexture: D3DERR_OUTOFVIDEOMEMORY\n" );
break;
case E_OUTOFMEMORY:
Warning( "ShaderAPIDX8::CreateD3DTexture: E_OUTOFMEMORY\n" );
break;
default:
break;
}
return 0;
}
++s_TextureCount;
return pBaseTexture;
}
//-----------------------------------------------------------------------------
// Texture destruction
//-----------------------------------------------------------------------------
void DestroyD3DTexture( IDirect3DBaseTexture* pTex )
{
if (pTex)
{
int ref = pTex->Release();
Assert( ref == 0 );
--s_TextureCount;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pTex -
// Output : int
//-----------------------------------------------------------------------------
int GetD3DTextureRefCount( IDirect3DBaseTexture *pTex )
{
if ( !pTex )
return 0;
pTex->AddRef();
int ref = pTex->Release();
return ref;
}
//-----------------------------------------------------------------------------
// See version 13 for a function that converts a texture to a mipmap (ConvertToMipmap)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Lock, unlock a texture...
//-----------------------------------------------------------------------------
static RECT s_LockedSrcRect;
static D3DLOCKED_RECT s_LockedRect;
#ifdef _DEBUG
static bool s_bInLock = false;
#endif
bool LockTexture( int bindId, int copy, IDirect3DBaseTexture* pTexture, int level,
D3DCUBEMAP_FACES cubeFaceID, int xOffset, int yOffset, int width, int height,
CPixelWriter& writer )
{
Assert( !s_bInLock );
IDirect3DSurface* pSurf;
HRESULT hr = GetSurfaceFromTexture( pTexture, level, cubeFaceID, &pSurf );
if (FAILED(hr))
return false;
s_LockedSrcRect.left = xOffset;
s_LockedSrcRect.right = xOffset + width;
s_LockedSrcRect.top = yOffset;
s_LockedSrcRect.bottom = yOffset + height;
RECORD_COMMAND( DX8_LOCK_TEXTURE, 6 );
RECORD_INT( bindId );
RECORD_INT( copy );
RECORD_INT( level );
RECORD_INT( cubeFaceID );
RECORD_STRUCT( &s_LockedSrcRect, sizeof(s_LockedSrcRect) );
RECORD_INT( D3DLOCK_NOSYSLOCK );
hr = pSurf->LockRect( &s_LockedRect, &s_LockedSrcRect, D3DLOCK_NOSYSLOCK );
pSurf->Release();
if (FAILED(hr))
return false;
writer.SetPixelMemory( GetImageFormat(pTexture), s_LockedRect.pBits, s_LockedRect.Pitch );
MaterialSystemStats()->IncrementCountedStat(
MATERIAL_SYSTEM_STATS_TEXTURE_BYTES_DOWNLOADED,
ShaderUtil()->GetMemRequired( width, height, GetImageFormat(pTexture), false) );
MaterialSystemStats()->IncrementCountedStat(
MATERIAL_SYSTEM_STATS_TEXTURE_TEXELS_DOWNLOADED,
width * height );
MaterialSystemStats()->IncrementCountedStat(
MATERIAL_SYSTEM_STATS_TEXTURE_UPLOADS, 1 );
#ifdef _DEBUG
s_bInLock = true;
#endif
return true;
}
void UnlockTexture( int bindId, int copy, IDirect3DBaseTexture* pTexture, int level,
D3DCUBEMAP_FACES cubeFaceID )
{
Assert( s_bInLock );
IDirect3DSurface* pSurf;
HRESULT hr = GetSurfaceFromTexture( pTexture, level, cubeFaceID, &pSurf );
if (FAILED(hr))
return;
#ifdef RECORD_TEXTURES
int width = s_LockedSrcRect.right - s_LockedSrcRect.left;
int height = s_LockedSrcRect.bottom - s_LockedSrcRect.top;
int imageFormatSize = ImageLoader::SizeInBytes( GetImageFormat( pTexture ) );
Assert( imageFormatSize != 0 );
int validDataBytesPerRow = imageFormatSize * width;
int storeSize = validDataBytesPerRow * height;
static CUtlVector< unsigned char > tmpMem;
if( tmpMem.Size() < storeSize )
{
tmpMem.AddMultipleToTail( storeSize - tmpMem.Size() );
}
unsigned char *pDst = tmpMem.Base();
unsigned char *pSrc = ( unsigned char * )s_LockedRect.pBits;
RECORD_COMMAND( DX8_SET_TEXTURE_DATA, 3 );
RECORD_INT( validDataBytesPerRow );
RECORD_INT( height );
int i;
for( i = 0; i < height; i++ )
{
memcpy( pDst, pSrc, validDataBytesPerRow );
pDst += validDataBytesPerRow;
pSrc += s_LockedRect.Pitch;
}
RECORD_STRUCT( tmpMem.Base(), storeSize );
#endif // RECORD_TEXTURES
RECORD_COMMAND( DX8_UNLOCK_TEXTURE, 4 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -