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