0023345: Crash when destroying OpenGl_Element
authorkgv <kgv@opencascade.com>
Fri, 12 Oct 2012 12:56:23 +0000 (16:56 +0400)
committerkgv <kgv@opencascade.com>
Fri, 12 Oct 2012 12:56:23 +0000 (16:56 +0400)
OpenGl_PrimitiveArray::Release() - avoid possible NULL-pointer dereference
OpenGl_GraphicDriver::RemoveView() - release GL resources within removing last view
Fixed OCC280 test command - do not remove old view until new one is initialized

src/OpenGl/OpenGl_GraphicDriver_7.cxx
src/OpenGl/OpenGl_PrimitiveArray.cxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_Structure.hxx
src/QABugs/QABugs_17.cxx

index b7e6414..d545154 100755 (executable)
@@ -409,17 +409,30 @@ Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer*         theFB
   return Standard_True;
 }
 
-void OpenGl_GraphicDriver::RemoveView (const Graphic3d_CView& ACView)
+void OpenGl_GraphicDriver::RemoveView (const Graphic3d_CView& theCView)
 {
-  if (myMapOfView.IsBound (ACView.ViewId))
-    myMapOfView.UnBind (ACView.ViewId);
+  Handle(OpenGl_Context) aShareCtx = GetSharedContext();
+  if (myMapOfView.IsBound (theCView.ViewId))
+    myMapOfView.UnBind (theCView.ViewId);
+
+  if (myMapOfWS.IsBound (theCView.WsId))
+    myMapOfWS.UnBind (theCView.WsId);
 
-  if (myMapOfWS.IsBound (ACView.WsId))
-    myMapOfWS.UnBind (ACView.WsId);
+  if (myMapOfWS.IsEmpty() && !myMapOfStructure.IsEmpty())
+  {
+    // The last view removed but some objects still present.
+    // Release GL resources now without object destruction.
+    for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
+         aStructIt.More (); aStructIt.Next())
+    {
+      OpenGl_Structure* aStruct = aStructIt.ChangeValue();
+      aStruct->ReleaseGlResources (aShareCtx);
+    }
+  }
 
-  OpenGl_CView *aCView = (OpenGl_CView *)ACView.ptrView;
+  OpenGl_CView *aCView = (OpenGl_CView *)theCView.ptrView;
   delete aCView;
-  ((Graphic3d_CView *)&ACView)->ptrView = NULL;
+  ((Graphic3d_CView *)&theCView)->ptrView = NULL;
 }
 
 void OpenGl_GraphicDriver::SetLight (const Graphic3d_CView& ACView)
index 8bb73e8..b29d51e 100755 (executable)
@@ -17,7 +17,6 @@
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-
 #include <OpenGl_IndexBuffer.hxx>
 #include <OpenGl_Context.hxx>
 
@@ -1552,7 +1551,10 @@ void OpenGl_PrimitiveArray::Release (const Handle(OpenGl_Context)& theContext)
   {
     if (!myVbos[anIter].IsNull())
     {
-      theContext->DelayedRelease (myVbos[anIter]);
+      if (!theContext.IsNull())
+      {
+        theContext->DelayedRelease (myVbos[anIter]);
+      }
       myVbos[anIter].Nullify();
     }
   }
index 8730522..20d5afd 100644 (file)
@@ -447,6 +447,42 @@ void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
   ClearHighlightColor (theGlCtx);
 }
 
+// =======================================================================
+// function : ReleaseGlResources
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
+{
+  for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
+  {
+    OpenGl_Group* aGroup = const_cast<OpenGl_Group*& > (anIter.ChangeValue());
+    if (aGroup != NULL)
+    {
+      aGroup->Release (theGlCtx);
+    }
+  }
+  if (myAspectLine != NULL)
+  {
+    myAspectLine->Release (theGlCtx);
+  }
+  if (myAspectFace != NULL)
+  {
+    myAspectFace->Release (theGlCtx);
+  }
+  if (myAspectMarker != NULL)
+  {
+    myAspectMarker->Release (theGlCtx);
+  }
+  if (myAspectText != NULL)
+  {
+    myAspectText->Release (theGlCtx);
+  }
+  if (myHighlightBox != NULL)
+  {
+    myHighlightBox->Release (theGlCtx);
+  }
+}
+
 //=======================================================================
 //function : SetZLayer
 //purpose  : 
index 11d6985..2650592 100644 (file)
@@ -84,6 +84,14 @@ public:
   virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const;
   virtual void Release (const Handle(OpenGl_Context)&   theGlCtx);
 
+  //! This method releases GL resources without actual elements destruction.
+  //! As result structure could be correctly destroyed layter without GL context
+  //! (after last window was closed for example).
+  //!
+  //! Notice however that reusage of this structure after calling this method is incorrect
+  //! and will lead to broken visualization due to loosed data.
+  void ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx);
+
 protected:
 
   virtual ~OpenGl_Structure();
index 79b5318..13f7e4a 100644 (file)
@@ -581,8 +581,6 @@ static Standard_Integer OCC280 (Draw_Interpretor& di, Standard_Integer argc, con
 
   Handle(Aspect_Window) asp = anOldView->Window();
   aViewer->SetViewOff (anOldView);
-  anOldView->Remove();
-  anOldView.Nullify();
 
   Handle(V3d_View) aNewView = aViewer->CreateView();
   ViewerTest::CurrentView (aNewView);
@@ -590,6 +588,9 @@ static Standard_Integer OCC280 (Draw_Interpretor& di, Standard_Integer argc, con
   aNewView->SetWindow (asp);
   if (!asp->IsMapped()) asp->Map();
 
+  anOldView->Remove();
+  anOldView.Nullify();
+
   aNewView->Update();
 
   // replace view in event manager