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

This commit is contained in:
rdb 2015-11-08 00:01:45 +01:00
parent 026ec613f5
commit 68f762aa20
9 changed files with 61 additions and 22 deletions

View File

@ -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.
}
////////////////////////////////////////////////////////////////////

View File

@ -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();

View File

@ -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;
}

View File

@ -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.
}
////////////////////////////////////////////////////////////////////

View File

@ -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.
}
////////////////////////////////////////////////////////////////////

View File

@ -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();

View File

@ -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.
}
////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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();
}