0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / OpenGl / OpenGl_Sampler.cxx
1 // Created on: 2014-10-08
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_Sampler.hxx>
17
18 #include <OpenGl_ArbSamplerObject.hxx>
19 #include <OpenGl_Context.hxx>
20 #include <OpenGl_Texture.hxx>
21 #include <Standard_Assert.hxx>
22
23 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Sampler,OpenGl_Resource)
24
25 // =======================================================================
26 // function : OpenGl_Sampler
27 // purpose  :
28 // =======================================================================
29 OpenGl_Sampler::OpenGl_Sampler (const Handle(Graphic3d_TextureParams)& theParams)
30 : myParams (theParams),
31   mySamplerRevision (0),
32   mySamplerID (NO_SAMPLER),
33   myIsImmutable (false)
34 {
35   if (myParams.IsNull())
36   {
37     myParams = new Graphic3d_TextureParams();
38   }
39 }
40
41 // =======================================================================
42 // function : ~OpenGl_Sampler
43 // purpose  :
44 // =======================================================================
45 OpenGl_Sampler::~OpenGl_Sampler()
46 {
47   Release (NULL);
48 }
49
50 // =======================================================================
51 // function : Release
52 // purpose  :
53 // =======================================================================
54 void OpenGl_Sampler::Release (OpenGl_Context* theCtx)
55 {
56   myIsImmutable = false;
57   mySamplerRevision = myParams->SamplerRevision() - 1;
58   if (!isValidSampler())
59   {
60     return;
61   }
62
63   // application can not handle this case by exception - this is bug in code
64   Standard_ASSERT_RETURN (theCtx != NULL,
65     "OpenGl_Sampler destroyed without GL context! Possible GPU memory leakage...",);
66
67   if (theCtx->IsValid())
68   {
69     theCtx->arbSamplerObject->glDeleteSamplers (1, &mySamplerID);
70   }
71
72   mySamplerID = NO_SAMPLER;
73 }
74
75 // =======================================================================
76 // function : Create
77 // purpose  :
78 // =======================================================================
79 Standard_Boolean OpenGl_Sampler::Create (const Handle(OpenGl_Context)& theCtx)
80 {
81   if (isValidSampler())
82   {
83     return Standard_True;
84   }
85   else if (theCtx->arbSamplerObject == NULL)
86   {
87     return Standard_False;
88   }
89
90   theCtx->arbSamplerObject->glGenSamplers (1, &mySamplerID);
91   return Standard_True;
92 }
93
94 // =======================================================================
95 // function : Init
96 // purpose  :
97 // =======================================================================
98 Standard_Boolean OpenGl_Sampler::Init (const Handle(OpenGl_Context)& theCtx,
99                                        const OpenGl_Texture& theTexture)
100 {
101   if (isValidSampler())
102   {
103     if (!ToUpdateParameters())
104     {
105       return Standard_True;
106     }
107     else if (!myIsImmutable)
108     {
109       applySamplerParams (theCtx, myParams, this, theTexture.GetTarget(), theTexture.MaxMipmapLevel());
110       return Standard_True;
111     }
112     Release (theCtx.get());
113   }
114
115   if (!Create (theCtx))
116   {
117     return Standard_False;
118   }
119
120   applySamplerParams (theCtx, myParams, this, theTexture.GetTarget(), theTexture.MaxMipmapLevel());
121   return Standard_True;
122 }
123
124 // =======================================================================
125 // function : Bind
126 // purpose  : Binds sampler object to the given texture unit
127 // =======================================================================
128 void OpenGl_Sampler::Bind (const Handle(OpenGl_Context)& theCtx,
129                            const Graphic3d_TextureUnit   theUnit)
130 {
131   if (isValidSampler())
132   {
133     theCtx->arbSamplerObject->glBindSampler (theUnit, mySamplerID);
134   }
135 }
136
137 // =======================================================================
138 // function : Unbind
139 // purpose  : Unbinds sampler object from the given texture unit
140 // =======================================================================
141 void OpenGl_Sampler::Unbind (const Handle(OpenGl_Context)& theCtx,
142                              const Graphic3d_TextureUnit   theUnit)
143 {
144   if (isValidSampler())
145   {
146     theCtx->arbSamplerObject->glBindSampler (theUnit, NO_SAMPLER);
147   }
148 }
149
150 // =======================================================================
151 // function : setParameter
152 // purpose  :
153 // =======================================================================
154 void OpenGl_Sampler::setParameter (const Handle(OpenGl_Context)& theCtx,
155                                    OpenGl_Sampler*  theSampler,
156                                    unsigned int     theTarget,
157                                    unsigned int     theParam,
158                                    Standard_Integer theValue)
159 {
160   if (theSampler != NULL && theSampler->isValidSampler())
161   {
162     theCtx->arbSamplerObject->glSamplerParameteri (theSampler->mySamplerID, theParam, theValue);
163   }
164   else
165   {
166     theCtx->core11fwd->glTexParameteri (theTarget, theParam, theValue);
167   }
168 }
169
170 // =======================================================================
171 // function : SetParameters
172 // purpose  :
173 // =======================================================================
174 void OpenGl_Sampler::SetParameters (const Handle(Graphic3d_TextureParams)& theParams)
175 {
176   if (myParams != theParams)
177   {
178     myParams = theParams;
179     mySamplerRevision = myParams->SamplerRevision() - 1;
180   }
181 }
182
183 // =======================================================================
184 // function : applySamplerParams
185 // purpose  :
186 // =======================================================================
187 void OpenGl_Sampler::applySamplerParams (const Handle(OpenGl_Context)& theCtx,
188                                          const Handle(Graphic3d_TextureParams)& theParams,
189                                          OpenGl_Sampler* theSampler,
190                                          const unsigned int theTarget,
191                                          const Standard_Integer theMaxMipLevels)
192 {
193   if (theSampler != NULL && theSampler->Parameters() == theParams)
194   {
195     theSampler->mySamplerRevision = theParams->SamplerRevision();
196   }
197
198   // setup texture filtering
199   const GLenum aFilter = (theParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
200   GLenum aFilterMin = aFilter;
201   if (theMaxMipLevels > 0)
202   {
203     aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
204     if (theParams->Filter() == Graphic3d_TOTF_BILINEAR)
205     {
206       aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
207     }
208     else if (theParams->Filter() == Graphic3d_TOTF_TRILINEAR)
209     {
210       aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
211     }
212   }
213
214   setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MIN_FILTER, aFilterMin);
215   setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAG_FILTER, aFilter);
216
217   // setup texture wrapping
218   const GLenum aWrapMode = theParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
219   setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_S, aWrapMode);
220   if (theTarget == GL_TEXTURE_1D)
221   {
222     return;
223   }
224
225   setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_T, aWrapMode);
226   if (theTarget == GL_TEXTURE_3D
227    || theTarget == GL_TEXTURE_CUBE_MAP)
228   {
229     if (theCtx->HasTextureBaseLevel())
230     {
231       setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_R, aWrapMode);
232     }
233     return;
234   }
235
236   if (theCtx->extAnis)
237   {
238     // setup degree of anisotropy filter
239     const GLint aMaxDegree = theCtx->MaxDegreeOfAnisotropy();
240     GLint aDegree;
241     switch (theParams->AnisoFilter())
242     {
243       case Graphic3d_LOTA_QUALITY:
244       {
245         aDegree = aMaxDegree;
246         break;
247       }
248       case Graphic3d_LOTA_MIDDLE:
249       {
250         aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
251         break;
252       }
253       case Graphic3d_LOTA_FAST:
254       {
255         aDegree = 2;
256         break;
257       }
258       case Graphic3d_LOTA_OFF:
259       default:
260       {
261         aDegree = 1;
262         break;
263       }
264     }
265
266     setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
267   }
268
269   if (theCtx->HasTextureBaseLevel()
270    && (theSampler == NULL || !theSampler->isValidSampler()))
271   {
272     const Standard_Integer aMaxLevel = Min (theMaxMipLevels, theParams->MaxLevel());
273     setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_BASE_LEVEL, theParams->BaseLevel());
274     setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAX_LEVEL,  aMaxLevel);
275   }
276 }
277
278 // =======================================================================
279 // function : applyGlobalTextureParams
280 // purpose  :
281 // =======================================================================
282 void OpenGl_Sampler::applyGlobalTextureParams (const Handle(OpenGl_Context)& theCtx,
283                                                const OpenGl_Texture& theTexture,
284                                                const Handle(Graphic3d_TextureParams)& theParams)
285 {
286   if (theCtx->core11ffp == NULL
287    || theParams->TextureUnit() >= theCtx->MaxTextureUnitsFFP())
288   {
289     return;
290   }
291
292   GLint anEnvMode = GL_MODULATE; // lighting mode
293   if (!theParams->IsModulate())
294   {
295     anEnvMode = GL_DECAL;
296     if (theTexture.GetFormat() == GL_ALPHA
297      || theTexture.GetFormat() == GL_LUMINANCE)
298     {
299       anEnvMode = GL_REPLACE;
300     }
301   }
302
303   // setup generation of texture coordinates
304   switch (theParams->GenMode())
305   {
306     case Graphic3d_TOTM_OBJECT:
307     {
308       theCtx->core11ffp->glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
309       theCtx->core11ffp->glTexGenfv (GL_S, GL_OBJECT_PLANE,     theParams->GenPlaneS().GetData());
310       if (theTexture.GetTarget() != GL_TEXTURE_1D)
311       {
312         theCtx->core11ffp->glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
313         theCtx->core11ffp->glTexGenfv (GL_T, GL_OBJECT_PLANE,     theParams->GenPlaneT().GetData());
314       }
315       break;
316     }
317     case Graphic3d_TOTM_SPHERE:
318     {
319       theCtx->core11ffp->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
320       if (theTexture.GetTarget() != GL_TEXTURE_1D)
321       {
322         theCtx->core11ffp->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
323       }
324       break;
325     }
326     case Graphic3d_TOTM_EYE:
327     {
328       theCtx->WorldViewState.Push();
329       theCtx->WorldViewState.SetIdentity();
330       theCtx->ApplyWorldViewMatrix();
331
332       theCtx->core11ffp->glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
333       theCtx->core11ffp->glTexGenfv (GL_S, GL_EYE_PLANE,        theParams->GenPlaneS().GetData());
334       if (theTexture.GetTarget() != GL_TEXTURE_1D)
335       {
336         theCtx->core11ffp->glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
337         theCtx->core11ffp->glTexGenfv (GL_T, GL_EYE_PLANE,        theParams->GenPlaneT().GetData());
338       }
339
340       theCtx->WorldViewState.Pop();
341       break;
342     }
343     case Graphic3d_TOTM_SPRITE:
344     {
345       if (theCtx->core20fwd != NULL)
346       {
347         theCtx->core11fwd->glEnable (GL_POINT_SPRITE);
348         theCtx->core11ffp->glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
349         anEnvMode = GL_REPLACE;
350       }
351       break;
352     }
353     case Graphic3d_TOTM_MANUAL:
354     default: break;
355   }
356
357   // setup lighting
358   theCtx->core11ffp->glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
359
360   switch (theTexture.GetTarget())
361   {
362     case GL_TEXTURE_1D:
363     {
364       if (theParams->GenMode() != Graphic3d_TOTM_MANUAL)
365       {
366         theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S);
367       }
368       theCtx->core11fwd->glEnable (GL_TEXTURE_1D);
369       break;
370     }
371     case GL_TEXTURE_2D:
372     {
373       if (theParams->GenMode() != Graphic3d_TOTM_MANUAL)
374       {
375         theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S);
376         theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_T);
377       }
378       theCtx->core11fwd->glEnable (GL_TEXTURE_2D);
379       break;
380     }
381     case GL_TEXTURE_3D:
382     default:
383     {
384       break;
385     }
386   }
387 }
388
389 // =======================================================================
390 // function : resetGlobalTextureParams
391 // purpose  :
392 // =======================================================================
393 void OpenGl_Sampler::resetGlobalTextureParams (const Handle(OpenGl_Context)& theCtx,
394                                                const OpenGl_Texture& theTexture,
395                                                const Handle(Graphic3d_TextureParams)& theParams)
396 {
397   if (theCtx->core11ffp == NULL)
398   {
399     return;
400   }
401
402   // reset texture matrix because some code may expect it is identity
403   GLint aMatrixMode = GL_TEXTURE;
404   theCtx->core11fwd->glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
405   theCtx->core11ffp->glMatrixMode (GL_TEXTURE);
406   theCtx->core11ffp->glLoadIdentity();
407   theCtx->core11ffp->glMatrixMode (aMatrixMode);
408
409   switch (theTexture.GetTarget())
410   {
411     case GL_TEXTURE_1D:
412     {
413       if (theParams->GenMode() != GL_NONE)
414       {
415         theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S);
416       }
417       theCtx->core11fwd->glDisable (GL_TEXTURE_1D);
418       break;
419     }
420     case GL_TEXTURE_2D:
421     {
422       if (theParams->GenMode() != GL_NONE)
423       {
424         theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S);
425         theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_T);
426         if (theParams->GenMode() == Graphic3d_TOTM_SPRITE
427          && theCtx->core20fwd != NULL)
428         {
429           theCtx->core11fwd->glDisable (GL_POINT_SPRITE);
430         }
431       }
432       theCtx->core11fwd->glDisable (GL_TEXTURE_2D);
433       break;
434     }
435     case GL_TEXTURE_3D:
436     default:
437     {
438       break;
439     }
440   }
441 }