Browse Source

Fix leak of prepared contexts, prevent deleting GL resources in wrong context in multi-GSG applications

rdb 10 years ago
parent
commit
68f762aa20

+ 1 - 1
panda/src/glstuff/glCgShaderContext_src.cxx

@@ -326,7 +326,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
 ////////////////////////////////////////////////////////////////////
 CLP(CgShaderContext)::
 ~CLP(CgShaderContext)() {
-  release_resources();
+  // Don't call release_resources; we may not have an active context.
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 2
panda/src/glstuff/glCgShaderContext_src.h

@@ -92,9 +92,9 @@ public:
     return _type_handle;
   }
   static void init_type() {
-    TypedObject::init_type();
+    ShaderContext::init_type();
     register_type(_type_handle, CLASSPREFIX_QUOTED "CgShaderContext",
-                  TypedObject::get_class_type());
+                  ShaderContext::get_class_type());
   }
   virtual TypeHandle get_type() const {
     return get_class_type();

+ 23 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -4684,6 +4684,13 @@ update_texture(TextureContext *tc, bool force) {
 void CLP(GraphicsStateGuardian)::
 release_texture(TextureContext *tc) {
   CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
+
+  glDeleteTextures(1, &gtc->_index);
+
+  if (gtc->_buffer != 0) {
+    _glDeleteBuffers(1, &gtc->_buffer);
+  }
+
   delete gtc;
 }
 
@@ -4817,6 +4824,11 @@ prepare_sampler(const SamplerState &sampler) {
 void CLP(GraphicsStateGuardian)::
 release_sampler(SamplerContext *sc) {
   CLP(SamplerContext) *gsc = DCAST(CLP(SamplerContext), sc);
+
+  if (gsc->_index != 0) {
+    _glDeleteSamplers(1, &gsc->_index);
+  }
+
   delete gsc;
 }
 #endif  // !OPENGLES
@@ -4923,6 +4935,17 @@ prepare_shader(Shader *se) {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 release_shader(ShaderContext *sc) {
+#ifndef OPENGLES_1
+  if (sc->is_of_type(CLP(ShaderContext)::get_class_type())) {
+    ((CLP(ShaderContext) *)sc)->release_resources();
+  }
+#if defined(HAVE_CG) && !defined(OPENGLES_2)
+  else if (sc->is_of_type(CLP(CgShaderContext)::get_class_type())) {
+    ((CLP(CgShaderContext) *)sc)->release_resources();
+  }
+#endif
+#endif
+
   delete sc;
 }
 

+ 1 - 4
panda/src/glstuff/glSamplerContext_src.cxx

@@ -39,10 +39,7 @@ CLP(SamplerContext)(CLP(GraphicsStateGuardian) *glgsg,
 ////////////////////////////////////////////////////////////////////
 CLP(SamplerContext)::
 ~CLP(SamplerContext)() {
-  if (_index != 0) {
-    _glgsg->_glDeleteSamplers(1, &_index);
-    _index = 0;
-  }
+  // Don't call glDeleteSamplers; we may not have an active context.
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/glstuff/glShaderContext_src.cxx

@@ -1513,7 +1513,7 @@ get_sampler_texture_type(int &out, GLenum param_type) {
 ////////////////////////////////////////////////////////////////////
 CLP(ShaderContext)::
 ~CLP(ShaderContext)() {
-  release_resources();
+  // Don't call release_resources; we may not have an active context.
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 2
panda/src/glstuff/glShaderContext_src.h

@@ -116,9 +116,9 @@ public:
     return _type_handle;
   }
   static void init_type() {
-    TypedObject::init_type();
+    ShaderContext::init_type();
     register_type(_type_handle, CLASSPREFIX_QUOTED "ShaderContext",
-                  TypedObject::get_class_type());
+                  ShaderContext::get_class_type());
   }
   virtual TypeHandle get_type() const {
     return get_class_type();

+ 1 - 7
panda/src/glstuff/glTextureContext_src.cxx

@@ -32,13 +32,7 @@ CLP(TextureContext)::
   }
 #endif
 
-  glDeleteTextures(1, &_index);
-  _index = 0;
-
-  if (_buffer != 0) {
-    _glgsg->_glDeleteBuffers(1, &_buffer);
-    _buffer = 0;
-  }
+  // Don't call glDeleteTextures; we may not have an active context.
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 0
panda/src/glstuff/glmisc_src.cxx

@@ -308,6 +308,9 @@ void CLP(init_classes)() {
   CLP(IndexBufferContext)::init_type();
 #ifndef OPENGLES_1
   CLP(ShaderContext)::init_type();
+#endif
+#if defined(HAVE_CG) && !defined(OPENGLES)
+  CLP(CgShaderContext)::init_type();
 #endif
   CLP(TextureContext)::init_type();
 #ifndef OPENGLES

+ 27 - 5
panda/src/gobj/preparedGraphicsObjects.cxx

@@ -63,7 +63,9 @@ PreparedGraphicsObjects::
   // There may be objects that are still prepared when we destruct.
   // If this is so, then all of the GSG's that own them have already
   // destructed, so we can assume their resources were internally
-  // cleaned up.  Quietly erase these remaining objects.
+  // cleaned up.  Besides, we may not even be allowed to call the
+  // GSG release methods since some APIs (eg. OpenGL) require a
+  // context current.  So we just call the destructors.
   ReMutexHolder holder(_lock);
 
   release_all_textures();
@@ -72,18 +74,38 @@ PreparedGraphicsObjects::
        tci != _released_textures.end();
        ++tci) {
     TextureContext *tc = (*tci);
-    tc->set_owning_chain(NULL);
+    delete tc;
   }
-  // Is this a leak?  Should we delete these TextureContexts?
   _released_textures.clear();
 
   release_all_samplers();
+  ReleasedSamplers::iterator ssci;
+  for (ssci = _released_samplers.begin();
+       ssci != _released_samplers.end();
+       ++ssci) {
+    SamplerContext *sc = (*ssci);
+    delete sc;
+  }
   _released_samplers.clear();
 
   release_all_geoms();
+  Geoms::iterator gci;
+  for (gci = _released_geoms.begin();
+       gci != _released_geoms.end();
+       ++gci) {
+    GeomContext *gc = (*gci);
+    delete gc;
+  }
   _released_geoms.clear();
 
   release_all_shaders();
+  Shaders::iterator sci;
+  for (sci = _released_shaders.begin();
+       sci != _released_shaders.end();
+       ++sci) {
+    ShaderContext *sc = (*sci);
+    delete sc;
+  }
   _released_shaders.clear();
 
   release_all_vertex_buffers();
@@ -92,7 +114,7 @@ PreparedGraphicsObjects::
        vbci != _released_vertex_buffers.end();
        ++vbci) {
     VertexBufferContext *vbc = (VertexBufferContext *)(*vbci);
-    vbc->set_owning_chain(NULL);
+    delete vbc;
   }
   _released_vertex_buffers.clear();
 
@@ -102,7 +124,7 @@ PreparedGraphicsObjects::
        ibci != _released_index_buffers.end();
        ++ibci) {
     IndexBufferContext *ibc = (IndexBufferContext *)(*ibci);
-    ibc->set_owning_chain(NULL);
+    delete ibc;
   }
   _released_index_buffers.clear();
 }