0025133: TKOpenGl - Crash on closing a view containing presentations with capping
[occt.git] / src / OpenGl / OpenGl_LayerList.cxx
1 // Created on: 2012-02-02
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_GlCore11.hxx>
17
18 #include <OpenGl_LayerList.hxx>
19 #include <OpenGl_Structure.hxx>
20 #include <OpenGl_Workspace.hxx>
21
22 #include <InterfaceGraphic_Graphic3d.hxx>
23 #include <InterfaceGraphic.hxx>
24
25 //=======================================================================
26 //function : OpenGl_LayerList
27 //purpose  : Constructor
28 //=======================================================================
29
30 OpenGl_LayerList::OpenGl_LayerList (const Standard_Integer theNbPriorities)
31  : myNbPriorities (theNbPriorities),
32    myNbStructures (0)
33 {
34   // insert default priority layer
35   myLayers.Append (OpenGl_Layer (myNbPriorities));
36   myLayerIds.Bind (0, myLayers.Length());
37 }
38
39 //=======================================================================
40 //function : ~OpenGl_LayerList
41 //purpose  : Destructor
42 //=======================================================================
43
44 OpenGl_LayerList::~OpenGl_LayerList ()
45 {
46 }
47
48 //=======================================================================
49 //function : defaultLayer
50 //purpose  :
51 //=======================================================================
52
53 OpenGl_Layer& OpenGl_LayerList::defaultLayer()
54 {
55   return myLayers.ChangeValue (1);
56 }
57
58 //=======================================================================
59 //function : NbPriorities
60 //purpose  : Method returns the number of available priorities
61 //=======================================================================
62
63 Standard_Integer OpenGl_LayerList::NbPriorities () const
64 {
65   return myNbPriorities;
66 }
67
68 //=======================================================================
69 //function : NbStructures
70 //purpose  : Method returns the number of available structures
71 //=======================================================================
72
73 Standard_Integer OpenGl_LayerList::NbStructures () const
74 {
75   return myNbStructures;
76 }
77
78 //=======================================================================
79 //function : AddLayer
80 //purpose  : 
81 //=======================================================================
82
83 void OpenGl_LayerList::AddLayer (const Standard_Integer theLayerId)
84 {
85   if (HasLayer (theLayerId))
86     return;
87
88   // add the new layer
89   myLayers.Append (OpenGl_Layer (myNbPriorities));
90   myLayerIds.Bind (theLayerId, myLayers.Length());
91 }
92
93 //=======================================================================
94 //function : HasLayer
95 //purpose  : 
96 //=======================================================================
97
98 Standard_Boolean OpenGl_LayerList::HasLayer 
99   (const Standard_Integer theLayerId) const
100 {
101   return myLayerIds.IsBound (theLayerId);
102 }
103
104 //=======================================================================
105 //function : Layer
106 //purpose  : 
107 //=======================================================================
108 OpenGl_Layer& OpenGl_LayerList::Layer (const Standard_Integer theLayerId)
109 {
110   return myLayers.ChangeValue (myLayerIds.Find (theLayerId));
111 }
112
113 //=======================================================================
114 //function : Layer
115 //purpose  : 
116 //=======================================================================
117 const OpenGl_Layer& OpenGl_LayerList::Layer (const Standard_Integer theLayerId) const
118 {
119   return myLayers.Value (myLayerIds.Find (theLayerId));
120 }
121
122 //=======================================================================
123 //function : RemoveLayer
124 //purpose  :
125 //=======================================================================
126
127 void OpenGl_LayerList::RemoveLayer (const Standard_Integer theLayerId)
128 {
129   if (!HasLayer (theLayerId) || theLayerId == 0)
130     return;
131
132   Standard_Integer aRemovePos = myLayerIds.Find (theLayerId);
133   
134   // move all displayed structures to first layer
135   const OpenGl_PriorityList& aList = myLayers.Value (aRemovePos).PriorityList();
136   defaultLayer ().PriorityList().Append (aList);
137
138   // remove layer
139   myLayers.Remove (aRemovePos);
140   myLayerIds.UnBind (theLayerId);
141
142   // updated sequence indexes in map
143   OpenGl_LayerSeqIds::Iterator aMapIt (myLayerIds);
144   for ( ; aMapIt.More (); aMapIt.Next ())
145   {
146     Standard_Integer& aSeqIdx = aMapIt.ChangeValue ();
147     if (aSeqIdx > aRemovePos)
148       aSeqIdx--;
149   }
150 }
151
152 //=======================================================================
153 //function : AddStructure
154 //purpose  :
155 //=======================================================================
156
157 void OpenGl_LayerList::AddStructure (const OpenGl_Structure *theStructure,
158                                      const Standard_Integer  theLayerId,
159                                      const Standard_Integer  thePriority,
160                                      Standard_Boolean isForChangePriority)
161 {
162   // add structure to associated layer,
163   // if layer doesn't exists, display structure in default layer
164   OpenGl_PriorityList& aList = !HasLayer (theLayerId) ? defaultLayer ().PriorityList() :
165     myLayers.ChangeValue (myLayerIds.Find (theLayerId)).PriorityList();
166
167   aList.Add (theStructure, thePriority, isForChangePriority);
168   myNbStructures++;
169
170   // Note: In ray-tracing mode we don't modify modification
171   // state here. It is redundant, because the possible changes
172   // will be handled in the loop for structures
173 }
174
175 //=======================================================================
176 //function : RemoveStructure
177 //purpose  : 
178 //=======================================================================
179
180 void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure *theStructure,
181                                         const Standard_Integer  theLayerId)
182 {
183   Standard_Integer aSeqPos = !HasLayer (theLayerId) ?
184     1 : myLayerIds.Find (theLayerId);
185   
186   OpenGl_PriorityList& aList = myLayers.ChangeValue (aSeqPos).PriorityList();
187
188   // remove structure from associated list
189   // if the structure is not found there,
190   // scan through layers and remove it
191   if (aList.Remove (theStructure) >= 0)
192   {
193     myNbStructures--;
194
195     if (theStructure->IsRaytracable())
196     {
197       myModificationState++;
198     }
199
200     return;
201   }
202   
203   // scan through layers and remove it
204   Standard_Integer aSeqId = 1;
205   OpenGl_SequenceOfLayers::Iterator anIts;
206   for (anIts.Init (myLayers); anIts.More (); anIts.Next (), aSeqId++)
207   {
208     OpenGl_PriorityList& aScanList = anIts.ChangeValue ().PriorityList();
209     if (aSeqPos == aSeqId)
210       continue;
211   
212     if (aScanList.Remove (theStructure) >= 0)
213     {
214       myNbStructures--;
215
216       if (theStructure->IsRaytracable())
217       {
218         myModificationState++;
219       }
220
221       return;
222     }
223   }
224 }
225
226 //=======================================================================
227 //function : InvalidateBVHData
228 //purpose  :
229 //=======================================================================
230 void OpenGl_LayerList::InvalidateBVHData (const Standard_Integer theLayerId)
231 {
232   Standard_Integer aSeqPos = !HasLayer (theLayerId) ?
233     1 : myLayerIds.Find (theLayerId);
234
235   OpenGl_PriorityList& aList = myLayers.ChangeValue (aSeqPos).PriorityList();
236
237   aList.InvalidateBVHData();
238 }
239
240 //=======================================================================
241 //function : ChangeLayer
242 //purpose  :
243 //=======================================================================
244
245 void OpenGl_LayerList::ChangeLayer (const OpenGl_Structure *theStructure,
246                                     const Standard_Integer  theOldLayerId,
247                                     const Standard_Integer  theNewLayerId)
248 {
249   Standard_Integer aSeqPos = !HasLayer (theOldLayerId) ?
250     1 : myLayerIds.Find (theOldLayerId);
251   
252   OpenGl_PriorityList& aList = myLayers.ChangeValue (aSeqPos).PriorityList();
253   Standard_Integer aPriority;
254
255   // take priority and remove structure from list found by <theOldLayerId>
256   // if the structure is not found there, scan through all other layers
257   if ((aPriority = aList.Remove (theStructure, Standard_True)) >= 0)
258   {
259     myNbStructures--;
260     AddStructure (theStructure, theNewLayerId, aPriority, Standard_True);
261   }
262   else
263   {
264     // scan through layers and remove it
265     Standard_Integer aSeqId = 1;
266     OpenGl_SequenceOfLayers::Iterator anIts;
267     for (anIts.Init (myLayers); anIts.More (); anIts.Next (), aSeqId++)
268     {
269       if (aSeqPos == aSeqId)
270         continue;
271   
272       // try to remove structure and get priority value from this layer
273       if ((aPriority = aList.Remove (theStructure, Standard_True)) >= 0)
274       {
275         myNbStructures--;
276         AddStructure (theStructure, theNewLayerId, aPriority, Standard_True);
277         break;
278       }
279     }
280   }
281 }
282
283 //=======================================================================
284 //function : ChangePriority
285 //purpose  :
286 //=======================================================================
287 void OpenGl_LayerList::ChangePriority (const OpenGl_Structure *theStructure,
288                                        const Standard_Integer theLayerId,
289                                        const Standard_Integer theNewPriority)
290 {
291   Standard_Integer aSeqPos = !HasLayer (theLayerId) ?
292     1 : myLayerIds.Find (theLayerId);
293
294   OpenGl_PriorityList& aList = myLayers.ChangeValue (aSeqPos).PriorityList();
295
296   if (aList.Remove (theStructure, Standard_True) >= 0)
297   {
298     myNbStructures--;
299     AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
300   }
301   else
302   {
303     Standard_Integer aSeqId = 1;
304     OpenGl_SequenceOfLayers::Iterator anIts;
305     for (anIts.Init (myLayers); anIts.More (); anIts.Next (), aSeqId++)
306     {
307       if (aSeqPos == aSeqId)
308         continue;
309
310       if (aList.Remove (theStructure, Standard_True) >= 0)
311       {
312         myNbStructures--;
313         AddStructure (theStructure, theLayerId, theNewPriority, Standard_True);
314         break;
315       }
316     }
317   }
318 }
319
320 //=======================================================================
321 //function : Render
322 //purpose  : Render this element
323 //=======================================================================
324
325 void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace) &theWorkspace) const
326 {
327   OpenGl_GlobalLayerSettings aDefaultSettings;
328   
329   glGetIntegerv (GL_DEPTH_FUNC, &aDefaultSettings.DepthFunc);
330   glGetBooleanv (GL_DEPTH_WRITEMASK, &aDefaultSettings.DepthMask);
331
332   OpenGl_SequenceOfLayers::Iterator anIts;
333   for (anIts.Init (myLayers); anIts.More(); anIts.Next())
334   {
335     const OpenGl_Layer& aLayer = anIts.Value ();
336     if (aLayer.PriorityList().NbStructures () > 0)
337     {
338       // render layer
339       aLayer.Render (theWorkspace, aDefaultSettings);
340     }
341   }
342
343   glDepthMask (aDefaultSettings.DepthMask);
344   glDepthFunc (aDefaultSettings.DepthFunc);
345 }