fix refcnt issues with fpsmeter

This commit is contained in:
cxgeorge 2002-04-06 00:06:29 +00:00
parent 3546fff47e
commit ba517a3317
4 changed files with 71 additions and 45 deletions

View File

@ -63,7 +63,6 @@ CD3DFont::CD3DFont( TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags ) {
// Desc: Font class destructor
//-----------------------------------------------------------------------------
CD3DFont::~CD3DFont() {
InvalidateDeviceObjects();
DeleteDeviceObjects();
}
@ -124,7 +123,7 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
VARIABLE_PITCH, m_strFontName );
if(NULL==hFont) {
cout << "CD3DFont InitDeviceObjects(): initial CreateFont failed! GetLastError=" << GetLastError() << endl;
dxgsg_cat.error() << "CD3DFont InitDeviceObjects(): initial CreateFont failed! GetLastError=" << GetLastError() << endl;
return E_FAIL;
}
@ -195,7 +194,7 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
// moved here to allow deletion of GDI objects
if(dwTexSize == 0) {
cout << "CD3DFont InitDeviceObjects() error: Texture didnt fit, creation failed!\n";
dxgsg_cat.error() << "CD3DFont InitDeviceObjects() error: Texture didnt fit, creation failed!\n";
return E_FAIL;
}
@ -229,7 +228,7 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
VARIABLE_PITCH, m_strFontName );
if(NULL==hFont) {
cout << "CD3DFont InitDeviceObjects(): optimal CreateFont failed! GetLastError=" << GetLastError() << endl;
dxgsg_cat.error() << "CD3DFont InitDeviceObjects(): optimal CreateFont failed! GetLastError=" << GetLastError() << endl;
return E_FAIL;
}
@ -255,6 +254,7 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
hr = m_pd3dDevice->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1,
0, D3DFMT_A4R4G4B4,
D3DPOOL_MANAGED, &m_pTexture );
if(FAILED(hr)) {
SelectObject ( hDC, hbmOld );
SelectObject ( hDC, hfOld );
@ -263,7 +263,7 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
DeleteObject( hFont );
DeleteDC( hDC );
cout << "CD3DFont InitDeviceObjs CreateTexture failed!" << D3DERRORSTRING(hr);
dxgsg_cat.error() << "CD3DFont InitDeviceObjs CreateTexture failed!" << D3DERRORSTRING(hr);
return hr;
};
@ -341,10 +341,12 @@ HRESULT CD3DFont::RestoreDeviceObjects() {
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
D3DPOOL_DEFAULT, // D3DUSAGE_DYNAMIC makes D3DPOOL_MANAGED impossible
&m_pVB ) )) {
cout << "CD3DFont CreateVB failed!" << D3DERRORSTRING(hr);
dxgsg_cat.error() << "CD3DFont CreateVB failed!" << D3DERRORSTRING(hr);
return hr;
}
PRINT_REFCNT(dxgsg,m_pd3dDevice);
// Create the state blocks for rendering text
for(UINT which=0; which<2; which++) {
m_pd3dDevice->BeginStateBlock();
@ -399,15 +401,26 @@ HRESULT CD3DFont::RestoreDeviceObjects() {
// Desc: Destroys all device-dependent objects
//-----------------------------------------------------------------------------
HRESULT CD3DFont::InvalidateDeviceObjects() {
/*
#ifdef _DEBUG
if(m_pVB) {
cout << "XXXX Releasing Font VertexBuffer\n";
}
#endif
*/
HRESULT hr;
SAFE_RELEASE( m_pVB );
PRINT_REFCNT(dxgsg,m_pd3dDevice);
if(IS_VALID_PTR(m_pd3dDevice)) {
// undo SetStreamSource before releasing VB
IDirect3DVertexBuffer8 *pStreamData=NULL;
UINT StreamStride;
hr = m_pd3dDevice->GetStreamSource(0,&pStreamData,&StreamStride);
SAFE_RELEASE(pStreamData); // undo GetStreamSource AddRef
if(pStreamData==m_pVB)
hr = m_pd3dDevice->SetStreamSource(0,NULL,0);
}
PRINT_REFCNT(dxgsg,m_pVB);
RELEASE(m_pVB,dxgsg,"d3dfont VB",RELEASE_ONCE);
PRINT_REFCNT(dxgsg,m_pd3dDevice);
// Delete the state blocks
if(m_pd3dDevice) {
@ -418,6 +431,8 @@ HRESULT CD3DFont::InvalidateDeviceObjects() {
m_pd3dDevice->DeleteStateBlock( m_dwDrawTextStateBlock );
}
PRINT_REFCNT(dxgsg,m_pd3dDevice);
m_dwSavedStateBlock = NULL;
m_dwDrawTextStateBlock = NULL;
@ -430,8 +445,14 @@ HRESULT CD3DFont::InvalidateDeviceObjects() {
// Desc: Destroys all device-dependent objects
//-----------------------------------------------------------------------------
HRESULT CD3DFont::DeleteDeviceObjects() {
PRINT_REFCNT(dxgsg,m_pd3dDevice);
InvalidateDeviceObjects();
SAFE_RELEASE( m_pTexture );
PRINT_REFCNT(dxgsg,m_pd3dDevice);
m_pd3dDevice = NULL;
return S_OK;
@ -560,7 +581,7 @@ HRESULT CD3DFont::DeferedDraw
FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
TCHAR* strText, DWORD dwFlags ) {
if(m_nDeferedCalls >= MaxCalls) {
cout << "CD3DFont DeferedDraw() error, MaxCalls exceeded!\n";
dxgsg_cat.error() << "CD3DFont DeferedDraw() error, MaxCalls exceeded!\n";
return E_FAIL ;
}
@ -570,7 +591,7 @@ HRESULT CD3DFont::DeferedDraw
int nStrLen = strlen ( strText ) + 1 ;
int nUsed = m_pTextBuffer - & m_pTextBuffer [ 0 ] ;
if(nUsed + nStrLen > TextBufferLength) {
cout << "CD3DFont DeferedDraw() error, TextBufferLength exceeded!\n";
dxgsg_cat.error() << "CD3DFont DeferedDraw() error, TextBufferLength exceeded!\n";
return E_FAIL ;
}
@ -616,14 +637,17 @@ HRESULT CD3DFont::EndText ( void ) {
hr = m_pd3dDevice->GetStreamSource(0,&pSavedStreamData,&SavedStreamStride);
if(FAILED(hr)) {
cout << "CD3DFont EndText GetStreamSource() failed!" << D3DERRORSTRING(hr);
dxgsg_cat.error() << "CD3DFont EndText GetStreamSource() failed!" << D3DERRORSTRING(hr);
return E_FAIL;
}
// undo GetStreamSource AddRef
SAFE_RELEASE(pSavedStreamData);
if((pSavedStreamData!=m_pVB)||(SavedStreamStride!=sizeof(FONT2DVERTEX))) {
hr = m_pd3dDevice->SetStreamSource(0,m_pVB,sizeof(FONT2DVERTEX));
if(FAILED(hr)) {
cout << "CD3DFont EndText initial SetStreamSource() failed!" << D3DERRORSTRING(hr);
dxgsg_cat.error() << "CD3DFont EndText initial SetStreamSource() failed!" << D3DERRORSTRING(hr);
return E_FAIL;
}
}
@ -797,7 +821,7 @@ HRESULT CD3DFont::EndText ( void ) {
if(IS_VALID_PTR(pSavedStreamData) && ((pSavedStreamData!=m_pVB)||(SavedStreamStride!=sizeof(FONT2DVERTEX)))) {
hr = m_pd3dDevice->SetStreamSource(0,pSavedStreamData,SavedStreamStride);
if(FAILED(hr)) {
cout << "CD3DFont EndText restore SetStreamSource() failed!" << D3DERRORSTRING(hr);
dxgsg_cat.error() << "CD3DFont EndText restore SetStreamSource() failed!" << D3DERRORSTRING(hr);
return E_FAIL;
}
pSavedStreamData->Release();

View File

@ -387,8 +387,6 @@ reset(void) {
// recreate dx objects without modifying gsg state, other than clearing state cache
void DXGraphicsStateGuardian::
free_dxgsg_objects(void) {
ULONG refcnt;
// dont want a full reset of gsg, just a state clear
GraphicsStateGuardian::clear_cached_state(); // want gsg to pass all state settings through
@ -737,9 +735,14 @@ dx_init(HCURSOR hMouseCursor) {
hr=S_OK;
SIZE TextRectSize;
PRINT_REFCNT(dxgsg,scrn.pD3DDevice);
_pStatMeterFont = new CD3DFont(_T("Arial"),12,D3DFONT_BOLD);
PRINT_REFCNT(dxgsg,scrn.pD3DDevice);
if(IS_VALID_PTR(_pStatMeterFont))
hr=_pStatMeterFont->InitDeviceObjects(scrn.pD3DDevice);
PRINT_REFCNT(dxgsg,scrn.pD3DDevice);
if(IS_VALID_PTR(_pStatMeterFont) && SUCCEEDED(hr)) {
// instead of computing offset every frame (could change based on font chars,
// do it once here. if we wanted top left corner instead of top right,
@ -754,6 +757,8 @@ dx_init(HCURSOR hMouseCursor) {
sprintf(fps_msg,FPS_MSG_FORMAT_STR,xsize,ysize,32,800.00f); // 6 == NUM_FPSMETER_LETTERS
hr = _pStatMeterFont->GetTextExtent(fps_msg,&TextRectSize);
PRINT_REFCNT(dxgsg,scrn.pD3DDevice);
if(SUCCEEDED(hr)) {
UINT xsize = scrn.pProps->_xsize;
@ -777,6 +782,7 @@ dx_init(HCURSOR hMouseCursor) {
_current_fps = 0.0f;
_start_frame_count = _cur_frame_count = 0;
}
PRINT_REFCNT(dxgsg,scrn.pD3DDevice);
// Make sure the DX state matches all of our initial attribute states.
PT(DepthTestTransition) dta = new DepthTestTransition;
@ -788,6 +794,8 @@ dx_init(HCURSOR hMouseCursor) {
dwa->issue(this);
cfa->issue(this);
ta->issue(this); // no curtextcontext, this does nothing. dx should already be properly inited above anyway
PRINT_REFCNT(dxgsg,scrn.pD3DDevice);
}
////////////////////////////////////////////////////////////////////
@ -3527,7 +3535,6 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
(void) ConvertD3DSurftoPixBuf(SrcCopyRect,pD3DSurf,pb);
ULONG refcnt;
RELEASE(pD3DSurf,dxgsg,"pD3DSurf",RELEASE_ONCE);
nassertv(!pb->_image.empty());
@ -5644,25 +5651,21 @@ dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled) {
if(bAtExitFnEverCalled)
return;
ULONG refcnt;
// unsafe to do the D3D releases after exit() called, since DLL_PROCESS_DETACH
// msg already delivered to d3d.dll and it's unloaded itself
if(!bAtExitFnEverCalled) {
PRINTREFCNT(scrn.pD3DDevice,"exit start IIDirect3DDevice8");
PRINT_REFCNT(dxgsg,scrn.pD3DDevice);
// these 2 calls release ddraw surfaces and vbuffers. unsafe unless not on exit
release_all_textures();
release_all_geoms();
PRINT_REFCNT(dxgsg,scrn.pD3DDevice);
SAFE_DELETE(_pStatMeterFont);
PRINTREFCNT(scrn.pD3DDevice,"after release_all_textures IDirect3DDevice8");
// RELEASE(_fpsmeter_font_surf,dxgsg,"fpsmeter fontsurf",false);
// PRINTREFCNT(scrn.pD3DDevice,"after fpsfont release IDirect3DDevice8");
PRINT_REFCNT(dxgsg,scrn.pD3DDevice);
// Do a safe check for releasing the D3DDEVICE. RefCount should be zero.
// if we're called from exit(), scrn.pD3DDevice may already have been released
@ -6901,7 +6904,6 @@ End:
SAFE_DELETE_ARRAY( pcrArrayColor );
SAFE_DELETE_ARRAY( pcrArrayMask );
ULONG refcnt;
RELEASE(pCursorBitmap,dxgsg,"pCursorBitmap",RELEASE_ONCE);
return hr;
}

View File

@ -1434,7 +1434,6 @@ IDirect3DTexture8 *DXTextureContext::CreateTexture(DXScreenData &scrn) {
return _pD3DTexture8;
error_exit:
ULONG refcnt;
RELEASE(_pD3DTexture8,dxgsg,"texture",RELEASE_ONCE);
return NULL;
@ -1496,7 +1495,6 @@ FillDDSurfTexturePixels(void) {
}
exit_FillDDSurf:
ULONG refcnt;
RELEASE(pMipLevel0,dxgsg,"texture",RELEASE_ONCE);
return hr;
@ -1755,8 +1753,6 @@ DeleteTexture( ) {
dxgsg_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n";
}
ULONG refcnt;
RELEASE(_pD3DTexture8,dxgsg,"texture",RELEASE_ONCE);
/*
#ifdef DEBUG_RELEASES

View File

@ -79,13 +79,14 @@
#define RELEASE_DOWN_TO_ZERO true
#define RELEASE_ONCE false
// #define DEBUG_RELEASES
//#define DEBUG_RELEASES
#ifdef DEBUG_RELEASES
#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) \
if(((OBJECT)!=NULL) && IS_VALID_PTR(OBJECT)) { \
#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) { \
ULONG refcnt; \
if(IS_VALID_PTR(OBJECT)) { \
refcnt = (OBJECT)->Release(); \
MODULE##_cat.debug() << DBGSTR << " released, refcnt = " << refcnt << endl; \
MODULE##_cat.debug() << DBGSTR << " released, refcnt = " << refcnt << " at " << __FILE__ << ":" << __LINE__ << endl; \
if((bDoDownToZero) && (refcnt>0)) { \
MODULE##_cat.warning() << DBGSTR << " released but still has a non-zero refcnt(" << refcnt << "), multi-releasing it down to zero!\n"; \
do { \
@ -95,12 +96,15 @@
(OBJECT) = NULL; \
} else { \
MODULE##_cat.debug() << DBGSTR << " not released, ptr == NULL" << endl; \
}
}}
#define PRINTREFCNT(OBJECT,STR) { (OBJECT)->AddRef(); dxgsg_cat.debug() << STR << " refcnt = " << (OBJECT)->Release() << endl; }
#define PRINT_REFCNT(MODULE,p) { ULONG refcnt; (p)->AddRef(); refcnt=(p)->Release(); \
MODULE##_cat.debug() << #p << " has refcnt = " << refcnt << " at " << __FILE__ << ":" << __LINE__ << endl; }
#else
#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) \
if(((OBJECT)!=NULL)&&(!IsBadWritePtr((OBJECT),4))) { \
#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) { \
ULONG refcnt; \
if(IS_VALID_PTR(OBJECT)) { \
refcnt=(OBJECT)->Release(); \
if((bDoDownToZero) && (refcnt>0)) { \
MODULE##_cat.warning() << DBGSTR << " released but still has a non-zero refcnt(" << refcnt << "), multi-releasing it down to zero!\n"; \
@ -109,9 +113,9 @@
} while(refcnt>0); \
} \
(OBJECT) = NULL; \
}
}}
#define PRINTREFCNT(OBJECT,STR)
#define PRINT_REFCNT(MODULE,p)
#endif
#ifdef DO_PSTATS