gstexture.cpp

来自「网络泡泡被.net管理」· C++ 代码 · 共 1,490 行 · 第 1/3 页

CPP
1,490
字号
// GsTexture.cpp: implementation of the CGsTexture class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "GSLib_Internal.h"
#include "gif89a.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CGsTexture::CGsTexture(CGsEngine* pEngine) : CGsSurface( pEngine )
{
	m_nUser		= 1;
	m_keySource	= "";
	m_BasePoint	= GPOINT(0,0);
	m_dwNumMipMaps	= 0;
	m_width		= 0;
	m_height	= 0;

	m_dxsf		= D3DX_SF_A8R8G8B8;

	m_isTexture	= TRUE;

	m_cache_memory	= NULL;
	m_link_cache_gif	= NULL;
	m_mode_cache	= 0;
	m_cache_pos			= 0;
	m_cache_fft			= GSF_UNKNOWN;

}

CGsTexture::~CGsTexture()
{
	Cleanup();
}

VOID CGsTexture::Cleanup()
{
	CDxSurface::Cleanup();
	m_BasePoint	= GPOINT(0,0);
	m_dwNumMipMaps	= 0;
	m_width		= 0;
	m_height	= 0;
	if (m_cache_fft==GSF_GIF)
	{
		m_link_cache_gif	= NULL;
		m_cache_pos			= 0;
	}
	else
	{
		SAFE_DELETE_ARRAY(m_cache_memory);
	}
	m_cache_fft			= GSF_UNKNOWN;
//	m_is_use_cache	= FALSE;
}

HRESULT CGsTexture::CreateEx( DWORD width, DWORD height, DXSF dxsf, DWORD dwNumMipMaps )
{
	HRESULT hr;
	if(width<=0 || height<=0)
		return S_OK;
	if(NULL == m_pEngine)
		return E_FAIL;
    LPDIRECT3DDEVICE7				pD3dDevice			= m_pEngine->GetD3dDevice();				
	if(!pD3dDevice)
		return E_FAIL;
	SAFE_RELEASE(m_pdds);

	m_dwNumMipMaps	= dwNumMipMaps;
	m_dxsf	= dxsf;
	hr = D3DXCreateTexture( pD3dDevice, NULL, &width, &height, &dxsf, NULL, &m_pdds, &m_dwNumMipMaps );
	if(FAILED(hr))
	{
		if(g_pDebug)
		{
			g_pDebug->ADD_LOG("failed to create texture(width=%dheight=%d) (name=%s)", width, height, m_keySource.c_str());
		}
		return hr;
	}
	OnCreate();
	m_BasePoint	= GPOINT(0,0);
	m_width		= width;//m_ddsd.dwWidth;
	m_height	= height;//m_ddsd.dwHeight;
	m_isTexture	= TRUE;
	return hr;
}

HRESULT CGsTexture::CreateShare(CGsTexture *pTexture)
{
	if(pTexture==NULL || pTexture->m_pdds==NULL)
		return E_FAIL;
	//if (m_pdds==pTexture->m_pdds)
	//{
	//	return S_OK;
	//}
	HRESULT hr = Create(pTexture->m_pdds);
	//pTexture->m_keySource = m_keySource;
	//m_BasePoint	= GPOINT(0,0);
	//m_width		= m_ddsd.dwWidth;
	//m_height	= m_ddsd.dwHeight;
	//m_isTexture	= TRUE;
	return hr;
}

HRESULT CGsTexture::CreateFromFile( const TCHAR* strFile, DWORD width, DWORD height, DXSF dxsf, DWORD dwNumMipMaps )
{
	HRESULT hr;
	if(NULL == m_pEngine)
		return E_FAIL;
    LPDIRECT3DDEVICE7				pD3dDevice			= m_pEngine->GetD3dDevice();				
	if(!pD3dDevice)
		return E_FAIL;
	SAFE_RELEASE(m_pdds);

	m_dwNumMipMaps	= dwNumMipMaps;
	m_dxsf	= dxsf;
	hr = D3DXCreateTextureFromFile( pD3dDevice, NULL, &width, &height, &dxsf, NULL, &m_pdds, &m_dwNumMipMaps, (TCHAR*)strFile, D3DX_FT_DEFAULT );
    m_pdds->GetSurfaceDesc( &m_ddsd );
	m_dwColorCount	= m_ddsd.ddpfPixelFormat.dwRGBBitCount;
	m_BasePoint	= GPOINT(0,0);
	m_width		= m_ddsd.dwWidth;
	m_height	= m_ddsd.dwHeight;
	m_isTexture	= TRUE;
	return OnCreate();
}

HRESULT CGsTexture::CreateFromFileEx(const TCHAR *strFile, PIX24 *pCK, DXSF dxsf, DWORD dwNumMipMaps)
{
	HRESULT hr;
	if(NULL == m_pEngine)
		return E_FAIL;
	SAFE_RELEASE(m_pdds);
	if(CGsFunc::FileCompareExt(strFile,"jpg"))
	{
		GSFBUF fbuf = CGsFunc::GSFBUF_Create(strFile, "rb");
		if(fbuf.p_fstream==NULL)
			return E_FAIL;
		SIZE size = CGsFunc::FileGetJpegSize(&fbuf);
		if(size.cx<=2048 || size.cy<=2048)
		{
			if(FAILED(hr=CreateEx(size.cx, size.cy, dxsf, dwNumMipMaps)))
			{
				fclose(fbuf.p_fstream);
				return hr;
			}
		}
		if(size.cx > m_width || size.cy > m_height)
		{
			CGsSurface::CreateEx(size.cx, size.cy);
			m_isTexture	= FALSE;
		}
		if(FAILED(hr=LoadFromJpegFile(&fbuf, pCK)))
		{
			fclose(fbuf.p_fstream);
			return hr;
		}
		m_width	 = size.cx;
		m_height = size.cy;
		fclose(fbuf.p_fstream);
	}
	else if(CGsFunc::FileCompareExt(strFile,"tga"))
	{
				if(FAILED(hr = CreateFromTGA(strFile)))
				{
					return hr;
				}
	}
	else
	{
		return CreateFromFile(strFile, 0, 0, dxsf, dwNumMipMaps);
	}


	return OnCreate();
}


VOID CGsTexture::CreateVirtual(LONG width, LONG height, LONG baseX, LONG baseY)
{
	SAFE_RELEASE(m_pdds);
	m_dwNumMipMaps	= 0;
	m_ddsd.dwWidth	= width;
	m_ddsd.dwHeight	= height;
	m_BasePoint		= GPOINT(baseX,baseY);
	m_width		= m_ddsd.dwWidth;
	m_height	= m_ddsd.dwHeight;
}


//-----------------------------------------------------------------------------
// Name: Lock()
// Desc: 
//-----------------------------------------------------------------------------
HRESULT CGsTexture::BeginLock(BYTE* &pDes, LONG &lPitch)
{
	if(!m_pdds)
		return E_FAIL;
	HRESULT hr;
	DDSURFACEDESC2	ddsd;
	memset(&ddsd,0,sizeof(ddsd));
	ddsd.dwSize	= sizeof(ddsd);
	hr = m_pdds->Lock (NULL, &ddsd, DDLOCK_WAIT, NULL);
	if(FAILED(hr))
		return hr;
	pDes	= (BYTE*)ddsd.lpSurface;
	lPitch	= ddsd.lPitch;
	return hr;
}
//-----------------------------------------------------------------------------
// Name: UnLock()
// Desc: 
//-----------------------------------------------------------------------------
HRESULT CGsTexture::EndLock()
{
	if(!m_pdds)
		return E_FAIL;
	return m_pdds->Unlock(NULL);
}

#pragma pack(push, 1)
struct t_texture_file_head
{
	DWORD	texture_width;
	DWORD	texture_height;
	DXSF	dxsf;
	DWORD	num_data;
	GPOINT	point_base;
	BOOL	bCompress;
};

struct t_compress_head
{
	BYTE	flag;	//0-行开始标识, 1-透明标识, 2-象素标识, 0x80-结束标识
	WORD	count;
};
#pragma pack(pop)

HRESULT CGsTexture::Import( const TCHAR* strFile )
{
//	fstream fbuf;
//	fbuf.open(strFile, ios::in | ios::out | ios::binary);
//	if(!fbuf)
//		return false;

	GSFBUF gsbuf;
	if((gsbuf.p_fstream	= fopen(strFile, "rb"))==NULL)
		return E_FAIL;
	gsbuf.pos_begin	= 0;
	gsbuf.file_size	= 0;
	HRESULT hr	= Import(gsbuf);

	fclose(gsbuf.p_fstream);
//	fbuf.close();

	return hr;
}
HRESULT CGsTexture::Import( GSFBUF &gsbuf )
{
	HRESULT hr;
	DWORD dwBytes	= 0;
	t_texture_file_head	head;

	fseek(gsbuf.p_fstream, gsbuf.pos_begin, SEEK_SET);

	ZeroMemory((void*)&head, sizeof(t_texture_file_head));

	fread(&head, sizeof(head), 1, gsbuf.p_fstream);

	Cleanup();
	m_BasePoint	= head.point_base;
	m_cache_fft	= GSF_TEX;
	if(head.dxsf==D3DX_SF_UNKNOWN)
	{
		fread(&m_ddsd, sizeof(m_ddsd), 1, gsbuf.p_fstream);
		hr	= Create(&m_ddsd);
		Clear(0);
		if(FAILED(hr))
			return hr;
		BYTE*	pData;
		LONG	lPitch;
		if(FAILED(hr = BeginLock(pData, lPitch)))
			return hr;

		char* pLine	= (char*)pData;


		//widthm_dwColorCount/8
		for(int i=0; i<m_ddsd.dwHeight; i++)
		{
			fread(pLine, 1, head.num_data, gsbuf.p_fstream);
			pLine	+= lPitch;
		}

		m_width		= head.texture_width;
		m_height	= head.texture_height;
		EndLock();

	}
	else
	{
		if(head.num_data!=0)
		{
			if(m_cache_memory==NULL)
			{
				m_cache_memory	= new char[head.num_data];
				fseek(gsbuf.p_fstream, gsbuf.pos_begin, SEEK_SET);
				fread(m_cache_memory, 1, head.num_data, gsbuf.p_fstream);
			}
			hr	= LoadFromMemory(m_cache_memory);
			if(m_mode_cache==0)
			{
				SAFE_DELETE_ARRAY(m_cache_memory);
			}
			//if(FAILED(hr))
			return hr;
		
		}
		else
		{
			hr = CreateEx(head.texture_width, head.texture_height, head.dxsf, head.num_data);
			Clear(0);
			if(FAILED(hr))
				return hr;
			if(head.dxsf!=m_dxsf)
				return E_FAIL;
			BYTE*	pData;
			LONG	lPitch;
			if(FAILED(hr = BeginLock(pData, lPitch)))
				return hr;

			char* pLine	= (char*)pData;
			t_compress_head ch;
			for(int i=0; i<head.texture_height; i++)
			{
				if(false == head.bCompress)
				{
//					pFileBuf->read(pLine, head.texture_width*m_dwColorCount/8);
					fread(pLine, 1, head.texture_width*m_dwColorCount/8, gsbuf.p_fstream);
				}
				else
				{
					char* pPixel	= pLine;
					while(1)
					{
//						pFileBuf->read((char*)&ch, sizeof(t_compress_head));
						fread(&ch, sizeof(ch), 1, gsbuf.p_fstream);
						switch (ch.flag) 
						{
							case 0:
								if(ch.count!=0)
									goto exit_line;
								break;
							case 1:
								pPixel	+= ch.count*m_dwColorCount/8;
								break;
							case 2:
//								pFileBuf->read(pPixel, ch.count*m_dwColorCount/8);
								fread(pPixel, 1, ch.count*m_dwColorCount/8, gsbuf.p_fstream);
								pPixel	+= ch.count*m_dwColorCount/8;
								break;
							case 0x80:
								goto exit_line;
								break;
							default:
								assert(false);
						}
					}
				}
				exit_line:
				pLine	+= lPitch;
			}
//			m_width		= m_ddsd.dwWidth;
//			m_height	= m_ddsd.dwHeight;
			m_width		= head.texture_width;
			m_height	= head.texture_height;

			EndLock();
		}
	}


	return S_OK;
}

HRESULT CGsTexture::UpdateFromCache()
{
	if(m_mode_cache>0)
	{
		switch(m_cache_fft) {
		case GSF_TEX:
			{
				return LoadFromMemory(m_cache_memory);
			}
			break;
		case GSF_GIF:
			{
				if(m_pEngine->CreateShareTexture(this, m_width, m_height, m_dxsf))
				{
					Clear(0);
					return LoadFromGifCache(m_link_cache_gif, m_cache_pos);
				}
				return S_OK;
			}
			break;
		}
	}
	return S_OK;
}

HRESULT CGsTexture::LoadFromMemory(char *pMem, D3DCOLOR crEdge)
{
	HRESULT		hr;


	t_texture_file_head	head	= *((t_texture_file_head*)pMem);

	pMem	+= sizeof(head);


//	if(head.bCompress)
	{
//		if(m_pdds && head.dxsf==m_dxsf && GetWidth()>=head.texture_width && GetHeight()>=head.texture_height)
//		{
//			Clear(0);
//		}
//		else
//		{
//			SAFE_RELEASE(m_pdds);
//		}
//		if(m_pdds==NULL)
		{
			if(m_mode_cache>=2)
			{
				if(!m_pEngine->CreatePublicTexture(this, head.texture_width, head.texture_height, head.dxsf))
				{
					return S_OK;
				}
				Clear(0);
			}
			else if (m_mode_cache==1)
			{
				if(!m_pEngine->CreateShareTexture(this, head.texture_width, head.texture_height, head.dxsf))
				{
					return S_OK;
				}
				Clear(0);
			}
			else
			{
				hr = CreateEx(head.texture_width, head.texture_height, head.dxsf, head.num_data);
				m_BasePoint = head.point_base;
				if(FAILED(hr))
					return hr;
			}
			//m_BasePoint	= head.point_base;
		}
	}
	if(head.dxsf!=m_dxsf)
		return E_FAIL;
	BYTE*	pData;
	LONG	lPitch;
	if(FAILED(hr = BeginLock(pData, lPitch)))
		return hr;

	if(head.bCompress)
	{
		char* pLine	= (char*)pData;
		t_compress_head ch;
		for(int i=0; i<head.texture_height; i++)
		{
			char* pPixel	= pLine;
			int color_byte	= m_dwColorCount/8;
			int ch_byte;
			while(1)
			{
				ch	= *((t_compress_head*)pMem);
				pMem	+= sizeof(t_compress_head);
				switch (ch.flag) 
				{
					case 0:
						if(ch.count!=0)
							goto exit_line;
						break;
					case 1:
						pPixel	+= ch.count*color_byte;
						break;
					case 2:
						ch_byte = ch.count*color_byte;
						memcpy(pPixel, pMem, ch_byte);
						pMem	+= ch_byte;
						pPixel	+= ch_byte;
						break;
					case 0x80:
						goto exit_line;
						break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?