b311480e |
1 | // Created by: Kirill GAVRILOV |
973c2be1 |
2 | // Copyright (c) 2011-2014 OPEN CASCADE SAS |
b311480e |
3 | // |
973c2be1 |
4 | // This file is part of Open CASCADE Technology software library. |
b311480e |
5 | // |
d5f74e42 |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
11 | // |
973c2be1 |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
b311480e |
14 | |
7fd59977 |
15 | #include <OpenGl_FrameBuffer.hxx> |
01ca42b2 |
16 | #include <OpenGl_ArbFBO.hxx> |
7fd59977 |
17 | |
fd4a6963 |
18 | #include <Standard_Assert.hxx> |
a2e4f780 |
19 | #include <TCollection_ExtendedString.hxx> |
fd4a6963 |
20 | |
92efcf78 |
21 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameBuffer,OpenGl_Resource) |
22 | |
3c4b62a4 |
23 | namespace |
24 | { |
25 | |
26 | //! Determine data type from texture sized format. |
27 | static bool getDepthDataFormat (GLint theTextFormat, |
28 | GLenum& thePixelFormat, |
29 | GLenum& theDataType) |
30 | { |
31 | switch (theTextFormat) |
32 | { |
33 | case GL_DEPTH24_STENCIL8: |
34 | { |
35 | thePixelFormat = GL_DEPTH_STENCIL; |
36 | theDataType = GL_UNSIGNED_INT_24_8; |
37 | return true; |
38 | } |
39 | case GL_DEPTH32F_STENCIL8: |
40 | { |
41 | thePixelFormat = GL_DEPTH_STENCIL; |
42 | theDataType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV; |
43 | return true; |
44 | } |
45 | case GL_DEPTH_COMPONENT16: |
46 | { |
2e26cf76 |
47 | thePixelFormat = GL_DEPTH_COMPONENT; |
3c4b62a4 |
48 | theDataType = GL_UNSIGNED_SHORT; |
49 | return true; |
50 | } |
51 | case GL_DEPTH_COMPONENT24: |
52 | { |
2e26cf76 |
53 | thePixelFormat = GL_DEPTH_COMPONENT; |
3c4b62a4 |
54 | theDataType = GL_UNSIGNED_INT; |
55 | return true; |
56 | } |
57 | case GL_DEPTH_COMPONENT32F: |
58 | { |
2e26cf76 |
59 | thePixelFormat = GL_DEPTH_COMPONENT; |
3c4b62a4 |
60 | theDataType = GL_FLOAT; |
61 | return true; |
62 | } |
63 | } |
64 | return false; |
65 | } |
66 | |
a1073ae2 |
67 | //! Determine data type from texture sized format. |
68 | static bool getColorDataFormat (GLint theTextFormat, |
69 | GLenum& thePixelFormat, |
70 | GLenum& theDataType) |
71 | { |
72 | switch (theTextFormat) |
73 | { |
74 | case GL_RGBA32F: |
75 | { |
76 | thePixelFormat = GL_RGBA; |
77 | theDataType = GL_FLOAT; |
78 | return true; |
79 | } |
80 | case GL_R32F: |
81 | { |
82 | thePixelFormat = GL_RED; |
83 | theDataType = GL_FLOAT; |
84 | return true; |
85 | } |
86 | case GL_RGBA16F: |
87 | { |
88 | thePixelFormat = GL_RGBA; |
89 | theDataType = GL_HALF_FLOAT; |
90 | return true; |
91 | } |
92 | case GL_R16F: |
93 | { |
94 | thePixelFormat = GL_RED; |
95 | theDataType = GL_HALF_FLOAT; |
96 | return true; |
97 | } |
98 | case GL_RGBA8: |
58772a28 |
99 | case GL_RGBA: |
a1073ae2 |
100 | { |
101 | thePixelFormat = GL_RGBA; |
58772a28 |
102 | theDataType = GL_UNSIGNED_BYTE; |
a1073ae2 |
103 | return true; |
104 | } |
58772a28 |
105 | case GL_RGB8: |
106 | case GL_RGB: |
a1073ae2 |
107 | { |
58772a28 |
108 | thePixelFormat = GL_RGB; |
109 | theDataType = GL_UNSIGNED_BYTE; |
a1073ae2 |
110 | return true; |
111 | } |
112 | } |
113 | return false; |
114 | } |
115 | |
116 | //! Checks whether two format arrays are equal or not. |
117 | static bool operator== (const OpenGl_ColorFormats& theFmt1, |
118 | const OpenGl_ColorFormats& theFmt2) |
119 | { |
120 | if (theFmt1.Length() != theFmt2.Length()) |
121 | return false; |
122 | OpenGl_ColorFormats::Iterator anIt1 (theFmt1); |
123 | OpenGl_ColorFormats::Iterator anIt2 (theFmt1); |
124 | for (; anIt1.More(); anIt1.Next(), anIt2.Next()) |
125 | { |
126 | if (anIt1.Value() != anIt2.Value()) |
127 | return false; |
128 | } |
129 | return true; |
130 | } |
3c4b62a4 |
131 | } |
7fd59977 |
132 | |
fd4a6963 |
133 | // ======================================================================= |
134 | // function : OpenGl_FrameBuffer |
135 | // purpose : |
136 | // ======================================================================= |
3c4b62a4 |
137 | OpenGl_FrameBuffer::OpenGl_FrameBuffer() |
a0b49de4 |
138 | : myInitVPSizeX (0), |
139 | myInitVPSizeY (0), |
140 | myVPSizeX (0), |
7fd59977 |
141 | myVPSizeY (0), |
3c4b62a4 |
142 | myNbSamples (0), |
3c4b62a4 |
143 | myDepthFormat (GL_DEPTH24_STENCIL8), |
7fd59977 |
144 | myGlFBufferId (NO_FRAMEBUFFER), |
a2e4f780 |
145 | myGlColorRBufferId (NO_RENDERBUFFER), |
146 | myGlDepthRBufferId (NO_RENDERBUFFER), |
147 | myIsOwnBuffer (false), |
18f4e8e2 |
148 | myDepthStencilTexture (new OpenGl_Texture()) |
7fd59977 |
149 | { |
a1073ae2 |
150 | myColorFormats.Append (GL_RGBA8); |
151 | myColorTextures.Append (new OpenGl_Texture()); |
7fd59977 |
152 | } |
153 | |
fd4a6963 |
154 | // ======================================================================= |
155 | // function : ~OpenGl_FrameBuffer |
156 | // purpose : |
157 | // ======================================================================= |
158 | OpenGl_FrameBuffer::~OpenGl_FrameBuffer() |
159 | { |
160 | Release (NULL); |
161 | } |
162 | |
163 | // ======================================================================= |
164 | // function : Init |
165 | // purpose : |
166 | // ======================================================================= |
2166f0fa |
167 | Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext, |
a1073ae2 |
168 | const GLsizei theSizeX, |
169 | const GLsizei theSizeY, |
170 | const GLint theColorFormat, |
171 | const GLint theDepthFormat, |
172 | const GLsizei theNbSamples) |
7fd59977 |
173 | { |
a1073ae2 |
174 | OpenGl_ColorFormats aColorFormats; |
175 | |
176 | aColorFormats.Append (theColorFormat); |
177 | |
178 | return Init (theGlContext, theSizeX, theSizeY, aColorFormats, theDepthFormat, theNbSamples); |
179 | } |
180 | |
181 | // ======================================================================= |
182 | // function : Init |
183 | // purpose : |
184 | // ======================================================================= |
185 | Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext, |
186 | const GLsizei theSizeX, |
187 | const GLsizei theSizeY, |
188 | const OpenGl_ColorFormats& theColorFormats, |
189 | const Handle(OpenGl_Texture)& theDepthStencilTexture, |
190 | const GLsizei theNbSamples) |
191 | { |
192 | myColorFormats = theColorFormats; |
193 | |
194 | OpenGl_TextureArray aTextures (myColorTextures); |
195 | if (!myColorTextures.IsEmpty()) |
196 | { |
197 | for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next()) |
198 | { |
199 | aTextureIt.Value()->Release (theGlContext.operator->()); |
200 | } |
201 | myColorTextures.Clear(); |
202 | } |
203 | for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength) |
204 | { |
205 | myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture()); |
206 | } |
207 | |
208 | myDepthFormat = theDepthStencilTexture->GetFormat(); |
209 | myNbSamples = theNbSamples; |
210 | if (theGlContext->arbFBO == NULL) |
211 | { |
212 | return Standard_False; |
213 | } |
214 | |
215 | // clean up previous state |
216 | Release (theGlContext.operator->()); |
217 | if (myColorFormats.IsEmpty() |
218 | && myDepthFormat == 0) |
219 | { |
220 | return Standard_False; |
221 | } |
222 | |
223 | myDepthStencilTexture = theDepthStencilTexture; |
224 | myIsOwnDepth = false; |
225 | myIsOwnBuffer = true; |
226 | |
227 | // setup viewport sizes as is |
228 | myVPSizeX = theSizeX; |
229 | myVPSizeY = theSizeY; |
230 | const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2; |
231 | const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2; |
232 | |
233 | // Create the textures (will be used as color buffer and depth-stencil buffer) |
234 | if (theNbSamples != 0) |
235 | { |
236 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
237 | { |
238 | const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); |
239 | const GLint aColorFormat = myColorFormats (aColorBufferIdx); |
240 | if (aColorFormat != 0 |
241 | && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples, |
242 | aColorFormat, aSizeX, aSizeY)) |
243 | { |
244 | Release (theGlContext.operator->()); |
245 | return Standard_False; |
246 | } |
247 | } |
248 | } |
249 | else |
250 | { |
251 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
252 | { |
253 | GLenum aPixelFormat = 0; |
254 | GLenum aDataType = 0; |
255 | const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); |
256 | const GLint aColorFormat = myColorFormats (aColorBufferIdx); |
257 | if (aColorFormat != 0 |
258 | && getColorDataFormat (aColorFormat, aPixelFormat, aDataType) |
259 | && !aColorTexture->Init (theGlContext, aColorFormat, |
260 | aPixelFormat, aDataType, |
261 | aSizeX, aSizeY, Graphic3d_TOT_2D)) |
262 | { |
263 | Release (theGlContext.operator->()); |
264 | return Standard_False; |
265 | } |
266 | } |
267 | } |
268 | |
269 | // Build FBO and setup it as texture |
270 | theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId); |
271 | theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); |
272 | |
273 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
274 | { |
275 | const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); |
276 | if (aColorTexture->IsValid()) |
277 | { |
278 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx, |
279 | aColorTexture->GetTarget(), aColorTexture->TextureId(), 0); |
280 | } |
281 | } |
282 | if (myDepthStencilTexture->IsValid()) |
283 | { |
284 | #ifdef GL_DEPTH_STENCIL_ATTACHMENT |
285 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, |
286 | myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); |
287 | #else |
288 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, |
289 | myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); |
290 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, |
291 | myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); |
292 | #endif |
293 | } |
294 | if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) |
295 | { |
296 | Release (theGlContext.operator->()); |
297 | return Standard_False; |
298 | } |
299 | |
300 | UnbindBuffer (theGlContext); |
301 | return Standard_True; |
302 | } |
303 | |
304 | // ======================================================================= |
305 | // function : Init |
306 | // purpose : |
307 | // ======================================================================= |
308 | Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext, |
309 | const GLsizei theSizeX, |
310 | const GLsizei theSizeY, |
311 | const OpenGl_ColorFormats& theColorFormats, |
312 | const GLint theDepthFormat, |
313 | const GLsizei theNbSamples) |
314 | { |
315 | myColorFormats = theColorFormats; |
316 | |
317 | OpenGl_TextureArray aTextures (myColorTextures); |
318 | if (!myColorTextures.IsEmpty()) |
319 | { |
320 | for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next()) |
321 | { |
322 | aTextureIt.Value()->Release (theGlContext.operator->()); |
323 | } |
324 | myColorTextures.Clear(); |
325 | } |
326 | for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength) |
327 | { |
328 | myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture()); |
329 | } |
330 | |
3c4b62a4 |
331 | myDepthFormat = theDepthFormat; |
332 | myNbSamples = theNbSamples; |
a0b49de4 |
333 | myInitVPSizeX = theSizeX; |
334 | myInitVPSizeY = theSizeY; |
01ca42b2 |
335 | if (theGlContext->arbFBO == NULL) |
7fd59977 |
336 | { |
7fd59977 |
337 | return Standard_False; |
338 | } |
339 | |
340 | // clean up previous state |
fd4a6963 |
341 | Release (theGlContext.operator->()); |
a1073ae2 |
342 | if (myColorFormats.IsEmpty() |
3c4b62a4 |
343 | && myDepthFormat == 0) |
344 | { |
345 | return Standard_False; |
346 | } |
7fd59977 |
347 | |
a447178e |
348 | myIsOwnBuffer = true; |
a1073ae2 |
349 | myIsOwnDepth = true; |
a447178e |
350 | |
7fd59977 |
351 | // setup viewport sizes as is |
62e1beed |
352 | myVPSizeX = theSizeX; |
353 | myVPSizeY = theSizeY; |
354 | const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2; |
355 | const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2; |
e473b95f |
356 | bool hasStencilRB = false; |
7fd59977 |
357 | |
18f4e8e2 |
358 | // Create the textures (will be used as color buffer and depth-stencil buffer) |
3c4b62a4 |
359 | if (theNbSamples != 0) |
7fd59977 |
360 | { |
a1073ae2 |
361 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
3c4b62a4 |
362 | { |
a1073ae2 |
363 | const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); |
364 | const GLint aColorFormat = myColorFormats (aColorBufferIdx); |
365 | if (aColorFormat != 0 |
366 | && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples, aColorFormat, aSizeX, aSizeY)) |
367 | { |
368 | Release (theGlContext.operator->()); |
369 | return Standard_False; |
370 | } |
3c4b62a4 |
371 | } |
372 | if (myDepthFormat != 0 |
373 | && !myDepthStencilTexture->Init2DMultisample (theGlContext, theNbSamples, myDepthFormat, aSizeX, aSizeY)) |
374 | { |
375 | Release (theGlContext.operator->()); |
376 | return Standard_False; |
377 | } |
7fd59977 |
378 | } |
3c4b62a4 |
379 | else |
fe3a29bc |
380 | { |
a1073ae2 |
381 | GLenum aPixelFormat = 0; |
382 | GLenum aDataType = 0; |
383 | |
384 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
3c4b62a4 |
385 | { |
a1073ae2 |
386 | const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); |
387 | const GLint aColorFormat = myColorFormats (aColorBufferIdx); |
388 | if (aColorFormat != 0 |
389 | && getColorDataFormat (aColorFormat, aPixelFormat, aDataType) |
390 | && !aColorTexture->Init (theGlContext, aColorFormat, |
391 | aPixelFormat, aDataType, |
392 | aSizeX, aSizeY, Graphic3d_TOT_2D)) |
393 | { |
394 | Release (theGlContext.operator->()); |
395 | return Standard_False; |
396 | } |
3c4b62a4 |
397 | } |
fe3a29bc |
398 | |
3c4b62a4 |
399 | // extensions (GL_OES_packed_depth_stencil, GL_OES_depth_texture) + GL version might be used to determine supported formats |
400 | // instead of just trying to create such texture |
3c4b62a4 |
401 | if (myDepthFormat != 0 |
402 | && getDepthDataFormat (myDepthFormat, aPixelFormat, aDataType) |
403 | && !myDepthStencilTexture->Init (theGlContext, myDepthFormat, |
404 | aPixelFormat, aDataType, |
405 | aSizeX, aSizeY, Graphic3d_TOT_2D)) |
406 | { |
407 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() |
408 | + "Warning! Depth textures are not supported by hardware!"; |
3b523c4c |
409 | theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
410 | GL_DEBUG_TYPE_PORTABILITY, |
3c4b62a4 |
411 | 0, |
3b523c4c |
412 | GL_DEBUG_SEVERITY_HIGH, |
3c4b62a4 |
413 | aMsg); |
414 | |
e473b95f |
415 | hasStencilRB = aPixelFormat == GL_DEPTH_STENCIL |
416 | && theGlContext->extPDS; |
417 | GLint aDepthStencilFormat = hasStencilRB |
418 | ? GL_DEPTH24_STENCIL8 |
419 | : GL_DEPTH_COMPONENT16; |
420 | |
3c4b62a4 |
421 | theGlContext->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId); |
422 | theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId); |
e473b95f |
423 | theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, aDepthStencilFormat, aSizeX, aSizeY); |
3c4b62a4 |
424 | theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER); |
425 | } |
fe3a29bc |
426 | } |
427 | |
7fd59977 |
428 | // Build FBO and setup it as texture |
01ca42b2 |
429 | theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId); |
430 | theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); |
a1073ae2 |
431 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
3c4b62a4 |
432 | { |
a1073ae2 |
433 | const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); |
434 | if (aColorTexture->IsValid()) |
435 | { |
436 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx, |
437 | aColorTexture->GetTarget(), aColorTexture->TextureId(), 0); |
438 | } |
3c4b62a4 |
439 | } |
fe3a29bc |
440 | if (myDepthStencilTexture->IsValid()) |
441 | { |
442 | #ifdef GL_DEPTH_STENCIL_ATTACHMENT |
443 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, |
3c4b62a4 |
444 | myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); |
fe3a29bc |
445 | #else |
446 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, |
3c4b62a4 |
447 | myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); |
fe3a29bc |
448 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, |
3c4b62a4 |
449 | myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); |
fe3a29bc |
450 | #endif |
451 | } |
452 | else if (myGlDepthRBufferId != NO_RENDERBUFFER) |
453 | { |
e473b95f |
454 | #ifdef GL_DEPTH_STENCIL_ATTACHMENT |
455 | theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, hasStencilRB ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, |
456 | GL_RENDERBUFFER, myGlDepthRBufferId); |
457 | #else |
fe3a29bc |
458 | theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, |
459 | GL_RENDERBUFFER, myGlDepthRBufferId); |
e473b95f |
460 | if (hasStencilRB) |
461 | { |
462 | theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, |
463 | GL_RENDERBUFFER, myGlDepthRBufferId); |
464 | } |
465 | #endif |
fe3a29bc |
466 | } |
01ca42b2 |
467 | if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) |
7fd59977 |
468 | { |
fd4a6963 |
469 | Release (theGlContext.operator->()); |
7fd59977 |
470 | return Standard_False; |
471 | } |
472 | |
18f4e8e2 |
473 | UnbindBuffer (theGlContext); |
7fd59977 |
474 | return Standard_True; |
475 | } |
476 | |
38a0206f |
477 | // ======================================================================= |
a1073ae2 |
478 | // function : InitLazy |
38a0206f |
479 | // purpose : |
480 | // ======================================================================= |
481 | Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext, |
482 | const GLsizei theViewportSizeX, |
3c4b62a4 |
483 | const GLsizei theViewportSizeY, |
484 | const GLint theColorFormat, |
485 | const GLint theDepthFormat, |
486 | const GLsizei theNbSamples) |
38a0206f |
487 | { |
a1073ae2 |
488 | OpenGl_ColorFormats aColorFormats; |
489 | |
490 | aColorFormats.Append (theColorFormat); |
491 | |
492 | return InitLazy (theGlContext, theViewportSizeX, theViewportSizeY, aColorFormats, theDepthFormat, theNbSamples); |
493 | } |
494 | |
495 | // ======================================================================= |
496 | // function : InitLazy |
497 | // purpose : |
498 | // ======================================================================= |
499 | Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext, |
500 | const GLsizei theViewportSizeX, |
501 | const GLsizei theViewportSizeY, |
502 | const OpenGl_ColorFormats& theColorFormats, |
503 | const GLint theDepthFormat, |
504 | const GLsizei theNbSamples) |
505 | { |
506 | if (myVPSizeX == theViewportSizeX |
507 | && myVPSizeY == theViewportSizeY |
508 | && myColorFormats == theColorFormats |
509 | && myDepthFormat == theDepthFormat |
510 | && myNbSamples == theNbSamples) |
38a0206f |
511 | { |
512 | return IsValid(); |
513 | } |
514 | |
a1073ae2 |
515 | return Init (theGlContext, theViewportSizeX, theViewportSizeY, theColorFormats, theDepthFormat, theNbSamples); |
38a0206f |
516 | } |
517 | |
a2e4f780 |
518 | // ======================================================================= |
519 | // function : InitWithRB |
520 | // purpose : |
521 | // ======================================================================= |
522 | Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& theGlCtx, |
62e1beed |
523 | const GLsizei theSizeX, |
524 | const GLsizei theSizeY, |
3c4b62a4 |
525 | const GLint theColorFormat, |
526 | const GLint theDepthFormat, |
a2e4f780 |
527 | const GLuint theColorRBufferFromWindow) |
528 | { |
a1073ae2 |
529 | myColorFormats.Clear(); |
530 | myColorFormats.Append (theColorFormat); |
531 | if (!myColorTextures.IsEmpty()) |
532 | { |
533 | Handle(OpenGl_Texture) aTexutre = myColorTextures.First(); |
534 | for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next()) |
535 | { |
536 | aTextureIt.Value()->Release (theGlCtx.operator->()); |
537 | } |
538 | myColorTextures.Clear(); |
539 | myColorTextures.Append (aTexutre); |
540 | } |
541 | |
3c4b62a4 |
542 | myDepthFormat = theDepthFormat; |
543 | myNbSamples = 0; |
a0b49de4 |
544 | myInitVPSizeX = theSizeX; |
545 | myInitVPSizeY = theSizeY; |
a2e4f780 |
546 | if (theGlCtx->arbFBO == NULL) |
547 | { |
548 | return Standard_False; |
549 | } |
550 | |
551 | // clean up previous state |
552 | Release (theGlCtx.operator->()); |
553 | |
a447178e |
554 | myIsOwnBuffer = true; |
a1073ae2 |
555 | myIsOwnDepth = true; |
a447178e |
556 | |
a2e4f780 |
557 | // setup viewport sizes as is |
62e1beed |
558 | myVPSizeX = theSizeX; |
559 | myVPSizeY = theSizeY; |
560 | const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2; |
561 | const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2; |
a2e4f780 |
562 | |
563 | // Create the render-buffers |
564 | if (theColorRBufferFromWindow != NO_RENDERBUFFER) |
565 | { |
566 | myGlColorRBufferId = theColorRBufferFromWindow; |
567 | } |
a1073ae2 |
568 | else if (theColorFormat != 0) |
a2e4f780 |
569 | { |
570 | theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlColorRBufferId); |
571 | theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlColorRBufferId); |
a1073ae2 |
572 | theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, theColorFormat, aSizeX, aSizeY); |
a2e4f780 |
573 | } |
574 | |
e473b95f |
575 | bool hasStencilRB = false; |
3c4b62a4 |
576 | if (myDepthFormat != 0) |
577 | { |
e473b95f |
578 | GLenum aPixelFormat = 0; |
579 | GLenum aDataType = 0; |
580 | getDepthDataFormat (myDepthFormat, aPixelFormat, aDataType); |
581 | hasStencilRB = aPixelFormat == GL_DEPTH_STENCIL; |
582 | |
3c4b62a4 |
583 | theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId); |
584 | theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId); |
585 | theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, myDepthFormat, aSizeX, aSizeY); |
586 | theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER); |
587 | } |
a2e4f780 |
588 | |
589 | // create FBO |
590 | theGlCtx->arbFBO->glGenFramebuffers (1, &myGlFBufferId); |
591 | theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); |
592 | theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
593 | GL_RENDERBUFFER, myGlColorRBufferId); |
3c4b62a4 |
594 | if (myGlDepthRBufferId != NO_RENDERBUFFER) |
595 | { |
596 | #ifdef GL_DEPTH_STENCIL_ATTACHMENT |
e473b95f |
597 | theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, hasStencilRB ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, |
3c4b62a4 |
598 | GL_RENDERBUFFER, myGlDepthRBufferId); |
599 | #else |
600 | theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, |
601 | GL_RENDERBUFFER, myGlDepthRBufferId); |
e473b95f |
602 | if (hasStencilRB) |
603 | { |
604 | theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, |
605 | GL_RENDERBUFFER, myGlDepthRBufferId); |
606 | } |
3c4b62a4 |
607 | #endif |
608 | } |
a2e4f780 |
609 | if (theGlCtx->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) |
610 | { |
611 | UnbindBuffer (theGlCtx); |
612 | Release (theGlCtx.operator->()); |
613 | return Standard_False; |
614 | } |
615 | |
616 | UnbindBuffer (theGlCtx); |
617 | return Standard_True; |
618 | } |
619 | |
620 | // ======================================================================= |
621 | // function : InitWrapper |
622 | // purpose : |
623 | // ======================================================================= |
624 | Standard_Boolean OpenGl_FrameBuffer::InitWrapper (const Handle(OpenGl_Context)& theGlCtx) |
625 | { |
3c4b62a4 |
626 | myNbSamples = 0; |
a2e4f780 |
627 | if (theGlCtx->arbFBO == NULL) |
628 | { |
629 | return Standard_False; |
630 | } |
631 | |
632 | // clean up previous state |
633 | Release (theGlCtx.operator->()); |
634 | |
635 | GLint anFbo = GLint(NO_FRAMEBUFFER); |
636 | ::glGetIntegerv (GL_FRAMEBUFFER_BINDING, &anFbo); |
637 | if (anFbo == GLint(NO_FRAMEBUFFER)) |
638 | { |
639 | return Standard_False; |
640 | } |
641 | |
642 | GLint aColorType = 0; |
643 | GLint aColorId = 0; |
644 | GLint aDepthType = 0; |
645 | GLint aDepthId = 0; |
646 | theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aColorType); |
647 | theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aDepthType); |
648 | |
649 | myGlFBufferId = GLuint(anFbo); |
650 | myIsOwnBuffer = false; |
a1073ae2 |
651 | myIsOwnDepth = false; |
a2e4f780 |
652 | if (aColorType == GL_RENDERBUFFER) |
653 | { |
654 | theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aColorId); |
655 | myGlColorRBufferId = aColorId; |
656 | } |
657 | else if (aColorType != GL_NONE) |
658 | { |
659 | TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), color attachment of unsupported type has been skipped!"; |
3b523c4c |
660 | theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
661 | GL_DEBUG_TYPE_ERROR, |
a2e4f780 |
662 | 0, |
3b523c4c |
663 | GL_DEBUG_SEVERITY_HIGH, |
a2e4f780 |
664 | aMsg); |
665 | } |
666 | |
667 | if (aDepthType == GL_RENDERBUFFER) |
668 | { |
669 | theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aDepthId); |
670 | myGlDepthRBufferId = aDepthId; |
671 | } |
672 | else if (aDepthType != GL_NONE) |
673 | { |
674 | TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), depth attachment of unsupported type has been skipped!"; |
3b523c4c |
675 | theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
676 | GL_DEBUG_TYPE_ERROR, |
a2e4f780 |
677 | 0, |
3b523c4c |
678 | GL_DEBUG_SEVERITY_HIGH, |
a2e4f780 |
679 | aMsg); |
680 | } |
681 | |
682 | // retrieve dimensions |
683 | GLuint aRBuffer = myGlColorRBufferId != NO_RENDERBUFFER ? myGlColorRBufferId : myGlDepthRBufferId; |
684 | if (aRBuffer != NO_RENDERBUFFER) |
685 | { |
686 | theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, aRBuffer); |
687 | theGlCtx->arbFBO->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &myVPSizeX); |
688 | theGlCtx->arbFBO->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &myVPSizeY); |
689 | theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER); |
690 | } |
691 | |
692 | return aRBuffer != NO_RENDERBUFFER; |
693 | } |
694 | |
fd4a6963 |
695 | // ======================================================================= |
696 | // function : Release |
697 | // purpose : |
698 | // ======================================================================= |
10b9c7df |
699 | void OpenGl_FrameBuffer::Release (OpenGl_Context* theGlCtx) |
7fd59977 |
700 | { |
18f4e8e2 |
701 | if (isValidFrameBuffer()) |
7fd59977 |
702 | { |
fd4a6963 |
703 | // application can not handle this case by exception - this is bug in code |
704 | Standard_ASSERT_RETURN (theGlCtx != NULL, |
705 | "OpenGl_FrameBuffer destroyed without GL context! Possible GPU memory leakage...",); |
a2e4f780 |
706 | if (theGlCtx->IsValid() |
707 | && myIsOwnBuffer) |
2166f0fa |
708 | { |
01ca42b2 |
709 | theGlCtx->arbFBO->glDeleteFramebuffers (1, &myGlFBufferId); |
a2e4f780 |
710 | if (myGlColorRBufferId != NO_RENDERBUFFER) |
711 | { |
712 | theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlColorRBufferId); |
713 | } |
714 | if (myGlDepthRBufferId != NO_RENDERBUFFER) |
715 | { |
716 | theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlDepthRBufferId); |
717 | } |
2166f0fa |
718 | } |
a2e4f780 |
719 | myGlFBufferId = NO_FRAMEBUFFER; |
720 | myGlColorRBufferId = NO_RENDERBUFFER; |
721 | myGlDepthRBufferId = NO_RENDERBUFFER; |
722 | myIsOwnBuffer = false; |
7fd59977 |
723 | } |
7fd59977 |
724 | |
a1073ae2 |
725 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
726 | { |
727 | myColorTextures (aColorBufferIdx)->Release (theGlCtx); |
728 | } |
729 | |
730 | if (myIsOwnDepth) |
731 | { |
732 | myDepthStencilTexture->Release (theGlCtx); |
733 | myIsOwnDepth = false; |
734 | } |
bf02aa7d |
735 | |
736 | myVPSizeX = 0; |
737 | myVPSizeY = 0; |
7fd59977 |
738 | } |
739 | |
fd4a6963 |
740 | // ======================================================================= |
741 | // function : SetupViewport |
742 | // purpose : |
743 | // ======================================================================= |
3bffef55 |
744 | void OpenGl_FrameBuffer::SetupViewport (const Handle(OpenGl_Context)& theGlCtx) |
fd4a6963 |
745 | { |
3bffef55 |
746 | const Standard_Integer aViewport[4] = { 0, 0, myVPSizeX, myVPSizeY }; |
747 | theGlCtx->ResizeViewport (aViewport); |
fd4a6963 |
748 | } |
749 | |
750 | // ======================================================================= |
751 | // function : ChangeViewport |
752 | // purpose : |
753 | // ======================================================================= |
754 | void OpenGl_FrameBuffer::ChangeViewport (const GLsizei theVPSizeX, |
755 | const GLsizei theVPSizeY) |
756 | { |
757 | myVPSizeX = theVPSizeX; |
758 | myVPSizeY = theVPSizeY; |
759 | } |
760 | |
761 | // ======================================================================= |
762 | // function : BindBuffer |
763 | // purpose : |
764 | // ======================================================================= |
765 | void OpenGl_FrameBuffer::BindBuffer (const Handle(OpenGl_Context)& theGlCtx) |
766 | { |
01ca42b2 |
767 | theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); |
fd4a6963 |
768 | } |
769 | |
b86bb3df |
770 | // ======================================================================= |
771 | // function : BindDrawBuffer |
772 | // purpose : |
773 | // ======================================================================= |
774 | void OpenGl_FrameBuffer::BindDrawBuffer (const Handle(OpenGl_Context)& theGlCtx) |
775 | { |
776 | theGlCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myGlFBufferId); |
777 | } |
778 | |
779 | // ======================================================================= |
780 | // function : BindReadBuffer |
781 | // purpose : |
782 | // ======================================================================= |
783 | void OpenGl_FrameBuffer::BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx) |
784 | { |
785 | theGlCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, myGlFBufferId); |
786 | } |
787 | |
fd4a6963 |
788 | // ======================================================================= |
789 | // function : UnbindBuffer |
790 | // purpose : |
791 | // ======================================================================= |
792 | void OpenGl_FrameBuffer::UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx) |
793 | { |
a2e4f780 |
794 | if (!theGlCtx->DefaultFrameBuffer().IsNull() |
795 | && theGlCtx->DefaultFrameBuffer().operator->() != this) |
796 | { |
797 | theGlCtx->DefaultFrameBuffer()->BindBuffer (theGlCtx); |
798 | } |
799 | else |
800 | { |
801 | theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, NO_FRAMEBUFFER); |
802 | } |
fd4a6963 |
803 | } |