From eee0f7321b222fa006e17a768fdf23a224cd6138 Mon Sep 17 00:00:00 2001 From: David Rose Date: Sun, 15 Mar 2009 00:01:05 +0000 Subject: [PATCH] fix vertex-buffer problem in callbacks --- panda/src/display/graphicsEngine.cxx | 1 + panda/src/display/graphicsStateGuardian.cxx | 13 ++++ panda/src/display/graphicsStateGuardian.h | 1 + .../glstuff/glGraphicsStateGuardian_src.cxx | 60 ++++++++++++++----- .../src/glstuff/glGraphicsStateGuardian_src.h | 2 + panda/src/gsgbase/graphicsStateGuardianBase.h | 1 + panda/src/pgraph/cullableObject.cxx | 1 + 7 files changed, 63 insertions(+), 16 deletions(-) diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index cef6229e42..04b85a61f1 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/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); diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index ef65c86084..7227df86fd 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/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 diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index b20b28e1f9..286e04ff22 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/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); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 17e79f09f7..2786de98d5 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/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 diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index a031957d98..130c2d113e 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/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(); diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 7567998aee..88e02111bb 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/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 diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index 4cfb9ed53b..c44b7f3056 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/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);