Browse Source

fix vertex-buffer problem in callbacks

David Rose 17 years ago
parent
commit
eee0f7321b

+ 1 - 0
panda/src/display/graphicsEngine.cxx

@@ -1763,6 +1763,7 @@ do_draw(CullResult *cull_result, SceneSetup *scene_setup,
     // Issue the draw callback on this DisplayRegion.
 
     // Set the GSG to the initial state.
+    gsg->clear_before_callback();
     gsg->set_state_and_transform(RenderState::make_empty(), TransformState::make_identity());
 
     DisplayRegionDrawCallbackData cbdata(cull_result, scene_setup);

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

@@ -1239,6 +1239,19 @@ prepare_display_region(DisplayRegionPipelineReader *dr,
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::clear_before_callback
+//       Access: Public, Virtual
+//  Description: Resets any non-standard graphics state that might
+//               give a callback apoplexy.  Some drivers require that
+//               the graphics state be restored to neutral before
+//               performing certain operations.  In OpenGL, for
+//               instance, this closes any open vertex buffers.
+////////////////////////////////////////////////////////////////////
+void GraphicsStateGuardian::
+clear_before_callback() {
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::clear_state_and_transform
 //       Access: Public, Virtual

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

@@ -225,6 +225,7 @@ public:
   virtual void prepare_display_region(DisplayRegionPipelineReader *dr,
                                       Lens::StereoChannel stereo_channel);
 
+  virtual void clear_before_callback();
   virtual void clear_state_and_transform();
 
   virtual CPT(TransformState) calc_projection_mat(const Lens *lens);

+ 44 - 16
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1537,6 +1537,20 @@ prepare_display_region(DisplayRegionPipelineReader *dr,
   do_point_size();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::clear_before_callback
+//       Access: Public, Virtual
+//  Description: Resets any non-standard graphics state that might
+//               give a callback apoplexy.  Some drivers require that
+//               the graphics state be restored to neutral before
+//               performing certain operations.  In OpenGL, for
+//               instance, this closes any open vertex buffers.
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+clear_before_callback() {
+  unbind_buffers();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::calc_projection_mat
 //       Access: Public, Virtual
@@ -1955,22 +1969,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 
     // Before we compile or call a display list, make sure the current
     // buffers are unbound, or the nVidia drivers may crash.
-    if (_current_vbuffer_index != 0) {
-      if (GLCAT.is_debug() && CLP(debug_buffers)) {
-        GLCAT.debug()
-          << "unbinding vertex buffer\n";
-      }
-      _glBindBuffer(GL_ARRAY_BUFFER, 0);
-      _current_vbuffer_index = 0;
-    }
-    if (_current_ibuffer_index != 0) {
-      if (GLCAT.is_debug() && CLP(debug_buffers)) {
-        GLCAT.debug()
-          << "unbinding index buffer\n";
-      }
-      _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-      _current_ibuffer_index = 0;
-    }
+    unbind_buffers();
 
     GeomContext *gc = ((Geom *)geom_reader->get_object())->prepare_now(get_prepared_objects(), this);
     nassertr(gc != (GeomContext *)NULL, false);
@@ -2303,6 +2302,35 @@ update_standard_vertex_arrays(bool force) {
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::unbind_buffers
+//       Access: Protected
+//  Description: Ensures the vertex and array buffers are no longer
+//               bound.  Some graphics drivers crash if these are left
+//               bound indiscriminantly.
+////////////////////////////////////////////////////////////////////
+void CLP(GraphicsStateGuardian)::
+unbind_buffers() {
+  if (_current_vbuffer_index != 0) {
+    if (GLCAT.is_debug() && CLP(debug_buffers)) {
+      GLCAT.debug()
+        << "unbinding vertex buffer\n";
+    }
+    _glBindBuffer(GL_ARRAY_BUFFER, 0);
+    _current_vbuffer_index = 0;
+  }
+  if (_current_ibuffer_index != 0) {
+    if (GLCAT.is_debug() && CLP(debug_buffers)) {
+      GLCAT.debug()
+        << "unbinding index buffer\n";
+    }
+    _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    _current_ibuffer_index = 0;
+  }
+
+  disable_standard_vertex_arrays();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::disable_standard_vertex_arrays
 //       Access: Protected

+ 2 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -115,6 +115,7 @@ public:
 
   virtual void prepare_display_region(DisplayRegionPipelineReader *dr,
                                       Lens::StereoChannel stereo_channel);
+  virtual void clear_before_callback();
   virtual CPT(TransformState) calc_projection_mat(const Lens *lens);
   virtual bool prepare_lens();
 
@@ -319,6 +320,7 @@ protected:
   static GLenum get_blend_func(ColorBlendAttrib::Operand operand);
   static GLenum get_usage(Geom::UsageHint usage_hint);
 
+  void unbind_buffers();
   void disable_standard_vertex_arrays();
   bool update_standard_vertex_arrays(bool force);
   void disable_standard_texture_bindings();

+ 1 - 0
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -128,6 +128,7 @@ public:
   // that display depends on.
   virtual SceneSetup *get_scene() const=0;
 
+  virtual void clear_before_callback()=0;
   virtual void clear_state_and_transform()=0;
 
 #ifndef CPPPARSER

+ 1 - 0
panda/src/pgraph/cullableObject.cxx

@@ -782,6 +782,7 @@ draw_fancy(GraphicsStateGuardianBase *gsg, bool force,
   nassertv(_fancy);
   if (_draw_callback != (CallbackObject *)NULL) {
     // It has a callback associated.
+    gsg->clear_before_callback();
     gsg->set_state_and_transform(_state, _internal_transform);
     GeomDrawCallbackData cbdata(this, gsg, force);
     _draw_callback->do_callback(&cbdata);