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); |
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 | // ======================================================================= |
270 | void 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 |
5c225e8e |
279 | if (theCtx->core11 == NULL |
280 | || theParams->TextureUnit() >= theCtx->MaxTextureUnitsFFP()) |
cc8cbabe |
281 | { |
282 | return; |
283 | } |
284 | |
285 | GLint anEnvMode = GL_MODULATE; // lighting mode |
286 | if (!theParams->IsModulate()) |
287 | { |
288 | anEnvMode = GL_DECAL; |
289 | if (theTexture.GetFormat() == GL_ALPHA |
290 | || theTexture.GetFormat() == GL_LUMINANCE) |
291 | { |
292 | anEnvMode = GL_REPLACE; |
293 | } |
294 | } |
295 | |
296 | // setup generation of texture coordinates |
297 | switch (theParams->GenMode()) |
298 | { |
299 | case Graphic3d_TOTM_OBJECT: |
300 | { |
301 | theCtx->core11->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); |
302 | theCtx->core11->glTexGenfv (GL_S, GL_OBJECT_PLANE, theParams->GenPlaneS().GetData()); |
303 | if (theTexture.GetTarget() != GL_TEXTURE_1D) |
304 | { |
305 | theCtx->core11->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); |
306 | theCtx->core11->glTexGenfv (GL_T, GL_OBJECT_PLANE, theParams->GenPlaneT().GetData()); |
307 | } |
308 | break; |
309 | } |
310 | case Graphic3d_TOTM_SPHERE: |
311 | { |
312 | theCtx->core11->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); |
313 | if (theTexture.GetTarget() != GL_TEXTURE_1D) |
314 | { |
315 | theCtx->core11->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); |
316 | } |
317 | break; |
318 | } |
319 | case Graphic3d_TOTM_EYE: |
320 | { |
321 | theCtx->WorldViewState.Push(); |
322 | theCtx->WorldViewState.SetIdentity(); |
323 | theCtx->ApplyWorldViewMatrix(); |
324 | |
325 | theCtx->core11->glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
326 | theCtx->core11->glTexGenfv (GL_S, GL_EYE_PLANE, theParams->GenPlaneS().GetData()); |
327 | if (theTexture.GetTarget() != GL_TEXTURE_1D) |
328 | { |
329 | theCtx->core11->glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); |
330 | theCtx->core11->glTexGenfv (GL_T, GL_EYE_PLANE, theParams->GenPlaneT().GetData()); |
331 | } |
332 | |
333 | theCtx->WorldViewState.Pop(); |
334 | break; |
335 | } |
336 | case Graphic3d_TOTM_SPRITE: |
337 | { |
338 | if (theCtx->core20fwd != NULL) |
339 | { |
340 | theCtx->core11fwd->glEnable (GL_POINT_SPRITE); |
341 | glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); |
342 | anEnvMode = GL_REPLACE; |
343 | } |
344 | break; |
345 | } |
346 | case Graphic3d_TOTM_MANUAL: |
347 | default: break; |
348 | } |
349 | |
350 | // setup lighting |
351 | glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode); |
352 | |
353 | switch (theTexture.GetTarget()) |
354 | { |
355 | case GL_TEXTURE_1D: |
356 | { |
357 | if (theParams->GenMode() != Graphic3d_TOTM_MANUAL) |
358 | { |
359 | theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S); |
360 | } |
361 | theCtx->core11fwd->glEnable (GL_TEXTURE_1D); |
362 | break; |
363 | } |
364 | case GL_TEXTURE_2D: |
365 | { |
366 | if (theParams->GenMode() != Graphic3d_TOTM_MANUAL) |
367 | { |
368 | theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_S); |
369 | theCtx->core11fwd->glEnable (GL_TEXTURE_GEN_T); |
370 | } |
371 | theCtx->core11fwd->glEnable (GL_TEXTURE_2D); |
372 | break; |
373 | } |
374 | default: break; |
375 | } |
376 | #endif |
377 | } |
378 | |
379 | // ======================================================================= |
380 | // function : resetGlobalTextureParams |
381 | // purpose : |
382 | // ======================================================================= |
383 | void OpenGl_Sampler::resetGlobalTextureParams (const Handle(OpenGl_Context)& theCtx, |
384 | const OpenGl_Texture& theTexture, |
385 | const Handle(Graphic3d_TextureParams)& theParams) |
386 | { |
387 | #if defined(GL_ES_VERSION_2_0) |
388 | (void )theCtx; |
389 | (void )theTexture; |
390 | (void )theParams; |
391 | #else |
392 | if (theCtx->core11 == NULL) |
393 | { |
394 | return; |
395 | } |
396 | |
397 | // reset texture matrix because some code may expect it is identity |
398 | GLint aMatrixMode = GL_TEXTURE; |
399 | theCtx->core11fwd->glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); |
400 | theCtx->core11->glMatrixMode (GL_TEXTURE); |
401 | theCtx->core11->glLoadIdentity(); |
402 | theCtx->core11->glMatrixMode (aMatrixMode); |
403 | |
404 | switch (theTexture.GetTarget()) |
405 | { |
406 | case GL_TEXTURE_1D: |
407 | { |
408 | if (theParams->GenMode() != GL_NONE) |
409 | { |
410 | theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S); |
411 | } |
412 | theCtx->core11fwd->glDisable (GL_TEXTURE_1D); |
413 | break; |
414 | } |
415 | case GL_TEXTURE_2D: |
416 | { |
417 | if (theParams->GenMode() != GL_NONE) |
418 | { |
419 | theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_S); |
420 | theCtx->core11fwd->glDisable (GL_TEXTURE_GEN_T); |
97e0059b |
421 | if (theParams->GenMode() == Graphic3d_TOTM_SPRITE |
422 | && theCtx->core20fwd != NULL) |
cc8cbabe |
423 | { |
424 | theCtx->core11fwd->glDisable (GL_POINT_SPRITE); |
425 | } |
426 | } |
427 | theCtx->core11fwd->glDisable (GL_TEXTURE_2D); |
428 | break; |
429 | } |
430 | default: break; |
431 | } |
432 | #endif |
25ef750e |
433 | } |