1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

OCC22199 OpenGL memory leaks in TKOpenGl

This commit is contained in:
KGV 2011-04-28 15:07:08 +00:00 committed by bugmaster
parent 28e8503452
commit 161c447667
17 changed files with 888 additions and 262 deletions

View File

@ -342,8 +342,10 @@ void AIS_TexturedShape::Compute(const Handle(PrsMgr_PresentationManager3d)& /*aP
BRepTools::Update(myshape); BRepTools::Update(myshape);
Handle(Graphic3d_StructureManager) aStrucMana = GetContext()->MainPrsMgr()->StructureManager(); Handle(Graphic3d_StructureManager) aStrucMana = GetContext()->MainPrsMgr()->StructureManager();
{
myAspect = (new Prs3d_ShadingAspect())->Aspect(); Handle(Prs3d_ShadingAspect) aPrs3d_ShadingAspect = new Prs3d_ShadingAspect;
myAspect = aPrs3d_ShadingAspect->Aspect();
}
if (!DoMapTexture) if (!DoMapTexture)
{ {
myAspect->SetTextureMapOff(); myAspect->SetTextureMapOff();

View File

@ -85,6 +85,7 @@ Graphic3d_ArrayOfPrimitives :: Graphic3d_ArrayOfPrimitives (
myPrimitiveArray->num_edges = 0; myPrimitiveArray->num_edges = 0;
myPrimitiveArray->VBOEnabled = -1; myPrimitiveArray->VBOEnabled = -1;
myPrimitiveArray->flagBufferVBO = -1; myPrimitiveArray->flagBufferVBO = -1;
myPrimitiveArray->contextId = 0;
for( int i =0 ; i < VBOMaxType ; i++){ for( int i =0 ; i < VBOMaxType ; i++){
myPrimitiveArray->bufferVBO[i] = 0; myPrimitiveArray->bufferVBO[i] = 0;

View File

@ -67,6 +67,7 @@ typedef struct {
Tint VBOEnabled; /* -1 - it is not known VBO status Tint VBOEnabled; /* -1 - it is not known VBO status
0 - draw object without VBO 0 - draw object without VBO
1 - draw object with VBO */ 1 - draw object with VBO */
Standard_Address contextId; /* remember context for VBO */
} CALL_DEF_PARRAY; } CALL_DEF_PARRAY;
#endif /* _InterfaceGraphic_PrimitiveArray_header_file_ */ #endif /* _InterfaceGraphic_PrimitiveArray_header_file_ */

View File

@ -240,3 +240,10 @@ OpenGl_graduatedtrihedron.hxx
OpenGl_togl_graduatedtrihedron.cxx OpenGl_togl_graduatedtrihedron.cxx
OpenGl_FrameBuffer.hxx OpenGl_FrameBuffer.hxx
OpenGl_FrameBuffer.cxx OpenGl_FrameBuffer.cxx
OpenGl_Resource.hxx
OpenGl_ResourceCleaner.cxx
OpenGl_ResourceCleaner.hxx
OpenGl_ResourceVBO.cxx
OpenGl_ResourceVBO.hxx
OpenGl_ResourceTexture.cxx
OpenGl_ResourceTexture.hxx

View File

@ -55,6 +55,8 @@ static unsigned long vRand = 1L;
#include <OpenGl_tgl_funcs.hxx> #include <OpenGl_tgl_funcs.hxx>
#include <OpenGl_LightBox.hxx> #include <OpenGl_LightBox.hxx>
#include <OpenGl_TextureBox.hxx> #include <OpenGl_TextureBox.hxx>
#include <OpenGl_ResourceCleaner.hxx>
#include <OpenGl_ResourceVBO.hxx>
#include <InterfaceGraphic_PrimitiveArray.hxx> #include <InterfaceGraphic_PrimitiveArray.hxx>
#include <OpenGl_Memory.hxx> #include <OpenGl_Memory.hxx>
#include <Standard.hxx> #include <Standard.hxx>
@ -232,6 +234,10 @@ static void BuildVBO( CALL_DEF_PARRAY* p )
if( p->flagBufferVBO == VBO_OK ) if( p->flagBufferVBO == VBO_OK )
clearRAMMemory(p); clearRAMMemory(p);
//specify context for VBO resource
p->contextId = (Standard_Address)GET_GL_CONTEXT();
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
@ -753,6 +759,21 @@ draw_array( call_def_parray p, Tint hflag,
static TStatus static TStatus
ParrayDelete( TSM_ELEM_DATA data, Tint n, cmn_key *k ) ParrayDelete( TSM_ELEM_DATA data, Tint n, cmn_key *k )
{ {
call_def_parray p = (call_def_parray)data.pdata;
if( p->VBOEnabled == VBO_OK ) {
OpenGl_ResourceCleaner* resCleaner = OpenGl_ResourceCleaner::GetInstance();
if( p->bufferVBO[VBOEdges] )
resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOEdges]) );
if( p->bufferVBO[VBOVertices] )
resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVertices]) );
if( p->bufferVBO[VBOVcolours] )
resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVcolours]) );
if( p->bufferVBO[VBOVnormals] )
resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVnormals]) );
if( p->bufferVBO[VBOVtexels] )
resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVtexels]) );
}
return TSuccess; return TSuccess;
} }

63
src/OpenGl/OpenGl_Resource.hxx Executable file
View File

@ -0,0 +1,63 @@
// File: OpenGl_Resource.hxx
// Created: 18.03.11 9:20:00
// Author: Anton POLETAEV
#ifndef _OPENGL_RESOURCE_H
#define _OPENGL_RESOURCE_H
#include <OpenGl_ResourceCleaner.hxx>
#include <MMgt_TShared.hxx>
#include <Standard.hxx>
#include <Standard_DefineHandle.hxx>
#include <Handle_MMgt_TShared.hxx>
class Standard_Transient;
class Handle(Standard_Type);
class Handle(MMgt_TShared);
class OpenGl_ResourceCleaner;
//! Class represents basic OpenGl memory resource, which
//! could be removed only if appropriate context is avaliable;
//! The cleaning procedure is done by OpenGl_ResourceCleaner
class OpenGl_Resource : public MMgt_TShared
{
public:
//! Constructor
OpenGl_Resource() : myId(0) { }
//! Constructor
OpenGl_Resource(GLuint theId) : myId(theId) { }
//! Copy constructor
OpenGl_Resource(const OpenGl_Resource& theBase) : myId(theBase.myId) { }
//! Copy operation
OpenGl_Resource& operator = (const OpenGl_Resource& theBase)
{
this->myId = theBase.myId;
return *this;
}
//! Destructor
virtual ~OpenGl_Resource() { }
//! method clean() is accessible only by OpenGl_ResourceCleaner
friend class OpenGl_ResourceCleaner;
protected:
//! Clean procedure, should be called only by OpenGl_ResourceCleaner;
//! Each type of resource has its own cleaning procedure
virtual void Clean() = 0;
protected:
GLuint myId; // Id of OpenGl memory resource
};
DEFINE_STANDARD_HANDLE(OpenGl_Resource,MMgt_TShared)
#endif

View File

@ -0,0 +1,210 @@
// File: OpenGl_ResourceCleaner.cxx
// Created: 18.03.11 9:40:00
// Author: Anton POLETAEV
#include <OpenGl_ResourceCleaner.hxx>
#include <OpenGl_ResourceVBO.hxx>
//=======================================================================
//function : OpenGl_ResourceCleaner
//purpose : Constructor
//=======================================================================
OpenGl_ResourceCleaner::OpenGl_ResourceCleaner()
{
mySharedContexts.Clear();
mySharedQueue.Clear();
myInstanceQueue.Clear();
}
//=======================================================================
//function : AppendContext
//purpose : Append given OpenGl context to the OpenGl_ResourceCleaner
// control list
//=======================================================================
void OpenGl_ResourceCleaner::AppendContext(GLCONTEXT theContext, Standard_Boolean isShared)
{
// appending shared context
if (isShared)
{
mySharedContexts.Add(theContext);
}
else
{
// if context is already in the list
if (myInstanceQueue.IsBound(theContext))
{
QueueOfResources *aQueue = &myInstanceQueue.ChangeFind(theContext);
aQueue->Clear();
}
else
{
// context is not in the list - create empty queue for it and add queue to the list
QueueOfResources aQueue;
aQueue.Clear();
myInstanceQueue.Bind(theContext, aQueue);
}
}
}
//=======================================================================
//function : AddResource
//purpose : Tell the OpenGl_ResourceCleaner to clean up the OpenGl
// memory resource
//=======================================================================
Standard_Boolean OpenGl_ResourceCleaner::AddResource(GLCONTEXT theContext, Handle_OpenGl_Resource theResource)
{
// if context found in the shared list
if (mySharedContexts.Contains(theContext))
{
mySharedQueue.Push(theResource);
return Standard_True;
}
// if not, then it might be found in the non-shared list
else if (myInstanceQueue.IsBound(theContext))
{
QueueOfResources * aQueue = &myInstanceQueue.ChangeFind(theContext);
aQueue->Push(theResource);
return Standard_True;
}
// context is not under OpenGl_ResourceCleaner control, do not tell to clean the resource
return Standard_False;
}
//=======================================================================
//function : Clear
//purpose : Cancel clean procedure for all the resources added to the
// OpenGl_ResourceCleaner
//=======================================================================
void OpenGl_ResourceCleaner::Clear()
{
mySharedQueue.Clear();
DataMapOfContextsResources::Iterator anIter(myInstanceQueue);
// remove the resources from the list
for (anIter.Reset(); anIter.More(); anIter.Next())
{
QueueOfResources * aQueue = &anIter.ChangeValue();
aQueue->Clear();
}
}
//=======================================================================
//function : Clear
//purpose : Cancel clean procedure for all the resources of the specific
// OpenGl context which were added to the OpenGl_ResourceCleaner
//=======================================================================
Standard_Boolean OpenGl_ResourceCleaner::Clear(GLCONTEXT theContext)
{
// check if the context in the the control list
if (myInstanceQueue.IsBound(theContext))
{
QueueOfResources * aQueue = &myInstanceQueue.ChangeFind(theContext);
aQueue->Clear();
return Standard_True;
}
return Standard_False;
}
//=======================================================================
//function : ClearShared
//purpose : Cancel clean procedure for all of the shared resources
//=======================================================================
void OpenGl_ResourceCleaner::ClearShared()
{
mySharedQueue.Clear();
}
//=======================================================================
//function : Cleanup
//purpose : Clear the unused resources for active OpenGl context
//=======================================================================
void OpenGl_ResourceCleaner::Cleanup()
{
GLCONTEXT aContext = GET_GL_CONTEXT();
// if we have active context, we can delete the resources
if (aContext != NULL)
// if the context is found in shared list
if (mySharedContexts.Contains(aContext))
{
while(mySharedQueue.Size() > 0)
{
mySharedQueue.Front()->Clean(); // delete resource memory
mySharedQueue.Pop();
}
}
// if the context is found in non-shared list
else if (myInstanceQueue.IsBound(aContext))
{
QueueOfResources * aQueue = &myInstanceQueue.ChangeFind(aContext);
while(aQueue->Size() > 0)
{
aQueue->Front()->Clean(); // delete resource memory
aQueue->Pop();
}
}
}
//=======================================================================
//function : RemoveContext
//purpose : Remove the OpenGl context from the OpenGl_ResourceCleaner list
//=======================================================================
void OpenGl_ResourceCleaner::RemoveContext(GLCONTEXT theContext)
{
// if context can be found in shared list try to remove it
// if it wasn't in there, try to remove it from non-shared list
if (!mySharedContexts.Remove(theContext))
myInstanceQueue.UnBind(theContext);
// if no contexts in shared list, then there is no need to clean
// the resources on redraw
if (mySharedContexts.Size() == 0)
mySharedQueue.Clear();
}
//=======================================================================
//function : GetSharedContext
//purpose : Get any of shared contexts from the OpenGl_ResourceCleaner list
//=======================================================================
GLCONTEXT OpenGl_ResourceCleaner::GetSharedContext() const
{
if(mySharedContexts.Size() > 0)
{
MapOfContexts::Iterator anIter(mySharedContexts);
anIter.Reset();
return anIter.Value();
}
return 0;
}
//=======================================================================
//function : GetInstance
//purpose : Get the global instance of OpenGl_ResourceCleaner
//=======================================================================
OpenGl_ResourceCleaner* OpenGl_ResourceCleaner::GetInstance()
{
// the static instance entity
static OpenGl_ResourceCleaner* anInstance = NULL;
if (anInstance == NULL)
anInstance = new OpenGl_ResourceCleaner;
return anInstance;
}

View File

@ -0,0 +1,79 @@
// File: OpenGl_ResourceCleaner.hxx
// Created: 18.03.11 9:30:00
// Author: Anton POLETAEV
#ifndef _OPENGL_RESOURCECLEANER_H
#define _OPENGL_RESOURCECLEANER_H
#include <OpenGl_tgl_all.hxx>
#include <NCollection_Queue.hxx>
#include <NCollection_List.hxx>
#include <NCollection_Map.hxx>
#include <NCollection_DataMap.hxx>
#include <OpenGl_Resource.hxx>
class OpenGl_Resource;
class Handle_OpenGl_Resource;
typedef NCollection_Queue<Handle_OpenGl_Resource> QueueOfResources;
typedef NCollection_DataMap<GLCONTEXT, QueueOfResources> DataMapOfContextsResources;
typedef NCollection_Map<GLCONTEXT> MapOfContexts;
//! OpenGl_ResourceCleaner should be used to clean OpenGl memory resources;
//! The reason is that the resources might be shared between the contexts and
//! should be cleaned up only while suitable context is active;
class OpenGl_ResourceCleaner
{
public:
//! Constructor
OpenGl_ResourceCleaner();
//! Destructor
virtual ~OpenGl_ResourceCleaner() { }
//! Append OpenGl context to the OpenGl_ResourceCleaner
//! control list.
void AppendContext(GLCONTEXT theContext, Standard_Boolean isShared);
//! Tell the OpenGl_ResourceCleaner to clean up the OpenGl memory resource
//! which has been created by the specified OpenGl context;
//! The context should be in the OpenGl_ResourceCleaner control list.
Standard_Boolean AddResource(GLCONTEXT theContext, Handle_OpenGl_Resource theResource);
//! Cancel clean procedure for all the resources added to the OpenGl_ResourceCleaner.
void Clear();
//! Cancel clean procedure for all the resources of the specific OpenGl context
//! which were added to the OpenGl_ResourceCleaner.
Standard_Boolean Clear(GLCONTEXT theContext);
//! Cancel clean procedure for all of the shared resources.
void ClearShared();
//! Clear the unused resources for active OpenGl context;
//! You should add the cleaner resources by AddResources method;
//! It is suggested to call this method right before the OpenGl
//! new frame drawing procedure starts.
void Cleanup();
//! Remove the OpenGl context from the OpenGl_ResourceCleaner control list.
void RemoveContext(GLCONTEXT theContext);
//! Get any of shared contexts from the OpenGl_ResourceCleaner list
//! to share resources with a new one
GLCONTEXT GetSharedContext() const;
//! Get the global instance of OpenGl_ResourceCleaner
static OpenGl_ResourceCleaner* GetInstance();
private:
DataMapOfContextsResources myInstanceQueue; // map for queues of non-shared context's resources
QueueOfResources mySharedQueue; // queue of shared context's resources
MapOfContexts mySharedContexts; // the control list of shared contexts
};
#endif

View File

@ -0,0 +1,45 @@
// File: OpenGl_ResourceTexture.cxx
// Created: 18.03.11 9:40:00
// Author: Anton POLETAEV
#include <OpenGl_ResourceTexture.hxx>
#include <OpenGl_tgl_all.hxx>
#include <OpenGl_Extension.hxx>
#ifdef __sgi
#define glGenTextures glGenTexturesEXT
#define glDeleteTextures glDeleteTexturesEXT
#define glBindTexture glBindTextureEXT
#endif /* IRIX */
//=======================================================================
//function : OpenGl_ResourceTexture
//purpose : Constructor
//=======================================================================
OpenGl_ResourceTexture::OpenGl_ResourceTexture(GLuint theId)
: OpenGl_Resource(theId)
{
}
//=======================================================================
//function : OpenGl_ResourceTexture
//purpose : Copy constructor
//=======================================================================
OpenGl_ResourceTexture::OpenGl_ResourceTexture(const OpenGl_ResourceTexture& theResource)
: OpenGl_Resource(theResource)
{
}
//=======================================================================
//function : Clean
//purpose : free OpenGl memory allocated for texture resource
//=======================================================================
void OpenGl_ResourceTexture::Clean()
{
glDeleteTextures(1, &myId);
}

View File

@ -0,0 +1,37 @@
// File: OpenGl_ResourceTexture.hxx
// Created: 18.03.11 9:40:00
// Author: Anton POLETAEV
#ifndef _OPENGL_RESOURCETEXTURE_H
#define _OPENGL_RESOURCETEXTURE_H
#include <OpenGl_Resource.hxx>
#include <Standard.hxx>
class OpenGl_Resource;
//! OpenGl_ResourceTexture represents the texture resource
//! for OpenGl_ResourceCleaner
class OpenGl_ResourceTexture : public OpenGl_Resource
{
public:
//! Constructor
OpenGl_ResourceTexture(GLuint theId);
//! Copy constructor
OpenGl_ResourceTexture(const OpenGl_ResourceTexture& theResource);
//! Destructor
~OpenGl_ResourceTexture() { }
protected:
//! Clean procedure for texture resource;
//! Should be called by the OpenGl_ResourceCleaner
void Clean();
};
#endif

View File

@ -0,0 +1,45 @@
// File: OpenGl_ResourceVBO.cxx
// Created: 18.03.11 9:50:00
// Author: Anton POLETAEV
#include <OpenGl_ResourceVBO.hxx>
#include <OpenGl_tgl_all.hxx>
#include <OpenGl_Extension.hxx>
typedef void (APIENTRY* PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
extern PFNGLDELETEBUFFERSARBPROC glVBODeleteBuffersARB;
extern int VBOExtension;
//=======================================================================
//function : OpenGl_ResourceVBO
//purpose : Constructor
//=======================================================================
OpenGl_ResourceVBO::OpenGl_ResourceVBO(GLuint theId)
: OpenGl_Resource(theId)
{
}
//=======================================================================
//function : OpenGl_ResourceVBO
//purpose : Copy constructor
//=======================================================================
OpenGl_ResourceVBO::OpenGl_ResourceVBO( const OpenGl_ResourceVBO& theResource)
: OpenGl_Resource(theResource)
{
}
//=======================================================================
//function : Clean
//purpose : free OpenGl memory allocated for vbo resource
//=======================================================================
void OpenGl_ResourceVBO::Clean()
{
if (VBOExtension)
glVBODeleteBuffersARB( 1 , &myId );
}

View File

@ -0,0 +1,37 @@
// File: OpenGl_ResourceVBO.hxx
// Created: 18.03.11 9:50:00
// Author: Anton POLETAEV
#ifndef _OPENGL_RESOURCEVBO_H
#define _OPENGL_RESOURCEVBO_H
#include <OpenGl_Resource.hxx>
#include <Standard.hxx>
class OpenGl_Resource;
//! OpenGl_ResourceVBO represents the Vertex Buffer
//! Object resource (VBO) for OpenGl_ResourceCleaner
class OpenGl_ResourceVBO : public OpenGl_Resource
{
public:
//! Constructor
OpenGl_ResourceVBO(GLuint theId);
//! Copy constructor
OpenGl_ResourceVBO(const OpenGl_ResourceVBO& theResource);
//! Destructor
~OpenGl_ResourceVBO() { }
protected:
//! Clean procedure for VBO resource;
//! Should be called by the OpenGl_ResourceCleaner
void Clean();
};
#endif

View File

@ -81,6 +81,8 @@
#include <OpenGl_ImageBox.hxx> #include <OpenGl_ImageBox.hxx>
#include <OpenGl_TextureBox.hxx> #include <OpenGl_TextureBox.hxx>
#include <OpenGl_Memory.hxx> #include <OpenGl_Memory.hxx>
#include <OpenGl_ResourceCleaner.hxx>
#include <OpenGl_ResourceTexture.hxx>
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
@ -184,7 +186,6 @@ static GLboolean use_bind_texture = GL_FALSE;
* Fonctions privees * Fonctions privees
*/ */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
/* /*
* recherche l'existence de datas de texture par son nom * recherche l'existence de datas de texture par son nom
@ -853,6 +854,7 @@ void SetCurrentTexture(TextureID ID)
void FreeTexture(TextureID ID) void FreeTexture(TextureID ID)
{ {
TextureDataID data; TextureDataID data;
bool notResource = false; // if there old-style texture deletion
#if defined(GL_EXT_texture_object) #if defined(GL_EXT_texture_object)
GLCONTEXT cur_context; GLCONTEXT cur_context;
@ -880,24 +882,35 @@ void FreeTexture(TextureID ID)
printf("FreeTexture::liberation de %d\n", ID); printf("FreeTexture::liberation de %d\n", ID);
#endif #endif
cur_context = 0; cur_context = 0;
bool isResource = false;
if (textab[ID].use_bind_texture[i]) if (textab[ID].use_bind_texture[i])
{ {
GL_MAKE_CURRENT(GetCurrentDisplay(), if( !OpenGl_ResourceCleaner::GetInstance()->AddResource(textab[ID].context[i],
textab[ID].drawable[i], new OpenGl_ResourceTexture(textab[ID].number[i])) )
textab[ID].context[i]); {
GL_MAKE_CURRENT(GetCurrentDisplay(),
textab[ID].drawable[i],
textab[ID].context[i]);
/*This check has been added to avoid exception, /*This check has been added to avoid exception,
which is raised when trying to delete textures when no rendering context which is raised when trying to delete textures when no rendering context
is available*/ is available*/
cur_context = GET_GL_CONTEXT(); cur_context = GET_GL_CONTEXT();
if( cur_context ) if( cur_context )
glDeleteTextures(1, &textab[ID].number[i]); glDeleteTextures(1, &textab[ID].number[i]);
notResource = true;
}
else
isResource = true;
} }
if( cur_context )
if( !isResource && cur_context )
glFinish(); glFinish();
} }
GL_MAKE_CURRENT(GetCurrentDisplay(),cur_drawable,cur_context); if( notResource )
GL_MAKE_CURRENT(GetCurrentDisplay(),cur_drawable,cur_context);
texdata[data].status = TEXDATA_NONE; texdata[data].status = TEXDATA_NONE;
#ifndef IMP141100 #ifndef IMP141100

View File

@ -59,6 +59,7 @@ GLboolean g_fBitmap;
#include <OpenGl_tgl_funcs.hxx> #include <OpenGl_tgl_funcs.hxx>
#include <OpenGl_tgl_subrvis.hxx> #include <OpenGl_tgl_subrvis.hxx>
#include <OpenGl_FrameBuffer.hxx> #include <OpenGl_FrameBuffer.hxx>
#include <OpenGl_ResourceCleaner.hxx>
#include <InterfaceGraphic_Graphic3d.hxx> #include <InterfaceGraphic_Graphic3d.hxx>
#include <InterfaceGraphic_Visual3d.hxx> #include <InterfaceGraphic_Visual3d.hxx>
@ -86,7 +87,7 @@ call_togl_redraw
aFrameBuffer->BindBuffer(); aFrameBuffer->BindBuffer();
swap = 0; // no need to swap buffers swap = 0; // no need to swap buffers
} }
OpenGl_ResourceCleaner::GetInstance()->Cleanup();
call_func_redraw_all_structs_begin (aview->WsId); call_func_redraw_all_structs_begin (aview->WsId);
if (anunderlayer->ptrLayer) if (anunderlayer->ptrLayer)
{ {
@ -162,6 +163,7 @@ call_togl_redraw_area
glScissor ((GLint )x, glScissor ((GLint )x,
(GLint )((int )aview->DefWindow.dy - (y + height)), (GLint )((int )aview->DefWindow.dy - (y + height)),
(GLsizei )width, (GLsizei )height); (GLsizei )width, (GLsizei )height);
OpenGl_ResourceCleaner::GetInstance()->Cleanup();
call_func_redraw_all_structs_begin (aview->WsId); call_func_redraw_all_structs_begin (aview->WsId);
if (anunderlayer->ptrLayer) if (anunderlayer->ptrLayer)
{ {

View File

@ -83,6 +83,7 @@ Old code resulted in crashes on some ATI Radeon cards under Linux.
#include <stdio.h> #include <stdio.h>
#include <OpenGl_Memory.hxx> #include <OpenGl_Memory.hxx>
#include <OpenGl_ResourceCleaner.hxx>
#ifdef WNT #ifdef WNT
@ -312,6 +313,8 @@ __declspec( dllexport ) int __fastcall __OpenGl_INIT__ (
if( !ctx) return TFailure; if( !ctx) return TFailure;
OpenGl_ResourceCleaner::GetInstance()->AppendContext( ctx, true );
cmap = XCreateColormap( disp, par, vis->visual, AllocNone ); cmap = XCreateColormap( disp, par, vis->visual, AllocNone );
color.red = (unsigned short) (bgcolr * 0xFFFF); color.red = (unsigned short) (bgcolr * 0xFFFF);
@ -455,12 +458,29 @@ __declspec( dllexport ) int __fastcall __OpenGl_INIT__ (
return 0; return 0;
} }
if (previous_ctx == 0 ) Standard_Boolean isShared = Standard_True;
{
previous_ctx = hte -> hGLRC;
} else
wglShareLists(previous_ctx, hte -> hGLRC);
if (previous_ctx == 0 )
previous_ctx = hte -> hGLRC;
// if we already have some shared context
else
{
// try to share context with one from resource cleaner list
GLCONTEXT shareCtx = OpenGl_ResourceCleaner::GetInstance()->GetSharedContext();
if (shareCtx != 0)
isShared = (Standard_Boolean)wglShareLists(shareCtx, hte -> hGLRC);
else
{
isShared = (Standard_Boolean)wglShareLists(previous_ctx, hte -> hGLRC);
// add shared previous_ctx to a control list if it's not there
if (isShared)
OpenGl_ResourceCleaner::GetInstance()->AppendContext(previous_ctx, isShared);
}
}
// add the context to OpenGl_ResourceCleaner control list
OpenGl_ResourceCleaner::GetInstance()->AppendContext( hte -> hGLRC, isShared);
_Txgl_Map.Bind( (Tint)par, hte ); _Txgl_Map.Bind( (Tint)par, hte );
return par; return par;
@ -771,6 +791,7 @@ __declspec( dllexport ) int __fastcall __OpenGl_INIT__ (
/* FSXXX sync necessary if non-direct rendering */ /* FSXXX sync necessary if non-direct rendering */
glXWaitGL(); glXWaitGL();
OpenGl_ResourceCleaner::GetInstance()->RemoveContext( ctx );
_Txgl_Map.UnBind( win ); _Txgl_Map.UnBind( win );
if (previous_ctx == ctx) { if (previous_ctx == ctx) {
@ -823,12 +844,16 @@ __declspec( dllexport ) int __fastcall __OpenGl_INIT__ (
if ( --hte -> nUsed == 0 ) if ( --hte -> nUsed == 0 )
{ {
OpenGl_ResourceCleaner::GetInstance()->RemoveContext( hte -> hGLRC );
#ifdef OCC954 #ifdef OCC954
if ( wglGetCurrentContext() != NULL ) if ( wglGetCurrentContext() != NULL )
#endif #endif
wglDeleteContext ( hte -> hGLRC ); wglDeleteContext ( hte -> hGLRC );
ReleaseDC ( win, hte -> hDC ); ReleaseDC ( win, hte -> hDC );
_Txgl_Map.UnBind( (Tint ) win ); _Txgl_Map.UnBind( (Tint ) win );
if( _Txgl_Map.Size() == 0 ) {
previous_ctx = 0;
}
delete hte; delete hte;
} }

View File

@ -1659,17 +1659,17 @@ Standard_Integer VTexture (Draw_Interpretor& di,Standard_Integer argc, const cha
if(myAISContext.IsNull()) if(myAISContext.IsNull())
{ {
di << "use 'vinit' command before " << argv[0] << "\n"; di << "use 'vinit' command before " << argv[0] << "\n";
return 0; return 1;
} }
Handle(AIS_InteractiveObject) TheAisIO; Handle(AIS_InteractiveObject) TheAisIO;
Handle(AIS_TexturedShape) myShape; Handle(AIS_TexturedShape) myShape;
Standard_Integer myPreviousMode = 0; Standard_Integer myPreviousMode = 0;
if (!argv[1]) if (argc<2 || !argv[1])
{ {
di << argv[0] <<" syntax error - Type 'help vtex'"<<"\n"; di << argv[0] <<" syntax error - Type 'help vtex'"<<"\n";
return 0; return 1;
} }
TCollection_AsciiString name = argv[1]; TCollection_AsciiString name = argv[1];
@ -1681,7 +1681,7 @@ Standard_Integer VTexture (Draw_Interpretor& di,Standard_Integer argc, const cha
if (TheAisIO.IsNull()) if (TheAisIO.IsNull())
{ {
di <<"shape "<<name.ToCString()<<" doesn\'t exist"<<"\n"; di <<"shape "<<name.ToCString()<<" doesn\'t exist"<<"\n";
return 0; return 1;
} }
if (TheAisIO->IsKind(STANDARD_TYPE(AIS_TexturedShape)) && !TheAisIO.IsNull()) if (TheAisIO->IsKind(STANDARD_TYPE(AIS_TexturedShape)) && !TheAisIO.IsNull())
@ -1691,7 +1691,7 @@ Standard_Integer VTexture (Draw_Interpretor& di,Standard_Integer argc, const cha
} }
else else
{ {
myAISContext->Erase(TheAisIO,Standard_False); myAISContext->Clear(TheAisIO,Standard_False);
myShape = new AIS_TexturedShape (DBRep::Get(argv[1])); myShape = new AIS_TexturedShape (DBRep::Get(argv[1]));
GetMapOfAIS().UnBind1(TheAisIO); GetMapOfAIS().UnBind1(TheAisIO);
GetMapOfAIS().UnBind2(name); GetMapOfAIS().UnBind2(name);
@ -1703,9 +1703,9 @@ Standard_Integer VTexture (Draw_Interpretor& di,Standard_Integer argc, const cha
if(argc<=1) if(argc<=1)
{ {
di << argv[0] <<" syntax error - Type 'help vtex'" << "\n"; di << argv[0] <<" syntax error - Type 'help vtex'" << "\n";
return 0; return 1;
} }
if (argv[2]) if (argc>2 && argv[2])
{ {
if(strcasecmp(argv[2],"?")==0) if(strcasecmp(argv[2],"?")==0)
{ {
@ -1744,7 +1744,7 @@ Standard_Integer VTexture (Draw_Interpretor& di,Standard_Integer argc, const cha
if(argc<2) if(argc<2)
{ {
di << argv[0] <<" syntax error - Type 'help vtex'" << "\n"; di << argv[0] <<" syntax error - Type 'help vtex'" << "\n";
return 0; return 1;
} }
myShape->SetTextureScale (( argv[2] ? Standard_True : Standard_False ), myShape->SetTextureScale (( argv[2] ? Standard_True : Standard_False ),
@ -1756,7 +1756,7 @@ Standard_Integer VTexture (Draw_Interpretor& di,Standard_Integer argc, const cha
if(argc<2) if(argc<2)
{ {
di << argv[0] <<" syntax error - Type 'help vtex'" << "\n"; di << argv[0] <<" syntax error - Type 'help vtex'" << "\n";
return 0; return 1;
} }
myShape->SetTextureOrigin (( argv[2] ? Standard_True : Standard_False ), myShape->SetTextureOrigin (( argv[2] ? Standard_True : Standard_False ),
( argv[2] ? atof(argv[2]) : 0.0 ), ( argv[2] ? atof(argv[2]) : 0.0 ),
@ -1767,9 +1767,9 @@ Standard_Integer VTexture (Draw_Interpretor& di,Standard_Integer argc, const cha
if(argc<2) if(argc<2)
{ {
di << argv[0] <<" syntax error - Type 'help vtex'" << "\n"; di << argv[0] <<" syntax error - Type 'help vtex'" << "\n";
return 0; return 1;
} }
if (argv[2]) if (argc>2 && argv[2])
{ {
di <<"Texture repeat enabled"<<"\n"; di <<"Texture repeat enabled"<<"\n";
myShape->SetTextureRepeat(Standard_True, atof(argv[2]), atof(argv[argc-1]) ); myShape->SetTextureRepeat(Standard_True, atof(argv[2]), atof(argv[argc-1]) );
@ -1789,7 +1789,7 @@ Standard_Integer VTexture (Draw_Interpretor& di,Standard_Integer argc, const cha
if(argc<2) if(argc<2)
{ {
di << argv[0] <<" syntax error - Type 'help vtex'" << "\n"; di << argv[0] <<" syntax error - Type 'help vtex'" << "\n";
return 0; return 1;
} }
myShape->SetTextureRepeat(Standard_False); myShape->SetTextureRepeat(Standard_False);
myShape->SetTextureOrigin(Standard_False); myShape->SetTextureOrigin(Standard_False);
@ -1805,7 +1805,7 @@ Standard_Integer VTexture (Draw_Interpretor& di,Standard_Integer argc, const cha
myAISContext->Display(myShape, Standard_True); myAISContext->Display(myShape, Standard_True);
myAISContext->Update(myShape,Standard_True); myAISContext->Update(myShape,Standard_True);
} }
return 1; return 0;
} }
//============================================================================== //==============================================================================

View File

@ -24,7 +24,7 @@
#include <Draw_Appli.hxx> #include <Draw_Appli.hxx>
#include <DBRep.hxx> #include <DBRep.hxx>
#include <OSD_Chronometer.hxx>
#include <TCollection_AsciiString.hxx> #include <TCollection_AsciiString.hxx>
#include <V3d_Viewer.hxx> #include <V3d_Viewer.hxx>
#include <V3d_View.hxx> #include <V3d_View.hxx>
@ -2390,131 +2390,169 @@ Handle( Poly_Triangulation ) CalculationOfSphere( double X , double Y , double Z
//function : VDrawSphere //function : VDrawSphere
//author : psn //author : psn
//purpose : Create an AIS shape. //purpose : Create an AIS shape.
//Draw arg : vdrawsphere [X] [Y] [Z] [Rezolution] [Radius] [VBOEnabled]
//=============================================================================================== //===============================================================================================
static int VDrawSphere (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
#include <OSD_Chronometer.hxx> {
// check for errors
static int VDrawSphere (Draw_Interpretor& di, Standard_Integer argc, const char** argv){ Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
// Verification des arguments if (aContextAIS.IsNull())
if ( argc > 9 ) {di<<argv[0]<<" Syntaxe error"<<"\n"; return 1;} {
std::cout << "Call vinit before!\n";
Standard_Real X,Y,Z; return 1;
X = atof(argv[1]); }
Y = atof(argv[2]); else if (argc < 3)
Z = atof(argv[3]); {
std::cout << "Use: " << argv[0]
Standard_Integer Rezolution = atoi(argv[4]); << " shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToEnableVBO=1] [NumberOfViewerUpdate=1] [ToShowEdges=0]\n";
Standard_Real Radius = atof(argv[5]); return 1;
Standard_Integer VBOenabled = atoi(argv[6]);;
Standard_Integer NumberOfViewerUpdate = 1;
Standard_Integer ShowEdges = 0;
if( argc == 9)
ShowEdges = atoi(argv[8]);
if( argc == 8)
NumberOfViewerUpdate = atoi(argv[7]);
if( argc == 7)
NumberOfViewerUpdate = 1;
Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
//ViewerTest::CurrentView()->SetTransparency(Standard_True);
//enable VBO
Handle(Graphic3d_GraphicDriver) aDriver =
Handle(Graphic3d_GraphicDriver)::DownCast(aContext->CurrentViewer()->Device()->GraphicDriver() );
aDriver->EnableVBO( VBOenabled );
Standard_Integer numberTriangles = 0, numberPoints = 0;
printf("Compute Triangulation...\n");
Handle(AIS_Triangulation) myShape = new AIS_Triangulation(CalculationOfSphere( X, Y, Z,
Rezolution,
Radius));
numberPoints = myShape->GetTriangulation()->Nodes().Length();
numberTriangles = myShape->GetTriangulation()->Triangles().Length();
Handle(TColStd_HArray1OfInteger) aColorArray = new TColStd_HArray1OfInteger(1,numberPoints);
int color = 0;
int red = 0 ;
int green = 255 ;
int blue = 0 ;
int alpha = 0 ; // not used
color = red;
color += green << 8;
color += blue << 16;
color += alpha << 24;
for( int i = 1; i <= numberPoints ; i++ ){
aColorArray->SetValue( i,color );
} }
//enable or disable color
myShape->SetColors(aColorArray);
printf("NumberOfPoints = %.i \n",numberPoints); // read the arguments
printf("NumberOfTriangles = %.i \n",numberTriangles); TCollection_AsciiString aShapeName (argv[1]);
int PointsSize = numberPoints * 12; Standard_Integer aResolution = atoi (argv[2]);
int NormalsSize = numberPoints * 12; Standard_Real aCenterX = (argc > 5) ? atof (argv[3]) : 0.0;
int ColorsSize = numberPoints * 12; Standard_Real aCenterY = (argc > 5) ? atof (argv[4]) : 0.0;
int TrianglesSize = numberTriangles * 3 * 4; Standard_Real aCenterZ = (argc > 5) ? atof (argv[5]) : 0.0;
int PolyConnectSize = numberPoints * 4 + numberTriangles * 6 * 4; Standard_Real aRadius = (argc > 6) ? atof (argv[6]) : 100.0;
int size = PointsSize + NormalsSize + ColorsSize + TrianglesSize ; Standard_Boolean isVBOEnabled = (argc > 7) ? atoi (argv[7]) : Standard_True;
size>>=20;//MB Standard_Integer aRedrawsNb = (argc > 8) ? atoi (argv[8]) : 1;
NormalsSize >>= 20; Standard_Boolean toShowEdges = (argc > 9) ? atoi (argv[9]) : Standard_False;
ColorsSize >>= 20;
TrianglesSize >>= 20; if (aRedrawsNb <= 0)
PolyConnectSize >>= 20; {
printf("Amount of memory required for PolyTriangulation without Normals: %i Mb \n", size - NormalsSize ); aRedrawsNb = 1;
printf("Amount of memory for colors: %i Mb \n",ColorsSize); }
printf("Amount of memory for PolyConnect: %i Mb \n", PolyConnectSize );
printf("Amount of graphic card memory required: %i Mb \n",size); // remove AIS object with given name from map
if (GetMapOfAIS().IsBound2 (aShapeName))
{
Handle(Standard_Transient) anObj = GetMapOfAIS().Find2 (aShapeName);
Handle(AIS_InteractiveObject) anInterObj = Handle(AIS_InteractiveObject)::DownCast (anObj);
if (anInterObj.IsNull())
{
std::cout << "Shape name was used for non AIS viewer\n!";
return 1;
}
aContextAIS->Remove (anInterObj, Standard_False);
GetMapOfAIS().UnBind2 (aShapeName);
}
// enable/disable VBO
Handle(Graphic3d_GraphicDriver) aDriver =
Handle(Graphic3d_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Device()->GraphicDriver());
if (!aDriver.IsNull())
{
aDriver->EnableVBO (isVBOEnabled);
}
std::cout << "Compute Triangulation...\n";
Handle(AIS_Triangulation) aShape
= new AIS_Triangulation (CalculationOfSphere (aCenterX, aCenterY, aCenterZ,
aResolution,
aRadius));
Standard_Integer aNumberPoints = aShape->GetTriangulation()->Nodes().Length();
Standard_Integer aNumberTriangles = aShape->GetTriangulation()->Triangles().Length();
// register the object in map
GetMapOfAIS().Bind (aShape, aShapeName);
// stupid initialization of Green color in RGBA space as integer
// probably wrong for big-endian CPUs
Standard_Integer aRed = 0;
Standard_Integer aGreen = 255;
Standard_Integer aBlue = 0;
Standard_Integer anAlpha = 0; // not used
Standard_Integer aColorInt = aRed;
aColorInt += aGreen << 8;
aColorInt += aBlue << 16;
aColorInt += anAlpha << 24;
// setup colors array per vertex
Handle(TColStd_HArray1OfInteger) aColorArray = new TColStd_HArray1OfInteger (1, aNumberPoints);
for (Standard_Integer aNodeId = 1; aNodeId <= aNumberPoints; ++aNodeId)
{
aColorArray->SetValue (aNodeId, aColorInt);
}
aShape->SetColors (aColorArray);
// show statistics
Standard_Integer aPointsSize = aNumberPoints * 3 * sizeof(float); // 3x GLfloat
Standard_Integer aNormalsSize = aNumberPoints * 3 * sizeof(float); // 3x GLfloat
Standard_Integer aColorsSize = aNumberPoints * 3 * sizeof(float); // 3x GLfloat without alpha
Standard_Integer aTrianglesSize = aNumberTriangles * 3 * sizeof(int); // 3x GLint
Standard_Integer aPolyConnectSize = aNumberPoints * 4 + aNumberTriangles * 6 * 4;
Standard_Integer aTotalSize = aPointsSize + aNormalsSize + aColorsSize + aTrianglesSize;
aTotalSize >>= 20; //MB
aNormalsSize >>= 20;
aColorsSize >>= 20;
aTrianglesSize >>= 20;
aPolyConnectSize >>= 20;
std::cout << "NumberOfPoints: " << aNumberPoints << "\n"
<< "NumberOfTriangles: " << aNumberTriangles << "\n"
<< "Amount of memory required for PolyTriangulation without Normals: " << (aTotalSize - aNormalsSize) << " Mb\n"
<< "Amount of memory for colors: " << aColorsSize << " Mb\n"
<< "Amount of memory for PolyConnect: " << aPolyConnectSize << " Mb\n"
<< "Amount of graphic card memory required: " << aTotalSize << " Mb\n";
// Setting material properties, very important for desirable visual result! // Setting material properties, very important for desirable visual result!
Graphic3d_MaterialAspect aMat( Graphic3d_NOM_PLASTIC ); Graphic3d_MaterialAspect aMat (Graphic3d_NOM_PLASTIC);
aMat.SetAmbient( 0.2 ); aMat.SetAmbient (0.2);
aMat.SetSpecular( 0.5 ); aMat.SetSpecular (0.5);
Handle(Graphic3d_AspectFillArea3d) aspect = new Graphic3d_AspectFillArea3d( Aspect_IS_SOLID, Handle(Graphic3d_AspectFillArea3d) anAspect
Quantity_NOC_RED, = new Graphic3d_AspectFillArea3d (Aspect_IS_SOLID,
Quantity_NOC_YELLOW, Quantity_NOC_RED,
Aspect_TOL_SOLID, Quantity_NOC_YELLOW,
1., Aspect_TOL_SOLID,
aMat, 1.0,
aMat); aMat,
aMat);
Handle(Prs3d_ShadingAspect) aShAsp = new Prs3d_ShadingAspect(); Handle(Prs3d_ShadingAspect) aShAsp = new Prs3d_ShadingAspect();
if (toShowEdges)
if( ShowEdges > 0 ) {
aspect->SetEdgeOn(); anAspect->SetEdgeOn();
}
else else
aspect->SetEdgeOff(); {
anAspect->SetEdgeOff();
}
aShAsp->SetAspect (anAspect);
aShape->Attributes()->SetShadingAspect (aShAsp);
aShAsp -> SetAspect( aspect ); aContextAIS->Display (aShape, Standard_False);
//aShAsp -> SetTransparency( 0.5 );
myShape -> Attributes() -> SetShadingAspect( aShAsp );
aContext->Display(myShape,Standard_False);
const Handle(V3d_Viewer)& viewer = aContext->CurrentViewer();
// Two viewer updates are needed in order to measure time spent on // Two viewer updates are needed in order to measure time spent on
// loading triangulation to graphic card memory + redrawing (1st update) and // loading triangulation to graphic card memory + redrawing (1st update) and
// time spent on redrawing itself (2nd and all further updates) // time spent on redrawing itself (2nd and all further updates)
OSD_Chronometer timer; OSD_Chronometer aTimer;
Standard_Real UserSeconds, SystemSeconds; Standard_Real aUserSeconds, aSystemSeconds;
timer.Start(); aTimer.Start();
for ( int repeat = 0; repeat < NumberOfViewerUpdate; repeat++ ){ const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
for (viewer->InitActiveViews();viewer->MoreActiveViews();viewer->NextActiveViews()) for (Standard_Integer anInteration = 0; anInteration < aRedrawsNb; ++anInteration)
{
for (aViewer->InitActiveViews(); aViewer->MoreActiveViews(); aViewer->NextActiveViews())
{ {
if( repeat == 0 ) if (anInteration == 0)
viewer->ActiveView()->Update(); {
aViewer->ActiveView()->Update();
}
else else
viewer->ActiveView()->Redraw(); {
aViewer->ActiveView()->Redraw();
}
} }
} }
timer.Show(UserSeconds,SystemSeconds); aTimer.Show (aUserSeconds, aSystemSeconds);
timer.Stop(); aTimer.Stop();
printf("Number of scene redrawings: %.i \n", NumberOfViewerUpdate); std::cout << "Number of scene redrawings: " << aRedrawsNb << "\n"
printf("User Seconds: %.20f sec \n", UserSeconds); << "CPU user time: "
printf("System Seconds: %.20f sec \n", SystemSeconds); << std::setiosflags(std::ios::fixed) << std::setprecision(16) << 1000.0 * aUserSeconds
printf("Average time of scene redrawing : %.20f sec \n", (UserSeconds)/(Standard_Real)NumberOfViewerUpdate); << " msec\n"
<< "CPU system time: "
<< std::setiosflags(std::ios::fixed) << std::setprecision(16) << 1000.0 * aSystemSeconds
<< " msec\n"
<< "CPU average time of scene redrawing: "
<< std::setiosflags(std::ios::fixed) << std::setprecision(16) << 1000.0 * (aUserSeconds / (Standard_Real )aRedrawsNb)
<< " msec\n";
return 0; return 0;
} }
@ -2584,7 +2622,7 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
__FILE__,VDrawText,group); __FILE__,VDrawText,group);
theCommands.Add("vdrawsphere", theCommands.Add("vdrawsphere",
"vdrawsphere: VDrawSphere X Y Z Fineness Radius EnableVBO [NumberOfViewerUpdate(Default=1)] [ShowEdges(Default=0)]", "vdrawsphere: vdrawsphere shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToEnableVBO=1] [NumberOfViewerUpdate=1] [ToShowEdges=0]\n",
__FILE__,VDrawSphere,group); __FILE__,VDrawSphere,group);
} }