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