0023418: Crash on the object displaying when running DRAW on remote station. OpenGL...
[occt.git] / src / OpenGl / OpenGl_Display.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <OpenGl_GlCore11.hxx>
22
23 #include <OpenGl_Display.hxx>
24
25 #include <OSD_Environment.hxx>
26 #include <TCollection_AsciiString.hxx>
27 #include <Aspect_GraphicDeviceDefinitionError.hxx>
28
29 #include <OpenGl_Light.hxx>
30
31 #if (!defined(_WIN32) && !defined(__WIN32__))
32   #include <X11/Xlib.h> // XOpenDisplay()
33 #endif
34
35 IMPLEMENT_STANDARD_HANDLE(OpenGl_Display,MMgt_TShared)
36 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Display,MMgt_TShared)
37
38 Handle(OpenGl_Display) openglDisplay;
39
40 namespace
41 {
42   #if (defined(_WIN32) || defined(__WIN32__))
43     static char* TheDummyDisplay = "DISPLAY";
44   #endif
45
46   static const OpenGl_Facilities myDefaultFacilities = { 1, 1, 1, 1, OpenGLMaxLights, 10000 };
47 };
48
49 /*----------------------------------------------------------------------*/
50
51 OpenGl_Display::OpenGl_Display (const Standard_CString theDisplay)
52 : myDisplay(NULL),
53   myFacilities(myDefaultFacilities),
54   myDBuffer(Standard_True),
55   myDither(Standard_True),
56   myBackDither(Standard_False),
57   myWalkthrough(Standard_False),
58   mySymPerspective(Standard_False),
59   myOffsetFactor(1.F),
60   myOffsetUnits(0.F),
61   myAntiAliasingMode(3),
62   myLinestyleBase(0),
63   myPatternBase(0),
64   myMarkerBase(0),
65   myFont(-1),
66   myFontSize(-1)
67 {
68 #if (defined(_WIN32) || defined(__WIN32__))
69   myDisplay = TheDummyDisplay;
70 #else
71   if (theDisplay != NULL && *theDisplay != '\0')
72   {
73     OSD_Environment aDispEnv ("DISPLAY", theDisplay);
74     aDispEnv.Build();
75   }
76
77   // Specifies the hardware display name, which determines the
78   // display and communications domain to be used.
79   // On a POSIX system, if the display_name is NULL, it defaults
80   // to the value of the DISPLAY environment variable.
81   myDisplay = XOpenDisplay (NULL);
82 #endif
83
84   Init();
85 }
86
87 /*----------------------------------------------------------------------*/
88
89 OpenGl_Display::OpenGl_Display (const Aspect_Display theDisplay)
90 : myDisplay(NULL),
91   myFacilities(myDefaultFacilities),
92   myDBuffer(Standard_True),
93   myDither(Standard_True),
94   myBackDither(Standard_False),
95   myWalkthrough(Standard_False),
96   mySymPerspective(Standard_False),
97   myOffsetFactor(1.F),
98   myOffsetUnits(0.F),
99   myAntiAliasingMode(3),
100   myLinestyleBase(0),
101   myPatternBase(0),
102   myMarkerBase(0),
103   myFont(-1),
104   myFontSize(-1)
105 {
106 #if (defined(_WIN32) || defined(__WIN32__))
107   myDisplay = TheDummyDisplay;
108 #else
109   myDisplay = theDisplay;
110 #endif
111
112   Init();
113 }
114
115 /*----------------------------------------------------------------------*/
116
117 OpenGl_Display::~OpenGl_Display ()
118 {
119   // Delete line styles
120   if (myLinestyleBase)
121   {
122     glDeleteLists((GLuint)myLinestyleBase,5);
123     myLinestyleBase = 0;
124   }
125   // Delete surface patterns
126   if (myPatternBase)
127   {
128     glDeleteLists((GLuint)myPatternBase,TEL_HS_USER_DEF_START);
129     myPatternBase = 0;
130   }
131   // Delete markers
132   if (myMarkerBase)
133   {
134     glDeleteLists((GLuint)myMarkerBase,60);
135     myMarkerBase = 0;
136   }
137   // Delete user markers
138   OpenGl_MapOfUserMarker::Iterator itm(myMapOfUM);
139   for (; itm.More(); itm.Next())
140   {
141     const OPENGL_MARKER_DATA &aData = itm.Value();
142     if (aData.Array)
143     {
144       delete[] aData.Array;
145     }
146     else if (aData.ListId != 0)
147     {
148       glDeleteLists ( aData.ListId, 1 );
149     }
150   }
151   myDisplay = NULL;
152 }
153
154 /*----------------------------------------------------------------------*/
155
156 Handle(OpenGl_Window) OpenGl_Display::GetWindow (const Aspect_Drawable AParent) const
157 {
158   Handle(OpenGl_Window) aWindow;
159   if ( myMapOfWindows.IsBound( AParent ) )
160   {
161     aWindow = myMapOfWindows.Find( AParent );
162   }
163   return aWindow;
164 }
165
166 /*----------------------------------------------------------------------*/
167
168 void OpenGl_Display::SetWindow (const Aspect_Drawable AParent, const Handle(OpenGl_Window) &AWindow)
169 {
170   if ( !myMapOfWindows.IsBound( AParent ) )
171   {
172     myMapOfWindows.Bind( AParent, AWindow );
173   }
174 }
175
176 /*----------------------------------------------------------------------*/
177
178 //GenerateMarkerBitmap
179 void OpenGl_Display::AddUserMarker (const Standard_Integer AIndex,
180                                    const Standard_Integer AMarkWidth,
181                                    const Standard_Integer AMarkHeight,
182                                    const Handle(TColStd_HArray1OfByte)& ATexture)
183 {
184   if (!myMapOfUM.IsBound(AIndex))
185   {
186     const OPENGL_MARKER_DATA anEmptyData = { 0, 0, 0, NULL };
187     myMapOfUM.Bind(AIndex,anEmptyData);
188   }
189
190   OPENGL_MARKER_DATA &aData = myMapOfUM.ChangeFind(AIndex);
191
192   if (aData.Array)
193   {
194     delete[] aData.Array;
195     aData.Array = NULL;
196   }
197
198   unsigned char *anArray = new unsigned char[ATexture->Length()];
199
200   const int aByteWidth = AMarkWidth / 8;
201   int i, anIndex = ATexture->Upper() - ATexture->Lower() - aByteWidth + 1;
202   for ( ; anIndex >= 0; anIndex -= aByteWidth )
203     for ( i = 0; i < aByteWidth; i++ )
204       anArray[ATexture->Upper() - ATexture->Lower() - aByteWidth + 1 - anIndex + i ] = ATexture->Value( anIndex + i + 1 );
205
206   aData.Width = AMarkWidth;
207   aData.Height = AMarkHeight;
208   aData.Array = anArray;
209 }
210
211 /*----------------------------------------------------------------------*/
212
213 void OpenGl_Display::UpdateUserMarkers ()
214 {
215   OpenGl_MapOfUserMarker::Iterator itm(myMapOfUM);
216   for (; itm.More(); itm.Next())
217   {
218     OPENGL_MARKER_DATA &aData = itm.ChangeValue();
219     if (aData.Array)
220     {
221       if (aData.ListId == 0)
222         aData.ListId = glGenLists(1);
223
224       glNewList( (GLuint)aData.ListId, GL_COMPILE );
225
226       GLint w = ( GLsizei ) aData.Width;
227       GLint h = ( GLsizei ) aData.Height;
228       glBitmap( w, h,
229                 0.5F * ( float )aData.Width, 0.5F * ( float )aData.Height,
230                 ( float )30.0, ( float )30.0,
231                 ( GLubyte* )aData.Array );
232
233       glEndList();
234
235       delete[] aData.Array;
236       aData.Array = NULL;
237     }
238   }
239 }
240
241 /*----------------------------------------------------------------------*/
242
243 Standard_Integer OpenGl_Display::GetUserMarkerListIndex (const Standard_Integer AIndex) const
244 {
245   if (myMapOfUM.IsBound(AIndex))
246   {
247     const OPENGL_MARKER_DATA &aData = myMapOfUM.Find(AIndex);
248     if (!aData.Array)
249       return aData.ListId;
250   }
251   return -1;
252 }
253
254 /*----------------------------------------------------------------------*/
255
256 void OpenGl_Display::Init()
257 {
258   if (myDisplay != NULL)
259   {
260   #if (!defined(_WIN32) && !defined(__WIN32__))
261     XSynchronize ((Display* )myDisplay, (getenv("CALL_SYNCHRO_X") != NULL) ? 1 : 0);
262
263     if (getenv("CSF_GraphicSync") != NULL)
264       XSynchronize ((Display* )myDisplay, 1);
265
266     // does the server know about OpenGL & GLX?
267     int aDummy;
268     if (!XQueryExtension ((Display* )myDisplay, "GLX", &aDummy, &aDummy, &aDummy))
269     {
270     #ifdef DEBUG
271       std::cerr << "This system doesn't appear to support OpenGL\n";
272     #endif
273     }
274   #endif
275   }
276   else
277   {
278     TCollection_AsciiString msg("OpenGl_Display::Init");
279   #if (!defined(_WIN32) && !defined(__WIN32__))
280     msg += " : Cannot connect to X server ";
281     msg += XDisplayName ((char*) NULL);
282   #endif
283     Aspect_GraphicDeviceDefinitionError::Raise(msg.ToCString());
284   }
285
286   if (getenv("CALL_OPENGL_NO_DBF") != NULL)
287     myDBuffer = Standard_False;
288
289   if (getenv("CALL_OPENGL_NO_DITHER") != NULL)
290     myDither = Standard_False;
291
292   if (getenv("CALL_OPENGL_NO_BACKDITHER") != NULL)
293     myBackDither = Standard_False;
294
295   if (getenv("CSF_WALKTHROUGH") != NULL)
296     myWalkthrough = Standard_True;
297
298   /* OCC18942: Test if symmetric perspective projection should be turned on */
299   if (getenv("CSF_SYM_PERSPECTIVE") != NULL)
300     mySymPerspective = Standard_True;
301
302   const char* pvalue = getenv("CALL_OPENGL_POLYGON_OFFSET");
303   if (pvalue)
304   {
305     float v1, v2;
306     const int n = sscanf(pvalue, "%f %f", &v1, &v2);
307     if (n > 0) myOffsetFactor = v1;
308     if (n > 1) myOffsetUnits  = v2;
309   }
310
311   pvalue = getenv("CALL_OPENGL_ANTIALIASING_MODE");
312   if (pvalue)
313   {
314     int v;
315     if ( sscanf(pvalue,"%d",&v) > 0 ) myAntiAliasingMode = v;
316   }
317 }