Przeglądaj źródła

First step in refactoring begin_frame and end_frame

Josh Yelon 20 lat temu
rodzic
commit
4477cdbafb

+ 52 - 0
panda/src/display/graphicsOutput.I

@@ -426,3 +426,55 @@ INLINE void GraphicsOutput::
 win_display_regions_changed() {
   _display_regions_stale = true;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::begin_frame_spam
+//       Access: Public
+//  Description: Display the spam message associated with begin_frame
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsOutput::
+begin_frame_spam() {
+  if (display_cat.is_spam()) {
+    display_cat.spam()
+      << "begin_frame(): " << get_type() << " "
+      << get_name() << " " << (void *)this << "\n";
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::end_frame_spam
+//       Access: Public
+//  Description: Display the spam message associated with end_frame
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsOutput::
+end_frame_spam() {
+  if (display_cat.is_spam()) {
+    display_cat.spam()
+      << "end_frame(): " << get_type() << " "
+      << get_name() << " " << (void *)this << "\n";
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::clear_cube_map_selection
+//       Access: Public
+//  Description: Clear the variables that select a cube-map face.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsOutput::
+clear_cube_map_selection() {
+  _cube_map_index = -1;
+  _cube_map_dr = NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::trigger_flip
+//       Access: Public
+//  Description: Set the flip_ready flag, only if legal to do so.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsOutput::
+trigger_flip() {
+  if (!_gsg->get_properties().is_single_buffered()) {
+    _flip_ready = true;
+  }
+}
+

+ 49 - 81
panda/src/display/graphicsOutput.cxx

@@ -962,34 +962,53 @@ reset_window(bool swapchain) {
 ////////////////////////////////////////////////////////////////////
 bool GraphicsOutput::
 begin_frame() {
-  if (display_cat.is_spam()) {
-    display_cat.spam()
-      << "begin_frame(): " << get_type() << " "
-      << get_name() << " " << (void *)this << "\n";
-  }
-
-  if (_gsg == (GraphicsStateGuardian *)NULL) {
-    return false;
-  }
+  return false;
+}
 
-  // Track the size of some other graphics output, if desired.
-  auto_resize();
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void GraphicsOutput::
+end_frame() {
+}
 
-  if (needs_context()) {
-    if (!make_context()) {
-      return false;
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::prepare_for_deletion
+//       Access: Protected
+//  Description: Set the delete flag, and do the usual cleanup 
+//               activities associated with that.
+////////////////////////////////////////////////////////////////////
+void GraphicsOutput::
+prepare_for_deletion() {
+  // But when show-buffers mode is enabled, we want to keep the
+  // window around until the user has a chance to see the texture.
+  // So we don't do most of the following in show-buffers mode.
+  if (!show_buffers) {
+    _active = false;
+    _delete_flag = true;
+    
+    // We have to be sure to remove all of the display regions
+    // immediately, so that circular reference counts can be cleared
+    // up (each display region keeps a pointer to a CullResult,
+    // which can hold all sorts of pointers).
+    remove_all_display_regions();
+    
+    // If we were rendering directly to texture, we can't delete the
+    // buffer until the texture is gone too.
+    for (int i=0; i<count_textures(); i++) {
+      if (get_rtm_mode(i) == RTM_bind_or_copy) {
+        _hold_textures.push_back(get_texture(i));
+      }
     }
   }
-
-  // Okay, we already have a GSG, so activate it.
-  make_current();
-
-  begin_render_texture();
-
-  _cube_map_index = -1;
-  _cube_map_dr = NULL;
-
-  return _gsg->begin_frame();
+  
+  // We have to be sure to clear the _textures pointers, though, or
+  // we'll end up holding a reference to the textures forever.
+  clear_render_textures();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1020,27 +1039,14 @@ clear() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsOutput::end_frame
-//       Access: Public, Virtual
-//  Description: This function will be called within the draw thread
-//               after rendering is completed for a given frame.  It
-//               should do whatever finalization is required.
+//     Function: GraphicsOutput::copy_to_textures
+//       Access: Protected
+//  Description: For all textures marked RTM_copy_texture,
+//               RTM_copy_ram, RTM_triggered_copy_texture, or
+//               RTM_triggered_copy_ram, do the necessary copies.
 ////////////////////////////////////////////////////////////////////
 void GraphicsOutput::
-end_frame() {
-  if (display_cat.is_spam()) {
-    display_cat.spam()
-      << "end_frame(): " << get_type() << " "
-      << get_name() << " " << (void *)this << "\n";
-  }
-
-  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
-  _gsg->end_frame();
-
-  // Handle all render-to-texture operations that use bind-to-texture
-  end_render_texture();
-
-  // Handle all render-to-texture operations that use copy-to-texture
+copy_to_textures() {
   for (int i=0; i<count_textures(); i++) {
     RenderTextureMode rtm_mode = get_rtm_mode(i);
     if ((rtm_mode == RTM_none)||(rtm_mode == RTM_bind_or_copy)) {
@@ -1082,44 +1088,6 @@ end_frame() {
     }
   }
   _trigger_copy = false;
-
-  // If we're not single-buffered, we're now ready to flip.
-  if (!_gsg->get_properties().is_single_buffered()) {
-    _flip_ready = true;
-  }
-
-  // In one-shot mode, we request the GraphicsEngine to delete the
-  // window after we have rendered a frame.
-  if (_one_shot) {
-    // But when show-buffers mode is enabled, we want to keep the
-    // window around until the user has a chance to see the texture.
-    // So we don't do most of the following in show-buffers mode.
-    if (!show_buffers) {
-      _active = false;
-      _delete_flag = true;
-
-      // We have to be sure to remove all of the display regions
-      // immediately, so that circular reference counts can be cleared
-      // up (each display region keeps a pointer to a CullResult,
-      // which can hold all sorts of pointers).
-      remove_all_display_regions();
-
-      // If we were rendering directly to texture, we can't delete the
-      // buffer until the texture is gone too.
-      for (int i=0; i<count_textures(); i++) {
-        if (get_rtm_mode(i) == RTM_bind_or_copy) {
-          _hold_textures.push_back(get_texture(i));
-        }
-      }
-    }
-
-    // We have to be sure to clear the _textures pointers, though, or
-    // we'll end up holding a reference to the textures forever.
-    clear_render_textures();
-  }
-
-  _cube_map_index = -1;
-  _cube_map_dr = NULL;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 10 - 0
panda/src/display/graphicsOutput.h

@@ -185,7 +185,17 @@ public:
   // thread other than the window thread.  These methods are normally
   // called by the GraphicsEngine.
   virtual void process_events();
+
+protected:
+
+  void prepare_for_deletion();
+  void copy_to_textures();
   
+  INLINE void begin_frame_spam();
+  INLINE void end_frame_spam();
+  INLINE void clear_cube_map_selection();
+  INLINE void trigger_flip();
+
 protected:
 
   class RenderTexture {

+ 48 - 0
panda/src/display/parasiteBuffer.cxx

@@ -96,6 +96,54 @@ get_host() {
   return _host;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ParasiteBuffer::begin_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               before beginning rendering for a given frame.  It
+//               should do whatever setup is required, and return true
+//               if the frame should be rendered, or false if it
+//               should be skipped.
+////////////////////////////////////////////////////////////////////
+bool ParasiteBuffer::
+begin_frame() {
+  begin_frame_spam();
+  if (_gsg == (GraphicsStateGuardian *)NULL) {
+    return false;
+  }
+  auto_resize();
+  if (needs_context()) {
+    if (!make_context()) {
+      return false;
+    }
+  }
+  make_current();
+  begin_render_texture();
+  clear_cube_map_selection();
+  return _gsg->begin_frame();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ParasiteBuffer::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void ParasiteBuffer::
+end_frame() {
+  end_frame_spam();
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+  _gsg->end_frame();
+  end_render_texture();
+  copy_to_textures();
+  trigger_flip();
+  if (_one_shot) {
+    prepare_for_deletion();
+  }
+  clear_cube_map_selection();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ParasiteBuffer::make_current
 //       Access: Public, Virtual

+ 3 - 1
panda/src/display/parasiteBuffer.h

@@ -63,10 +63,12 @@ PUBLISHED:
   virtual bool is_active() const;
 
 public:
+  virtual bool begin_frame();
+  virtual void end_frame();
   virtual GraphicsOutput *get_host();
   virtual void make_current();
   virtual void auto_resize();
-
+  
 private:
   PT(GraphicsOutput) _host;
   bool _track_host_size;

+ 31 - 4
panda/src/dxgsg8/wdxGraphicsBuffer8.cxx

@@ -81,14 +81,41 @@ wdxGraphicsBuffer8::
 ////////////////////////////////////////////////////////////////////
 bool wdxGraphicsBuffer8::
 begin_frame() {
+  begin_frame_spam();
   if (_gsg == (GraphicsStateGuardian *)NULL) {
     return false;
   }
+  auto_resize();
+  if (needs_context()) {
+    if (!make_context()) {
+      return false;
+    }
+  }
+  make_current();
+  begin_render_texture();
+  clear_cube_map_selection();
+  return _gsg->begin_frame();
+}
 
-  DXGraphicsStateGuardian8 *dxgsg;
-  DCAST_INTO_R(dxgsg, _gsg, false);
-
-  return GraphicsBuffer::begin_frame();
+////////////////////////////////////////////////////////////////////
+//     Function: wdxGraphicsBuffer8::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void wdxGraphicsBuffer8::
+end_frame() {
+  end_frame_spam();
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+  _gsg->end_frame();
+  end_render_texture();
+  copy_to_textures();
+  trigger_flip();
+  if (_one_shot) {
+    prepare_for_deletion();
+  }
+  clear_cube_map_selection();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/dxgsg8/wdxGraphicsBuffer8.h

@@ -42,6 +42,7 @@ public:
   virtual ~wdxGraphicsBuffer8();
 
   virtual bool begin_frame();
+  virtual void end_frame();
   virtual void select_cube_map(int cube_map_index);
 
   virtual void make_current();

+ 35 - 2
panda/src/dxgsg8/wdxGraphicsWindow8.cxx

@@ -100,6 +100,10 @@ make_current() {
 ////////////////////////////////////////////////////////////////////
 bool wdxGraphicsWindow8::
 begin_frame() {
+  begin_frame_spam();
+  if (_gsg == (GraphicsStateGuardian *)NULL) {
+    return false;
+  }
   if (_awaiting_restore) {
     // The fullscreen window was recently restored; we can't continue
     // until the GSG says we can.
@@ -111,12 +115,41 @@ begin_frame() {
 
     init_resized_window();
   }
-
-  bool return_val = WinGraphicsWindow::begin_frame();
+  auto_resize();
+  if (needs_context()) {
+    if (!make_context()) {
+      return false;
+    }
+  }
+  make_current();
+  begin_render_texture();
+  clear_cube_map_selection();
+  bool return_val = _gsg->begin_frame();
   _dxgsg->set_render_target();
   return return_val;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: wdxGraphicsWindow8::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void wdxGraphicsWindow8::
+end_frame() {
+  end_frame_spam();
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+  _gsg->end_frame();
+  end_render_texture();
+  copy_to_textures();
+  trigger_flip();
+  if (_one_shot) {
+    prepare_for_deletion();
+  }
+  clear_cube_map_selection();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: wdxGraphicsWindow8::end_flip
 //       Access: Public, Virtual

+ 2 - 2
panda/src/dxgsg8/wdxGraphicsWindow8.h

@@ -38,9 +38,9 @@ public:
                      const string &name);
   virtual ~wdxGraphicsWindow8();
 
-  virtual void make_current();
-
   virtual bool begin_frame();
+  virtual void end_frame();
+  virtual void make_current();
   virtual void end_flip();
 
   virtual int verify_window_sizes(int numsizes, int *dimen);

+ 32 - 6
panda/src/dxgsg9/wdxGraphicsBuffer9.cxx

@@ -78,16 +78,42 @@ wdxGraphicsBuffer9::
 ////////////////////////////////////////////////////////////////////
 bool wdxGraphicsBuffer9::
 begin_frame() {
+  DBG_S dxgsg9_cat.debug ( ) << "wdxGraphicsBuffer9::begin_frame\n"; DBG_E
+  begin_frame_spam();
   if (_gsg == (GraphicsStateGuardian *)NULL) {
     return false;
   }
+  auto_resize();
+  if (needs_context()) {
+    if (!make_context()) {
+      return false;
+    }
+  }
+  make_current();
+  begin_render_texture();
+  clear_cube_map_selection();
+  return _gsg->begin_frame();
+}
 
-  DBG_S dxgsg9_cat.debug ( ) << "wdxGraphicsBuffer9::begin_frame\n"; DBG_E
-
-  DXGraphicsStateGuardian9 *dxgsg;
-  DCAST_INTO_R(dxgsg, _gsg, false);
-
-  return GraphicsBuffer::begin_frame();
+////////////////////////////////////////////////////////////////////
+//     Function: wdxGraphicsBuffer9::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void wdxGraphicsBuffer9::
+end_frame() {
+  end_frame_spam();
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+  _gsg->end_frame();
+  end_render_texture();
+  copy_to_textures();
+  trigger_flip();
+  if (_one_shot) {
+    prepare_for_deletion();
+  }
+  clear_cube_map_selection();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/dxgsg9/wdxGraphicsBuffer9.h

@@ -42,6 +42,7 @@ public:
   virtual ~wdxGraphicsBuffer9();
 
   virtual bool begin_frame();
+  virtual void end_frame();
   virtual void select_cube_map(int cube_map_index);
 
   virtual void make_current();

+ 35 - 2
panda/src/dxgsg9/wdxGraphicsWindow9.cxx

@@ -100,6 +100,10 @@ make_current() {
 ////////////////////////////////////////////////////////////////////
 bool wdxGraphicsWindow9::
 begin_frame() {
+  begin_frame_spam();
+  if (_gsg == (GraphicsStateGuardian *)NULL) {
+    return false;
+  }
   if (_awaiting_restore) {
     // The fullscreen window was recently restored; we can't continue
     // until the GSG says we can.
@@ -111,12 +115,41 @@ begin_frame() {
 
     init_resized_window();
   }
-
-  bool return_val = WinGraphicsWindow::begin_frame();
+  auto_resize();
+  if (needs_context()) {
+    if (!make_context()) {
+      return false;
+    }
+  }
+  make_current();
+  begin_render_texture();
+  clear_cube_map_selection();
+  bool return_val = _gsg->begin_frame();
   _dxgsg->set_render_target();
   return return_val;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: wdxGraphicsWindow9::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void wdxGraphicsWindow9::
+end_frame() {
+  end_frame_spam();
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+  _gsg->end_frame();
+  end_render_texture();
+  copy_to_textures();
+  trigger_flip();
+  if (_one_shot) {
+    prepare_for_deletion();
+  }
+  clear_cube_map_selection();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: wdxGraphicsWindow9::end_flip
 //       Access: Public, Virtual

+ 2 - 1
panda/src/dxgsg9/wdxGraphicsWindow9.h

@@ -41,6 +41,7 @@ public:
   virtual void make_current();
 
   virtual bool begin_frame();
+  virtual void end_frame();
   virtual void end_flip();
 
   virtual int verify_window_sizes(int numsizes, int *dimen);
@@ -105,4 +106,4 @@ private:
 
 #include "wdxGraphicsWindow9.I"
 
-#endif
+#endif

+ 48 - 0
panda/src/glxdisplay/glxGraphicsBuffer.cxx

@@ -62,6 +62,54 @@ glxGraphicsBuffer::
   nassertv(_pbuffer == None);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsBuffer::begin_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               before beginning rendering for a given frame.  It
+//               should do whatever setup is required, and return true
+//               if the frame should be rendered, or false if it
+//               should be skipped.
+////////////////////////////////////////////////////////////////////
+bool glxGraphicsBuffer::
+begin_frame() {
+  begin_frame_spam();
+  if (_gsg == (GraphicsStateGuardian *)NULL) {
+    return false;
+  }
+  auto_resize();
+  if (needs_context()) {
+    if (!make_context()) {
+      return false;
+    }
+  }
+  make_current();
+  begin_render_texture();
+  clear_cube_map_selection();
+  return _gsg->begin_frame();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsBuffer::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsBuffer::
+end_frame() {
+  end_frame_spam();
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+  _gsg->end_frame();
+  end_render_texture();
+  copy_to_textures();
+  trigger_flip();
+  if (_one_shot) {
+    prepare_for_deletion();
+  }
+  clear_cube_map_selection();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsBuffer::make_current
 //       Access: Public, Virtual

+ 2 - 0
panda/src/glxdisplay/glxGraphicsBuffer.h

@@ -41,6 +41,8 @@ public:
 
   virtual ~glxGraphicsBuffer();
 
+  virtual bool begin_frame();
+  virtual void end_frame();
   virtual void make_current();
   virtual void release_gsg();
 

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

@@ -171,13 +171,46 @@ release_gsg() {
 ////////////////////////////////////////////////////////////////////
 bool glxGraphicsWindow::
 begin_frame() {
+  begin_frame_spam();
+  if (_gsg == (GraphicsStateGuardian *)NULL) {
+    return false;
+  }
   if (_awaiting_configure) {
     // Don't attempt to draw while we have just reconfigured the
     // window and we haven't got the notification back yet.
     return false;
   }
+  auto_resize();
+  if (needs_context()) {
+    if (!make_context()) {
+      return false;
+    }
+  }
+  make_current();
+  begin_render_texture();
+  clear_cube_map_selection();
+  return _gsg->begin_frame();
+}
 
-  return GraphicsWindow::begin_frame();
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsWindow::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsWindow::
+end_frame() {
+  end_frame_spam();
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+  _gsg->end_frame();
+  end_render_texture();
+  copy_to_textures();
+  trigger_flip();
+  if (_one_shot) {
+    prepare_for_deletion();
+  }
+  clear_cube_map_selection();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/glxdisplay/glxGraphicsWindow.h

@@ -43,6 +43,7 @@ public:
   virtual void release_gsg();
 
   virtual bool begin_frame();
+  virtual void end_frame();
   virtual void begin_flip();
 
   virtual void process_events();

+ 48 - 0
panda/src/mesadisplay/osMesaGraphicsBuffer.cxx

@@ -46,6 +46,54 @@ OsMesaGraphicsBuffer::
 ~OsMesaGraphicsBuffer() {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: OsMesaGraphicsBuffer::begin_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               before beginning rendering for a given frame.  It
+//               should do whatever setup is required, and return true
+//               if the frame should be rendered, or false if it
+//               should be skipped.
+////////////////////////////////////////////////////////////////////
+bool OsMesaGraphicsBuffer::
+begin_frame() {
+  begin_frame_spam();
+  if (_gsg == (GraphicsStateGuardian *)NULL) {
+    return false;
+  }
+  auto_resize();
+  if (needs_context()) {
+    if (!make_context()) {
+      return false;
+    }
+  }
+  make_current();
+  begin_render_texture();
+  clear_cube_map_selection();
+  return _gsg->begin_frame();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OsMesaGraphicsBuffer::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void OsMesaGraphicsBuffer::
+end_frame() {
+  end_frame_spam();
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+  _gsg->end_frame();
+  end_render_texture();
+  copy_to_textures();
+  trigger_flip();
+  if (_one_shot) {
+    prepare_for_deletion();
+  }
+  clear_cube_map_selection();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: OsMesaGraphicsBuffer::make_current
 //       Access: Public, Virtual

+ 2 - 0
panda/src/mesadisplay/osMesaGraphicsBuffer.h

@@ -38,6 +38,8 @@ public:
 
   virtual ~OsMesaGraphicsBuffer();
 
+  virtual bool begin_frame();
+  virtual void end_frame();
   virtual void make_current();
 
 protected:

+ 32 - 1
panda/src/wgldisplay/wglGraphicsBuffer.cxx

@@ -66,6 +66,7 @@ wglGraphicsBuffer::
 ////////////////////////////////////////////////////////////////////
 bool wglGraphicsBuffer::
 begin_frame() {
+  begin_frame_spam();
   if (_gsg == (GraphicsStateGuardian *)NULL) {
     return false;
   }
@@ -86,7 +87,37 @@ begin_frame() {
     }
   }
 
-  return GraphicsBuffer::begin_frame();
+  auto_resize();
+  if (needs_context()) {
+    if (!make_context()) {
+      return false;
+    }
+  }
+  make_current();
+  begin_render_texture();
+  clear_cube_map_selection();
+  return _gsg->begin_frame();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsBuffer::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void wglGraphicsBuffer::
+end_frame() {
+  end_frame_spam();
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+  _gsg->end_frame();
+  end_render_texture();
+  copy_to_textures();
+  trigger_flip();
+  if (_one_shot) {
+    prepare_for_deletion();
+  }
+  clear_cube_map_selection();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/wgldisplay/wglGraphicsBuffer.h

@@ -47,6 +47,7 @@ public:
   virtual ~wglGraphicsBuffer();
 
   virtual bool begin_frame();
+  virtual void end_frame();
   virtual void select_cube_map(int cube_map_index);
 
   virtual void make_current();

+ 48 - 0
panda/src/wgldisplay/wglGraphicsWindow.cxx

@@ -147,6 +147,54 @@ wglGraphicsWindow::
 ~wglGraphicsWindow() {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsWindow::begin_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               before beginning rendering for a given frame.  It
+//               should do whatever setup is required, and return true
+//               if the frame should be rendered, or false if it
+//               should be skipped.
+////////////////////////////////////////////////////////////////////
+bool wglGraphicsWindow::
+begin_frame() {
+  begin_frame_spam();
+  if (_gsg == (GraphicsStateGuardian *)NULL) {
+    return false;
+  }
+  auto_resize();
+  if (needs_context()) {
+    if (!make_context()) {
+      return false;
+    }
+  }
+  make_current();
+  begin_render_texture();
+  clear_cube_map_selection();
+  return _gsg->begin_frame();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsWindow::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void wglGraphicsWindow::
+end_frame() {
+  end_frame_spam();
+  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+  _gsg->end_frame();
+  end_render_texture();
+  copy_to_textures();
+  trigger_flip();
+  if (_one_shot) {
+    prepare_for_deletion();
+  }
+  clear_cube_map_selection();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: wglGraphicsWindow::make_context
 //       Access: Public, Virtual

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

@@ -33,10 +33,11 @@ public:
                     const string &name);
   virtual ~wglGraphicsWindow();
 
+  virtual bool begin_frame();
+  virtual void end_frame();
   virtual bool make_context();
   virtual void make_current();
   virtual void release_gsg();
-
   virtual void begin_flip();
 
 protected: