0031580: Visualization, TKOpenGl - cubemap initialization error on OpenGL ES 2.0
[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 {
faff3767 108 applySamplerParams (theCtx, myParams, this, theTexture.GetTarget(), theTexture.MaxMipmapLevel());
cc8cbabe 109 return Standard_True;
110 }
111 Release (theCtx.get());
112 }
113
114 if (!Create (theCtx))
115 {
116 return Standard_False;
25ef750e 117 }
118
faff3767 119 applySamplerParams (theCtx, myParams, this, theTexture.GetTarget(), theTexture.MaxMipmapLevel());
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,
faff3767 190 const Standard_Integer theMaxMipLevels)
cc8cbabe 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;
faff3767 200 if (theMaxMipLevels > 0)
cc8cbabe 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);
67312b79 226 if (theTarget == GL_TEXTURE_3D
227 || theTarget == GL_TEXTURE_CUBE_MAP)
cc8cbabe 228 {
e4e3254a 229 if (theCtx->HasTextureBaseLevel())
230 {
231 setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_R, aWrapMode);
232 }
cc8cbabe 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 }
67312b79 268
cd43c08f 269 if (theCtx->HasTextureBaseLevel()
270 && (theSampler == NULL || !theSampler->isValidSampler()))
67312b79 271 {
faff3767 272 const Standard_Integer aMaxLevel = Min (theMaxMipLevels, theParams->MaxLevel());
67312b79 273 setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_BASE_LEVEL, theParams->BaseLevel());
faff3767 274 setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAX_LEVEL, aMaxLevel);
67312b79 275 }
cc8cbabe 276}
277
278// =======================================================================
279// function : applyGlobalTextureParams
280// purpose :
281// =======================================================================
282void OpenGl_Sampler::applyGlobalTextureParams (const Handle(OpenGl_Context)& theCtx,
283 const OpenGl_Texture& theTexture,
284 const Handle(Graphic3d_TextureParams)& theParams)
285{
286#if defined(GL_ES_VERSION_2_0)
287 (void )theCtx;
288 (void )theTexture;
289 (void )theParams;
290#else
5c225e8e 291 if (theCtx->core11 == NULL
292 || theParams->TextureUnit() >= theCtx->MaxTextureUnitsFFP())
cc8cbabe 293 {
294 return;
295 }
296
297 GLint anEnvMode = GL_MODULATE; // lighting mode
298 if (!theParams->IsModulate())
299 {
300 anEnvMode = GL_DECAL;
301 if (theTexture.GetFormat() == GL_ALPHA
302 || theTexture.GetFormat() == GL_LUMINANCE)
303 {
304 anEnvMode = GL_REPLACE;
305 }
306 }
307
308 // setup generation of texture coordinates
309 switch (theParams->GenMode())
310 {
311 case Graphic3d_TOTM_OBJECT:
312 {
313 theCtx->core11->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
314 theCtx->core11->glTexGenfv (GL_S, GL_OBJECT_PLANE, theParams->GenPlaneS().GetData());
315 if (theTexture.GetTarget() != GL_TEXTURE_1D)
316 {
317 theCtx->core11->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
318 theCtx->core11->glTexGenfv (GL_T, GL_OBJECT_PLANE, theParams->GenPlaneT().GetData());
319 }
320 break;
321 }
322 case Graphic3d_TOTM_SPHERE:
323 {
324 theCtx->core11->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
325 if (theTexture.GetTarget() != GL_TEXTURE_1D)
326 {
327 theCtx->core11->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
328 }
329 break;
330 }
331 case Graphic3d_TOTM_EYE:
332 {
333 theCtx->WorldViewState.Push();
334 theCtx->WorldViewState.SetIdentity();
335 theCtx->ApplyWorldViewMatrix();
336
337 theCtx->core11->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
338 theCtx->core11->glTexGenfv (GL_S, GL_EYE_PLANE, theParams->GenPlaneS().GetData());
339 if (theTexture.GetTarget() != GL_TEXTURE_1D)
340 {
341 theCtx->core11->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
342 theCtx->core11->glTexGenfv (GL_T, GL_EYE_PLANE, theParams->GenPlaneT().GetData());
343 }
344
345 theCtx->WorldViewState.Pop();
346 break;
347 }
348 case Graphic3d_TOTM_SPRITE:
349 {
350 if (theCtx->core20fwd != NULL)
351 {
352 theCtx->core11fwd->glEnable (GL_POINT_SPRITE);
353 glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
354 anEnvMode = GL_REPLACE;
355 }
356 break;
357 }
358 case Graphic3d_TOTM_MANUAL:
359 default: break;
360 }
361
362 // setup lighting
363 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
364
365 switch (theTexture.GetTarget())
366 {
367 case GL_TEXTURE_1D:
368 {
369 if (theParams->GenMode() != Graphic3d_TOTM_MANUAL)
370 {
371 theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S);
372 }
373 theCtx->core11fwd->glEnable (GL_TEXTURE_1D);
374 break;
375 }
376 case GL_TEXTURE_2D:
377 {
378 if (theParams->GenMode() != Graphic3d_TOTM_MANUAL)
379 {
380 theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S);
381 theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_T);
382 }
383 theCtx->core11fwd->glEnable (GL_TEXTURE_2D);
384 break;
385 }
386 default: break;
387 }
388#endif
389}
390
391// =======================================================================
392// function : resetGlobalTextureParams
393// purpose :
394// =======================================================================
395void OpenGl_Sampler::resetGlobalTextureParams (const Handle(OpenGl_Context)& theCtx,
396 const OpenGl_Texture& theTexture,
397 const Handle(Graphic3d_TextureParams)& theParams)
398{
399#if defined(GL_ES_VERSION_2_0)
400 (void )theCtx;
401 (void )theTexture;
402 (void )theParams;
403#else
404 if (theCtx->core11 == NULL)
405 {
406 return;
407 }
408
409 // reset texture matrix because some code may expect it is identity
410 GLint aMatrixMode = GL_TEXTURE;
411 theCtx->core11fwd->glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
412 theCtx->core11->glMatrixMode (GL_TEXTURE);
413 theCtx->core11->glLoadIdentity();
414 theCtx->core11->glMatrixMode (aMatrixMode);
415
416 switch (theTexture.GetTarget())
417 {
418 case GL_TEXTURE_1D:
419 {
420 if (theParams->GenMode() != GL_NONE)
421 {
422 theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S);
423 }
424 theCtx->core11fwd->glDisable (GL_TEXTURE_1D);
425 break;
426 }
427 case GL_TEXTURE_2D:
428 {
429 if (theParams->GenMode() != GL_NONE)
430 {
431 theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S);
432 theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_T);
97e0059b 433 if (theParams->GenMode() == Graphic3d_TOTM_SPRITE
434 && theCtx->core20fwd != NULL)
cc8cbabe 435 {
436 theCtx->core11fwd->glDisable (GL_POINT_SPRITE);
437 }
438 }
439 theCtx->core11fwd->glDisable (GL_TEXTURE_2D);
440 break;
441 }
442 default: break;
443 }
444#endif
25ef750e 445}