1 // Created on: 2014-10-08
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_Sampler.hxx>
18 #include <OpenGl_ArbSamplerObject.hxx>
19 #include <OpenGl_Context.hxx>
20 #include <OpenGl_Texture.hxx>
21 #include <Standard_Assert.hxx>
23 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Sampler,OpenGl_Resource)
25 // =======================================================================
26 // function : OpenGl_Sampler
28 // =======================================================================
29 OpenGl_Sampler::OpenGl_Sampler (const Handle(Graphic3d_TextureParams)& theParams)
30 : myParams (theParams),
31 mySamplerRevision (0),
32 mySamplerID (NO_SAMPLER),
35 if (myParams.IsNull())
37 myParams = new Graphic3d_TextureParams();
41 // =======================================================================
42 // function : ~OpenGl_Sampler
44 // =======================================================================
45 OpenGl_Sampler::~OpenGl_Sampler()
50 // =======================================================================
53 // =======================================================================
54 void OpenGl_Sampler::Release (OpenGl_Context* theCtx)
56 myIsImmutable = false;
57 mySamplerRevision = myParams->SamplerRevision() - 1;
58 if (!isValidSampler())
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...",);
67 if (theCtx->IsValid())
69 theCtx->arbSamplerObject->glDeleteSamplers (1, &mySamplerID);
72 mySamplerID = NO_SAMPLER;
75 // =======================================================================
78 // =======================================================================
79 Standard_Boolean OpenGl_Sampler::Create (const Handle(OpenGl_Context)& theCtx)
85 else if (theCtx->arbSamplerObject == NULL)
87 return Standard_False;
90 theCtx->arbSamplerObject->glGenSamplers (1, &mySamplerID);
94 // =======================================================================
97 // =======================================================================
98 Standard_Boolean OpenGl_Sampler::Init (const Handle(OpenGl_Context)& theCtx,
99 const OpenGl_Texture& theTexture)
101 if (isValidSampler())
103 if (!ToUpdateParameters())
105 return Standard_True;
107 else if (!myIsImmutable)
109 applySamplerParams (theCtx, myParams, this, theTexture.GetTarget(), theTexture.MaxMipmapLevel());
110 return Standard_True;
112 Release (theCtx.get());
115 if (!Create (theCtx))
117 return Standard_False;
120 applySamplerParams (theCtx, myParams, this, theTexture.GetTarget(), theTexture.MaxMipmapLevel());
121 return Standard_True;
124 // =======================================================================
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)
131 if (isValidSampler())
133 theCtx->arbSamplerObject->glBindSampler (theUnit, mySamplerID);
137 // =======================================================================
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)
144 if (isValidSampler())
146 theCtx->arbSamplerObject->glBindSampler (theUnit, NO_SAMPLER);
150 // =======================================================================
151 // function : setParameter
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)
160 if (theSampler != NULL && theSampler->isValidSampler())
162 theCtx->arbSamplerObject->glSamplerParameteri (theSampler->mySamplerID, theParam, theValue);
166 theCtx->core11fwd->glTexParameteri (theTarget, theParam, theValue);
170 // =======================================================================
171 // function : SetParameters
173 // =======================================================================
174 void OpenGl_Sampler::SetParameters (const Handle(Graphic3d_TextureParams)& theParams)
176 if (myParams != theParams)
178 myParams = theParams;
179 mySamplerRevision = myParams->SamplerRevision() - 1;
183 // =======================================================================
184 // function : applySamplerParams
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)
193 if (theSampler != NULL && theSampler->Parameters() == theParams)
195 theSampler->mySamplerRevision = theParams->SamplerRevision();
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)
203 aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
204 if (theParams->Filter() == Graphic3d_TOTF_BILINEAR)
206 aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
208 else if (theParams->Filter() == Graphic3d_TOTF_TRILINEAR)
210 aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
214 setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MIN_FILTER, aFilterMin);
215 setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAG_FILTER, aFilter);
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)
225 setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_T, aWrapMode);
226 if (theTarget == GL_TEXTURE_3D
227 || theTarget == GL_TEXTURE_CUBE_MAP)
229 if (theCtx->HasTextureBaseLevel())
231 setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_R, aWrapMode);
238 // setup degree of anisotropy filter
239 const GLint aMaxDegree = theCtx->MaxDegreeOfAnisotropy();
241 switch (theParams->AnisoFilter())
243 case Graphic3d_LOTA_QUALITY:
245 aDegree = aMaxDegree;
248 case Graphic3d_LOTA_MIDDLE:
250 aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
253 case Graphic3d_LOTA_FAST:
258 case Graphic3d_LOTA_OFF:
266 setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
269 if (theCtx->HasTextureBaseLevel()
270 && (theSampler == NULL || !theSampler->isValidSampler()))
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);
278 // =======================================================================
279 // function : applyGlobalTextureParams
281 // =======================================================================
282 void OpenGl_Sampler::applyGlobalTextureParams (const Handle(OpenGl_Context)& theCtx,
283 const OpenGl_Texture& theTexture,
284 const Handle(Graphic3d_TextureParams)& theParams)
286 if (theCtx->core11ffp == NULL
287 || theParams->TextureUnit() >= theCtx->MaxTextureUnitsFFP())
292 GLint anEnvMode = GL_MODULATE; // lighting mode
293 if (!theParams->IsModulate())
295 anEnvMode = GL_DECAL;
296 if (theTexture.GetFormat() == GL_ALPHA
297 || theTexture.GetFormat() == GL_LUMINANCE)
299 anEnvMode = GL_REPLACE;
303 // setup generation of texture coordinates
304 switch (theParams->GenMode())
306 case Graphic3d_TOTM_OBJECT:
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)
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());
317 case Graphic3d_TOTM_SPHERE:
319 theCtx->core11ffp->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
320 if (theTexture.GetTarget() != GL_TEXTURE_1D)
322 theCtx->core11ffp->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
326 case Graphic3d_TOTM_EYE:
328 theCtx->WorldViewState.Push();
329 theCtx->WorldViewState.SetIdentity();
330 theCtx->ApplyWorldViewMatrix();
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)
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());
340 theCtx->WorldViewState.Pop();
343 case Graphic3d_TOTM_SPRITE:
345 if (theCtx->core20fwd != NULL)
347 theCtx->core11fwd->glEnable (GL_POINT_SPRITE);
348 theCtx->core11ffp->glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
349 anEnvMode = GL_REPLACE;
353 case Graphic3d_TOTM_MANUAL:
358 theCtx->core11ffp->glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
360 switch (theTexture.GetTarget())
364 if (theParams->GenMode() != Graphic3d_TOTM_MANUAL)
366 theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S);
368 theCtx->core11fwd->glEnable (GL_TEXTURE_1D);
373 if (theParams->GenMode() != Graphic3d_TOTM_MANUAL)
375 theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S);
376 theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_T);
378 theCtx->core11fwd->glEnable (GL_TEXTURE_2D);
389 // =======================================================================
390 // function : resetGlobalTextureParams
392 // =======================================================================
393 void OpenGl_Sampler::resetGlobalTextureParams (const Handle(OpenGl_Context)& theCtx,
394 const OpenGl_Texture& theTexture,
395 const Handle(Graphic3d_TextureParams)& theParams)
397 if (theCtx->core11ffp == NULL)
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);
409 switch (theTexture.GetTarget())
413 if (theParams->GenMode() != GL_NONE)
415 theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S);
417 theCtx->core11fwd->glDisable (GL_TEXTURE_1D);
422 if (theParams->GenMode() != GL_NONE)
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)
429 theCtx->core11fwd->glDisable (GL_POINT_SPRITE);
432 theCtx->core11fwd->glDisable (GL_TEXTURE_2D);