Просмотр исходного кода

update resize stuff, add d3dfont

cxgeorge 24 лет назад
Родитель
Сommit
b63d9bed71

+ 2 - 2
panda/src/dxgsg8/Sources.pp

@@ -15,7 +15,7 @@
   // need to install these due to external projects that link directly with libpandadx (bartop)  
   // need to install these due to external projects that link directly with libpandadx (bartop)  
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \
     dxgsg8base.h config_dxgsg8.h dxGraphicsStateGuardian8.I dxGraphicsStateGuardian8.h \
     dxgsg8base.h config_dxgsg8.h dxGraphicsStateGuardian8.I dxGraphicsStateGuardian8.h \
-    dxTextureContext8.h dxGeomNodeContext8.h dxGeomNodeContext8.I
+    dxTextureContext8.h dxGeomNodeContext8.h dxGeomNodeContext8.I d3dfont8.h
 
 
   // build dxGraphicsStateGuardian separately since its so big
   // build dxGraphicsStateGuardian separately since its so big
   
   
@@ -23,6 +23,6 @@
     dxGraphicsStateGuardian8.cxx dxSavedFrameBuffer8.I dxSavedFrameBuffer8.h $[INSTALL_HEADERS]
     dxGraphicsStateGuardian8.cxx dxSavedFrameBuffer8.I dxSavedFrameBuffer8.h $[INSTALL_HEADERS]
     
     
   #define INCLUDED_SOURCES \
   #define INCLUDED_SOURCES \
-    config_dxgsg8.cxx dxSavedFrameBuffer8.cxx dxTextureContext8.cxx dxGeomNodeContext8.cxx
+    config_dxgsg8.cxx dxSavedFrameBuffer8.cxx dxTextureContext8.cxx dxGeomNodeContext8.cxx d3dfont8.cxx
 
 
 #end lib_target
 #end lib_target

+ 633 - 0
panda/src/dxgsg8/d3dfont8.cxx

@@ -0,0 +1,633 @@
+//-----------------------------------------------------------------------------
+// File: D3DFont.cpp
+//
+// Desc: Texture-based font class
+//
+//-----------------------------------------------------------------------------
+
+#ifndef STRICT
+#define STRICT
+#endif
+
+#include "dxgsg8base.h"
+#include <stdio.h>
+#include <tchar.h>
+#include <d3dx8.h>
+#include "d3dfont8.h"
+
+//-----------------------------------------------------------------------------
+// Custom vertex types for rendering text
+//-----------------------------------------------------------------------------
+#define MAX_NUM_VERTICES 50*6
+
+struct FONT2DVERTEX {
+    D3DXVECTOR4 p;   DWORD color;     FLOAT tu, tv;
+};
+struct FONT3DVERTEX {
+    D3DXVECTOR3 p;   D3DXVECTOR3 n;   FLOAT tu, tv;
+};
+
+#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
+#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
+
+inline FONT2DVERTEX InitFont2DVertex( const D3DXVECTOR4& p, D3DCOLOR color,
+                                      FLOAT tu, FLOAT tv ) {
+    FONT2DVERTEX v;   v.p = p;   v.color = color;   v.tu = tu;   v.tv = tv;
+    return v;
+}
+
+inline FONT3DVERTEX InitFont3DVertex( const D3DXVECTOR3& p, const D3DXVECTOR3& n,
+                                      FLOAT tu, FLOAT tv ) {
+    FONT3DVERTEX v;   v.p = p;   v.n = n;   v.tu = tu;   v.tv = tv;
+    return v;
+}
+
+//-----------------------------------------------------------------------------
+// Name: CD3DFont()
+// Desc: Font class constructor
+//-----------------------------------------------------------------------------
+CD3DFont::CD3DFont( TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags ) {
+    _tcscpy( m_strFontName, strFontName );
+    m_dwFontHeight         = dwHeight;
+    m_dwFontFlags          = dwFlags;
+
+    m_pd3dDevice           = NULL;
+    m_pTexture             = NULL;
+    m_pVB                  = NULL;
+
+    m_dwSavedStateBlock    = 0L;
+    m_dwDrawTextStateBlock = 0L;
+}
+
+//-----------------------------------------------------------------------------
+// Name: ~CD3DFont()
+// Desc: Font class destructor
+//-----------------------------------------------------------------------------
+CD3DFont::~CD3DFont() {
+    InvalidateDeviceObjects();
+    DeleteDeviceObjects();
+}
+
+//-----------------------------------------------------------------------------
+// Name: InitDeviceObjects()
+// Desc: Initializes device-dependent objects, including the vertex buffer used
+//       for rendering text and the texture map which stores the font image.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
+    HRESULT hr;
+
+    // Keep a local copy of the device
+    m_pd3dDevice = pd3dDevice;
+
+    // Establish the font and texture size
+    m_fTextScale  = 1.0f; // Draw fonts into texture without scaling
+
+    // Large fonts need larger textures
+    if(m_dwFontHeight > 40)
+        m_dwTexWidth = m_dwTexHeight = 1024;
+    else if(m_dwFontHeight > 20)
+        m_dwTexWidth = m_dwTexHeight = 512;
+    else
+        m_dwTexWidth  = m_dwTexHeight = 256;
+
+    // If requested texture is too big, use a smaller texture and smaller font,
+    // and scale up when rendering.
+    D3DCAPS8 d3dCaps;
+    m_pd3dDevice->GetDeviceCaps( &d3dCaps );
+
+    if(m_dwTexWidth > d3dCaps.MaxTextureWidth) {
+        m_fTextScale = (FLOAT)d3dCaps.MaxTextureWidth / (FLOAT)m_dwTexWidth;
+        m_dwTexWidth = m_dwTexHeight = d3dCaps.MaxTextureWidth;
+    }
+
+    // Create a new texture for the font
+    hr = m_pd3dDevice->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1,
+                                      0, D3DFMT_A4R4G4B4,
+                                      D3DPOOL_MANAGED, &m_pTexture );
+    if(FAILED(hr)) {
+        cout << "CD3DFONT CreateTexture failed!" << D3DERRORSTRING(hr);
+        return hr;
+    }
+
+    // Prepare to create a bitmap
+    DWORD*      pBitmapBits;
+    BITMAPINFO bmi;
+    ZeroMemory( &bmi.bmiHeader,  sizeof(BITMAPINFOHEADER) );
+    bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
+    bmi.bmiHeader.biWidth       =  (int)m_dwTexWidth;
+    bmi.bmiHeader.biHeight      = -(int)m_dwTexHeight;
+    bmi.bmiHeader.biPlanes      = 1;
+    bmi.bmiHeader.biCompression = BI_RGB;
+    bmi.bmiHeader.biBitCount    = 32;
+
+    // Create a DC and a bitmap for the font
+    HDC     hDC       = CreateCompatibleDC( NULL );
+    HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
+                                          (VOID**)&pBitmapBits, NULL, 0 );
+    SetMapMode( hDC, MM_TEXT );
+
+    // Create a font.  By specifying ANTIALIASED_QUALITY, we might get an
+    // antialiased font, but this is not guaranteed.
+    INT nHeight    = -MulDiv( m_dwFontHeight, 
+                              (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
+    DWORD dwBold   = (m_dwFontFlags&D3DFONT_BOLD)   ? FW_BOLD : FW_NORMAL;
+    DWORD dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE    : FALSE;
+    HFONT hFont    = CreateFont( nHeight, 0, 0, 0, dwBold, dwItalic,
+                                 FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
+                                 CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
+                                 VARIABLE_PITCH, m_strFontName );
+    if(NULL==hFont) {
+        cout << "CD3DFONT CreateFont failed!\n";
+        return E_FAIL;
+    }
+
+    SelectObject( hDC, hbmBitmap );
+    SelectObject( hDC, hFont );
+
+    // Set text properties
+    SetTextColor( hDC, RGB(255,255,255) );
+    SetBkColor(   hDC, 0x00000000 );
+    SetTextAlign( hDC, TA_TOP );
+
+    // Loop through all printable character and output them to the bitmap..
+    // Meanwhile, keep track of the corresponding tex coords for each character.
+    DWORD x = 0;
+    DWORD y = 0;
+    TCHAR str[2] = _T("x");
+    SIZE size;
+
+    for(TCHAR c=32; c<127; c++) {
+        str[0] = c;
+        GetTextExtentPoint32( hDC, str, 1, &size );
+
+        if((DWORD)(x+size.cx+1) > m_dwTexWidth) {
+            x  = 0;
+            y += size.cy+1;
+        }
+
+        ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL );
+
+        m_fTexCoords[c-32][0] = ((FLOAT)(x+0))/m_dwTexWidth;
+        m_fTexCoords[c-32][1] = ((FLOAT)(y+0))/m_dwTexHeight;
+        m_fTexCoords[c-32][2] = ((FLOAT)(x+0+size.cx))/m_dwTexWidth;
+        m_fTexCoords[c-32][3] = ((FLOAT)(y+0+size.cy))/m_dwTexHeight;
+
+        x += size.cx+1;
+    }
+
+    // Lock the surface and write the alpha values for the set pixels
+    D3DLOCKED_RECT d3dlr;
+    m_pTexture->LockRect( 0, &d3dlr, 0, 0 );
+    BYTE* pDstRow = (BYTE*)d3dlr.pBits;
+    WORD* pDst16;
+    BYTE bAlpha; // 4-bit measure of pixel intensity
+
+    for(y=0; y < m_dwTexHeight; y++) {
+        pDst16 = (WORD*)pDstRow;
+        for(x=0; x < m_dwTexWidth; x++) {
+            bAlpha = (BYTE)((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4);
+            if(bAlpha > 0) {
+                *pDst16++ = (bAlpha << 12) | 0x0fff;
+            } else {
+                *pDst16++ = 0x0000;
+            }
+        }
+        pDstRow += d3dlr.Pitch;
+    }
+
+    // Done updating texture, so clean up used objects
+    m_pTexture->UnlockRect(0);
+    DeleteObject( hbmBitmap );
+    DeleteDC( hDC );
+    DeleteObject( hFont );
+
+    return RestoreDeviceObjects();
+}
+
+//-----------------------------------------------------------------------------
+// Name: RestoreDeviceObjects()
+// Desc:
+//-----------------------------------------------------------------------------
+HRESULT CD3DFont::RestoreDeviceObjects(void) {
+    HRESULT hr;
+
+    // Create vertex buffer for the letters
+    if(FAILED( hr = m_pd3dDevice->CreateVertexBuffer( MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
+                                                      D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
+                                                      D3DPOOL_DEFAULT, &m_pVB ) )) {
+        cout << "CD3DFONT::RestoreDevObjs() CreateVB failed!" << D3DERRORSTRING(hr);
+        return hr;
+    }
+
+    // Create the state blocks for rendering text
+    for(UINT which=0; which<2; which++) {
+        m_pd3dDevice->BeginStateBlock();
+        m_pd3dDevice->SetTexture( 0, m_pTexture );
+
+        if(D3DFONT_ZENABLE & m_dwFontFlags)
+            m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
+        else
+            m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
+
+        m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
+        m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,   D3DBLEND_SRCALPHA );
+        m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,  D3DBLEND_INVSRCALPHA );
+        m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE,  TRUE );
+        m_pd3dDevice->SetRenderState( D3DRS_ALPHAREF,         0x08 );
+        m_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC,  D3DCMP_GREATEREQUAL );
+        m_pd3dDevice->SetRenderState( D3DRS_FILLMODE,   D3DFILL_SOLID );
+        m_pd3dDevice->SetRenderState( D3DRS_CULLMODE,   D3DCULL_CCW );
+        m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE,    FALSE );
+        m_pd3dDevice->SetRenderState( D3DRS_CLIPPING,         TRUE );
+        m_pd3dDevice->SetRenderState( D3DRS_EDGEANTIALIAS,    FALSE );
+        m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE,  FALSE );
+        m_pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND,      FALSE );
+        m_pd3dDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE );
+        m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,        FALSE );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_POINT );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_POINT );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
+        m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_DISABLE );
+        m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
+
+        if(which==0)
+            m_pd3dDevice->EndStateBlock( &m_dwSavedStateBlock );
+        else
+            m_pd3dDevice->EndStateBlock( &m_dwDrawTextStateBlock );
+    }
+
+    return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: InvalidateDeviceObjects()
+// Desc: Destroys all device-dependent objects
+//-----------------------------------------------------------------------------
+HRESULT CD3DFont::InvalidateDeviceObjects() {
+    SAFE_RELEASE( m_pVB );
+
+    // Delete the state blocks
+    if(IS_VALID_PTR(m_pd3dDevice)) {
+        if(m_dwSavedStateBlock)
+            m_pd3dDevice->DeleteStateBlock( m_dwSavedStateBlock );
+        if(m_dwDrawTextStateBlock)
+            m_pd3dDevice->DeleteStateBlock( m_dwDrawTextStateBlock );
+    }
+
+    m_dwSavedStateBlock    = NULL;
+    m_dwDrawTextStateBlock = NULL;
+
+    return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: DeleteDeviceObjects()
+// Desc: Destroys all device-dependent objects
+//-----------------------------------------------------------------------------
+HRESULT CD3DFont::DeleteDeviceObjects() {
+    SAFE_RELEASE( m_pTexture );
+    m_pd3dDevice = NULL;
+
+    return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: GetTextExtent()
+// Desc: Get the dimensions of a text string
+//-----------------------------------------------------------------------------
+HRESULT CD3DFont::GetTextExtent( TCHAR* strText, SIZE* pSize ) {
+    if(NULL==strText || NULL==pSize)
+        return E_FAIL;
+
+    FLOAT fRowWidth  = 0.0f;
+    FLOAT fRowHeight = (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight;
+    FLOAT fWidth     = 0.0f;
+    FLOAT fHeight    = fRowHeight;
+
+    while(*strText) {
+        TCHAR c = *strText++;
+
+        if(c == _T('\n')) {
+            fRowWidth = 0.0f;
+            fHeight  += fRowHeight;
+        }
+        if(c < _T(' '))
+            continue;
+
+        FLOAT tx1 = m_fTexCoords[c-32][0];
+        FLOAT tx2 = m_fTexCoords[c-32][2];
+
+        fRowWidth += (tx2-tx1)*m_dwTexWidth;
+
+        if(fRowWidth > fWidth)
+            fWidth = fRowWidth;
+    }
+
+    pSize->cx = (int)fWidth;
+    pSize->cy = (int)fHeight;
+
+    return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: DrawTextScaled()
+// Desc: Draws scaled 2D text.  Note that x and y are in viewport coordinates
+//       (ranging from -1 to +1).  fXScale and fYScale are the size fraction 
+//       relative to the entire viewport.  For example, a fXScale of 0.25 is
+//       1/8th of the screen width.  This allows you to output text at a fixed
+//       fraction of the viewport, even if the screen or window size changes.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,
+                                  FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
+                                  TCHAR* strText, DWORD dwFlags ) {
+    if(m_pd3dDevice == NULL)
+        return E_FAIL;
+
+    // Set up renderstate
+    m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock );
+    m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock );
+    m_pd3dDevice->SetVertexShader( D3DFVF_FONT2DVERTEX );
+    m_pd3dDevice->SetPixelShader( NULL );
+    m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT2DVERTEX) );
+
+    // Set filter states
+    if(dwFlags & D3DFONT_FILTERED) {
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
+    }
+
+    D3DVIEWPORT8 vp;
+    m_pd3dDevice->GetViewport( &vp );
+    FLOAT sx  = (x+1.0f)*vp.Width/2;
+    FLOAT sy  = (y+1.0f)*vp.Height/2;
+    FLOAT sz  = z;
+    FLOAT rhw = 1.0f;
+    FLOAT fStartX = sx;
+
+    FLOAT fLineHeight = ( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight;
+
+    // Fill vertex buffer
+    FONT2DVERTEX* pVertices;
+    DWORD         dwNumTriangles = 0L;
+    m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
+
+    while(*strText) {
+        TCHAR c = *strText++;
+
+        if(c == _T('\n')) {
+            sx  = fStartX;
+            sy += fYScale*vp.Height;
+        }
+        if(c < _T(' '))
+            continue;
+
+        FLOAT tx1 = m_fTexCoords[c-32][0];
+        FLOAT ty1 = m_fTexCoords[c-32][1];
+        FLOAT tx2 = m_fTexCoords[c-32][2];
+        FLOAT ty2 = m_fTexCoords[c-32][3];
+
+        FLOAT w = (tx2-tx1)*m_dwTexWidth;
+        FLOAT h = (ty2-ty1)*m_dwTexHeight;
+
+        w *= (fXScale*vp.Width)/fLineHeight;
+        h *= (fYScale*vp.Height)/fLineHeight;
+
+        if(c != _T(' ')) {
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx1, ty2 );
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 );
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 );
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx2, ty1 );
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 );
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 );
+            dwNumTriangles += 2;
+
+            if(dwNumTriangles*3 > (MAX_NUM_VERTICES-6)) {
+                // Unlock, render, and relock the vertex buffer
+                m_pVB->Unlock();
+                m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
+                m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
+                dwNumTriangles = 0L;
+            }
+        }
+
+        sx += w;
+    }
+
+    // Unlock and render the vertex buffer
+    m_pVB->Unlock();
+    if(dwNumTriangles > 0)
+        m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
+
+    // Restore the modified renderstates
+    m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock );
+
+    return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: DrawText()
+// Desc: Draws 2D text
+//-----------------------------------------------------------------------------
+HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
+                            TCHAR* strText, DWORD dwFlags ) {
+    if(m_pd3dDevice == NULL)
+        return E_FAIL;
+
+    // Setup renderstate
+    m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock );
+    m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock );
+    m_pd3dDevice->SetVertexShader( D3DFVF_FONT2DVERTEX );
+    m_pd3dDevice->SetPixelShader( NULL );
+    m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT2DVERTEX) );
+
+    // Set filter states
+    if(dwFlags & D3DFONT_FILTERED) {
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
+    }
+
+    FLOAT fStartX = sx;
+
+    // Fill vertex buffer
+    FONT2DVERTEX* pVertices = NULL;
+    DWORD         dwNumTriangles = 0;
+    m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
+
+    while(*strText) {
+        TCHAR c = *strText++;
+
+        if(c == _T('\n')) {
+            sx = fStartX;
+            sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight;
+        }
+        if(c < _T(' '))
+            continue;
+
+        FLOAT tx1 = m_fTexCoords[c-32][0];
+        FLOAT ty1 = m_fTexCoords[c-32][1];
+        FLOAT tx2 = m_fTexCoords[c-32][2];
+        FLOAT ty2 = m_fTexCoords[c-32][3];
+
+        FLOAT w = (tx2-tx1) *  m_dwTexWidth / m_fTextScale;
+        FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale;
+
+        if(c != _T(' ')) {
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx1, ty2 );
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 );
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 );
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx2, ty1 );
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 );
+            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 );
+            dwNumTriangles += 2;
+
+            if(dwNumTriangles*3 > (MAX_NUM_VERTICES-6)) {
+                // Unlock, render, and relock the vertex buffer
+                m_pVB->Unlock();
+                m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
+                pVertices = NULL;
+                m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
+                dwNumTriangles = 0L;
+            }
+        }
+
+        sx += w;
+    }
+
+    // Unlock and render the vertex buffer
+    m_pVB->Unlock();
+    if(dwNumTriangles > 0)
+        m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
+
+    // Restore the modified renderstates
+    m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock );
+
+    return S_OK;
+}
+
+
+/*
+
+//-----------------------------------------------------------------------------
+// Name: Render3DText()
+// Desc: Renders 3D text
+//-----------------------------------------------------------------------------
+HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
+{
+    if( m_pd3dDevice == NULL )
+        return E_FAIL;
+
+    // Setup renderstate
+    m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock );
+    m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock );
+    m_pd3dDevice->SetVertexShader( D3DFVF_FONT3DVERTEX );
+    m_pd3dDevice->SetPixelShader( NULL );
+    m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT3DVERTEX) );
+
+    // Set filter states
+    if( dwFlags & D3DFONT_FILTERED )
+    {
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
+        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
+    }
+
+    // Position for each text element
+    FLOAT x = 0.0f;
+    FLOAT y = 0.0f;
+
+    // Center the text block at the origin
+    if( dwFlags & D3DFONT_CENTERED )
+    {
+        SIZE sz;
+        GetTextExtent( strText, &sz );
+        x = -(((FLOAT)sz.cx)/10.0f)/2.0f;
+        y = -(((FLOAT)sz.cy)/10.0f)/2.0f;
+    }
+
+    // Turn off culling for two-sided text
+    if( dwFlags & D3DFONT_TWOSIDED )
+        m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
+
+    FLOAT fStartX = x;
+    TCHAR c;
+
+    // Fill vertex buffer
+    FONT3DVERTEX* pVertices;
+    DWORD         dwVertex       = 0L;
+    DWORD         dwNumTriangles = 0L;
+    m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
+
+    while( c = *strText++ )
+    {
+        if( c == '\n' )
+        {
+            x = fStartX;
+            y -= (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f;
+        }
+        if( c < 32 )
+            continue;
+
+        FLOAT tx1 = m_fTexCoords[c-32][0];
+        FLOAT ty1 = m_fTexCoords[c-32][1];
+        FLOAT tx2 = m_fTexCoords[c-32][2];
+        FLOAT ty2 = m_fTexCoords[c-32][3];
+
+        FLOAT w = (tx2-tx1) * m_dwTexWidth  / ( 10.0f * m_fTextScale );
+        FLOAT h = (ty2-ty1) * m_dwTexHeight / ( 10.0f * m_fTextScale );
+
+        if( c != _T(' ') )
+        {
+            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+0,0), D3DXVECTOR3(0,0,-1), tx1, ty2 );
+            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 );
+            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 );
+            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+h,0), D3DXVECTOR3(0,0,-1), tx2, ty1 );
+            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 );
+            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 );
+            dwNumTriangles += 2;
+
+            if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) )
+            {
+                // Unlock, render, and relock the vertex buffer
+                m_pVB->Unlock();
+                m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
+                m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
+                dwNumTriangles = 0L;
+            }
+        }
+
+        x += w;
+    }
+
+    // Unlock and render the vertex buffer
+    m_pVB->Unlock();
+    if( dwNumTriangles > 0 )
+        m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
+
+    // Restore the modified renderstates
+    m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock );
+
+    return S_OK;
+}
+*/

+ 70 - 0
panda/src/dxgsg8/d3dfont8.h

@@ -0,0 +1,70 @@
+//-----------------------------------------------------------------------------
+// File: D3DFont.h
+//
+// Desc: Texture-based font class
+//-----------------------------------------------------------------------------
+#ifndef D3DFONT_H
+#define D3DFONT_H
+#include <tchar.h>
+#include <D3D8.h>
+
+
+// Font creation flags
+#define D3DFONT_BOLD        0x0001
+#define D3DFONT_ITALIC      0x0002
+#define D3DFONT_ZENABLE     0x0004
+
+// Font rendering flags
+#define D3DFONT_CENTERED    0x0001
+#define D3DFONT_TWOSIDED    0x0002
+#define D3DFONT_FILTERED    0x0004
+
+
+//-----------------------------------------------------------------------------
+// Name: class CD3DFont
+// Desc: Texture-based font class for doing text in a 3D scene.
+//-----------------------------------------------------------------------------
+class CD3DFont
+{
+    TCHAR   m_strFontName[80];            // Font properties
+    DWORD   m_dwFontHeight;
+    DWORD   m_dwFontFlags;
+
+    LPDIRECT3DDEVICE8       m_pd3dDevice; // A D3DDevice used for rendering
+    LPDIRECT3DTEXTURE8      m_pTexture;   // The d3d texture for this font
+    LPDIRECT3DVERTEXBUFFER8 m_pVB;        // VertexBuffer for rendering text
+    DWORD   m_dwTexWidth;                 // Texture dimensions
+    DWORD   m_dwTexHeight;
+    FLOAT   m_fTextScale;
+    FLOAT   m_fTexCoords[128-32][4];
+
+    // Stateblocks for setting and restoring render states
+    DWORD   m_dwSavedStateBlock;
+    DWORD   m_dwDrawTextStateBlock;
+
+public:
+    // 2D and 3D text drawing functions
+    HRESULT DrawText( FLOAT x, FLOAT y, DWORD dwColor, 
+                      TCHAR* strText, DWORD dwFlags=0L );
+    HRESULT DrawTextScaled( FLOAT x, FLOAT y, FLOAT z, 
+                            FLOAT fXScale, FLOAT fYScale, DWORD dwColor, 
+                            TCHAR* strText, DWORD dwFlags=0L );
+//    HRESULT Render3DText( TCHAR* strText, DWORD dwFlags=0L );
+    
+    // Function to get extent of text
+    HRESULT GetTextExtent( TCHAR* strText, SIZE* pSize );
+
+    // Initializing and destroying device-dependent objects
+    HRESULT InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice );
+    HRESULT RestoreDeviceObjects(void);
+    HRESULT InvalidateDeviceObjects(void);
+    HRESULT DeleteDeviceObjects(void);
+
+    // Constructor / destructor
+    CD3DFont( TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags=0L );
+    ~CD3DFont();
+};
+
+#endif
+
+

+ 60 - 19
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -272,6 +272,7 @@ set_color_clear_value(const Colorf& value) {
   _d3dcolor_clear_value =  Colorf_to_D3DCOLOR(value);
   _d3dcolor_clear_value =  Colorf_to_D3DCOLOR(value);
 }
 }
 
 
+#if 0
 void DXGraphicsStateGuardian::SetFPSMeterPosition(void) {
 void DXGraphicsStateGuardian::SetFPSMeterPosition(void) {
     if(_fpsmeter_verts==NULL)
     if(_fpsmeter_verts==NULL)
       return;
       return;
@@ -339,7 +340,6 @@ void DXGraphicsStateGuardian::SetFPSMeterPosition(void) {
 }
 }
 
 
 void DXGraphicsStateGuardian::FillFPSMeterTexture(void) {
 void DXGraphicsStateGuardian::FillFPSMeterTexture(void) {
-/*
     assert(_fpsmeter_font_surf!=NULL);
     assert(_fpsmeter_font_surf!=NULL);
     HRESULT hr;
     HRESULT hr;
 
 
@@ -412,8 +412,9 @@ void DXGraphicsStateGuardian::FillFPSMeterTexture(void) {
         }
         }
     #endif
     #endif
     _fpsmeter_font_surf->Unlock(NULL);
     _fpsmeter_font_surf->Unlock(NULL);
-*/
 }
 }
+#endif
+
 
 
 void DXGraphicsStateGuardian::
 void DXGraphicsStateGuardian::
 reset_panda_gsg(void) {
 reset_panda_gsg(void) {
@@ -455,18 +456,19 @@ DXGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
     // allocate local buffers used during rendering
     // allocate local buffers used during rendering
 
 
     ZeroMemory(&scrn,sizeof(DXScreenData));
     ZeroMemory(&scrn,sizeof(DXScreenData));
-    _bShowFPSMeter = false;
     _bDXisReady = false;
     _bDXisReady = false;
 
 
     _pFvfBufBasePtr = NULL;
     _pFvfBufBasePtr = NULL;
     _index_buf=NULL;
     _index_buf=NULL;
-    _fpsmeter_verts=NULL;
     _light_enabled = NULL;
     _light_enabled = NULL;
     _cur_light_enabled = NULL;
     _cur_light_enabled = NULL;
     _clip_plane_enabled = (bool *)NULL;
     _clip_plane_enabled = (bool *)NULL;
     _cur_clip_plane_enabled = (bool *)NULL;
     _cur_clip_plane_enabled = (bool *)NULL;
 
 
-    _fpsmeter_font_surf=NULL;
+//    _fpsmeter_verts=NULL;
+//    _fpsmeter_font_surf=NULL;
+    _pFPSFont=NULL;
+    _bShowFPSMeter = false;
 
 
     _max_light_range = __D3DLIGHT_RANGE_MAX;
     _max_light_range = __D3DLIGHT_RANGE_MAX;
 
 
@@ -874,6 +876,16 @@ dx_init(HCURSOR hMouseCursor) {
     if(FAILED(hr))
     if(FAILED(hr))
         dxgsg_cat.error() << "CreateDX8Cursor failed!\n";
         dxgsg_cat.error() << "CreateDX8Cursor failed!\n";
 
 
+    if(_bShowFPSMeter) {
+        assert(_pFPSFont == NULL);
+        _pFPSFont = new CD3DFont(_T("Arial"),12,0x0);
+        assert(IS_VALID_PTR(_pFPSFont));
+        hr=_pFPSFont->InitDeviceObjects(scrn.pD3DDevice);
+        if(FAILED(hr)) {
+            _bShowFPSMeter=false;
+        }
+    }
+
     // comment out FPS meter stuff for the moment
     // comment out FPS meter stuff for the moment
     #if 0
     #if 0
     // need to release this better, so dx_init can be called multiple times
     // need to release this better, so dx_init can be called multiple times
@@ -5583,7 +5595,7 @@ void DXGraphicsStateGuardian::
 free_pointers() {
 free_pointers() {
     SAFE_DELETE_ARRAY(_index_buf);
     SAFE_DELETE_ARRAY(_index_buf);
     SAFE_DELETE_ARRAY(_pFvfBufBasePtr);
     SAFE_DELETE_ARRAY(_pFvfBufBasePtr);
-    SAFE_DELETE_ARRAY(_fpsmeter_verts);
+//    SAFE_DELETE_ARRAY(_fpsmeter_verts);
     SAFE_DELETE_ARRAY(_cur_clip_plane_enabled);
     SAFE_DELETE_ARRAY(_cur_clip_plane_enabled);
     SAFE_DELETE_ARRAY(_clip_plane_enabled);
     SAFE_DELETE_ARRAY(_clip_plane_enabled);
     SAFE_DELETE_ARRAY(_cur_light_enabled);
     SAFE_DELETE_ARRAY(_cur_light_enabled);
@@ -5794,20 +5806,17 @@ bool recreate_tex_callback(TextureContext *tc,void *void_dxgsg_ptr) {
 
 
 // release all textures and vertex/index buffers
 // release all textures and vertex/index buffers
 HRESULT DXGraphicsStateGuardian::DeleteAllDeviceObjects(void) {
 HRESULT DXGraphicsStateGuardian::DeleteAllDeviceObjects(void) {
-  // BUGBUG: need to handle vertexbuffer handling here
+  // BUGBUG: need to release any vertexbuffers here
 
 
   // cant access template in libpanda.dll directly due to vc++ limitations, use traverser to get around it
   // cant access template in libpanda.dll directly due to vc++ limitations, use traverser to get around it
   traverse_prepared_textures(delete_tex_callback,this);
   traverse_prepared_textures(delete_tex_callback,this);
 
 
-#if 0
-  ULONG refcnt;
-
-  if(_bShowFPSMeter)
-     RELEASE(_fpsmeter_font_surf,dxgsg,"fpsmeter fontsurf",false);
-#endif
-
   if(dxgsg_cat.is_debug())
   if(dxgsg_cat.is_debug())
       dxgsg_cat.debug() << "release of all textures complete\n";
       dxgsg_cat.debug() << "release of all textures complete\n";
+
+  if(IS_VALID_PTR(_pFPSFont)) {
+       _pFPSFont->DeleteDeviceObjects();
+  }
   return S_OK;
   return S_OK;
 }
 }
 
 
@@ -5815,6 +5824,10 @@ HRESULT DXGraphicsStateGuardian::DeleteAllDeviceObjects(void) {
 HRESULT DXGraphicsStateGuardian::RecreateAllDeviceObjects(void) {
 HRESULT DXGraphicsStateGuardian::RecreateAllDeviceObjects(void) {
   // BUGBUG: need to handle vertexbuffer handling here
   // BUGBUG: need to handle vertexbuffer handling here
 
 
+    if(IS_VALID_PTR(_pFPSFont)) {
+       _pFPSFont->RestoreDeviceObjects();
+    }
+
   // cant access template in libpanda.dll directly due to vc++ limitations, use traverser to get around it
   // cant access template in libpanda.dll directly due to vc++ limitations, use traverser to get around it
   traverse_prepared_textures(recreate_tex_callback,this);
   traverse_prepared_textures(recreate_tex_callback,this);
 
 
@@ -5824,7 +5837,11 @@ HRESULT DXGraphicsStateGuardian::RecreateAllDeviceObjects(void) {
 }
 }
 
 
 HRESULT DXGraphicsStateGuardian::ReleaseAllDeviceObjects(void) {
 HRESULT DXGraphicsStateGuardian::ReleaseAllDeviceObjects(void) {
-    // release any D3DPOOL_DEFAULT objects
+    // release any D3DPOOL_DEFAULT objects here (currently none)
+
+    if(IS_VALID_PTR(_pFPSFont)) {
+       _pFPSFont->InvalidateDeviceObjects();
+    }
     return S_OK;
     return S_OK;
 }
 }
 
 
@@ -5848,7 +5865,8 @@ HRESULT DXGraphicsStateGuardian::RestoreAllDeviceObjects(void) {
   // cant access template in libpanda.dll directly due to vc++ limitations, use traverser to get around it
   // cant access template in libpanda.dll directly due to vc++ limitations, use traverser to get around it
 //  traverse_prepared_textures(refill_tex_callback,this);
 //  traverse_prepared_textures(refill_tex_callback,this);
 
 
-//  if(_bShowFPSMeter)
+  if(IS_VALID_PTR(_pFPSFont))
+    _pFPSFont->RestoreDeviceObjects();
 //      FillFPSMeterTexture();
 //      FillFPSMeterTexture();
 
 
   if(dxgsg_cat.is_debug())
   if(dxgsg_cat.is_debug())
@@ -5966,6 +5984,19 @@ void DXGraphicsStateGuardian::show_windowed_frame(void) {
 }
 }
 */
 */
 
 
+HRESULT DXGraphicsStateGuardian::reset_d3d_device(D3DPRESENT_PARAMETERS *pPresParams) {
+  HRESULT hr;
+
+  ReleaseAllDeviceObjects();
+
+  hr=scrn.pD3DDevice->Reset(pPresParams);
+  if(SUCCEEDED(hr)) {
+     if(pPresParams!=&scrn.PresParams)
+         memcpy(&scrn.PresParams,pPresParams,sizeof(D3DPRESENT_PARAMETERS));
+  }
+  return hr;
+}
+
 bool DXGraphicsStateGuardian::CheckCooperativeLevel(bool bDoReactivateWindow) {
 bool DXGraphicsStateGuardian::CheckCooperativeLevel(bool bDoReactivateWindow) {
 
 
     HRESULT hr = scrn.pD3DDevice->TestCooperativeLevel();
     HRESULT hr = scrn.pD3DDevice->TestCooperativeLevel();
@@ -5977,13 +6008,23 @@ bool DXGraphicsStateGuardian::CheckCooperativeLevel(bool bDoReactivateWindow) {
     switch(hr) {
     switch(hr) {
         case D3DERR_DEVICENOTRESET:
         case D3DERR_DEVICENOTRESET:
              _bDXisReady = false;
              _bDXisReady = false;
-             ReleaseAllDeviceObjects();
-             hr=scrn.pD3DDevice->Reset(&scrn.PresParams);
+             hr=reset_d3d_device(&scrn.PresParams);
+             if(FAILED(hr)) {
+                // I think this shouldnt fail unless I've screwed up the PresParams from the original working ones somehow
+                dxgsg_cat.error() << "CheckCooperativeLevel Reset() failed, hr = " << D3DERRORSTRING(hr);
+                exit(1);
+             }
+
              if(bDoReactivateWindow)
              if(bDoReactivateWindow)
                  _win->reactivate_window();  //must reactivate window before you can restore surfaces (otherwise you are in WRONGVIDEOMODE, and DDraw RestoreAllSurfaces fails)
                  _win->reactivate_window();  //must reactivate window before you can restore surfaces (otherwise you are in WRONGVIDEOMODE, and DDraw RestoreAllSurfaces fails)
              RestoreAllDeviceObjects();  
              RestoreAllDeviceObjects();  
              hr = scrn.pD3DDevice->TestCooperativeLevel();
              hr = scrn.pD3DDevice->TestCooperativeLevel();
-             assert(SUCCEEDED(hr));
+             if(FAILED(hr)) {
+                // internal chk, shouldnt fail 
+                dxgsg_cat.error() << "TestCooperativeLevel following Reset() failed, hr = " << D3DERRORSTRING(hr);
+                exit(1);
+             }
+
             break;
             break;
 
 
         case D3DERR_DEVICELOST:
         case D3DERR_DEVICELOST:

+ 12 - 6
panda/src/dxgsg8/dxGraphicsStateGuardian8.h

@@ -41,6 +41,8 @@
 #include "dxgsg8base.h"
 #include "dxgsg8base.h"
 #include "dxGeomNodeContext8.h"
 #include "dxGeomNodeContext8.h"
 #include "dxTextureContext8.h"
 #include "dxTextureContext8.h"
+#include "d3dfont8.h"
+
 #include <vector>
 #include <vector>
 
 
 class PlaneNode;
 class PlaneNode;
@@ -370,14 +372,17 @@ protected:
   DWORD _start_frame_count;
   DWORD _start_frame_count;
   DWORD _cur_frame_count;
   DWORD _cur_frame_count;
   float _current_fps;
   float _current_fps;
-  DWORD *_fpsmeter_verts;
-  DWORD _fpsmeter_fvfflags;
+//  DWORD *_fpsmeter_verts;
+//  DWORD _fpsmeter_fvfflags;
 //  LPDIRECTDRAWSURFACE7 _fpsmeter_font_surf;
 //  LPDIRECTDRAWSURFACE7 _fpsmeter_font_surf;
-  void *_fpsmeter_font_surf;
-  float _fps_u_usedwidth,_fps_v_usedheight;  // fraction of fps font texture actually used
-  DWORD _fps_vertexsize;   // size of verts used to render fps meter
+//  void *_fpsmeter_font_surf;
+//  float _fps_u_usedwidth,_fps_v_usedheight;  // fraction of fps font texture actually used
+//  DWORD _fps_vertexsize;   // size of verts used to render fps meter
+//  void  FillFPSMeterTexture(void);
+  ::CD3DFont *_pFPSFont;
+
   void  SetFPSMeterPosition(void);
   void  SetFPSMeterPosition(void);
-  void  FillFPSMeterTexture(void);
+
 
 
 public:
 public:
   static GraphicsStateGuardian*
   static GraphicsStateGuardian*
@@ -393,6 +398,7 @@ public:
 
 
   void  dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled);
   void  dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled);
   void reset_panda_gsg(void);
   void reset_panda_gsg(void);
+  HRESULT reset_d3d_device(D3DPRESENT_PARAMETERS *pPresParams);
 
 
   #define DO_REACTIVATE_WINDOW true
   #define DO_REACTIVATE_WINDOW true
   bool CheckCooperativeLevel(bool bDoReactivateWindow = false);
   bool CheckCooperativeLevel(bool bDoReactivateWindow = false);

+ 1 - 0
panda/src/dxgsg8/dxgsg8_composite1.cxx

@@ -2,3 +2,4 @@
 #include "dxSavedFrameBuffer8.cxx"
 #include "dxSavedFrameBuffer8.cxx"
 #include "dxTextureContext8.cxx"
 #include "dxTextureContext8.cxx"
 #include "dxGeomNodeContext8.cxx"
 #include "dxGeomNodeContext8.cxx"
+#include "d3dfont8.cxx"

+ 3 - 0
panda/src/dxgsg8/dxgsg8base.h

@@ -72,6 +72,9 @@
 #define SAFE_DELETE(p)       { if(p) { assert(IS_VALID_PTR(p));   delete (p);     (p)=NULL; } }
 #define SAFE_DELETE(p)       { if(p) { assert(IS_VALID_PTR(p));   delete (p);     (p)=NULL; } }
 #define SAFE_DELETE_ARRAY(p) { if(p) { assert(IS_VALID_PTR(p));   delete[] (p);   (p)=NULL; } }
 #define SAFE_DELETE_ARRAY(p) { if(p) { assert(IS_VALID_PTR(p));   delete[] (p);   (p)=NULL; } }
 
 
+// for stuff outside a panda class
+#define SAFE_RELEASE(p)      { if(p) { assert(IS_VALID_PTR(p)); (p)->Release(); (p)=NULL; } }
+
 // this is bDoDownToZero argument to RELEASE()
 // this is bDoDownToZero argument to RELEASE()
 #define RELEASE_DOWN_TO_ZERO true
 #define RELEASE_DOWN_TO_ZERO true
 #define RELEASE_ONCE false
 #define RELEASE_ONCE false