Browse Source

more fullscreen fixes

David Rose 18 years ago
parent
commit
554430ab21

+ 24 - 12
panda/src/display/graphicsStateGuardian.cxx

@@ -39,6 +39,7 @@
 #include "displayRegion.h"
 #include "displayRegion.h"
 #include "graphicsOutput.h"
 #include "graphicsOutput.h"
 #include "texturePool.h"
 #include "texturePool.h"
+#include "geomMunger.h"
 
 
 #include <algorithm>
 #include <algorithm>
 #include <limits.h>
 #include <limits.h>
@@ -192,6 +193,8 @@ GraphicsStateGuardian::
     delete _stencil_render_states;
     delete _stencil_render_states;
     _stencil_render_states = 0;
     _stencil_render_states = 0;
   }
   }
+
+  GeomMunger::unregister_mungers_for_gsg(this);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -614,31 +617,40 @@ end_occlusion_query() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(GeomMunger) GraphicsStateGuardian::
 PT(GeomMunger) GraphicsStateGuardian::
 get_geom_munger(const RenderState *state, Thread *current_thread) {
 get_geom_munger(const RenderState *state, Thread *current_thread) {
+  // We can cast the RenderState to a non-const object because we are
+  // only updating a cache within the RenderState, not really changing
+  // any of its properties.
+  RenderState *nc_state = ((RenderState *)state);
+
   // Before we even look up the map, see if the _last_mi value points
   // Before we even look up the map, see if the _last_mi value points
   // to this GSG.  This is likely because we tend to visit the same
   // to this GSG.  This is likely because we tend to visit the same
   // state multiple times during a frame.  Also, this might well be
   // state multiple times during a frame.  Also, this might well be
   // the only GSG in the world anyway.
   // the only GSG in the world anyway.
-  if (!state->_mungers.empty()) {
-    RenderState::Mungers::const_iterator mi = state->_last_mi;
+  if (!nc_state->_mungers.empty()) {
+    RenderState::Mungers::const_iterator mi = nc_state->_last_mi;
     if (!(*mi).first.was_deleted() && (*mi).first == this) {
     if (!(*mi).first.was_deleted() && (*mi).first == this) {
-      return (*mi).second;
+      if ((*mi).second->is_registered()) {
+        return (*mi).second;
+      }
     }
     }
   }
   }
 
 
   // Nope, we have to look it up in the map.
   // Nope, we have to look it up in the map.
-  RenderState::Mungers::const_iterator mi = state->_mungers.find(this);
-  if (mi != state->_mungers.end() && !(*mi).first.was_deleted()) {
-    ((RenderState *)state)->_last_mi = mi;
-    return (*mi).second;
+  RenderState::Mungers::iterator mi = nc_state->_mungers.find(this);
+  if (mi != nc_state->_mungers.end() && !(*mi).first.was_deleted()) {
+    if ((*mi).second->is_registered()) {
+      nc_state->_last_mi = mi;
+      return (*mi).second;
+    }
+    // This GeomMunger is no longer registered.  Remove it from the
+    // map.
+    nc_state->_mungers.erase(mi);
   }
   }
 
 
   // Nothing in the map; create a new entry.
   // Nothing in the map; create a new entry.
-  PT(GeomMunger) munger = make_geom_munger(state, current_thread);
+  PT(GeomMunger) munger = make_geom_munger(nc_state, current_thread);
+  nassertr(munger->is_registered(), munger);
 
 
-  // Cast the RenderState to a non-const object.  We can do this
-  // because we are only updating a cache within the RenderState, not
-  // really changing any of its properties.
-  RenderState *nc_state = (RenderState *)state;
   mi = nc_state->_mungers.insert(RenderState::Mungers::value_type(this, munger)).first;
   mi = nc_state->_mungers.insert(RenderState::Mungers::value_type(this, munger)).first;
   nc_state->_last_mi = mi;
   nc_state->_last_mi = mi;
 
 

+ 1 - 1
panda/src/display/standardMunger.I

@@ -25,5 +25,5 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GraphicsStateGuardian *StandardMunger::
 INLINE GraphicsStateGuardian *StandardMunger::
 get_gsg() const {
 get_gsg() const {
-  return _gsg;
+  return (GraphicsStateGuardian *)GeomMunger::get_gsg();
 }
 }

+ 8 - 12
panda/src/display/standardMunger.cxx

@@ -38,11 +38,11 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
                int num_components,
                int num_components,
                StandardMunger::NumericType numeric_type,
                StandardMunger::NumericType numeric_type,
                StandardMunger::Contents contents) :
                StandardMunger::Contents contents) :
+  StateMunger(gsg),
   _num_components(num_components),
   _num_components(num_components),
   _numeric_type(numeric_type),
   _numeric_type(numeric_type),
   _contents(contents)
   _contents(contents)
 {
 {
-  _gsg = DCAST(GraphicsStateGuardian, gsg);
   _render_mode = state->get_render_mode();
   _render_mode = state->get_render_mode();
 
 
   _munge_color = false;
   _munge_color = false;
@@ -54,7 +54,7 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
   if (color_attrib != (ColorAttrib *)NULL && 
   if (color_attrib != (ColorAttrib *)NULL && 
       color_attrib->get_color_type() == ColorAttrib::T_flat) {
       color_attrib->get_color_type() == ColorAttrib::T_flat) {
 
 
-    if (!_gsg->get_color_scale_via_lighting()) {
+    if (!get_gsg()->get_color_scale_via_lighting()) {
       // We only need to munge the color directly if the GSG says it
       // We only need to munge the color directly if the GSG says it
       // can't cheat the color via lighting (presumably, in this case,
       // can't cheat the color via lighting (presumably, in this case,
       // by applying a material).
       // by applying a material).
@@ -78,8 +78,8 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
 
 
     // If the GSG says it can't cheat this RGB or alpha scale, we have
     // If the GSG says it can't cheat this RGB or alpha scale, we have
     // to apply the color scale directly.
     // to apply the color scale directly.
-    if ((color_scale_attrib->has_rgb_scale() && !_gsg->get_color_scale_via_lighting()) ||
-        (color_scale_attrib->has_alpha_scale() && !_gsg->get_alpha_scale_via_texture(tex_attrib))) {
+    if ((color_scale_attrib->has_rgb_scale() && !get_gsg()->get_color_scale_via_lighting()) ||
+        (color_scale_attrib->has_alpha_scale() && !get_gsg()->get_alpha_scale_via_texture(tex_attrib))) {
       _munge_color_scale = true;
       _munge_color_scale = true;
     }
     }
 
 
@@ -127,9 +127,9 @@ munge_data_impl(const GeomVertexData *data) {
     if (table != (TransformBlendTable *)NULL &&
     if (table != (TransformBlendTable *)NULL &&
         table->get_num_transforms() != 0 &&
         table->get_num_transforms() != 0 &&
         table->get_max_simultaneous_transforms() <= 
         table->get_max_simultaneous_transforms() <= 
-        _gsg->get_max_vertex_transforms()) {
+        get_gsg()->get_max_vertex_transforms()) {
       if (matrix_palette && 
       if (matrix_palette && 
-          table->get_num_transforms() <= _gsg->get_max_vertex_transform_indices()) {
+          table->get_num_transforms() <= get_gsg()->get_max_vertex_transform_indices()) {
 
 
         if (table->get_num_transforms() == table->get_max_simultaneous_transforms()) {
         if (table->get_num_transforms() == table->get_max_simultaneous_transforms()) {
           // We can support an indexed palette, but since that won't
           // We can support an indexed palette, but since that won't
@@ -145,7 +145,7 @@ munge_data_impl(const GeomVertexData *data) {
         }
         }
 
 
       } else if (table->get_num_transforms() <=
       } else if (table->get_num_transforms() <=
-                 _gsg->get_max_vertex_transforms()) {
+                 get_gsg()->get_max_vertex_transforms()) {
         // We can't support an indexed palette, but we have few enough
         // We can't support an indexed palette, but we have few enough
         // transforms that we can do a nonindexed table.
         // transforms that we can do a nonindexed table.
         animation.set_hardware(table->get_num_transforms(), false);
         animation.set_hardware(table->get_num_transforms(), false);
@@ -172,7 +172,7 @@ munge_data_impl(const GeomVertexData *data) {
 bool StandardMunger::
 bool StandardMunger::
 munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data,
 munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data,
                 Thread *current_thread) {
                 Thread *current_thread) {
-  int supported_geom_rendering = _gsg->get_supported_geom_rendering();
+  int supported_geom_rendering = get_gsg()->get_supported_geom_rendering();
 
 
   int unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
   int unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
   if (unsupported_bits != 0) {
   if (unsupported_bits != 0) {
@@ -225,10 +225,6 @@ int StandardMunger::
 compare_to_impl(const GeomMunger *other) const {
 compare_to_impl(const GeomMunger *other) const {
   const StandardMunger *om = DCAST(StandardMunger, other);
   const StandardMunger *om = DCAST(StandardMunger, other);
 
 
-  if (_gsg != om->_gsg) {
-    return _gsg < om->_gsg ? -1 : 1;
-  }
-
   if (_render_mode != om->_render_mode) {
   if (_render_mode != om->_render_mode) {
     return _render_mode < om->_render_mode ? -1 : 1;
     return _render_mode < om->_render_mode ? -1 : 1;
   }
   }

+ 0 - 1
panda/src/display/standardMunger.h

@@ -56,7 +56,6 @@ private:
   int _num_components;
   int _num_components;
   NumericType _numeric_type;
   NumericType _numeric_type;
   Contents _contents;
   Contents _contents;
-  WPT(GraphicsStateGuardian) _gsg;
   CPT(RenderModeAttrib) _render_mode;
   CPT(RenderModeAttrib) _render_mode;
 
 
   bool _munge_color;
   bool _munge_color;

+ 28 - 8
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -159,6 +159,9 @@ DXGraphicsStateGuardian9(GraphicsPipe *pipe) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DXGraphicsStateGuardian9::
 DXGraphicsStateGuardian9::
 ~DXGraphicsStateGuardian9() {
 ~DXGraphicsStateGuardian9() {
+  dxgsg9_cat.debug()
+    << "DXGraphicsStateGuardian9 " << this << " destructing\n";
+
   if (IS_VALID_PTR(_d3d_device)) {
   if (IS_VALID_PTR(_d3d_device)) {
     _d3d_device->SetTexture(0, NULL);  // this frees reference to the old texture
     _d3d_device->SetTexture(0, NULL);  // this frees reference to the old texture
   }
   }
@@ -895,10 +898,16 @@ prepare_lens() {
 bool DXGraphicsStateGuardian9::
 bool DXGraphicsStateGuardian9::
 begin_frame(Thread *current_thread) {
 begin_frame(Thread *current_thread) {
 
 
-DBG_S dxgsg9_cat.debug ( ) << "^^^^^^^^^^^ begin_frame \n"; DBG_E
+  DBG_S dxgsg9_cat.debug ( ) << "^^^^^^^^^^^ begin_frame \n"; DBG_E
 
 
   GraphicsStateGuardian::begin_frame(current_thread);
   GraphicsStateGuardian::begin_frame(current_thread);
 
 
+  if (_d3d_device == NULL) {
+    dxgsg9_cat.debug()
+      << this << "::begin_frame(): no device.\n";
+    return false;
+  }
+
   if (_lru)
   if (_lru)
   {
   {
     _lru -> begin_frame ( );
     _lru -> begin_frame ( );
@@ -2369,8 +2378,11 @@ reset() {
   // TransformState::make_identity());
   // TransformState::make_identity());
   // want gsg to pass all state settings down so any non-matching defaults we set here get overwritten
   // want gsg to pass all state settings down so any non-matching defaults we set here get overwritten
 
 
-  assert(_screen->_d3d9 != NULL);
-  assert(_d3d_device != NULL);
+  nassertv(_screen->_d3d9 != NULL);
+  
+  if (_d3d_device == NULL) {
+    return;
+  }
 
 
   D3DCAPS9 d3d_caps;
   D3DCAPS9 d3d_caps;
   _d3d_device->GetDeviceCaps(&d3d_caps);
   _d3d_device->GetDeviceCaps(&d3d_caps);
@@ -2728,7 +2740,7 @@ reset() {
   } else {
   } else {
     // every card is going to have vertex fog, since it's implemented
     // every card is going to have vertex fog, since it's implemented
     // in d3d runtime.
     // in d3d runtime.
-    assert((_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX) != 0);
+    nassertv((_screen->_d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX) != 0);
 
 
     // vertex fog may look crappy if you have large polygons in the
     // vertex fog may look crappy if you have large polygons in the
     // foreground and they get clipped, so you may want to disable it
     // foreground and they get clipped, so you may want to disable it
@@ -4334,6 +4346,10 @@ set_context(DXScreenData *new_context) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 void DXGraphicsStateGuardian9::
 set_render_target() {
 set_render_target() {
+  if (_d3d_device == NULL) {
+    return;
+  }
+
   LPDIRECT3DSURFACE9 back = NULL, stencil = NULL;
   LPDIRECT3DSURFACE9 back = NULL, stencil = NULL;
 
 
   UINT swap_chain;
   UINT swap_chain;
@@ -4566,9 +4582,9 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
                  DXScreenData **screen) {
                  DXScreenData **screen) {
   HRESULT hr;
   HRESULT hr;
 
 
-  assert(IS_VALID_PTR(presentation_params));
-  assert(IS_VALID_PTR(_screen->_d3d9));
-  assert(IS_VALID_PTR(_d3d_device));
+  nassertr(IS_VALID_PTR(presentation_params), E_FAIL);
+  nassertr(IS_VALID_PTR(_screen->_d3d9), E_FAIL);
+  nassertr(IS_VALID_PTR(_d3d_device), E_FAIL);
 
 
   // for windowed mode make sure our format matches the desktop fmt,
   // for windowed mode make sure our format matches the desktop fmt,
   // in case the desktop mode has been changed
   // in case the desktop mode has been changed
@@ -4681,10 +4697,14 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
 bool DXGraphicsStateGuardian9::
 bool DXGraphicsStateGuardian9::
 check_cooperative_level() {
 check_cooperative_level() {
   bool bDoReactivateWindow = false;
   bool bDoReactivateWindow = false;
+  if (_d3d_device == NULL) {
+    return false;
+  }
+
   HRESULT hr = _d3d_device->TestCooperativeLevel();
   HRESULT hr = _d3d_device->TestCooperativeLevel();
 
 
   if (SUCCEEDED(hr)) {
   if (SUCCEEDED(hr)) {
-    assert(SUCCEEDED(_last_testcooplevel_result));
+    nassertr(SUCCEEDED(_last_testcooplevel_result), false);
     return true;
     return true;
   }
   }
 
 

+ 13 - 8
panda/src/dxgsg9/wdxGraphicsWindow9.cxx

@@ -251,7 +251,11 @@ verify_window_sizes(int numsizes, int *dimen) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void wdxGraphicsWindow9::
 void wdxGraphicsWindow9::
 close_window() {
 close_window() {
-  wdxdisplay9_cat.debug() << "wdx closed window\n";
+  if (wdxdisplay9_cat.is_debug()) {
+    wdxdisplay9_cat.debug() 
+      << "wdxGraphicsWindow9::close_window() " << this << "\n";
+  }
+
   if (_gsg != (GraphicsStateGuardian *)NULL) {
   if (_gsg != (GraphicsStateGuardian *)NULL) {
     _gsg.clear();
     _gsg.clear();
     _active = false;
     _active = false;
@@ -316,6 +320,7 @@ open_window() {
       wdxdisplay9_cat.debug() << "device width " << _wcontext._display_mode.Width << "\n";
       wdxdisplay9_cat.debug() << "device width " << _wcontext._display_mode.Width << "\n";
       if (!create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer)) {
       if (!create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer)) {
         wdxdisplay9_cat.error() << "Unable to create window with specified parameters.\n";
         wdxdisplay9_cat.error() << "Unable to create window with specified parameters.\n";
+        close_window();
         return false;
         return false;
       }
       }
       _dxgsg->get_pipe()->make_device((void*)(&_wcontext));
       _dxgsg->get_pipe()->make_device((void*)(&_wcontext));
@@ -565,8 +570,8 @@ create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer
 
 
   PRINT_REFCNT(wdxdisplay9, _d3d9);
   PRINT_REFCNT(wdxdisplay9, _d3d9);
 
 
-  assert(_d3d9 != NULL);
-  assert(pD3DCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION);
+  nassertr(_d3d9 != NULL, false);
+  nassertr(pD3DCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION, false);
 
 
   bool do_sync = sync_video;
   bool do_sync = sync_video;
 
 
@@ -993,14 +998,14 @@ choose_device() {
 bool wdxGraphicsWindow9::
 bool wdxGraphicsWindow9::
 consider_device(wdxGraphicsPipe9 *dxpipe, DXDeviceInfo *device_info) {
 consider_device(wdxGraphicsPipe9 *dxpipe, DXDeviceInfo *device_info) {
 
 
-  assert(dxpipe != NULL);
+  nassertr(dxpipe != NULL, false);
   WindowProperties properties = get_properties();
   WindowProperties properties = get_properties();
   DWORD dwRenderWidth = properties.get_x_size();
   DWORD dwRenderWidth = properties.get_x_size();
   DWORD dwRenderHeight = properties.get_y_size();
   DWORD dwRenderHeight = properties.get_y_size();
   HRESULT hr;
   HRESULT hr;
   LPDIRECT3D9 _d3d9 = dxpipe->__d3d9;
   LPDIRECT3D9 _d3d9 = dxpipe->__d3d9;
 
 
-  assert(_dxgsg != NULL);
+  nassertr(_dxgsg != NULL, false);
   _wcontext._d3d9 = _d3d9;
   _wcontext._d3d9 = _d3d9;
   _wcontext._is_dx9_1 = dxpipe->__is_dx9_1;
   _wcontext._is_dx9_1 = dxpipe->__is_dx9_1;
   _wcontext._card_id = device_info->cardID;  // could this change by end?
   _wcontext._card_id = device_info->cardID;  // could this change by end?
@@ -1207,8 +1212,8 @@ init_resized_window() {
   DWORD newWidth = _wcontext._presentation_params.BackBufferWidth;
   DWORD newWidth = _wcontext._presentation_params.BackBufferWidth;
   DWORD newHeight = _wcontext._presentation_params.BackBufferHeight;
   DWORD newHeight = _wcontext._presentation_params.BackBufferHeight;
 
 
-  assert((newWidth != 0) && (newHeight != 0));
-  assert(_wcontext._window != NULL);
+  nassertv((newWidth != 0) && (newHeight != 0));
+  nassertv(_wcontext._window != NULL);
 
 
   if (_wcontext._presentation_params.Windowed) {
   if (_wcontext._presentation_params.Windowed) {
     POINT ul, lr;
     POINT ul, lr;
@@ -1231,7 +1236,7 @@ init_resized_window() {
   }
   }
 
 
   // clear window to black ASAP
   // clear window to black ASAP
-  assert(_wcontext._window != NULL);
+  nassertv(_wcontext._window != NULL);
   ClearToBlack(_wcontext._window, get_properties());
   ClearToBlack(_wcontext._window, get_properties());
 
 
   // clear textures and VB's out of video&AGP mem, so cache is reset
   // clear textures and VB's out of video&AGP mem, so cache is reset

+ 22 - 0
panda/src/gobj/geomMunger.I

@@ -17,6 +17,17 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomMunger::get_gsg
+//       Access: Public
+//  Description: Returns a pointer to the GSG that created this
+//               munger.
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsStateGuardianBase *GeomMunger::
+get_gsg() const {
+  return _gsg;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomMunger::is_registered
 //     Function: GeomMunger::is_registered
 //       Access: Public
 //       Access: Public
@@ -50,6 +61,17 @@ register_munger(GeomMunger *munger, Thread *current_thread) {
   return get_registry()->register_munger(munger, current_thread);
   return get_registry()->register_munger(munger, current_thread);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomMunger::unregister_mungers_for_gsg
+//       Access: Public, Static
+//  Description: Removes all the mungers from the registry that are
+//               associated with the indicated GSG.
+////////////////////////////////////////////////////////////////////
+INLINE void GeomMunger::
+unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg) {
+  get_registry()->unregister_mungers_for_gsg(gsg);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomMunger::munge_format
 //     Function: GeomMunger::munge_format
 //       Access: Public
 //       Access: Public

+ 31 - 3
panda/src/gobj/geomMunger.cxx

@@ -33,7 +33,8 @@ PStatCollector GeomMunger::_munge_pcollector("*:Munge");
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GeomMunger::
 GeomMunger::
-GeomMunger() :
+GeomMunger(GraphicsStateGuardianBase *gsg) :
+  _gsg(gsg),
   _is_registered(false)
   _is_registered(false)
 {
 {
 #ifndef NDEBUG
 #ifndef NDEBUG
@@ -281,8 +282,8 @@ compare_to_impl(const GeomMunger *other) const {
 //               they would produce a different answer to
 //               they would produce a different answer to
 //               munge_format(), munge_data(), or munge_geom().  (They
 //               munge_format(), munge_data(), or munge_geom().  (They
 //               still might be different in other ways, but if they
 //               still might be different in other ways, but if they
-//               would produce the same answer, this function consider
-//               them to be the same.)
+//               would produce the same answer, this function will
+//               consider them to be the same.)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int GeomMunger::
 int GeomMunger::
 geom_compare_to_impl(const GeomMunger *other) const {
 geom_compare_to_impl(const GeomMunger *other) const {
@@ -417,3 +418,30 @@ unregister_munger(GeomMunger *munger) {
   munger->_registered_key = _mungers.end();
   munger->_registered_key = _mungers.end();
   munger->do_unregister();
   munger->do_unregister();
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomMunger::Registry::unregister_mungers_for_gsg
+//       Access: Public
+//  Description: Removes all the mungers from the registry that are
+//               associated with the indicated GSG.
+////////////////////////////////////////////////////////////////////
+void GeomMunger::Registry::
+unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg) {
+  MutexHolder holder(_registry_lock);
+
+  Mungers::iterator mi = _mungers.begin();
+  while (mi != _mungers.end()) {
+    GeomMunger *munger = (*mi);
+    Mungers::iterator mnext = mi;
+    ++mnext;
+
+    if (munger->get_gsg() == gsg) {
+      nassertv(mi == munger->_registered_key);
+      _mungers.erase(mi);
+      munger->_registered_key = _mungers.end();
+      munger->do_unregister();
+    }
+
+    mi = mnext;
+  }
+}

+ 7 - 1
panda/src/gobj/geomMunger.h

@@ -59,13 +59,16 @@ class Geom;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GeomMunger : public TypedReferenceCount, public GeomEnums {
 class EXPCL_PANDA GeomMunger : public TypedReferenceCount, public GeomEnums {
 public:
 public:
-  GeomMunger();
+  GeomMunger(GraphicsStateGuardianBase *gsg);
   GeomMunger(const GeomMunger &copy);
   GeomMunger(const GeomMunger &copy);
   void operator = (const GeomMunger &copy);
   void operator = (const GeomMunger &copy);
   virtual ~GeomMunger();
   virtual ~GeomMunger();
 
 
+  INLINE GraphicsStateGuardianBase *get_gsg() const;
+
   INLINE bool is_registered() const;
   INLINE bool is_registered() const;
   INLINE static PT(GeomMunger) register_munger(GeomMunger *munger, Thread *current_thread);
   INLINE static PT(GeomMunger) register_munger(GeomMunger *munger, Thread *current_thread);
+  INLINE static void unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg);
 
 
   INLINE CPT(GeomVertexFormat) munge_format(const GeomVertexFormat *format,
   INLINE CPT(GeomVertexFormat) munge_format(const GeomVertexFormat *format,
                                               const GeomVertexAnimationSpec &animation) const;
                                               const GeomVertexAnimationSpec &animation) const;
@@ -117,6 +120,8 @@ private:
   // This mutex protects the above.
   // This mutex protects the above.
   Mutex _formats_lock;
   Mutex _formats_lock;
 
 
+  GraphicsStateGuardianBase *_gsg;
+
   bool _is_registered;
   bool _is_registered;
   typedef pset<GeomMunger *, IndirectCompareTo<GeomMunger> > Mungers;
   typedef pset<GeomMunger *, IndirectCompareTo<GeomMunger> > Mungers;
   class EXPCL_PANDA Registry {
   class EXPCL_PANDA Registry {
@@ -124,6 +129,7 @@ private:
     Registry();
     Registry();
     PT(GeomMunger) register_munger(GeomMunger *munger, Thread *current_thread);
     PT(GeomMunger) register_munger(GeomMunger *munger, Thread *current_thread);
     void unregister_munger(GeomMunger *munger);
     void unregister_munger(GeomMunger *munger);
+    void unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg);
 
 
     Mungers _mungers;
     Mungers _mungers;
     Mutex _registry_lock;
     Mutex _registry_lock;

+ 11 - 0
panda/src/pgraph/stateMunger.I

@@ -16,3 +16,14 @@
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: StateMunger::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE StateMunger::
+StateMunger(GraphicsStateGuardianBase *gsg) :
+  GeomMunger(gsg)
+{
+}

+ 1 - 0
panda/src/pgraph/stateMunger.h

@@ -33,6 +33,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA StateMunger : public GeomMunger {
 class EXPCL_PANDA StateMunger : public GeomMunger {
 public:
 public:
+  INLINE StateMunger(GraphicsStateGuardianBase *gsg);
   virtual ~StateMunger();
   virtual ~StateMunger();
   CPT(RenderState) munge_state(const RenderState *state);
   CPT(RenderState) munge_state(const RenderState *state);
 
 

+ 4 - 4
panda/src/windisplay/winGraphicsWindow.cxx

@@ -335,15 +335,15 @@ close_window() {
   set_cursor_out_of_window();
   set_cursor_out_of_window();
   DestroyWindow(_hWnd);
   DestroyWindow(_hWnd);
 
 
-  // Remove the window handle from our global map.
-  _window_handles.erase(_hWnd);
-  _hWnd = (HWND)0;
-
   if (is_fullscreen()) {
   if (is_fullscreen()) {
     // revert to default display mode.
     // revert to default display mode.
     ChangeDisplaySettings(NULL, 0x0);
     ChangeDisplaySettings(NULL, 0x0);
   }
   }
 
 
+  // Remove the window handle from our global map.
+  _window_handles.erase(_hWnd);
+  _hWnd = (HWND)0;
+
   GraphicsWindow::close_window();
   GraphicsWindow::close_window();
 }
 }