1372 lines
39 KiB
C++
1372 lines
39 KiB
C++
#include "stdafx.h"
|
|
#include "KRenderDeviceDX.h"
|
|
#include "KResourceDX.h"
|
|
#include <dump/XException.h>
|
|
|
|
#include "SDebug_Util.h"
|
|
|
|
int g_TexRef = 0;
|
|
|
|
static inline D3DFORMAT GetD3DFormat( K3DFORMAT fmt )
|
|
{
|
|
return D3DFORMAT( fmt );
|
|
|
|
//switch ( fmt )
|
|
//{
|
|
// default:
|
|
// case K3DFMT_UNKNOWN : return D3DFMT_UNKNOWN ;
|
|
//
|
|
// case K3DFMT_R8G8B8 : return K3DFMT_R8G8B8 ;
|
|
// case K3DFMT_A8R8G8B8 : return K3DFMT_A8R8G8B8 ;
|
|
// case K3DFMT_X8R8G8B8 : return K3DFMT_X8R8G8B8 ;
|
|
// case K3DFMT_R5G6B5 : return K3DFMT_R5G6B5 ;
|
|
// case K3DFMT_X1R5G5B5 : return K3DFMT_X1R5G5B5 ;
|
|
// case K3DFMT_A1R5G5B5 : return K3DFMT_A1R5G5B5 ;
|
|
// case K3DFMT_A4R4G4B4 : return K3DFMT_A4R4G4B4 ;
|
|
// case K3DFMT_R3G3B2 : return K3DFMT_R3G3B2 ;
|
|
// case K3DFMT_A8 : return K3DFMT_A8 ;
|
|
// case K3DFMT_A8R3G3B2 : return K3DFMT_A8R3G3B2 ;
|
|
// case K3DFMT_X4R4G4B4 : return K3DFMT_X4R4G4B4 ;
|
|
// case K3DFMT_A2B10G10R10 : return K3DFMT_A2B10G10R10 ;
|
|
// case K3DFMT_G16R16 : return K3DFMT_G16R16 ;
|
|
//
|
|
// case K3DFMT_A8P8 : return K3DFMT_A8P8 ;
|
|
// case K3DFMT_P8 : return K3DFMT_P8 ;
|
|
//
|
|
// case K3DFMT_L8 : return K3DFMT_L8 ;
|
|
// case K3DFMT_A8L8 : return K3DFMT_A8L8 ;
|
|
// case K3DFMT_A4L4 : return K3DFMT_A4L4 ;
|
|
//
|
|
// case K3DFMT_V8U8 : return K3DFMT_V8U8 ;
|
|
// case K3DFMT_L6V5U5 : return K3DFMT_L6V5U5 ;
|
|
// case K3DFMT_X8L8V8U8 : return K3DFMT_X8L8V8U8 ;
|
|
// case K3DFMT_Q8W8V8U8 : return K3DFMT_Q8W8V8U8 ;
|
|
// case K3DFMT_V16U16 : return K3DFMT_V16U16 ;
|
|
// case K3DFMT_W11V11U10 : return K3DFMT_W11V11U10 ;
|
|
// case K3DFMT_A2W10V10U10 : return K3DFMT_A2W10V10U10 ;
|
|
//
|
|
// case K3DFMT_UYVY : return K3DFMT_UYVY ;
|
|
// case K3DFMT_YUY2 : return K3DFMT_YUY2 ;
|
|
// case K3DFMT_DXT1 : return K3DFMT_DXT1 ;
|
|
// case K3DFMT_DXT2 : return K3DFMT_DXT2 ;
|
|
// case K3DFMT_DXT3 : return K3DFMT_DXT3 ;
|
|
// case K3DFMT_DXT4 : return K3DFMT_DXT4 ;
|
|
// case K3DFMT_DXT5 : return K3DFMT_DXT5 ;
|
|
//
|
|
// case K3DFMT_D16_LOCKABLE : return K3DFMT_D16_LOCKABLE ;
|
|
// case K3DFMT_D32 : return K3DFMT_D32 ;
|
|
// case K3DFMT_D15S1 : return K3DFMT_D15S1 ;
|
|
// case K3DFMT_D24S8 : return K3DFMT_D24S8 ;
|
|
// case K3DFMT_D16 : return K3DFMT_D16 ;
|
|
// case K3DFMT_D24X8 : return K3DFMT_D24X8 ;
|
|
// case K3DFMT_D24X4S4 : return K3DFMT_D24X4S4 ;
|
|
//
|
|
// case K3DFMT_VERTEXDATA : return K3DFMT_VERTEXDATA ;
|
|
// case K3DFMT_INDEX16 : return K3DFMT_INDEX16 ;
|
|
// case K3DFMT_INDEX32 : return K3DFMT_INDEX32 ;
|
|
//
|
|
// case K3DFMT_R32F : return K3DFMT_R32F ;
|
|
//}
|
|
}
|
|
|
|
K3DTextureDX::K3DTextureDX( K3DRenderDeviceDX *dev )
|
|
{
|
|
m_bLocked = false;
|
|
m_dev = dev;
|
|
m_d3dtex = NULL;
|
|
m_usage = 0;
|
|
|
|
m_pool = D3DPOOL_MANAGED;
|
|
|
|
// _oprint( "TC:(%08X)\n", this );
|
|
}
|
|
|
|
K3DTextureDX::~K3DTextureDX()
|
|
{
|
|
//if( m_strName.length() )
|
|
// _oprint( "TD:(%08X : %s)\n", this, m_strName.c_str() );
|
|
//else
|
|
// _oprint( "TD:(%08X)\n", this );
|
|
|
|
if ( m_d3dtex) g_TexRef--;
|
|
SAFE_RELEASE(m_d3dtex);
|
|
}
|
|
|
|
template< typename T > static inline T _max( const T& a, const T& b ) { return a > b ? a : b; }
|
|
template< typename T > static inline T _min( const T& a, const T& b ) { return a < b ? a : b; }
|
|
|
|
bool K3DTextureDX::Initialize( KStream &stream, int nQuality, D3DPOOL pool/* = D3DPOOL_MANAGED*/, K3DFORMAT fmt/* = K3DFMT_UNKNOWN*/ )
|
|
{
|
|
//if( pool == D3DPOOL_DEFAULT )
|
|
// _oprint( "K3DTextureDX::Initialize : (0x%08X)\n", this );
|
|
|
|
void *pSrc = stream.GetMappedPtr( KStream::MAPPED_READ );
|
|
if ( pSrc == NULL ) return false;
|
|
|
|
bool original = false;
|
|
if(nQuality >= 10000 || nQuality < 0)
|
|
{
|
|
nQuality = 0;
|
|
original = true;
|
|
}
|
|
|
|
HRESULT res;
|
|
m_nQuality = nQuality;
|
|
D3DXIMAGE_INFO infoImg;
|
|
D3DXGetImageInfoFromFileInMemory( pSrc, static_cast<UINT>(stream.GetLength()), &infoImg );
|
|
|
|
m_origin_size.width = infoImg.Width;
|
|
m_origin_size.height = infoImg.Height;
|
|
|
|
if ( m_nQuality != 0 )
|
|
{
|
|
// 너무 작은 텍스쳐는 뭉게지는것 같아서.. 임시로 추가해봄 -.-
|
|
infoImg.Width = _max( infoImg.Width / (1 << m_nQuality), _min( infoImg.Width, 32U ) );
|
|
infoImg.Height = _max( infoImg.Height / (1 << m_nQuality), _min( infoImg.Height, 32U ) );
|
|
infoImg.MipLevels = _max( (int) (infoImg.MipLevels - m_nQuality), 1 );
|
|
|
|
res = D3DXCreateTextureFromFileInMemoryEx( m_dev->GetD3DDevice(), pSrc,
|
|
static_cast<UINT>(stream.GetLength()), infoImg.Width, infoImg.Height,
|
|
infoImg.MipLevels, 0, GetD3DFormat( fmt ), pool, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &m_d3dtex );
|
|
}
|
|
else {
|
|
res = D3DXCreateTextureFromFileInMemoryEx( m_dev->GetD3DDevice(), pSrc,
|
|
static_cast<UINT>(stream.GetLength()), infoImg.Width, infoImg.Height,
|
|
infoImg.MipLevels, 0, GetD3DFormat( fmt ), pool, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &m_d3dtex );
|
|
// infoImg.MipLevels, 0, D3DFMT_UNKNOWN, original ? D3DPOOL_MANAGED : D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &m_d3dtex );
|
|
// infoImg.MipLevels, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_POINT, D3DX_FILTER_POINT, 0, NULL, NULL, &m_d3dtex );
|
|
}
|
|
|
|
stream.FreeMappedPtr( pSrc );
|
|
|
|
if ( res != D3D_OK )
|
|
{
|
|
/// 2011.05.12 - prodongi
|
|
std::string errStr;
|
|
if( res == D3DERR_NOTAVAILABLE ) errStr = "D3DERR_NOTAVAILABLE";
|
|
else if( res == D3DERR_OUTOFVIDEOMEMORY ) errStr = "D3DERR_OUTOFVIDEOMEMORY";
|
|
else if( res == D3DERR_INVALIDCALL ) errStr = "D3DERR_INVALIDCALL";
|
|
else if( res == E_OUTOFMEMORY ) errStr = "E_OUTOFMEMORY";
|
|
else errStr = "";
|
|
_oprint("***DEVICE ERROR : %s[%d]\n", errStr.c_str(), res);
|
|
|
|
#ifdef _DEV
|
|
MessageBox(HWND_DESKTOP, errStr.c_str(), "Failed D3DXCreateTextureFromFileInMemoryEx", MB_OK);
|
|
#endif
|
|
/*
|
|
if( res == D3DERR_NOTAVAILABLE ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_NOTAVAILABLE" ); }
|
|
else if( res == D3DERR_OUTOFVIDEOMEMORY ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_OUTOFVIDEOMEMORY" ); }
|
|
else if( res == D3DERR_INVALIDCALL ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_INVALIDCALL" ); }
|
|
else if( res == E_OUTOFMEMORY ) { _oprint( "***DEVICE ERROR : %s\n", "E_OUTOFMEMORY" ); }
|
|
*/
|
|
|
|
m_d3dtex = NULL;
|
|
m_pSurface = NULL;
|
|
return false;
|
|
}
|
|
|
|
g_TexRef++;
|
|
|
|
m_fmt = fmt;
|
|
m_pool = pool;
|
|
m_pSurface = m_d3dtex;
|
|
m_size.width = infoImg.Width ;
|
|
m_size.height = infoImg.Height;
|
|
m_nMipsLevels = infoImg.MipLevels;
|
|
m_format = static_cast<K3DFORMAT>(infoImg.Format);
|
|
return true;
|
|
}
|
|
|
|
bool K3DTextureDX::CreateNew( DWORD width, DWORD height, DWORD usage, K3DFORMAT format, D3DPOOL pool/* = D3DPOOL_DEFAULT*/ )
|
|
{
|
|
//if( pool == D3DPOOL_DEFAULT )
|
|
// _oprint( "DeviceLost : K3DTextureDX::CreateNew : (0x%08X)\n", this );
|
|
|
|
HRESULT res = m_dev->GetD3DDevice()->CreateTexture( width, height, 1, usage, GetD3DFormat(format), pool, &m_d3dtex, NULL );
|
|
if ( res != D3D_OK )
|
|
{
|
|
if( res == D3DERR_NOTAVAILABLE ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_NOTAVAILABLE" ); }
|
|
else if( res == D3DERR_OUTOFVIDEOMEMORY ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_OUTOFVIDEOMEMORY" ); }
|
|
else if( res == D3DERR_INVALIDCALL ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_INVALIDCALL" ); }
|
|
else if( res == E_OUTOFMEMORY ) { _oprint( "***DEVICE ERROR : %s\n", "E_OUTOFMEMORY" ); }
|
|
|
|
m_d3dtex = NULL;
|
|
m_pSurface = NULL;
|
|
return false;
|
|
}
|
|
m_pool = pool;
|
|
m_usage = usage;
|
|
m_pSurface = m_d3dtex;
|
|
D3DSURFACE_DESC desc;
|
|
m_d3dtex->GetLevelDesc( 0, &desc );
|
|
m_size.width = desc.Width;
|
|
m_size.height = desc.Height;
|
|
|
|
g_TexRef++;
|
|
|
|
m_nMipsLevels = 1;
|
|
m_fmt = format;
|
|
m_format = static_cast<K3DFORMAT>(desc.Format);
|
|
return true;
|
|
}
|
|
|
|
bool K3DTextureDX::CreateNew( DWORD width, DWORD height, K3DFORMAT format, D3DPOOL pool/* = D3DPOOL_MANAGED*/, int nLevel /*= 1*/ )
|
|
{
|
|
//if( pool == D3DPOOL_DEFAULT )
|
|
// _oprint( "DeviceLost : K3DTextureDX::CreateNew : (0x%08X)\n", this );
|
|
|
|
HRESULT res = D3DXCreateTexture( m_dev->GetD3DDevice(), width, height, nLevel, 0, GetD3DFormat(format), pool, &m_d3dtex );
|
|
if ( res != D3D_OK )
|
|
{
|
|
if( res == D3DERR_NOTAVAILABLE ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_NOTAVAILABLE" ); }
|
|
else if( res == D3DERR_OUTOFVIDEOMEMORY ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_OUTOFVIDEOMEMORY" ); }
|
|
else if( res == D3DERR_INVALIDCALL ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_INVALIDCALL" ); }
|
|
else if( res == E_OUTOFMEMORY ) { _oprint( "***DEVICE ERROR : %s\n", "E_OUTOFMEMORY" ); }
|
|
|
|
m_d3dtex = NULL;
|
|
m_pSurface = NULL;
|
|
return false;
|
|
}
|
|
|
|
g_TexRef++;
|
|
|
|
m_pSurface = m_d3dtex;
|
|
D3DSURFACE_DESC desc;
|
|
m_d3dtex->GetLevelDesc( 0, &desc );
|
|
m_size.width = desc.Width;
|
|
m_size.height = desc.Height;
|
|
m_format = static_cast<K3DFORMAT>(desc.Format);
|
|
return true;
|
|
}
|
|
|
|
bool K3DTextureDX::IsValid() const
|
|
{
|
|
return m_d3dtex ? true : false;
|
|
}
|
|
|
|
void K3DTextureDX::Refresh( KStream &stream, int nQuality )
|
|
{
|
|
if ( m_d3dtex) g_TexRef--;
|
|
|
|
SAFE_RELEASE(m_d3dtex);
|
|
Initialize( stream, nQuality );
|
|
}
|
|
|
|
void K3DTextureDX::LockRect( KRect *rect, void** ppBuf, int& stride )
|
|
{
|
|
if ( !m_bLocked && m_d3dtex != NULL )
|
|
{
|
|
D3DLOCKED_RECT rt;
|
|
|
|
HRESULT hr = m_d3dtex->LockRect( 0, &rt, (const RECT*)rect, 0/*D3DLOCK_NOSYSLOCK*/ );
|
|
if ( hr == D3D_OK )
|
|
{
|
|
*ppBuf = rt.pBits;
|
|
stride = rt.Pitch;
|
|
m_bLocked = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ppBuf = NULL;
|
|
stride = 0;
|
|
}
|
|
}
|
|
|
|
void K3DTextureDX::Unlock()
|
|
{
|
|
if ( m_bLocked )
|
|
{
|
|
m_d3dtex->UnlockRect(0);
|
|
m_bLocked = false;
|
|
}
|
|
}
|
|
|
|
bool K3DTextureDX::PreReload()
|
|
{
|
|
if (m_d3dtex) g_TexRef--;
|
|
SAFE_RELEASE(m_d3dtex);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DTextureDX::Reload()
|
|
{
|
|
//Device Lost 처리
|
|
if( m_pool == D3DPOOL_DEFAULT )
|
|
{
|
|
if (m_d3dtex) g_TexRef--;
|
|
SAFE_RELEASE(m_d3dtex);
|
|
|
|
CreateNew( m_size.width, m_size.height, m_usage, m_format, m_pool );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DTextureDX::SaveToFile( const std::string& strFile )
|
|
{
|
|
if( D3DXSaveTextureToFile( strFile.c_str(), D3DXIFF_DDS, m_d3dtex, NULL ) == D3D_OK ) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
// 추가. bintitle.
|
|
#include <dxerr9.h>
|
|
|
|
bool K3DTextureDX::LoadFromFile( const std::string& strFile )
|
|
{
|
|
HRESULT hr;
|
|
if( !FAILED( hr = D3DXCreateTextureFromFile( m_dev->GetD3DDevice(), strFile.c_str(), &m_d3dtex ) ) )
|
|
{
|
|
m_origin_size.width = 20; // 테스트 강제 적용.
|
|
m_origin_size.height = 20;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
const TCHAR* szError = DXGetErrorString9(hr);
|
|
::MessageBox( NULL, szError, "Load Fail", MB_OK );
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
struct Color_RGB {
|
|
// 2010.04.23 순서를 수정했습니다. - prodongi
|
|
double red,green,blue; //doubles used for best accuracy
|
|
//double red,blue, green; //doubles used for best accuracy
|
|
};
|
|
struct Color_HSV {
|
|
double hue, sat, val;
|
|
};
|
|
struct Color_HSV RGBtoHSV(struct Color_RGB RGB)
|
|
{
|
|
struct Color_HSV HSV; //structure to return
|
|
double vals[3]; //thue = temporary var (linked to hue)
|
|
unsigned char maxc=0, minc=0; //red=0, green=1, blue=2
|
|
vals[0]=RGB.red;
|
|
vals[1]=RGB.green;
|
|
vals[2]=RGB.blue;
|
|
|
|
//red is set as maximum and minimum
|
|
if(vals[1]>vals[maxc]) maxc=1; //if green is greater, make green the max.
|
|
if(vals[2]>vals[maxc]) maxc=2; //if blue is greater, make blue the max
|
|
if(vals[1]<vals[minc]) minc=1; //if green is less, make green the min.
|
|
if(vals[2]<vals[minc]) minc=2; //if blue is less, make blue the min.
|
|
|
|
HSV.val = vals[maxc]; //set the HSV.val to the maximum component value (this is a final value)
|
|
if(vals[maxc]==0) //if maximum component is 0, color must be black
|
|
HSV.sat = HSV.hue = 0; //so set values to 0 manually to avoid div by 0 errors
|
|
else
|
|
{ //otherwise, calculate the values
|
|
HSV.sat=255*(1-(vals[minc]/vals[maxc])); //compressed equation - original: HSV.sat=((vals[maxc]-vals[minc])/vals[maxc])*255;
|
|
HSV.hue = 60 * ((maxc*2) + (vals[(maxc+1)%3] - vals[(maxc+2)%3])/(vals[maxc] - vals[minc])); //this cannot be simplified - and i havn't got time to explain it
|
|
}
|
|
if(HSV.hue < 0) HSV.hue += 360; //corrector for hues in -60 to 0 range
|
|
return HSV;
|
|
}
|
|
struct Color_RGB HSVtoRGB(struct Color_HSV HSV)
|
|
{
|
|
struct Color_RGB RGB; //structure to return
|
|
double min,thue,vals[3]; //thue = temporary var (linked to hue)
|
|
unsigned char maxc; //red=0, green=1, blue=2
|
|
/* The biggest component (r,g or b) of the colour can be detemined
|
|
* by where the hue lies.
|
|
* The maximum component is eaqul to the 'value' in HSV,
|
|
* so we can set the biggest component to HSV.val,
|
|
* and also set the marker for which is the biggest component(maxc)
|
|
*
|
|
* The maximum component can be determined by where the hue lies:
|
|
* it lies in one of three groups
|
|
*
|
|
* If the maximum component is red (0), it lies in the third of the
|
|
* spectrum around red, i.e. -60 to 60
|
|
* If the maximum component is green (120), it lies in the third of the
|
|
* spectrum around green, i.e. 60 to 180
|
|
* If the maximum component is blue (240), it lies in the third of the
|
|
* spectrum around blue, i.e. 180 to 300
|
|
*/
|
|
|
|
|
|
/* since the spectrum is circular, we can take the 300-360 section and
|
|
* fit it into -60 -> 0, to fit help the group seperation
|
|
*/
|
|
if(HSV.hue>300)
|
|
HSV.hue-=360;
|
|
/* we now determine the maximum component (maxc) by the hue groups
|
|
*/
|
|
if(HSV.hue<60) //if it is below 60, then it is red (maxc 0)
|
|
maxc=0; //The range is -60 -> 60, and there is never anything below -60
|
|
else if(HSV.hue>=180) //if it is above 180, then it is blue (maxc 2)
|
|
maxc=2; //The range is 180 -> 300, and there is never anything above 300, or it would have been modified earlier
|
|
else //otherwise, it must be between 60 and 180, which is green (maxc 1)
|
|
maxc=1; //The range is 60 -> 180
|
|
|
|
|
|
vals[maxc]=HSV.val; //vals holds the r, g, and b values temporarialy, so set the maximum one to HSV.val (the value of the maximim component is HSV.val)
|
|
/* the first of these formulae calculates the minimum
|
|
* value. it has been "shrink-wrapped", so dont try to make sense of it
|
|
*
|
|
* I dont understand it anymore, and i'm not sure if i even did when i wrote it
|
|
*/
|
|
min = (HSV.val*(255-HSV.sat)) / 255;
|
|
/* the second of these formulae calculates a value 'thue'.
|
|
* the formaula results in a value between -1 and 1, representing
|
|
* the position of the hue in it's group
|
|
* this may help: (green "hue group" used as an example.)
|
|
*
|
|
* lwr bound ## green ## upr bound
|
|
* 60 120 180 -----> Hue
|
|
* |-----|-----|-----------|
|
|
* hue= 90
|
|
*
|
|
* lwr bound ## green ## upr bound
|
|
* -1 0 1 -----> tHue
|
|
* |-----|-----|-----------|
|
|
* hue= -0.5
|
|
*
|
|
* this part is done in the first half of the equation ((HSV.hue/60)-(2*maxc))
|
|
*
|
|
* the second part multiplies it by the difference between
|
|
* the maximum and minimum to get a value that is
|
|
* the difference between the minimum component and the middle component.
|
|
* i dont really understand why, but it works. * (HSV.val-min)
|
|
*/
|
|
thue=(((HSV.hue/60)-(2*maxc)) * (HSV.val-min));
|
|
if(thue>0) //if the hue is more like the color group above it,
|
|
{ //i.e. a green that is more 'bluey' than 'reddy'
|
|
vals[(maxc+2)%3] = min; //then the minimum component is the one it is less like, the group below
|
|
vals[(maxc+1)%3] = min+thue; //and the middle component is the one it is more like, the group above
|
|
}
|
|
else //otherwise, it must be more like the colour group below it
|
|
{ //i.e. a green that is more 'reddy' than 'bluey'
|
|
vals[(maxc+1)%3] = min; //then the minimum component is the one it is less like, the group above
|
|
vals[(maxc+2)%3] = min+thue; //and the middle component is the one it is more like, the group below
|
|
}
|
|
RGB.red=vals[0]; // now stuff the aray values into the return structure
|
|
RGB.green=vals[1];
|
|
RGB.blue=vals[2];
|
|
return RGB;
|
|
}
|
|
|
|
HRESULT K3DTextureDX::LoadSurfaceFromSurface( K3DTexture* pDestTexture, DWORD c1, DWORD c2, DWORD c3, DWORD c4, short nMode )
|
|
{
|
|
if( !IsValid() ) return S_FALSE;
|
|
if( pDestTexture == NULL || !pDestTexture->IsValid() ) return S_FALSE;
|
|
|
|
K3DTextureDX* pDestTextureDX = (K3DTextureDX*)pDestTexture;
|
|
|
|
int nMipCount = GetMipsLevels();
|
|
|
|
D3DSURFACE_DESC sd;
|
|
HRESULT hr;
|
|
|
|
LPDIRECT3DSURFACE9 psurfSrc = NULL;
|
|
LPDIRECT3DSURFACE9 psurfDest = NULL;
|
|
|
|
KColor cols[4];
|
|
|
|
int i, fr[4], fg[4], fb[4];
|
|
cols[0].color = c1; cols[1].color = c2; cols[2].color = c3; cols[3].color = c4;
|
|
for ( i=0 ; i<4 ; ++i )
|
|
{
|
|
if ( cols[i].color == 0 )
|
|
fr[i] = fg[i] = fb[i] = 0;
|
|
else
|
|
{
|
|
fr[i] = int(cols[i].r) - 128;
|
|
fg[i] = int(cols[i].g) - 128;
|
|
fb[i] = int(cols[i].b) - 128;
|
|
}
|
|
}
|
|
|
|
int r,g,b;
|
|
KColor *colbuf, *newcolbuf;
|
|
|
|
for( int i(0); nMipCount>i; i++ )
|
|
{
|
|
m_d3dtex->GetLevelDesc(i, &sd);
|
|
|
|
hr = m_d3dtex->GetSurfaceLevel(i, &psurfSrc);
|
|
hr = pDestTextureDX->GetD3DTexture()->GetSurfaceLevel(i, &psurfDest);
|
|
|
|
if( psurfSrc && psurfDest )
|
|
{
|
|
hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_FILTER_LINEAR/*D3DX_FILTER_TRIANGLE*/, 0);
|
|
|
|
//Colorized
|
|
if( (c1 != 0 || c2 != 0 || c3 != 0 || c4 != 0) && hr== S_OK )
|
|
{
|
|
D3DLOCKED_RECT lr;
|
|
|
|
hr = psurfDest->LockRect(&lr, NULL, 0);
|
|
|
|
DWORD xp;
|
|
DWORD yp;
|
|
DWORD* pdwRow = (DWORD*)lr.pBits;
|
|
|
|
LONG dataBytesPerRow = 4 * sd.Width;
|
|
|
|
colbuf = NULL;
|
|
newcolbuf= NULL;
|
|
|
|
if( nMode == COLORIZED_DEF )
|
|
{
|
|
Color_RGB rgb = {cols[1].r, cols[1].g, cols[1].b};
|
|
Color_HSV hsv = RGBtoHSV(rgb);
|
|
|
|
for (yp = 0; yp < sd.Height; yp++)
|
|
{
|
|
colbuf = (KColor*)pdwRow;
|
|
newcolbuf = (KColor*)pdwRow;
|
|
|
|
for (xp = 0; xp < sd.Width; xp++)
|
|
{
|
|
switch( (int)(colbuf->a >> 5) )
|
|
{
|
|
case 0:
|
|
newcolbuf->color = colbuf->color;
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
r = int(colbuf->r) + fr[0];
|
|
g = int(colbuf->g) + fg[0];
|
|
b = int(colbuf->b) + fb[0];
|
|
newcolbuf->r = unsigned char((r > 255) ? (255) : ( (r<0) ? (0) : r ));
|
|
newcolbuf->g = unsigned char((g > 255) ? (255) : ( (g<0) ? (0) : g ));
|
|
newcolbuf->b = unsigned char((b > 255) ? (255) : ( (b<0) ? (0) : b ));
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
r = int(colbuf->r) + fr[1];
|
|
g = int(colbuf->g) + fg[1];
|
|
b = int(colbuf->b) + fb[1];
|
|
|
|
newcolbuf->r = unsigned char((r > 255) ? (255) : ( (r<0) ? (0) : r ));
|
|
newcolbuf->g = unsigned char((g > 255) ? (255) : ( (g<0) ? (0) : g ));
|
|
newcolbuf->b = unsigned char((b > 255) ? (255) : ( (b<0) ? (0) : b ));
|
|
break;
|
|
case 5:
|
|
case 6:
|
|
r = int(colbuf->r) + fr[2];
|
|
g = int(colbuf->g) + fg[2];
|
|
b = int(colbuf->b) + fb[2];
|
|
newcolbuf->r = unsigned char((r > 255) ? (255) : ( (r<0) ? (0) : r ));
|
|
newcolbuf->g = unsigned char((g > 255) ? (255) : ( (g<0) ? (0) : g ));
|
|
newcolbuf->b = unsigned char((b > 255) ? (255) : ( (b<0) ? (0) : b ));
|
|
break;
|
|
case 7:
|
|
r = int(colbuf->r) + fr[3];
|
|
g = int(colbuf->g) + fg[3];
|
|
b = int(colbuf->b) + fb[3];
|
|
newcolbuf->r = unsigned char((r > 255) ? (255) : ( (r<0) ? (0) : r ));
|
|
newcolbuf->g = unsigned char((g > 255) ? (255) : ( (g<0) ? (0) : g ));
|
|
newcolbuf->b = unsigned char((b > 255) ? (255) : ( (b<0) ? (0) : b ));
|
|
break;
|
|
}
|
|
|
|
//0~127 사이의 알파값은 유지
|
|
if( colbuf->a >= 128 )
|
|
newcolbuf->a = 255;
|
|
|
|
colbuf++;
|
|
newcolbuf++;
|
|
}
|
|
pdwRow += lr.Pitch / 4;
|
|
}//for
|
|
}
|
|
else if( nMode == COLORIZED_KEEP_ALPHA )
|
|
{
|
|
for (yp = 0; yp < sd.Height; yp++)
|
|
{
|
|
colbuf = (KColor*)pdwRow;
|
|
newcolbuf = (KColor*)pdwRow;
|
|
|
|
for (xp = 0; xp < sd.Width; xp++)
|
|
{
|
|
if( colbuf->a != 0 )
|
|
{
|
|
r = int(colbuf->r) + fr[0];
|
|
g = int(colbuf->g) + fg[0];
|
|
b = int(colbuf->b) + fb[0];
|
|
|
|
newcolbuf->r = unsigned char((r > 255) ? (255) : ( (r<0) ? (0) : r ));
|
|
newcolbuf->g = unsigned char((g > 255) ? (255) : ( (g<0) ? (0) : g ));
|
|
newcolbuf->b = unsigned char((b > 255) ? (255) : ( (b<0) ? (0) : b ));
|
|
}
|
|
|
|
colbuf++;
|
|
newcolbuf++;
|
|
}
|
|
pdwRow += lr.Pitch / 4;
|
|
}//for
|
|
}
|
|
else if( nMode == COLORIZED_USEALPHA )
|
|
{
|
|
for (yp = 0; yp < sd.Height; yp++)
|
|
{
|
|
colbuf = (KColor*)pdwRow;
|
|
newcolbuf = (KColor*)pdwRow;
|
|
|
|
for (xp = 0; xp < sd.Width; xp++)
|
|
{
|
|
if( colbuf->a != 0 )
|
|
{
|
|
newcolbuf->r = cols[0].r;
|
|
newcolbuf->g = cols[0].g;
|
|
newcolbuf->b = cols[0].b;
|
|
}
|
|
|
|
colbuf++;
|
|
newcolbuf++;
|
|
}
|
|
pdwRow += lr.Pitch / 4;
|
|
}//for
|
|
}
|
|
else if( nMode == COLORIZED_GRAY )
|
|
{
|
|
Color_RGB rgb = {cols[1].r, cols[1].g, cols[1].b};
|
|
Color_HSV hsv = RGBtoHSV(rgb);
|
|
|
|
for (yp = 0; yp < sd.Height; yp++)
|
|
{
|
|
colbuf = (KColor*)pdwRow;
|
|
newcolbuf = (KColor*)pdwRow;
|
|
|
|
for (xp = 0; xp < sd.Width; xp++)
|
|
{
|
|
//if (colbuf->a == 172)
|
|
// _oprint( "alpha : %d\n", colbuf->a );
|
|
|
|
switch ((int)(colbuf->a >> 5))
|
|
{
|
|
case 3:
|
|
case 4:
|
|
{
|
|
// 2010.04.27 nrgb값이 -가 나올때가 있어서, 적용 방식을 수정했습니다. - prodongi
|
|
/*
|
|
Color_RGB irgb = { colbuf->r, colbuf->g, colbuf->b };
|
|
Color_HSV ohsv = RGBtoHSV(irgb);
|
|
|
|
hsv.val = ohsv.val;
|
|
Color_RGB nrgb = HSVtoRGB(hsv);
|
|
|
|
// 2010.04.23 형변환 워닝 수정 - prodongi
|
|
newcolbuf->r = (unsigned char)nrgb.red;
|
|
newcolbuf->g = (unsigned char)nrgb.green;
|
|
newcolbuf->b = (unsigned char)nrgb.blue;
|
|
*/
|
|
float ratio = (float)(colbuf->r)/255.0f;
|
|
float inv_ratio = 1.0f - ratio;
|
|
newcolbuf->r = (unsigned char)((float)colbuf->r * inv_ratio + (float)rgb.red * ratio);
|
|
newcolbuf->g = (unsigned char)((float)colbuf->g * inv_ratio + (float)rgb.green * ratio);
|
|
newcolbuf->b = (unsigned char)((float)colbuf->b * inv_ratio + (float)rgb.blue * ratio);
|
|
}
|
|
break;
|
|
default:
|
|
newcolbuf->r = colbuf->r;
|
|
newcolbuf->g = colbuf->g;
|
|
newcolbuf->b = colbuf->b;
|
|
}
|
|
|
|
//0~127 사이의 알파값은 유지
|
|
if( colbuf->a >= 128 )
|
|
newcolbuf->a = 255;
|
|
|
|
colbuf++;
|
|
newcolbuf++;
|
|
}
|
|
pdwRow += lr.Pitch / 4;
|
|
}//for
|
|
}
|
|
|
|
psurfDest->UnlockRect();
|
|
}
|
|
|
|
SAFE_RELEASE(psurfSrc );
|
|
SAFE_RELEASE(psurfDest);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
K3DRenderTargetDX::K3DRenderTargetDX( K3DRenderDeviceDX *dev )
|
|
{
|
|
m_bLocked = false;
|
|
m_dev = dev;
|
|
m_d3dtex = NULL;
|
|
m_pD3DDepth = NULL;
|
|
//m_pD3DDepthTex = NULL;
|
|
}
|
|
|
|
K3DRenderTargetDX::~K3DRenderTargetDX()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void K3DRenderTargetDX::Clear()
|
|
{
|
|
SAFE_RELEASE(m_d3dtex);
|
|
SAFE_RELEASE(m_pD3DDepth);
|
|
//SAFE_RELEASE(m_pD3DDepthTex);
|
|
m_pSurface = NULL;
|
|
}
|
|
|
|
bool K3DRenderTargetDX::CreateNew( DWORD width, DWORD height, UINT nLevels, K3DFORMAT format, DWORD dwDepthUsage, bool bDepth16Bit /*=false*/ )
|
|
{
|
|
Clear();
|
|
|
|
m_nLevels = nLevels;
|
|
|
|
HRESULT res = D3DXCreateTexture( m_dev->GetD3DDevice(), width, height, m_nLevels, D3DUSAGE_RENDERTARGET,
|
|
GetD3DFormat(format), D3DPOOL_DEFAULT, &m_d3dtex );
|
|
if ( res != D3D_OK )
|
|
{
|
|
if( res == D3DERR_NOTAVAILABLE ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_NOTAVAILABLE" ); }
|
|
else if( res == D3DERR_OUTOFVIDEOMEMORY ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_OUTOFVIDEOMEMORY" ); }
|
|
else if( res == D3DERR_INVALIDCALL ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_INVALIDCALL" ); }
|
|
else if( res == E_OUTOFMEMORY ) { _oprint( "***DEVICE ERROR : %s\n", "E_OUTOFMEMORY" ); }
|
|
|
|
//m_d3dtex = NULL;
|
|
//m_pSurface = NULL;
|
|
Clear();
|
|
return false;
|
|
}
|
|
//m_bUseDepth = bUseDepth;
|
|
m_dwDepthUsage = dwDepthUsage;
|
|
#ifdef _KUI_INVALIDATION
|
|
m_bDepth16Bit = bDepth16Bit;
|
|
#endif
|
|
D3DSURFACE_DESC desc;
|
|
m_d3dtex->GetLevelDesc( 0, &desc );
|
|
m_size.width = desc.Width;
|
|
m_size.height = desc.Height;
|
|
m_format = static_cast<K3DFORMAT>(desc.Format);
|
|
|
|
if( dwDepthUsage == DEPTH_ENABLE )
|
|
{
|
|
if( bDepth16Bit )
|
|
{
|
|
res = m_dev->GetD3DDevice()->CreateDepthStencilSurface( m_size.width, m_size.height,
|
|
D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, TRUE, &m_pD3DDepth, NULL );
|
|
}
|
|
else
|
|
{
|
|
res = m_dev->GetD3DDevice()->CreateDepthStencilSurface( m_size.width, m_size.height,
|
|
D3DFMT_D24X8, D3DMULTISAMPLE_NONE, 0, TRUE, &m_pD3DDepth, NULL );
|
|
}
|
|
if ( res != D3D_OK )
|
|
{
|
|
Clear();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// if( dwDepthUsage == DEPTH_ENABLE || dwDepthUsage == DEPTH_USEASTEXTURE)
|
|
// {
|
|
// //ATI 계열은 D3DFMT_D24X8, D3DFMT_D24S8 만들 수 없다.
|
|
// res = m_dev->GetD3DDevice()->CreateTexture( width, height, 1, D3DUSAGE_DEPTHSTENCIL, D3DFMT_D24X8, D3DPOOL_DEFAULT, &m_pD3DDepth, NULL );
|
|
//// res = m_dev->GetD3DDevice()->CreateTexture( width, height, 1, D3DUSAGE_DEPTHSTENCIL, D3DFMT_D24S8, D3DPOOL_DEFAULT, &m_pD3DDepth, NULL );
|
|
// if ( res != D3D_OK )
|
|
// {
|
|
// Clear();
|
|
// return false;
|
|
// }
|
|
// }
|
|
|
|
//if( dwDepthUsage == DEPTH_USEASTEXTURE )
|
|
//{
|
|
// m_pSurface = m_pD3DDepth;
|
|
//}
|
|
//else
|
|
//{
|
|
m_pSurface = m_d3dtex;
|
|
//}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DRenderTargetDX::IsValid() const
|
|
{
|
|
return m_d3dtex ? true : false;
|
|
}
|
|
|
|
void K3DRenderTargetDX::LockRect( KRect *rect, void** ppBuf, int& stride )
|
|
{
|
|
*ppBuf = NULL;
|
|
stride = 0;
|
|
}
|
|
|
|
void K3DRenderTargetDX::Unlock()
|
|
{
|
|
}
|
|
|
|
void K3DRenderTargetDX::CopyTo( K3DTexture *pTex )
|
|
{
|
|
LPDIRECT3DDEVICE9 d3ddev = m_dev->GetD3DDevice();
|
|
LPDIRECT3DSURFACE9 src, dst;
|
|
m_d3dtex->GetSurfaceLevel( 0, &src );
|
|
K3DTextureDX *pDXTex = reinterpret_cast<K3DTextureDX*>(pTex);
|
|
pDXTex->GetD3DTexture()->GetSurfaceLevel( 0, &dst );
|
|
HRESULT hr;
|
|
hr = d3ddev->StretchRect( src, NULL, dst, NULL, D3DTEXF_NONE );
|
|
assert( hr == S_OK );
|
|
|
|
SAFE_RELEASE(src);
|
|
SAFE_RELEASE(dst);
|
|
}
|
|
|
|
K3DTexture *K3DRenderTargetDX::CreateCloneTexture()
|
|
{
|
|
K3DTexture *pTex = m_dev->CreateTexture( GetWidth(), GetHeight(), GetFormat() );
|
|
CopyTo( pTex );
|
|
|
|
return pTex;
|
|
}
|
|
|
|
bool K3DRenderTargetDX::PreReload()
|
|
{
|
|
Clear();
|
|
return true;
|
|
}
|
|
|
|
bool K3DRenderTargetDX::Reload()
|
|
{
|
|
#ifdef _KUI_INVALIDATION
|
|
CreateNew( m_size.width, m_size.height, m_nLevels, m_format, m_dwDepthUsage, m_bDepth16Bit );
|
|
#else
|
|
CreateNew( m_size.width, m_size.height, m_nLevels, m_format, m_dwDepthUsage );
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DRenderTargetDX::SaveToFile( const std::string& strFile )
|
|
{
|
|
if( D3DXSaveTextureToFile( strFile.c_str(), D3DXIFF_DDS, m_d3dtex, NULL ) == D3D_OK ) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
///CubeTexture
|
|
K3DRenderTargetCubeDX::K3DRenderTargetCubeDX( K3DRenderDeviceDX* dev ) : m_dev( dev ),
|
|
m_d3dcubetex( NULL ),
|
|
m_pD3DDepth( NULL ),
|
|
m_bLocked( false )
|
|
{
|
|
}
|
|
|
|
K3DRenderTargetCubeDX::~K3DRenderTargetCubeDX()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void K3DRenderTargetCubeDX::Clear()
|
|
{
|
|
SAFE_RELEASE(m_d3dcubetex);
|
|
SAFE_RELEASE(m_pD3DDepth);
|
|
m_pSurface = NULL;
|
|
}
|
|
|
|
bool K3DRenderTargetCubeDX::CreateNew( DWORD size, UINT nLevels, K3DFORMAT format, DWORD dwDepthUsage )
|
|
{
|
|
Clear();
|
|
|
|
m_nLevels = nLevels;
|
|
|
|
HRESULT res = D3DXCreateCubeTexture( m_dev->GetD3DDevice(), size, m_nLevels, D3DUSAGE_RENDERTARGET,
|
|
GetD3DFormat(format), D3DPOOL_DEFAULT, &m_d3dcubetex );
|
|
if ( res != D3D_OK )
|
|
{
|
|
if( res == D3DERR_NOTAVAILABLE ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_NOTAVAILABLE" ); }
|
|
else if( res == D3DERR_OUTOFVIDEOMEMORY ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_OUTOFVIDEOMEMORY" ); }
|
|
else if( res == D3DERR_INVALIDCALL ) { _oprint( "***DEVICE ERROR : %s\n", "D3DERR_INVALIDCALL" ); }
|
|
else if( res == E_OUTOFMEMORY ) { _oprint( "***DEVICE ERROR : %s\n", "E_OUTOFMEMORY" ); }
|
|
|
|
Clear();
|
|
return false;
|
|
}
|
|
|
|
m_dwDepthUsage = dwDepthUsage;
|
|
D3DSURFACE_DESC desc;
|
|
m_d3dcubetex->GetLevelDesc( 0, &desc );
|
|
m_size.width = desc.Width;
|
|
m_size.height = desc.Height;
|
|
m_format = static_cast<K3DFORMAT>(desc.Format);
|
|
|
|
if( dwDepthUsage == DEPTH_ENABLE )
|
|
{
|
|
res = m_dev->GetD3DDevice()->CreateDepthStencilSurface( m_size.width, m_size.height,
|
|
D3DFMT_D24X8, D3DMULTISAMPLE_NONE, 0, TRUE, &m_pD3DDepth, NULL );
|
|
if ( res != D3D_OK )
|
|
{
|
|
Clear();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
m_pSurface = m_d3dcubetex;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DRenderTargetCubeDX::IsValid() const
|
|
{
|
|
return m_d3dcubetex ? true : false;
|
|
}
|
|
|
|
void K3DRenderTargetCubeDX::LockRect( KRect *rect, void** ppBuf, int& stride )
|
|
{
|
|
*ppBuf = NULL;
|
|
stride = 0;
|
|
}
|
|
|
|
void K3DRenderTargetCubeDX::Unlock()
|
|
{
|
|
}
|
|
|
|
void K3DRenderTargetCubeDX::CopyTo( K3DTexture *pTex )
|
|
{
|
|
K3DRenderTargetCubeDX *pDXCubeTex = reinterpret_cast<K3DRenderTargetCubeDX*>(pTex);
|
|
|
|
for( int nCubeface = 0; nCubeface < 6; ++nCubeface )
|
|
GetCubeMapSurface( pDXCubeTex, (D3DCUBEMAP_FACES)nCubeface );
|
|
}
|
|
|
|
void K3DRenderTargetCubeDX::GetCubeMapSurface( K3DRenderTargetCubeDX* pCubeTexture, D3DCUBEMAP_FACES cubeFace )
|
|
{
|
|
LPDIRECT3DDEVICE9 d3ddev = m_dev->GetD3DDevice();
|
|
LPDIRECT3DSURFACE9 src, dst;
|
|
|
|
m_d3dcubetex->GetCubeMapSurface( cubeFace, 0, &src );
|
|
pCubeTexture->GetD3DCubeTexture()->GetCubeMapSurface( cubeFace, 0, &dst );
|
|
|
|
HRESULT hr;
|
|
hr = d3ddev->StretchRect( src, NULL, dst, NULL, D3DTEXF_NONE );
|
|
assert( hr == S_OK );
|
|
|
|
SAFE_RELEASE(src);
|
|
SAFE_RELEASE(dst);
|
|
}
|
|
|
|
K3DTexture *K3DRenderTargetCubeDX::CreateCloneTexture()
|
|
{
|
|
K3DTexture *pTex = m_dev->CreateTexture( GetWidth(), GetHeight(), GetFormat() );
|
|
CopyTo( pTex );
|
|
|
|
return pTex;
|
|
}
|
|
|
|
bool K3DRenderTargetCubeDX::PreReload()
|
|
{
|
|
Clear();
|
|
return true;
|
|
}
|
|
|
|
bool K3DRenderTargetCubeDX::Reload()
|
|
{
|
|
CreateNew( m_size.width, m_nLevels, m_format, m_dwDepthUsage );
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//IndexBufferDX
|
|
K3DIndexBufferDX::K3DIndexBufferDX( K3DRenderDeviceDX *dev )
|
|
{
|
|
m_dev = dev;
|
|
m_bLocked = false;
|
|
m_d3dib = NULL;
|
|
}
|
|
|
|
K3DIndexBufferDX::~K3DIndexBufferDX()
|
|
{
|
|
if ( m_bLocked ) Unlock();
|
|
SAFE_RELEASE(m_d3dib);
|
|
}
|
|
|
|
bool K3DIndexBufferDX::Initialize( KStream &stream, int count, bool use32bit )
|
|
{
|
|
int formatsize;
|
|
int fmt;
|
|
if ( use32bit )
|
|
{
|
|
formatsize = 4;
|
|
fmt = D3DFMT_INDEX32;
|
|
}
|
|
else
|
|
{
|
|
formatsize = 2;
|
|
fmt = D3DFMT_INDEX16;
|
|
}
|
|
|
|
|
|
HRESULT hr = m_dev->GetD3DDevice()->CreateIndexBuffer(
|
|
count * formatsize, D3DUSAGE_WRITEONLY, static_cast<D3DFORMAT>(fmt), D3DPOOL_MANAGED, &m_d3dib, NULL );
|
|
unsigned char *pBuf;
|
|
if( hr == D3D_OK )
|
|
{
|
|
m_d3dib->Lock( 0, count * formatsize, (void**)&pBuf, 0 );
|
|
assert(pBuf && "m_d3dib->Lock( 0, count * formatsize, (void**)&pBuf, 0 );");
|
|
|
|
stream.Read( pBuf, count * formatsize );
|
|
|
|
m_d3dib->Unlock();
|
|
|
|
SetValidVtx( true );
|
|
|
|
m_format = static_cast<K3DFORMAT>(fmt);
|
|
m_idxCount = count;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool K3DIndexBufferDX::CreateNew( int count, bool use32bit )
|
|
{
|
|
int formatsize;
|
|
int fmt;
|
|
if ( use32bit )
|
|
{
|
|
formatsize = 4;
|
|
fmt = D3DFMT_INDEX32;
|
|
}
|
|
else
|
|
{
|
|
formatsize = 2;
|
|
fmt = D3DFMT_INDEX16;
|
|
}
|
|
m_format = static_cast<K3DFORMAT>(fmt);
|
|
m_idxCount = count;
|
|
HRESULT hr = m_dev->GetD3DDevice()->CreateIndexBuffer(
|
|
count * formatsize, D3DUSAGE_WRITEONLY, static_cast<D3DFORMAT>(fmt), D3DPOOL_MANAGED, &m_d3dib, NULL );
|
|
if( hr == D3D_OK )
|
|
{
|
|
SetValidVtx( true );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void K3DIndexBufferDX::Lock( void** ppBuf, int& size, DWORD flags )
|
|
{
|
|
if ( m_bLocked == false && m_d3dib != NULL )
|
|
{
|
|
//int formatsize = (m_format == K3DFMT_INDEX16) ? 2 : 4;
|
|
if ( m_d3dib->Lock( 0, 0, ppBuf, flags ) == D3D_OK )
|
|
{
|
|
m_bLocked = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ppBuf = NULL;
|
|
}
|
|
}
|
|
|
|
void K3DIndexBufferDX::Unlock()
|
|
{
|
|
if ( m_bLocked == true )
|
|
{
|
|
m_d3dib->Unlock();
|
|
m_bLocked = false;
|
|
|
|
}
|
|
}
|
|
|
|
bool K3DIndexBufferDX::PreReload()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool K3DIndexBufferDX::Reload()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
|
|
//#define _VB_DEBUG_
|
|
|
|
#ifdef _VB_DEBUG_
|
|
volatile int g_nVB_RefCount = 0;
|
|
#endif
|
|
|
|
K3DVertexBufferDX::K3DVertexBufferDX()
|
|
{
|
|
#ifdef _VB_DEBUG_
|
|
InterlockedIncrement( (volatile LONG *)&g_nVB_RefCount );
|
|
// _performance_print( "K3DVertexBufferDX 01 : %d\n", g_nVB_RefCount );
|
|
#endif
|
|
|
|
m_usage = D3DUSAGE_WRITEONLY;
|
|
m_type = RESTYPE_VERTEXBUFFER;
|
|
m_dev = NULL;
|
|
m_bLocked = false;
|
|
m_d3dvb = NULL;
|
|
//Device Lost 처리
|
|
m_pBackUpBuf = NULL;
|
|
m_bIsDeviceLost = false;
|
|
}
|
|
|
|
K3DVertexBufferDX::K3DVertexBufferDX( K3DRenderDeviceDX *dev )
|
|
{
|
|
#ifdef _VB_DEBUG_
|
|
InterlockedIncrement( (volatile LONG *)&g_nVB_RefCount );
|
|
// _performance_print( "K3DVertexBufferDX 02 : %d\n", g_nVB_RefCount );
|
|
#endif
|
|
|
|
m_usage = D3DUSAGE_WRITEONLY;
|
|
m_type = RESTYPE_VERTEXBUFFER;
|
|
m_dev = dev;
|
|
m_bLocked = false;
|
|
m_d3dvb = NULL;
|
|
//Device Lost 처리
|
|
m_pBackUpBuf = NULL;
|
|
m_bIsDeviceLost = false;
|
|
}
|
|
|
|
K3DVertexBufferDX::~K3DVertexBufferDX()
|
|
{
|
|
#ifdef _VB_DEBUG_
|
|
InterlockedDecrement( (volatile LONG *)&g_nVB_RefCount );
|
|
_performance_print( "K3DVertexBufferDX ~ : %d\tStride:%d\tvtxCount:%d\tFVF:%d\tUsage:%d\n", g_nVB_RefCount, m_vtxStride, m_vtxCount, m_format, m_usage );
|
|
#endif
|
|
|
|
//백업 버퍼 삭제
|
|
SAFE_DELETE_ARRAY( m_pBackUpBuf );
|
|
|
|
SAFE_RELEASE(m_d3dvb);
|
|
|
|
if( m_bIsDeviceLost && GetRefCount() <= 1 )
|
|
m_dev->DelReloadVertexList(this);
|
|
}
|
|
|
|
void K3DVertexBufferDX::Recycle() // 재사용
|
|
{
|
|
// KResource::Recycle(); //삭제 됨
|
|
// return;
|
|
|
|
if( m_bUseRecycle )
|
|
m_dev->AddRecycleVertexBuffer( this, m_format, m_usage, m_vtxStride, m_vtxCount );
|
|
else
|
|
KResource::Recycle(); //삭제 됨
|
|
}
|
|
|
|
bool K3DVertexBufferDX::Initialize( KStream &stream, int vertexformat, int count )
|
|
{
|
|
m_format = vertexformat;
|
|
m_vtxCount = count;
|
|
|
|
m_vtxStride = K3DVertexBuffer::CalcVertexStride( vertexformat );
|
|
HRESULT hr = m_dev->GetD3DDevice()->CreateVertexBuffer(
|
|
m_vtxStride * m_vtxCount, D3DUSAGE_WRITEONLY, vertexformat, D3DPOOL_MANAGED, &m_d3dvb, NULL );
|
|
|
|
if( hr == D3D_OK )
|
|
{
|
|
unsigned char *pBuf;
|
|
m_d3dvb->Lock( 0, m_vtxStride * m_vtxCount, (void**)&pBuf, 0 );
|
|
assert(pBuf && "m_d3dvb->Lock( 0, m_vtxStride * m_vtxCount, (void**)&pBuf, 0 );");
|
|
stream.Read( pBuf, m_vtxStride * m_vtxCount );
|
|
m_d3dvb->Unlock();
|
|
|
|
SetValidVtx( true );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DVertexBufferDX::CreateNewSpeedTree( unsigned int nStride, DWORD Usage, int count, int vertexformat )
|
|
{
|
|
m_bIsDeviceLost = true;
|
|
|
|
m_usage = Usage;
|
|
m_format = vertexformat;
|
|
m_vtxCount = count;
|
|
m_vtxStride = nStride;
|
|
m_type = RESTYPE_VERTEXBUFFERSPEEDTREE;
|
|
HRESULT hr;
|
|
if(m_usage & D3DUSAGE_DYNAMIC)
|
|
m_Pool = D3DPOOL_DEFAULT;
|
|
else
|
|
m_Pool = D3DPOOL_MANAGED;
|
|
|
|
hr = m_dev->GetD3DDevice()->CreateVertexBuffer( nStride * m_vtxCount, m_usage, vertexformat, m_Pool, &m_d3dvb, NULL );
|
|
|
|
if( hr == D3D_OK )
|
|
SetValidVtx( true );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DVertexBufferDX::CreateNewSpeedGrass( unsigned int nStride, DWORD Usage, int count, int vertexformat )
|
|
{
|
|
m_bIsDeviceLost = true;
|
|
|
|
m_usage = Usage;
|
|
m_format = vertexformat;
|
|
m_vtxCount = count;
|
|
m_vtxStride = nStride;
|
|
m_type = RESTYPE_VERTEXBUFFERSPEEDGRASS;
|
|
|
|
HRESULT hr;
|
|
if(m_usage & D3DUSAGE_DYNAMIC)
|
|
m_Pool = D3DPOOL_DEFAULT;
|
|
else
|
|
m_Pool = D3DPOOL_MANAGED;
|
|
|
|
hr = m_dev->GetD3DDevice()->CreateVertexBuffer( nStride * m_vtxCount, m_usage, vertexformat, m_Pool, &m_d3dvb, NULL );
|
|
|
|
if( hr == D3D_OK )
|
|
SetValidVtx( true );
|
|
|
|
return true;
|
|
}
|
|
|
|
//Blend 용 버텍스~
|
|
bool K3DVertexBufferDX::CreateNewBlend( unsigned int nStride, int count, int vertexformat )
|
|
{
|
|
m_format = vertexformat;
|
|
m_vtxCount = count;
|
|
m_vtxStride = nStride;
|
|
m_Pool = D3DPOOL_MANAGED;
|
|
|
|
HRESULT hr = m_dev->GetD3DDevice()->CreateVertexBuffer( nStride * m_vtxCount, m_usage, vertexformat, D3DPOOL_MANAGED, &m_d3dvb, NULL );
|
|
m_type = RESTYPE_VERTEXBUFFERBLEND;
|
|
|
|
if( hr == D3D_OK )
|
|
SetValidVtx( true );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DVertexBufferDX::CreateNewPoolDefault( unsigned int nStride, int count, int vertexformat, DWORD Usage )
|
|
{
|
|
m_format = vertexformat;
|
|
m_vtxCount = count;
|
|
m_vtxStride = nStride;
|
|
m_usage = Usage;
|
|
m_Pool = D3DPOOL_DEFAULT;
|
|
|
|
HRESULT hr = m_dev->GetD3DDevice()->CreateVertexBuffer( nStride * m_vtxCount, m_usage, vertexformat, D3DPOOL_DEFAULT, &m_d3dvb, NULL );
|
|
m_type = RESTYPE_VERTEXBUFFERPOOLDEFAULT;
|
|
|
|
if( hr == D3D_OK )
|
|
SetValidVtx( true );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DVertexBufferDX::CreateNew( int vertexformat, int count )
|
|
{
|
|
m_format = vertexformat;
|
|
m_vtxCount = count;
|
|
m_vtxStride = K3DVertexBuffer::CalcVertexStride( vertexformat );
|
|
m_Pool = D3DPOOL_MANAGED;
|
|
|
|
HRESULT hr = m_dev->GetD3DDevice()->CreateVertexBuffer(
|
|
m_vtxStride * m_vtxCount, D3DUSAGE_WRITEONLY, vertexformat, D3DPOOL_MANAGED, &m_d3dvb, NULL );
|
|
|
|
if( hr == D3D_OK )
|
|
SetValidVtx( true );
|
|
|
|
return true;
|
|
}
|
|
|
|
void K3DVertexBufferDX::Lock( void** pBuf, int& size, DWORD flags )
|
|
{
|
|
if ( m_bLocked == false && m_d3dvb != NULL )
|
|
{
|
|
if ( m_d3dvb->Lock( 0, 0, pBuf, flags ) == D3D_OK )
|
|
m_bLocked = true;
|
|
}
|
|
else
|
|
{
|
|
*pBuf = NULL;
|
|
}
|
|
}
|
|
|
|
void K3DVertexBufferDX::Unlock()
|
|
{
|
|
if ( m_bLocked == true && m_d3dvb )
|
|
{
|
|
m_d3dvb->Unlock();
|
|
m_bLocked = false;
|
|
}
|
|
}
|
|
|
|
bool K3DVertexBufferDX::Backup()
|
|
{
|
|
//버퍼에 백업..
|
|
int nSize = m_vtxCount*m_vtxStride;
|
|
SAFE_DELETE_ARRAY( m_pBackUpBuf );
|
|
m_pBackUpBuf = new char[nSize];
|
|
memset( m_pBackUpBuf, 0, sizeof(char)*nSize );
|
|
|
|
void *pTempBuf = NULL;
|
|
|
|
if(m_usage & D3DUSAGE_DYNAMIC)
|
|
Lock( (void**)&pTempBuf, nSize, D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD );
|
|
else
|
|
Lock( (void**)&pTempBuf, nSize );
|
|
|
|
if( pTempBuf )
|
|
{
|
|
memcpy( m_pBackUpBuf, pTempBuf, sizeof(char)*nSize );
|
|
Unlock();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DVertexBufferDX::PreReload()
|
|
{
|
|
SAFE_RELEASE(m_d3dvb);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool K3DVertexBufferDX::Reload()
|
|
{
|
|
//백업 버퍼로 복구
|
|
int nSize = m_vtxCount*m_vtxStride;
|
|
void *pTempBuf = NULL;
|
|
|
|
if( m_type == RESTYPE_VERTEXBUFFERSPEEDGRASS || m_type == RESTYPE_VERTEXBUFFERSPEEDTREE )
|
|
{
|
|
CreateNewSpeedTree( m_vtxStride, m_usage, m_vtxCount, m_format );
|
|
Lock( (void**)&pTempBuf, nSize );
|
|
}
|
|
else if ( m_type == RESTYPE_VERTEXBUFFERPOOLDEFAULT )
|
|
{
|
|
CreateNewPoolDefault( m_vtxStride, m_vtxCount, m_format, m_usage );
|
|
Lock( (void**)&pTempBuf, nSize, D3DLOCK_NOOVERWRITE );
|
|
if( pTempBuf == NULL )
|
|
Lock( (void**)&pTempBuf, nSize, D3DLOCK_DISCARD );
|
|
}
|
|
|
|
if( pTempBuf && m_pBackUpBuf )
|
|
{
|
|
memcpy( pTempBuf, m_pBackUpBuf, sizeof(char)*nSize );
|
|
}
|
|
|
|
Unlock();
|
|
|
|
return true;
|
|
}
|