Browse Source

minor restructure of close_window(), etc.

David Rose 24 years ago
parent
commit
8090dda677

+ 14 - 2
panda/src/display/graphicsStateGuardian.I

@@ -20,7 +20,7 @@
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::set_render_traverser
 //     Function: GraphicsStateGuardian::set_render_traverser
-//       Access: Public
+//       Access: Published
 //  Description: Sets the traverser that will be used to render the
 //  Description: Sets the traverser that will be used to render the
 //               scene graph.  If this is unset, nothing will be
 //               scene graph.  If this is unset, nothing will be
 //               rendered.
 //               rendered.
@@ -32,7 +32,7 @@ set_render_traverser(RenderTraverser *rt) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_render_traverser
 //     Function: GraphicsStateGuardian::get_render_traverser
-//       Access: Public
+//       Access: Published
 //  Description: Returns the traverser that will be used to render the
 //  Description: Returns the traverser that will be used to render the
 //               scene graph.
 //               scene graph.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -41,6 +41,18 @@ get_render_traverser() const {
   return _render_traverser;
   return _render_traverser;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::is_closed
+//       Access: Public
+//  Description: Returns true if the window associated with this GSG
+//               has been closed, and hence the resources associated
+//               with this GSG have been freed.
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsStateGuardian::
+is_closed() const {
+  return (_win == (GraphicsWindow *)NULL);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_state
 //     Function: GraphicsStateGuardian::get_state
 //       Access: Public
 //       Access: Public

+ 13 - 0
panda/src/display/graphicsStateGuardian.cxx

@@ -733,6 +733,19 @@ unmark_prepared_geom_node(GeomNodeContext *gnc) {
   return removed;
   return removed;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::close_gsg
+//       Access: Protected, Virtual
+//  Description: This is called by the associated GraphicsWindow when
+//               close_window() is called.  It should null out the
+//               _win pointer and possibly free any open resources
+//               associated with the GSG.
+////////////////////////////////////////////////////////////////////
+void GraphicsStateGuardian::
+close_gsg() {
+  _win = (GraphicsWindow *)NULL;
+}
+
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 6 - 1
panda/src/display/graphicsStateGuardian.h

@@ -84,6 +84,8 @@ PUBLISHED:
   void clear_attribute(TypeHandle type);
   void clear_attribute(TypeHandle type);
 
 
 public:
 public:
+  INLINE bool is_closed() const;
+
   virtual TextureContext *prepare_texture(Texture *tex);
   virtual TextureContext *prepare_texture(Texture *tex);
   virtual void apply_texture(TextureContext *tc);
   virtual void apply_texture(TextureContext *tc);
   virtual void release_texture(TextureContext *tc);
   virtual void release_texture(TextureContext *tc);
@@ -165,6 +167,8 @@ protected:
   bool mark_prepared_geom_node(GeomNodeContext *gnc);
   bool mark_prepared_geom_node(GeomNodeContext *gnc);
   bool unmark_prepared_geom_node(GeomNodeContext *gnc);
   bool unmark_prepared_geom_node(GeomNodeContext *gnc);
 
 
+  virtual void close_gsg();
+
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
   // These functions are used to update the active texture memory
   // These functions are used to update the active texture memory
   // usage record (and other frame-based measurements) in Pstats.
   // usage record (and other frame-based measurements) in Pstats.
@@ -300,7 +304,8 @@ public:
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
 
 
-friend class GraphicsPipe;
+  friend class GraphicsPipe;
+  friend class GraphicsWindow;
 };
 };
 
 
 #include "graphicsStateGuardian.I"
 #include "graphicsStateGuardian.I"

+ 115 - 83
panda/src/display/graphicsWindow.I

@@ -20,7 +20,7 @@
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_properties
 //     Function: GraphicsWindow::get_properties
-//       Access: Public
+//       Access: Published
 //  Description: Returns the full Properties structure that describes
 //  Description: Returns the full Properties structure that describes
 //               the window.
 //               the window.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -31,7 +31,7 @@ get_properties() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_width
 //     Function: GraphicsWindow::get_width
-//       Access: Public
+//       Access: Published
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GraphicsWindow::
 INLINE int GraphicsWindow::
@@ -41,7 +41,7 @@ get_width() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_height
 //     Function: GraphicsWindow::get_height
-//       Access: Public
+//       Access: Published
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GraphicsWindow::
 INLINE int GraphicsWindow::
@@ -51,7 +51,7 @@ get_height() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_xorg
 //     Function: GraphicsWindow::get_xorg
-//       Access: Public
+//       Access: Published
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GraphicsWindow::
 INLINE int GraphicsWindow::
@@ -61,7 +61,7 @@ get_xorg() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_yorg
 //     Function: GraphicsWindow::get_yorg
-//       Access: Public
+//       Access: Published
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GraphicsWindow::
 INLINE int GraphicsWindow::
@@ -71,19 +71,24 @@ get_yorg() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_gsg
 //     Function: GraphicsWindow::get_gsg
-//       Access: Public
+//       Access: Published
 //  Description: Returns the GSG that is associated with this window.
 //  Description: Returns the GSG that is associated with this window.
 //               There is a one-to-one association between windows and
 //               There is a one-to-one association between windows and
 //               GSG's.
 //               GSG's.
+//
+//               It is invalid to call this if the window has been
+//               closed; that is, if is_closed() returns true.  In
+//               this case the GSG has been closed as well.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GraphicsStateGuardian *GraphicsWindow::
 INLINE GraphicsStateGuardian *GraphicsWindow::
 get_gsg() const {
 get_gsg() const {
+  nassertr(!is_closed(), NULL);
   return _gsg;
   return _gsg;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_pipe
 //     Function: GraphicsWindow::get_pipe
-//       Access: Public
+//       Access: Published
 //  Description: Returns the GraphicsPipe that this window is
 //  Description: Returns the GraphicsPipe that this window is
 //               associated with.  It is possible that the
 //               associated with.  It is possible that the
 //               GraphicsPipe might have been deleted while an
 //               GraphicsPipe might have been deleted while an
@@ -97,8 +102,104 @@ get_pipe() const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsWindow::get_num_input_devices
+//     Function: GraphicsWindow::close_window
+//       Access: Published
+//  Description: Closes the window and frees all resources associated
+//               with it, including the GSG.  The window may not be
+//               opened again.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindow::
+close_window() {
+  if (!is_closed()) {
+    do_close_window();
+    release_gsg();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::is_closed
+//       Access: Published
+//  Description: Returns true if close_window() has been called on
+//               this window, false otherwise.  If the window has been
+//               closed, most of its interface is no longer valid.
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsWindow::
+is_closed() const {
+  return (_gsg == (GraphicsStateGuardian *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::set_frame_number
+//       Access: Published
+//  Description: Sets the current frame number of the window.  This
+//               affects the frame numbers written for %f in a RIB or
+//               image filename template.  The frame number is
+//               initially zero, and it increments at each call to
+//               end_frame().
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindow::
+set_frame_number(const int f) {
+  _frame_number = f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::get_frame_number
+//       Access: Published
+//  Description: Returns the current frame number of the window.  See
+//               set_frame_number().
+////////////////////////////////////////////////////////////////////
+INLINE int GraphicsWindow::
+get_frame_number() const {
+  return _frame_number;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::set_draw_callback
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindow::
+set_draw_callback(Callback *c) {
+  _draw_callback = c;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::set_idle_callback
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindow::
+set_idle_callback(Callback *c) {
+  _idle_callback = c;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::call_draw_callback
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindow::
+call_draw_callback(bool force_redraw) {
+  if (_draw_callback) {
+    _draw_callback->draw(force_redraw);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::call_idle_callback
 //       Access: Public
 //       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindow::
+call_idle_callback() {
+  if (_idle_callback) {
+    _idle_callback->idle();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::get_num_input_devices
+//       Access: Published
 //  Description: Returns the number of separate input devices
 //  Description: Returns the number of separate input devices
 //               associated with the window.  Typically, a window will
 //               associated with the window.  Typically, a window will
 //               have exactly one input device: the keyboard/mouse
 //               have exactly one input device: the keyboard/mouse
@@ -113,7 +214,7 @@ get_num_input_devices() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_input_device_name
 //     Function: GraphicsWindow::get_input_device_name
-//       Access: Public
+//       Access: Published
 //  Description: Returns the name of the nth input device.
 //  Description: Returns the name of the nth input device.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE string GraphicsWindow::
 INLINE string GraphicsWindow::
@@ -124,7 +225,7 @@ get_input_device_name(int device) const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::has_pointer
 //     Function: GraphicsWindow::has_pointer
-//       Access: Public
+//       Access: Published
 //  Description: Returns true if the nth input device has a
 //  Description: Returns true if the nth input device has a
 //               screen-space pointer (for instance, a mouse), false
 //               screen-space pointer (for instance, a mouse), false
 //               otherwise.
 //               otherwise.
@@ -137,7 +238,7 @@ has_pointer(int device) const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::has_keyboard
 //     Function: GraphicsWindow::has_keyboard
-//       Access: Public
+//       Access: Published
 //  Description: Returns true if the nth input device has a keyboard,
 //  Description: Returns true if the nth input device has a keyboard,
 //               false otherwise.
 //               false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -149,7 +250,7 @@ has_keyboard(int device) const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_mouse_data
 //     Function: GraphicsWindow::get_mouse_data
-//       Access: Public
+//       Access: Published
 //  Description: Returns the MouseData associated with the nth input
 //  Description: Returns the MouseData associated with the nth input
 //               device.
 //               device.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -162,7 +263,7 @@ get_mouse_data(int device) const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::has_button_event
 //     Function: GraphicsWindow::has_button_event
-//       Access: Public
+//       Access: Published
 //  Description: Returns true if the indicated device has a pending
 //  Description: Returns true if the indicated device has a pending
 //               button event (a mouse button or keyboard button
 //               button event (a mouse button or keyboard button
 //               down/up), false otherwise.  If this returns true, the
 //               down/up), false otherwise.  If this returns true, the
@@ -177,7 +278,7 @@ has_button_event(int device) const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_button_event
 //     Function: GraphicsWindow::get_button_event
-//       Access: Public
+//       Access: Published
 //  Description: Assuming a previous call to has_button_event()
 //  Description: Assuming a previous call to has_button_event()
 //               returned true, this returns the pending button event.
 //               returned true, this returns the pending button event.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -187,72 +288,3 @@ get_button_event(int device) {
   return _input_devices[device].get_button_event();
   return _input_devices[device].get_button_event();
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsWindow::set_frame_number
-//       Access: Public
-//  Description: Sets the current frame number of the window.  This
-//               affects the frame numbers written for %f in a RIB or
-//               image filename template.  The frame number is
-//               initially zero, and it increments at each call to
-//               end_frame().
-////////////////////////////////////////////////////////////////////
-INLINE void GraphicsWindow::
-set_frame_number(const int f) {
-  _frame_number = f;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsWindow::get_frame_number
-//       Access: Public
-//  Description: Returns the current frame number of the window.  See
-//               set_frame_number().
-////////////////////////////////////////////////////////////////////
-INLINE int GraphicsWindow::
-get_frame_number() const {
-  return _frame_number;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsWindow::set_draw_callback
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GraphicsWindow::
-set_draw_callback(Callback *c) {
-  _draw_callback = c;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsWindow::set_idle_callback
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GraphicsWindow::
-set_idle_callback(Callback *c) {
-  _idle_callback = c;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsWindow::call_draw_callback
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GraphicsWindow::
-call_draw_callback(bool force_redraw) {
-  if (_draw_callback) {
-    _draw_callback->draw(force_redraw);
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsWindow::call_idle_callback
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void GraphicsWindow::
-call_idle_callback() {
-  if (_idle_callback) {
-    _idle_callback->idle();
-  }
-}
-

+ 53 - 1
panda/src/display/graphicsWindow.cxx

@@ -184,11 +184,22 @@ operator=(const GraphicsWindow&) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::Destructor
 //     Function: GraphicsWindow::Destructor
-//       Access: Public
+//       Access: Public, Virtual
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GraphicsWindow::
 GraphicsWindow::
 ~GraphicsWindow() {
 ~GraphicsWindow() {
+  // First, call close_window().  This tells our GSG to let go of its
+  // pointer to us, and also eventually calls do_close_window().
+  // However, do_close_window() is a virtual function that might be
+  // extended in a derived class, but we don't have any derived
+  // virtual functions by the time the destructor is called.
+  
+  // Therefore, if a derived class has redefined do_close_window(), it
+  // should also call close_window() in its own destructor.
+  close_window();
+
+
   // We don't have to destruct our child channels explicitly, since
   // We don't have to destruct our child channels explicitly, since
   // they are all reference-counted and will go away when their
   // they are all reference-counted and will go away when their
   // pointers do.  However, we do need to zero out their pointers to
   // pointers do.  However, we do need to zero out their pointers to
@@ -514,6 +525,47 @@ make_gsg() {
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::release_gsg
+//       Access: Protected
+//  Description: Releases the current GSG pointer, if it is currently
+//               held.  This invalidates the window and marks it
+//               closed; it should not be called unless the code to
+//               close the window is also called.
+////////////////////////////////////////////////////////////////////
+void GraphicsWindow::
+release_gsg() {
+  if (_gsg != (GraphicsStateGuardian *)NULL) {
+    // First, we save the GSG pointer and then NULL it out.  That way,
+    // if the GSG happens to call close_window() while it is closing
+    // itself, it won't be recursive (because we'll already be marked
+    // closed).
+    PT(GraphicsStateGuardian) gsg = _gsg;
+    _gsg.clear();
+
+    // Now we tell the GSG it's time to sleep.
+    gsg->close_gsg();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::do_close_window
+//       Access: Protected, Virtual
+//  Description: An internal function to release whatever system
+//               resources are held by the window and actually close
+//               it.  This is called by close_window().  
+//
+//               If a derived class redefines this function, it should
+//               also arrange to call close_window() (or its
+//               equivalent) from its own destructor, since we cannot
+//               call a virtual function from this destructor.
+////////////////////////////////////////////////////////////////////
+void GraphicsWindow::
+do_close_window() {
+  display_cat.info()
+    << "Closing " << get_type() << "\n";
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_factory
 //     Function: GraphicsWindow::get_factory
 //       Access: Public, Static
 //       Access: Public, Static

+ 5 - 3
panda/src/display/graphicsWindow.h

@@ -113,14 +113,14 @@ PUBLISHED:
   INLINE int get_yorg() const;
   INLINE int get_yorg() const;
 
 
   INLINE GraphicsStateGuardian *get_gsg() const;
   INLINE GraphicsStateGuardian *get_gsg() const;
-
   INLINE GraphicsPipe *get_pipe() const;
   INLINE GraphicsPipe *get_pipe() const;
 
 
+  INLINE void close_window();
+  INLINE bool is_closed() const;
+
   INLINE void set_frame_number(const int);
   INLINE void set_frame_number(const int);
   INLINE int get_frame_number() const;
   INLINE int get_frame_number() const;
 
 
-  virtual void close_window(int exit_status) {return;};  //release windowing system resources
-
 public:
 public:
   virtual void resized(const int, const int);
   virtual void resized(const int, const int);
 
 
@@ -179,6 +179,8 @@ public:
 
 
 protected:
 protected:
   void make_gsg();
   void make_gsg();
+  void release_gsg();
+  virtual void do_close_window();
 
 
   typedef vector_GraphicsWindowInputDevice InputDevices;
   typedef vector_GraphicsWindowInputDevice InputDevices;
   InputDevices _input_devices;
   InputDevices _input_devices;

+ 4 - 4
panda/src/framework/framework.cxx

@@ -431,11 +431,11 @@ void event_esc(CPT_Event ev) {
 #endif
 #endif
 
 
    if(ev->get_name()=="q") {
    if(ev->get_name()=="q") {
-      // if app ever exits using exit() without close_window, hopefully this will work
-      framework_cat.debug() << "Testing unsafe, no close_window(), direct exit() of framework\n";
+     // if app ever exits using exit() without close_window, hopefully this will work
+     framework_cat.debug() << "Testing unsafe, no close_window(), direct exit() of framework\n";
    } else {
    } else {
-    main_win->close_window(0);
-    framework_cat.debug() << "Exiting framework\n";
+     main_win->close_window();
+     framework_cat.debug() << "Exiting framework\n";
    }
    }
 
 
    main_win = NULL;
    main_win = NULL;

+ 3 - 3
panda/src/glgsg/glGraphicsStateGuardian.cxx

@@ -1768,9 +1768,9 @@ release_texture(TextureContext *tc) {
   GLTextureContext *gtc = DCAST(GLTextureContext, tc);
   GLTextureContext *gtc = DCAST(GLTextureContext, tc);
   Texture *tex = tc->_texture;
   Texture *tex = tc->_texture;
 
 
-  HGLRC curcxt=wglGetCurrentContext();
-  if(curcxt!=NULL)
-      glDeleteTextures(1, &gtc->_index);
+  if (!is_closed()) {
+    glDeleteTextures(1, &gtc->_index);
+  }
   gtc->_index = 0;
   gtc->_index = 0;
 
 
   bool erased = unmark_prepared_texture(gtc);
   bool erased = unmark_prepared_texture(gtc);

+ 5 - 1
panda/src/glxdisplay/glxGraphicsWindow.cxx

@@ -1155,10 +1155,14 @@ void glxGraphicsWindow::process_event(XEvent event)
       handle_mouse_motion(event.xcrossing.x, event.xcrossing.y);
       handle_mouse_motion(event.xcrossing.x, event.xcrossing.y);
     }
     }
     break;
     break;
+
+  case DestroyNotify:
+    close_window();
+    break;
+
   case UnmapNotify:
   case UnmapNotify:
   case VisibilityNotify:
   case VisibilityNotify:
   case ClientMessage:
   case ClientMessage:
-  case DestroyNotify:
   case CirculateNotify:
   case CirculateNotify:
   case CreateNotify:
   case CreateNotify:
   case GravityNotify:
   case GravityNotify:

+ 5 - 3
panda/src/wdxdisplay/wdxGraphicsWindow.cxx

@@ -178,6 +178,7 @@ void wdxGraphicsWindow::DestroyMe(bool bAtExitFnCalled) {
       _dxgsg->dx_cleanup(_props._fullscreen, bAtExitFnCalled);
       _dxgsg->dx_cleanup(_props._fullscreen, bAtExitFnCalled);
       _dxgsg=NULL;
       _dxgsg=NULL;
   }
   }
+  release_gsg();
 
 
   if(_hdc!=NULL) {
   if(_hdc!=NULL) {
     ReleaseDC(_mwindow,_hdc);
     ReleaseDC(_mwindow,_hdc);
@@ -195,7 +196,8 @@ void wdxGraphicsWindow::DestroyMe(bool bAtExitFnCalled) {
   }
   }
 }
 }
 
 
-void wdxGraphicsWindow::close_window(int exit_status) {
+void wdxGraphicsWindow::do_close_window() {
+  GraphicsWindow::do_close_window();
    DestroyMe(false);
    DestroyMe(false);
 }
 }
 
 
@@ -205,7 +207,7 @@ void wdxGraphicsWindow::close_window(int exit_status) {
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 wdxGraphicsWindow::~wdxGraphicsWindow(void) {
 wdxGraphicsWindow::~wdxGraphicsWindow(void) {
-   DestroyMe(false);
+   close_window();
 }
 }
 
 
 void DestroyAllWindows(bool bAtExitFnCalled) {
 void DestroyAllWindows(bool bAtExitFnCalled) {
@@ -262,7 +264,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
             break;
             break;
 
 
         case WM_CLOSE:
         case WM_CLOSE:
-          DestroyMe(false);
+          close_window();
 
 
           // BUGBUG:  right now there is no way to tell the panda app the graphics window is invalid or
           // BUGBUG:  right now there is no way to tell the panda app the graphics window is invalid or
           //          has been closed by the user, to prevent further methods from being called on the window.
           //          has been closed by the user, to prevent further methods from being called on the window.

+ 1 - 1
panda/src/wdxdisplay/wdxGraphicsWindow.h

@@ -115,7 +115,7 @@ public:
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
 
 
   void DestroyMe(bool bAtExitFnCalled);
   void DestroyMe(bool bAtExitFnCalled);
-  virtual void close_window(int exit_status);
+  virtual void do_close_window();
 
 
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;

+ 5 - 4
panda/src/wgldisplay/wglGraphicsWindow.cxx

@@ -96,7 +96,7 @@ void wglGraphicsWindow::DestroyMe(bool bAtExitFnCalled) {
       report_errors();
       report_errors();
 
 
       // implicitly calls gsg destructors which release GL objects (textures, display lists, etc)
       // implicitly calls gsg destructors which release GL objects (textures, display lists, etc)
-      _gsg = NULL;
+      release_gsg();
     
     
       HGLRC curcxt=wglGetCurrentContext();
       HGLRC curcxt=wglGetCurrentContext();
       if(curcxt!=NULL) 
       if(curcxt!=NULL) 
@@ -134,7 +134,8 @@ void wglGraphicsWindow::DestroyMe(bool bAtExitFnCalled) {
   }
   }
 }
 }
 
 
-void wglGraphicsWindow::close_window(int exit_status) {
+void wglGraphicsWindow::do_close_window() {
+  GraphicsWindow::do_close_window();
    DestroyMe(false);
    DestroyMe(false);
 }
 }
 
 
@@ -144,7 +145,7 @@ void wglGraphicsWindow::close_window(int exit_status) {
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 wglGraphicsWindow::~wglGraphicsWindow(void) {
 wglGraphicsWindow::~wglGraphicsWindow(void) {
-   DestroyMe(false);
+   close_window();
 }
 }
 
 
 void DestroyAllWindows(bool bAtExitFnCalled) {
 void DestroyAllWindows(bool bAtExitFnCalled) {
@@ -1330,7 +1331,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
       break;
       break;
 
 
     case WM_CLOSE:
     case WM_CLOSE:
-          DestroyMe(false);
+          close_window();
 
 
           // BUGBUG:  right now there is no way to tell the panda app the graphics window is invalid or
           // BUGBUG:  right now there is no way to tell the panda app the graphics window is invalid or
           //          has been closed by the user, to prevent further methods from being called on the window.
           //          has been closed by the user, to prevent further methods from being called on the window.

+ 3 - 1
panda/src/wgldisplay/wglGraphicsWindow.h

@@ -143,7 +143,9 @@ public:
   LONG WINAPI window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
   LONG WINAPI window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
   ButtonHandle lookup_key(WPARAM wparam) const;
   ButtonHandle lookup_key(WPARAM wparam) const;
   void DestroyMe(bool bAtExitFnCalled);
   void DestroyMe(bool bAtExitFnCalled);
-  virtual void close_window(int exit_status);
+
+protected:
+  virtual void do_close_window();
 
 
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;