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