0023544: Texture management in TKOpenGl should be redesigned
[occt.git] / src / OpenGl / OpenGl_Workspace.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 #include <OpenGl_GlCore12.hxx>
21
22 #include <InterfaceGraphic.hxx>
23
24 #include <OpenGl_Workspace.hxx>
25
26 #include <OpenGl_AspectLine.hxx>
27 #include <OpenGl_AspectFace.hxx>
28 #include <OpenGl_AspectMarker.hxx>
29 #include <OpenGl_AspectText.hxx>
30 #include <OpenGl_Context.hxx>
31
32 #include <OpenGl_Texture.hxx>
33
34 #include <Graphic3d_TextureParams.hxx>
35
36 IMPLEMENT_STANDARD_HANDLE(OpenGl_Workspace,OpenGl_Window)
37 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,OpenGl_Window)
38
39 namespace
40 {
41   static const TEL_COLOUR myDefaultHighlightColor = { { 1.F, 1.F, 1.F, 1.F } };
42
43   static const OpenGl_AspectLine myDefaultAspectLine;
44   static const OpenGl_AspectFace myDefaultAspectFace;
45   static const OpenGl_AspectMarker myDefaultAspectMarker;
46   static const OpenGl_AspectText myDefaultAspectText;
47
48   static const OpenGl_TextParam myDefaultTextParam =
49   {
50     16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
51   };
52
53   static const OpenGl_Matrix myDefaultMatrix =
54   {
55     {{ 1.0F, 0.0F, 0.0F, 0.0F },
56      { 0.0F, 1.0F, 0.0F, 0.0F },
57      { 0.0F, 0.0F, 1.0F, 0.0F },
58      { 0.0F, 0.0F, 0.0F, 1.0F }}
59   };
60
61 };
62
63 // =======================================================================
64 // function : OpenGl_Workspace
65 // purpose  :
66 // =======================================================================
67 OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_Display)& theDisplay,
68                                     const CALL_DEF_WINDOW&        theCWindow,
69                                     Aspect_RenderingContext       theGContext,
70                                     const Handle(OpenGl_Context)& theShareCtx)
71 : OpenGl_Window (theDisplay, theCWindow, theGContext, theShareCtx),
72   myTransientList (0),
73   myIsTransientOpen (Standard_False),
74   myRetainMode (Standard_False),
75   myUseTransparency (Standard_False),
76   myUseZBuffer (Standard_False),
77   myUseDepthTest (Standard_True),
78   myUseGLLight (Standard_True),
79   myBackBufferRestored (Standard_False),
80   //
81   NamedStatus (0),
82   DegenerateModel (0),
83   SkipRatio (0.F),
84   HighlightColor (&myDefaultHighlightColor),
85   AspectLine_set (&myDefaultAspectLine),
86   AspectLine_applied (NULL),
87   AspectFace_set (&myDefaultAspectFace),
88   AspectFace_applied (NULL),
89   AspectMarker_set (&myDefaultAspectMarker),
90   AspectMarker_applied (NULL),
91   AspectText_set (&myDefaultAspectText),
92   AspectText_applied (NULL),
93   TextParam_set (&myDefaultTextParam),
94   TextParam_applied (NULL),
95   ViewMatrix_applied (&myDefaultMatrix),
96   StructureMatrix_applied (&myDefaultMatrix),
97   PolygonOffset_applied (NULL)
98 {
99   theDisplay->InitAttributes();
100
101   // General initialization of the context
102
103   // Eviter d'avoir les faces mal orientees en noir.
104   // Pourrait etre utiliser pour detecter les problemes d'orientation
105   glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
106
107   // Optimisation pour le Fog et l'antialiasing
108   glHint (GL_FOG_HINT,            GL_FASTEST);
109   glHint (GL_POINT_SMOOTH_HINT,   GL_FASTEST);
110   glHint (GL_LINE_SMOOTH_HINT,    GL_FASTEST);
111   glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
112
113   // Polygon Offset
114   EnablePolygonOffset();
115 }
116
117 // =======================================================================
118 // function : ~OpenGl_Workspace
119 // purpose  :
120 // =======================================================================
121 OpenGl_Workspace::~OpenGl_Workspace()
122 {
123 }
124
125 // =======================================================================
126 // function : Activate
127 // purpose  :
128 // =======================================================================
129 Standard_Boolean OpenGl_Workspace::Activate()
130 {
131   if (!OpenGl_Window::Activate())
132     return Standard_False;
133
134   DegenerateModel         = 0;
135   SkipRatio               = 0.0f;
136   ViewMatrix_applied      = &myDefaultMatrix;
137   StructureMatrix_applied = &myDefaultMatrix;
138
139   ResetAppliedAspect();
140
141   return Standard_True;
142 }
143
144 // =======================================================================
145 // function : UseTransparency
146 // purpose  : call_togl_transparency
147 // =======================================================================
148 void OpenGl_Workspace::UseTransparency (const Standard_Boolean theFlag)
149 {
150   if ((myUseTransparency ? 1 : 0) != (theFlag ? 1 : 0))
151   {
152     myUseTransparency = theFlag;
153     EraseAnimation();
154   }
155 }
156
157 //=======================================================================
158 //function : ResetAppliedAspect
159 //purpose  : Sets default values of GL parameters in accordance with default aspects
160 //=======================================================================
161 void OpenGl_Workspace::ResetAppliedAspect()
162 {
163   NamedStatus           = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
164   HighlightColor        = &myDefaultHighlightColor;
165   AspectLine_set        = &myDefaultAspectLine;
166   AspectLine_applied    = NULL;
167   AspectFace_set        = &myDefaultAspectFace;
168   AspectFace_applied    = NULL;
169   AspectMarker_set      = &myDefaultAspectMarker;
170   AspectMarker_applied  = NULL;
171   AspectText_set        = &myDefaultAspectText;
172   AspectText_applied    = NULL;
173   TextParam_set         = &myDefaultTextParam;
174   TextParam_applied     = NULL;
175   PolygonOffset_applied = NULL;
176
177   AspectLine(Standard_True);
178   AspectFace(Standard_True);
179   AspectMarker(Standard_True);
180   AspectText(Standard_True);
181 }
182
183 // =======================================================================
184 // function : DisableTexture
185 // purpose  :
186 // =======================================================================
187 Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
188 {
189   if (myTextureBound.IsNull())
190   {
191     return myTextureBound;
192   }
193
194   // reset texture matrix because some code may expect it is identity
195   GLint aMatrixMode = GL_TEXTURE;
196   glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
197   glMatrixMode (GL_TEXTURE);
198   glLoadIdentity();
199   glMatrixMode (aMatrixMode);
200
201   myTextureBound->Unbind (myGlContext);
202   switch (myTextureBound->GetTarget())
203   {
204     case GL_TEXTURE_1D:
205     {
206       if (myTextureBound->GetParams()->GenMode() != GL_NONE)
207       {
208         glDisable (GL_TEXTURE_GEN_S);
209       }
210       glDisable (GL_TEXTURE_1D);
211       break;
212     }
213     case GL_TEXTURE_2D:
214     {
215       if (myTextureBound->GetParams()->GenMode() != GL_NONE)
216       {
217         glDisable (GL_TEXTURE_GEN_S);
218         glDisable (GL_TEXTURE_GEN_T);
219       }
220       glDisable (GL_TEXTURE_2D);
221       break;
222     }
223     default: break;
224   }
225
226   Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
227   myTextureBound.Nullify();
228   return aPrevTexture;
229 }
230
231 // =======================================================================
232 // function : setTextureParams
233 // purpose  :
234 // =======================================================================
235 void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&                theTexture,
236                                          const Handle(Graphic3d_TextureParams)& theParams)
237 {
238   const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
239   if (aParams.IsNull())
240   {
241     return;
242   }
243
244   GLint aMatrixMode = GL_TEXTURE;
245   glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
246
247   // setup texture matrix
248   glMatrixMode (GL_TEXTURE);
249   glLoadIdentity();
250   const Graphic3d_Vec2& aScale = aParams->Scale();
251   const Graphic3d_Vec2& aTrans = aParams->Translation();
252   glScalef     ( aScale.x(),  aScale.y(), 1.0f);
253   glTranslatef (-aTrans.x(), -aTrans.y(), 0.0f);
254   glRotatef (-aParams->Rotation(), 0.0f, 0.0f, 1.0f);
255
256   // setup generation of texture coordinates
257   switch (aParams->GenMode())
258   {
259     case Graphic3d_TOTM_OBJECT:
260     {
261       glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
262       glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
263       if (theTexture->GetTarget() != GL_TEXTURE_1D)
264       {
265         glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
266         glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
267       }
268       break;
269     }
270     case Graphic3d_TOTM_SPHERE:
271     {
272       glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
273       if (theTexture->GetTarget() != GL_TEXTURE_1D)
274       {
275         glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
276       }
277       break;
278     }
279     case Graphic3d_TOTM_EYE:
280     {
281       glMatrixMode (GL_MODELVIEW);
282       glPushMatrix();
283       glLoadIdentity();
284
285       glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
286       glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
287
288       if (theTexture->GetTarget() != GL_TEXTURE_1D)
289       {
290         glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
291         glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
292       }
293       glPopMatrix();
294       break;
295     }
296     case Graphic3d_TOTM_MANUAL:
297     default: break;
298   }
299
300   // setup lighting
301   glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aParams->IsModulate() ? GL_MODULATE : GL_DECAL);
302
303   // setup texture filtering and wrapping
304   //if (theTexture->GetParams() != theParams)
305   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
306   const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : GL_CLAMP;
307   switch (theTexture->GetTarget())
308   {
309     case GL_TEXTURE_1D:
310     {
311       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
312       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
313       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
314       break;
315     }
316     case GL_TEXTURE_2D:
317     {
318       GLenum aFilterMin = aFilter;
319       if (theTexture->HasMipmaps())
320       {
321         aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
322         if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
323         {
324           aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
325         }
326         else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
327         {
328           aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
329         }
330
331         if (myGlContext->extAnis)
332         {
333           // setup degree of anisotropy filter
334           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
335           switch (aParams->AnisoFilter())
336           {
337             case Graphic3d_LOTA_QUALITY:
338             {
339               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aMaxDegree);
340               break;
341             }
342             case Graphic3d_LOTA_MIDDLE:
343             {
344
345               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2));
346               break;
347             }
348             case Graphic3d_LOTA_FAST:
349             {
350               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2);
351               break;
352             }
353             case Graphic3d_LOTA_OFF:
354             default:
355             {
356               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
357               break;
358             }
359           }
360         }
361       }
362       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
363       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
364       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
365       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
366       break;
367     }
368     default: break;
369   }
370
371   switch (theTexture->GetTarget())
372   {
373     case GL_TEXTURE_1D:
374     {
375       if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
376       {
377         glEnable (GL_TEXTURE_GEN_S);
378       }
379       glEnable (GL_TEXTURE_1D);
380       break;
381     }
382     case GL_TEXTURE_2D:
383     {
384       if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
385       {
386         glEnable (GL_TEXTURE_GEN_S);
387         glEnable (GL_TEXTURE_GEN_T);
388       }
389       glEnable (GL_TEXTURE_2D);
390       break;
391     }
392     default: break;
393   }
394
395   glMatrixMode (aMatrixMode); // turn back active matrix
396   theTexture->SetParams (aParams);
397 }
398
399 // =======================================================================
400 // function : EnableTexture
401 // purpose  :
402 // =======================================================================
403 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
404                                                         const Handle(Graphic3d_TextureParams)& theParams)
405 {
406   if (theTexture.IsNull() || !theTexture->IsValid())
407   {
408     return DisableTexture();
409   }
410
411   if (myTextureBound.IsNull() && myTextureBound == theTexture)
412   {
413     Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
414     myTextureBound = theTexture;
415     return aPrevTexture;
416   }
417
418   Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
419   myTextureBound = theTexture;
420   myTextureBound->Bind (myGlContext);
421   setTextureParams (myTextureBound, theParams);
422
423   return aPrevTexture;
424 }