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 |
22 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Sampler,OpenGl_Resource) |
23 | |
25ef750e |
24 | // ======================================================================= |
25 | // function : OpenGl_Sampler |
26 | // purpose : |
27 | // ======================================================================= |
cc8cbabe |
28 | OpenGl_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 | // ======================================================================= |
44 | OpenGl_Sampler::~OpenGl_Sampler() |
45 | { |
46 | Release (NULL); |
47 | } |
48 | |
49 | // ======================================================================= |
50 | // function : Release |
51 | // purpose : |
52 | // ======================================================================= |
cc8cbabe |
53 | void 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 |
78 | Standard_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 | // ======================================================================= |
97 | Standard_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 |
127 | void 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 |
140 | void 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 |
153 | void 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 | // ======================================================================= |
173 | void 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 | // ======================================================================= |
186 | void 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); |
67312b79 |
226 | if (theTarget == GL_TEXTURE_3D |
227 | || theTarget == GL_TEXTURE_CUBE_MAP) |
cc8cbabe |
228 | { |
229 | setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_R, aWrapMode); |
230 | return; |
231 | } |
232 | |
233 | if (theCtx->extAnis) |
234 | { |
235 | // setup degree of anisotropy filter |
236 | const GLint aMaxDegree = theCtx->MaxDegreeOfAnisotropy(); |
237 | GLint aDegree; |
238 | switch (theParams->AnisoFilter()) |
239 | { |
240 | case Graphic3d_LOTA_QUALITY: |
241 | { |
242 | aDegree = aMaxDegree; |
243 | break; |
244 | } |
245 | case Graphic3d_LOTA_MIDDLE: |
246 | { |
247 | aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2); |
248 | break; |
249 | } |
250 | case Graphic3d_LOTA_FAST: |
251 | { |
252 | aDegree = 2; |
253 | break; |
254 | } |
255 | case Graphic3d_LOTA_OFF: |
256 | default: |
257 | { |
258 | aDegree = 1; |
259 | break; |
260 | } |
261 | } |
262 | |
263 | setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree); |
264 | } |
67312b79 |
265 | |
266 | if (theCtx->IsGlGreaterEqual(1, 2) && |
267 | (theSampler == NULL || !theSampler->isValidSampler())) |
268 | { |
269 | setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_BASE_LEVEL, theParams->BaseLevel()); |
270 | setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAX_LEVEL, theParams->MaxLevel()); |
271 | } |
cc8cbabe |
272 | } |
273 | |
274 | // ======================================================================= |
275 | // function : applyGlobalTextureParams |
276 | // purpose : |
277 | // ======================================================================= |
278 | void OpenGl_Sampler::applyGlobalTextureParams (const Handle(OpenGl_Context)& theCtx, |
279 | const OpenGl_Texture& theTexture, |
280 | const Handle(Graphic3d_TextureParams)& theParams) |
281 | { |
282 | #if defined(GL_ES_VERSION_2_0) |
283 | (void )theCtx; |
284 | (void )theTexture; |
285 | (void )theParams; |
286 | #else |
5c225e8e |
287 | if (theCtx->core11 == NULL |
288 | || theParams->TextureUnit() >= theCtx->MaxTextureUnitsFFP()) |
cc8cbabe |
289 | { |
290 | return; |
291 | } |
292 | |
293 | GLint anEnvMode = GL_MODULATE; // lighting mode |
294 | if (!theParams->IsModulate()) |
295 | { |
296 | anEnvMode = GL_DECAL; |
297 | if (theTexture.GetFormat() == GL_ALPHA |
298 | || theTexture.GetFormat() == GL_LUMINANCE) |
299 | { |
300 | anEnvMode = GL_REPLACE; |
301 | } |
302 | } |
303 | |
304 | // setup generation of texture coordinates |
305 | switch (theParams->GenMode()) |
306 | { |
307 | case Graphic3d_TOTM_OBJECT: |
308 | { |
309 | theCtx->core11->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); |
310 | theCtx->core11->glTexGenfv (GL_S, GL_OBJECT_PLANE, theParams->GenPlaneS().GetData()); |
311 | if (theTexture.GetTarget() != GL_TEXTURE_1D) |
312 | { |
313 | theCtx->core11->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); |
314 | theCtx->core11->glTexGenfv (GL_T, GL_OBJECT_PLANE, theParams->GenPlaneT().GetData()); |
315 | } |
316 | break; |
317 | } |
318 | case Graphic3d_TOTM_SPHERE: |
319 | { |
320 | theCtx->core11->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); |
321 | if (theTexture.GetTarget() != GL_TEXTURE_1D) |
322 | { |
323 | theCtx->core11->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); |
324 | } |
325 | break; |
326 | } |
327 | case Graphic3d_TOTM_EYE: |
328 | { |
329 | theCtx->WorldViewState.Push(); |
330 | theCtx->WorldViewState.SetIdentity(); |
331 | theCtx->ApplyWorldViewMatrix(); |
332 | |
333 | theCtx->core11->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
334 | theCtx->core11->glTexGenfv (GL_S, GL_EYE_PLANE, theParams->GenPlaneS().GetData()); |
335 | if (theTexture.GetTarget() != GL_TEXTURE_1D) |
336 | { |
337 | theCtx->core11->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
338 | theCtx->core11->glTexGenfv (GL_T, GL_EYE_PLANE, theParams->GenPlaneT().GetData()); |
339 | } |
340 | |
341 | theCtx->WorldViewState.Pop(); |
342 | break; |
343 | } |
344 | case Graphic3d_TOTM_SPRITE: |
345 | { |
346 | if (theCtx->core20fwd != NULL) |
347 | { |
348 | theCtx->core11fwd->glEnable (GL_POINT_SPRITE); |
349 | glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); |
350 | anEnvMode = GL_REPLACE; |
351 | } |
352 | break; |
353 | } |
354 | case Graphic3d_TOTM_MANUAL: |
355 | default: break; |
356 | } |
357 | |
358 | // setup lighting |
359 | glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode); |
360 | |
361 | switch (theTexture.GetTarget()) |
362 | { |
363 | case GL_TEXTURE_1D: |
364 | { |
365 | if (theParams->GenMode() != Graphic3d_TOTM_MANUAL) |
366 | { |
367 | theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S); |
368 | } |
369 | theCtx->core11fwd->glEnable (GL_TEXTURE_1D); |
370 | break; |
371 | } |
372 | case GL_TEXTURE_2D: |
373 | { |
374 | if (theParams->GenMode() != Graphic3d_TOTM_MANUAL) |
375 | { |
376 | theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S); |
377 | theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_T); |
378 | } |
379 | theCtx->core11fwd->glEnable (GL_TEXTURE_2D); |
380 | break; |
381 | } |
382 | default: break; |
383 | } |
384 | #endif |
385 | } |
386 | |
387 | // ======================================================================= |
388 | // function : resetGlobalTextureParams |
389 | // purpose : |
390 | // ======================================================================= |
391 | void OpenGl_Sampler::resetGlobalTextureParams (const Handle(OpenGl_Context)& theCtx, |
392 | const OpenGl_Texture& theTexture, |
393 | const Handle(Graphic3d_TextureParams)& theParams) |
394 | { |
395 | #if defined(GL_ES_VERSION_2_0) |
396 | (void )theCtx; |
397 | (void )theTexture; |
398 | (void )theParams; |
399 | #else |
400 | if (theCtx->core11 == NULL) |
401 | { |
402 | return; |
403 | } |
404 | |
405 | // reset texture matrix because some code may expect it is identity |
406 | GLint aMatrixMode = GL_TEXTURE; |
407 | theCtx->core11fwd->glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); |
408 | theCtx->core11->glMatrixMode (GL_TEXTURE); |
409 | theCtx->core11->glLoadIdentity(); |
410 | theCtx->core11->glMatrixMode (aMatrixMode); |
411 | |
412 | switch (theTexture.GetTarget()) |
413 | { |
414 | case GL_TEXTURE_1D: |
415 | { |
416 | if (theParams->GenMode() != GL_NONE) |
417 | { |
418 | theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S); |
419 | } |
420 | theCtx->core11fwd->glDisable (GL_TEXTURE_1D); |
421 | break; |
422 | } |
423 | case GL_TEXTURE_2D: |
424 | { |
425 | if (theParams->GenMode() != GL_NONE) |
426 | { |
427 | theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S); |
428 | theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_T); |
97e0059b |
429 | if (theParams->GenMode() == Graphic3d_TOTM_SPRITE |
430 | && theCtx->core20fwd != NULL) |
cc8cbabe |
431 | { |
432 | theCtx->core11fwd->glDisable (GL_POINT_SPRITE); |
433 | } |
434 | } |
435 | theCtx->core11fwd->glDisable (GL_TEXTURE_2D); |
436 | break; |
437 | } |
438 | default: break; |
439 | } |
440 | #endif |
25ef750e |
441 | } |