Browse Source

make window handling more robust

cxgeorge 24 years ago
parent
commit
99bdb6641d

+ 1 - 1
panda/src/dxgsg/dxGraphicsStateGuardian.I

@@ -114,7 +114,7 @@ enable_dither(bool val) {
   if (_dither_enabled != val) {
     _dither_enabled = val;
 
-  #ifdef NDEBUG
+  #ifdef _DEBUG
     {
         if(val && (_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER))
            dxgsg_cat.error() << "no HW support for color dithering!!\n";

+ 78 - 27
panda/src/dxgsg/dxGraphicsStateGuardian.cxx

@@ -412,15 +412,16 @@ init_dx(  LPDIRECTDRAW7     context,
 
     SetRect(&clip_rect, 0,0,0,0);     // no clip rect set
 
-    _d3dDevice->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1);
-
     // Lighting, let's turn it off by default
     _lighting_enabled = true;
     enable_lighting(false);
 
-    // Dither, let's turn it off
-    _dither_enabled = true;
-    enable_dither(false);
+    // turn on dithering if the rendertarget is < 8bits/color channel
+    DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd_back);
+    _back->GetSurfaceDesc(&ddsd_back);
+    _dither_enabled = ((ddsd_back.ddpfPixelFormat.dwRGBBitCount < 24) &&
+                       (_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER));
+   _d3dDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, _dither_enabled);
 
     // Stencil test is off by default
     _stencil_test_enabled = false;
@@ -431,6 +432,8 @@ init_dx(  LPDIRECTDRAW7     context,
     enable_line_smooth(false);
 //  enable_multisample(true);
 
+    _d3dDevice->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1);
+
     // technically DX7's front-end has no limit on the number of lights, but it's simpler for
     // this implementation to set a small GL-like limit to make the light array traversals short
     // and so I dont have to write code that reallocs light arrays
@@ -449,6 +452,9 @@ init_dx(  LPDIRECTDRAW7     context,
         _light_enabled[i] = false;
     }
 
+    if(dx_auto_normalize_lighting)
+         _d3dDevice->SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, true);
+
     // Set up the clip plane id map
     _max_clip_planes = D3DMAXUSERCLIPPLANES;
     _available_clip_plane_ids = PTA(PlaneNode*)(_max_clip_planes);
@@ -511,9 +517,11 @@ init_dx(  LPDIRECTDRAW7     context,
     if(dx_full_screen_antialiasing) {
       if(_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT) {
         _d3dDevice->SetRenderState(D3DRENDERSTATE_ANTIALIAS,D3DANTIALIAS_SORTINDEPENDENT);
-        dxgsg_cat.debug() << "enabling full-screen anti-aliasing\n";
+        if(dxgsg_cat.is_debug()) 
+            dxgsg_cat.debug() << "enabling full-screen anti-aliasing\n";
       } else {
-        dxgsg_cat.debug() << "device doesnt support full-screen anti-aliasing\n";
+        if(dxgsg_cat.is_debug()) 
+            dxgsg_cat.debug() << "device doesnt support full-screen anti-aliasing\n";
       }
     }
 
@@ -524,13 +532,12 @@ init_dx(  LPDIRECTDRAW7     context,
              _d3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, dx_force_backface_culling);
       } else {
           dx_force_backface_culling=0;
-          dxgsg_cat.debug() << "error, invalid value for dx-force-backface-culling\n";
+          if(dxgsg_cat.is_debug()) 
+              dxgsg_cat.debug() << "error, invalid value for dx-force-backface-culling\n";
       }
     }
 #endif
 
-     if(dx_auto_normalize_lighting)
-         _d3dDevice->SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, true);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1728,6 +1735,19 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) {
     D3DMATRIX OldD3DWorldMatrix;
     _d3dDevice->GetTransform(D3DTRANSFORMSTATE_WORLD, &OldD3DWorldMatrix);
 
+    // ATI sez:  most applications ignore the fact that since alpha blended primitives
+    // combine the data in the frame buffer with the data in the current pixel, pixels 
+    // can be dithered multiple times and accentuate the dither pattern. This is particularly
+    // true in particle systems which rely on the cumulative visual effect of many overlapping
+    // alpha blended primitives.
+
+    bool bReEnableDither=_dither_enabled;
+    if(bReEnableDither) {
+        enable_dither(false);
+    }
+
+    _d3dDevice->GetTransform(D3DTRANSFORMSTATE_WORLD, &OldD3DWorldMatrix);
+
     Geom::VertexIterator vi = geom->make_vertex_iterator();
     Geom::ColorIterator ci = geom->make_color_iterator();
 
@@ -2018,6 +2038,9 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) {
 
     // restore the matrices
     _d3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &OldD3DWorldMatrix);
+
+    if(bReEnableDither)
+        enable_dither(true);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -5358,33 +5381,59 @@ void DXGraphicsStateGuardian::init_type(void) {
 //  Description: Clean up the DirectX environment.
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian::
-dx_cleanup() {
+dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled) {
 
     release_all_textures();
     release_all_geoms();
 
-    // Do a safe check for releasing the D3DDEVICE. RefCount should be zero.
-    if (_d3dDevice!=NULL) {
-        if (0 < _d3dDevice->Release()) {
-            dxgsg_cat.error() << "DXGraphicsStateGuardian::destructor - d3dDevice reference count > 0" << endl;
+    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(!bAtExitFnCalled) {
+        // Do a safe check for releasing the D3DDEVICE. RefCount should be zero.
+        // if we're called from exit(), _d3dDevice may already have been released
+        if (_d3dDevice!=NULL) {
+            if (0 < (refcnt =  _d3dDevice->Release())) {
+                dxgsg_cat.error() << "dx_cleanup - d3dDevice reference count = " <<  refcnt << ", should be zero!\n";
+            }
         }
+    
         _d3dDevice = NULL;  // clear the pointer in the Gsg
+    
+        // Release the DDraw and D3D objects used by the app
+        RELEASE(_zbuf);
+        RELEASE(_back);
+        RELEASE(_pri);
+    
+        RELEASE(_d3d);
     }
 
-    // Release the DDraw and D3D objects used by the app
-    RELEASE(_zbuf);
-    RELEASE(_back);
-    RELEASE(_pri);
-
-    RELEASE(_d3d);
+    // for some reason, DLL_PROCESS_DETACH has not yet been sent to ddraw, so we can still call its fns
 
     // Do a safe check for releasing DDRAW. RefCount should be zero.
     if (_pDD!=NULL) {
-        int val;
-        if (0 < (val = _pDD->Release())) {
-            dxgsg_cat.error()
-            << "DXGraphicsStateGuardian::destructor -  IDDraw Obj reference count = " << val << ", should be zero!\n";
+        if(bRestoreDisplayMode) {
+          HRESULT hr = _pDD->RestoreDisplayMode(); 
+          if(dxgsg_cat.is_spam())
+                dxgsg_cat.spam() << "dx_cleanup -  Restoring original desktop DisplayMode\n";
+          if(FAILED(hr)) {
+                dxgsg_cat.error() << "dx_cleanup -  RestoreDisplayMode failed, hr = " << ConvD3DErrorToString(hr) << endl;
+          }
         }
+
+        refcnt = _pDD->Release();
+
+        if(bAtExitFnCalled) {
+            // refcnt may be > 1
+           while (refcnt>0) {
+               refcnt = _pDD->Release();
+           }
+        } else {
+            if(refcnt>0)
+                dxgsg_cat.error() << "dx_cleanup - IDDraw Obj reference count = " << refcnt << ", should be zero!\n";
+        }
+
         _pDD  = NULL;
     }
 }
@@ -5591,13 +5640,15 @@ void DXGraphicsStateGuardian::show_full_screen_frame(void) {
       // This means that mode changes had taken place, surfaces
       // were lost but still we are in the original mode, so we
       // simply restore all surfaces and keep going.
-      _dx_ready = FALSE;
 
 #ifdef _DEBUG
-      if(dxgsg_cat.is_spam())
+      if(dxgsg_cat.is_spam() && _dx_ready) {
           dxgsg_cat.spam() << "DXGraphicsStateGuardian:: no exclusive mode, waiting...\n";
+      }
 #endif
 
+      _dx_ready = FALSE;
+
       Sleep( 500 ); // Dont consume CPU.
       throw_event("PandaPaused");   // throw panda event to invoke network-only processing
 

+ 4 - 2
panda/src/dxgsg/dxGraphicsStateGuardian.h

@@ -65,7 +65,7 @@ INLINE ostream &operator << (ostream &out, GLenum v) {
     ZeroMemory(&var, sizeof(type));  \
     var.dwSize = sizeof(type);
 
-#define RELEASE(object) if (object!=NULL) {object->Release(); object = NULL;}
+#define RELEASE(OBJECT) if(((OBJECT)!=NULL)&&(!IsBadWritePtr((OBJECT),4))) {(OBJECT)->Release(); (OBJECT) = NULL;}
 
 #if defined(NOTIFY_DEBUG) || defined(DO_PSTATS)
 // This function now serves both to print a debug message to the
@@ -412,7 +412,8 @@ public:
   INLINE bool GetDXReady(void)  { return _dx_ready;}
   void DXGraphicsStateGuardian::SetTextureBlendMode(TextureApplyProperty::Mode TexBlendMode,bool bJustEnable);
 
-  void  dx_cleanup();
+  void  dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled);
+
   void  dx_setup_after_resize(RECT viewrect,HWND mwindow) ;
   void  show_frame();
   void  show_full_screen_frame();
@@ -425,6 +426,7 @@ public:
           LPDIRECT3DDEVICE7    d3dDevice,
           RECT  viewrect);
    friend HRESULT CALLBACK EnumTexFmtsCallback( LPDDPIXELFORMAT pddpf, VOID* param );
+
 private:
   static TypeHandle _type_handle;
 };