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