1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <OpenGl_FrameBuffer.hxx>
16 #include <OpenGl_ArbFBO.hxx>
18 #include <NCollection_AlignedAllocator.hxx>
19 #include <Standard_Assert.hxx>
20 #include <TCollection_ExtendedString.hxx>
22 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameBuffer,OpenGl_Resource)
26 //! Checks whether two format arrays are equal or not.
27 static bool operator== (const OpenGl_ColorFormats& theFmt1,
28 const OpenGl_ColorFormats& theFmt2)
30 if (theFmt1.Length() != theFmt2.Length())
32 OpenGl_ColorFormats::Iterator anIt1 (theFmt1);
33 OpenGl_ColorFormats::Iterator anIt2 (theFmt1);
34 for (; anIt1.More(); anIt1.Next(), anIt2.Next())
36 if (anIt1.Value() != anIt2.Value())
42 //! Return TRUE if GL_DEPTH_STENCIL_ATTACHMENT can be used.
43 static bool hasDepthStencilAttach (const Handle(OpenGl_Context)& theCtx)
46 // supported since WebGL 2.0,
47 // while WebGL 1.0 + GL_WEBGL_depth_texture needs GL_DEPTH_STENCIL_ATTACHMENT
48 // and NOT separate GL_DEPTH_ATTACHMENT+GL_STENCIL_ATTACHMENT calls which is different to OpenGL ES 2.0 + extension
49 return theCtx->IsGlGreaterEqual (3, 0) || theCtx->extPDS;
50 #elif defined(GL_ES_VERSION_2_0)
51 // supported since OpenGL ES 3.0,
52 // while OpenGL ES 2.0 + GL_EXT_packed_depth_stencil needs separate GL_DEPTH_ATTACHMENT+GL_STENCIL_ATTACHMENT calls
53 return theCtx->IsGlGreaterEqual (3, 0);
55 // available on desktop since OpenGL 3.0
56 // or OpenGL 2.0 + GL_ARB_framebuffer_object (GL_EXT_framebuffer_object is unsupported by OCCT)
63 // =======================================================================
64 // function : OpenGl_FrameBuffer
66 // =======================================================================
67 OpenGl_FrameBuffer::OpenGl_FrameBuffer()
73 myDepthFormat (GL_DEPTH24_STENCIL8),
74 myGlFBufferId (NO_FRAMEBUFFER),
75 myGlColorRBufferId (NO_RENDERBUFFER),
76 myGlDepthRBufferId (NO_RENDERBUFFER),
77 myIsOwnBuffer (false),
79 myDepthStencilTexture (new OpenGl_Texture())
81 myColorFormats.Append (GL_RGBA8);
82 myColorTextures.Append (new OpenGl_Texture());
85 // =======================================================================
86 // function : ~OpenGl_FrameBuffer
88 // =======================================================================
89 OpenGl_FrameBuffer::~OpenGl_FrameBuffer()
94 // =======================================================================
97 // =======================================================================
98 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
99 const GLsizei theSizeX,
100 const GLsizei theSizeY,
101 const GLint theColorFormat,
102 const GLint theDepthFormat,
103 const GLsizei theNbSamples)
105 OpenGl_ColorFormats aColorFormats;
107 aColorFormats.Append (theColorFormat);
109 return Init (theGlContext, theSizeX, theSizeY, aColorFormats, theDepthFormat, theNbSamples);
112 // =======================================================================
115 // =======================================================================
116 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
117 const GLsizei theSizeX,
118 const GLsizei theSizeY,
119 const OpenGl_ColorFormats& theColorFormats,
120 const Handle(OpenGl_Texture)& theDepthStencilTexture,
121 const GLsizei theNbSamples)
123 myColorFormats = theColorFormats;
125 OpenGl_TextureArray aTextures (myColorTextures);
126 if (!myColorTextures.IsEmpty())
128 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
130 aTextureIt.Value()->Release (theGlContext.operator->());
132 myColorTextures.Clear();
134 for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength)
136 myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture());
139 myDepthFormat = theDepthStencilTexture->GetFormat();
140 myNbSamples = theNbSamples;
141 if (theGlContext->arbFBO == NULL)
143 return Standard_False;
146 // clean up previous state
147 Release (theGlContext.operator->());
148 if (myColorFormats.IsEmpty()
149 && myDepthFormat == 0)
151 return Standard_False;
154 myDepthStencilTexture = theDepthStencilTexture;
155 myIsOwnDepth = false;
156 myIsOwnBuffer = true;
158 // setup viewport sizes as is
159 myVPSizeX = theSizeX;
160 myVPSizeY = theSizeY;
161 const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
162 const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
164 // Create the textures (will be used as color buffer and depth-stencil buffer)
165 if (theNbSamples != 0)
167 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
169 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
170 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
171 if (aColorFormat != 0
172 && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples,
173 aColorFormat, aSizeX, aSizeY))
175 Release (theGlContext.get());
176 return Standard_False;
182 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
184 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
185 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
186 const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindSizedFormat (theGlContext, aColorFormat);
187 if (aFormat.IsValid()
188 && !aColorTexture->Init (theGlContext, aFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TOT_2D))
190 Release (theGlContext.get());
191 return Standard_False;
196 // Build FBO and setup it as texture
197 theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
198 theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
200 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
202 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
203 if (aColorTexture->IsValid())
205 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx,
206 aColorTexture->GetTarget(), aColorTexture->TextureId(), 0);
209 if (myDepthStencilTexture->IsValid())
211 if (hasDepthStencilAttach (theGlContext))
213 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
214 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
218 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
219 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
220 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
221 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
224 if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
226 Release (theGlContext.operator->());
227 return Standard_False;
230 UnbindBuffer (theGlContext);
231 return Standard_True;
234 // =======================================================================
237 // =======================================================================
238 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
239 const GLsizei theSizeX,
240 const GLsizei theSizeY,
241 const OpenGl_ColorFormats& theColorFormats,
242 const GLint theDepthFormat,
243 const GLsizei theNbSamples)
245 myColorFormats = theColorFormats;
247 OpenGl_TextureArray aTextures (myColorTextures);
248 if (!myColorTextures.IsEmpty())
250 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
252 aTextureIt.Value()->Release (theGlContext.operator->());
254 myColorTextures.Clear();
256 for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength)
258 myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture());
261 myDepthFormat = theDepthFormat;
262 myNbSamples = theNbSamples;
263 myInitVPSizeX = theSizeX;
264 myInitVPSizeY = theSizeY;
265 if (theGlContext->arbFBO == NULL)
267 return Standard_False;
270 // clean up previous state
271 Release (theGlContext.operator->());
272 if (myColorFormats.IsEmpty()
273 && myDepthFormat == 0)
275 return Standard_False;
278 myIsOwnBuffer = true;
281 // setup viewport sizes as is
282 myVPSizeX = theSizeX;
283 myVPSizeY = theSizeY;
284 const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
285 const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
286 bool hasStencilRB = false;
288 // Create the textures (will be used as color buffer and depth-stencil buffer)
289 if (theNbSamples != 0)
291 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
293 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
294 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
295 if (aColorFormat != 0
296 && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples, aColorFormat, aSizeX, aSizeY))
298 Release (theGlContext.operator->());
299 return Standard_False;
302 if (myDepthFormat != 0
303 && !myDepthStencilTexture->Init2DMultisample (theGlContext, theNbSamples, myDepthFormat, aSizeX, aSizeY))
305 Release (theGlContext.operator->());
306 return Standard_False;
311 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
313 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
314 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
315 const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindSizedFormat (theGlContext, aColorFormat);
316 if (aFormat.IsValid()
317 && !aColorTexture->Init (theGlContext, aFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TOT_2D))
319 Release (theGlContext.operator->());
320 return Standard_False;
324 // extensions (GL_OES_packed_depth_stencil, GL_OES_depth_texture) + GL version might be used to determine supported formats
325 // instead of just trying to create such texture
326 const OpenGl_TextureFormat aDepthFormat = OpenGl_TextureFormat::FindSizedFormat (theGlContext, myDepthFormat);
327 if (aDepthFormat.IsValid()
328 && !myDepthStencilTexture->Init (theGlContext, aDepthFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TOT_2D))
330 theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
331 "Warning! Depth textures are not supported by hardware!");
333 hasStencilRB = aDepthFormat.PixelFormat() == GL_DEPTH_STENCIL
334 && theGlContext->extPDS;
335 GLint aDepthStencilFormat = hasStencilRB
336 ? GL_DEPTH24_STENCIL8
337 : GL_DEPTH_COMPONENT16;
339 theGlContext->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId);
340 theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId);
341 theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, aDepthStencilFormat, aSizeX, aSizeY);
342 theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
346 // Build FBO and setup it as texture
347 theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
348 theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
349 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
351 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
352 if (aColorTexture->IsValid())
354 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx,
355 aColorTexture->GetTarget(), aColorTexture->TextureId(), 0);
359 if (myDepthStencilTexture->IsValid())
361 if (hasDepthStencilAttach (theGlContext))
363 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
364 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
368 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
369 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
370 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
371 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
374 else if (myGlDepthRBufferId != NO_RENDERBUFFER)
376 if (hasDepthStencilAttach (theGlContext) && hasStencilRB)
378 theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
379 GL_RENDERBUFFER, myGlDepthRBufferId);
383 theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
384 GL_RENDERBUFFER, myGlDepthRBufferId);
387 theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
388 GL_RENDERBUFFER, myGlDepthRBufferId);
392 if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
394 Release (theGlContext.operator->());
395 return Standard_False;
398 UnbindBuffer (theGlContext);
399 return Standard_True;
402 // =======================================================================
403 // function : InitLazy
405 // =======================================================================
406 Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext,
407 const GLsizei theViewportSizeX,
408 const GLsizei theViewportSizeY,
409 const GLint theColorFormat,
410 const GLint theDepthFormat,
411 const GLsizei theNbSamples)
413 OpenGl_ColorFormats aColorFormats;
415 aColorFormats.Append (theColorFormat);
417 return InitLazy (theGlContext, theViewportSizeX, theViewportSizeY, aColorFormats, theDepthFormat, theNbSamples);
420 // =======================================================================
421 // function : InitLazy
423 // =======================================================================
424 Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext,
425 const GLsizei theViewportSizeX,
426 const GLsizei theViewportSizeY,
427 const OpenGl_ColorFormats& theColorFormats,
428 const GLint theDepthFormat,
429 const GLsizei theNbSamples)
431 if (myVPSizeX == theViewportSizeX
432 && myVPSizeY == theViewportSizeY
433 && myColorFormats == theColorFormats
434 && myDepthFormat == theDepthFormat
435 && myNbSamples == theNbSamples)
440 return Init (theGlContext, theViewportSizeX, theViewportSizeY, theColorFormats, theDepthFormat, theNbSamples);
443 // =======================================================================
444 // function : InitWithRB
446 // =======================================================================
447 Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& theGlCtx,
448 const GLsizei theSizeX,
449 const GLsizei theSizeY,
450 const GLint theColorFormat,
451 const GLint theDepthFormat,
452 const GLuint theColorRBufferFromWindow)
454 myColorFormats.Clear();
455 myColorFormats.Append (theColorFormat);
456 if (!myColorTextures.IsEmpty())
458 Handle(OpenGl_Texture) aTexutre = myColorTextures.First();
459 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
461 aTextureIt.Value()->Release (theGlCtx.operator->());
463 myColorTextures.Clear();
464 myColorTextures.Append (aTexutre);
467 myDepthFormat = theDepthFormat;
469 myInitVPSizeX = theSizeX;
470 myInitVPSizeY = theSizeY;
471 if (theGlCtx->arbFBO == NULL)
473 return Standard_False;
476 // clean up previous state
477 Release (theGlCtx.operator->());
479 myIsOwnBuffer = true;
482 // setup viewport sizes as is
483 myVPSizeX = theSizeX;
484 myVPSizeY = theSizeY;
485 const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
486 const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
488 // Create the render-buffers
489 if (theColorRBufferFromWindow != NO_RENDERBUFFER)
491 myGlColorRBufferId = theColorRBufferFromWindow;
493 else if (theColorFormat != 0)
495 theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlColorRBufferId);
496 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlColorRBufferId);
497 theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, theColorFormat, aSizeX, aSizeY);
500 bool hasStencilRB = false;
501 if (myDepthFormat != 0)
503 const OpenGl_TextureFormat aDepthFormat = OpenGl_TextureFormat::FindSizedFormat (theGlCtx, myDepthFormat);
504 hasStencilRB = aDepthFormat.PixelFormat() == GL_DEPTH_STENCIL;
506 theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId);
507 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId);
508 theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, myDepthFormat, aSizeX, aSizeY);
509 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
513 theGlCtx->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
514 theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
515 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
516 GL_RENDERBUFFER, myGlColorRBufferId);
517 if (myGlDepthRBufferId != NO_RENDERBUFFER)
519 if (hasDepthStencilAttach (theGlCtx) && hasStencilRB)
521 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
522 GL_RENDERBUFFER, myGlDepthRBufferId);
526 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
527 GL_RENDERBUFFER, myGlDepthRBufferId);
530 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
531 GL_RENDERBUFFER, myGlDepthRBufferId);
535 if (theGlCtx->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
537 UnbindBuffer (theGlCtx);
538 Release (theGlCtx.operator->());
539 return Standard_False;
542 UnbindBuffer (theGlCtx);
543 return Standard_True;
546 // =======================================================================
547 // function : InitWrapper
549 // =======================================================================
550 Standard_Boolean OpenGl_FrameBuffer::InitWrapper (const Handle(OpenGl_Context)& theGlCtx)
553 if (theGlCtx->arbFBO == NULL)
555 return Standard_False;
558 // clean up previous state
559 Release (theGlCtx.operator->());
561 GLint anFbo = GLint(NO_FRAMEBUFFER);
562 ::glGetIntegerv (GL_FRAMEBUFFER_BINDING, &anFbo);
563 if (anFbo == GLint(NO_FRAMEBUFFER))
565 return Standard_False;
568 GLint aColorType = 0;
570 GLint aDepthType = 0;
572 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aColorType);
573 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aDepthType);
575 myGlFBufferId = GLuint(anFbo);
576 myIsOwnBuffer = false;
577 myIsOwnDepth = false;
578 if (aColorType == GL_RENDERBUFFER)
580 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aColorId);
581 myGlColorRBufferId = aColorId;
583 else if (aColorType != GL_NONE)
585 TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), color attachment of unsupported type has been skipped!";
586 theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
589 GL_DEBUG_SEVERITY_HIGH,
593 if (aDepthType == GL_RENDERBUFFER)
595 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aDepthId);
596 myGlDepthRBufferId = aDepthId;
598 else if (aDepthType != GL_NONE)
600 TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), depth attachment of unsupported type has been skipped!";
601 theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
604 GL_DEBUG_SEVERITY_HIGH,
608 // retrieve dimensions
609 GLuint aRBuffer = myGlColorRBufferId != NO_RENDERBUFFER ? myGlColorRBufferId : myGlDepthRBufferId;
610 if (aRBuffer != NO_RENDERBUFFER)
612 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, aRBuffer);
613 theGlCtx->arbFBO->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &myVPSizeX);
614 theGlCtx->arbFBO->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &myVPSizeY);
615 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
618 return aRBuffer != NO_RENDERBUFFER;
621 // =======================================================================
622 // function : Release
624 // =======================================================================
625 void OpenGl_FrameBuffer::Release (OpenGl_Context* theGlCtx)
627 if (isValidFrameBuffer())
629 // application can not handle this case by exception - this is bug in code
630 Standard_ASSERT_RETURN (theGlCtx != NULL,
631 "OpenGl_FrameBuffer destroyed without GL context! Possible GPU memory leakage...",);
632 if (theGlCtx->IsValid()
635 theGlCtx->arbFBO->glDeleteFramebuffers (1, &myGlFBufferId);
636 if (myGlColorRBufferId != NO_RENDERBUFFER)
638 theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlColorRBufferId);
640 if (myGlDepthRBufferId != NO_RENDERBUFFER)
642 theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlDepthRBufferId);
645 myGlFBufferId = NO_FRAMEBUFFER;
646 myGlColorRBufferId = NO_RENDERBUFFER;
647 myGlDepthRBufferId = NO_RENDERBUFFER;
648 myIsOwnBuffer = false;
651 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
653 myColorTextures (aColorBufferIdx)->Release (theGlCtx);
658 myDepthStencilTexture->Release (theGlCtx);
659 myIsOwnDepth = false;
666 // =======================================================================
667 // function : SetupViewport
669 // =======================================================================
670 void OpenGl_FrameBuffer::SetupViewport (const Handle(OpenGl_Context)& theGlCtx)
672 const Standard_Integer aViewport[4] = { 0, 0, myVPSizeX, myVPSizeY };
673 theGlCtx->ResizeViewport (aViewport);
676 // =======================================================================
677 // function : ChangeViewport
679 // =======================================================================
680 void OpenGl_FrameBuffer::ChangeViewport (const GLsizei theVPSizeX,
681 const GLsizei theVPSizeY)
683 myVPSizeX = theVPSizeX;
684 myVPSizeY = theVPSizeY;
687 // =======================================================================
688 // function : BindBuffer
690 // =======================================================================
691 void OpenGl_FrameBuffer::BindBuffer (const Handle(OpenGl_Context)& theGlCtx)
693 theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
694 theGlCtx->SetFrameBufferSRGB (true);
697 // =======================================================================
698 // function : BindDrawBuffer
700 // =======================================================================
701 void OpenGl_FrameBuffer::BindDrawBuffer (const Handle(OpenGl_Context)& theGlCtx)
703 theGlCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myGlFBufferId);
704 theGlCtx->SetFrameBufferSRGB (true);
707 // =======================================================================
708 // function : BindReadBuffer
710 // =======================================================================
711 void OpenGl_FrameBuffer::BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx)
713 theGlCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, myGlFBufferId);
716 // =======================================================================
717 // function : UnbindBuffer
719 // =======================================================================
720 void OpenGl_FrameBuffer::UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx)
722 if (!theGlCtx->DefaultFrameBuffer().IsNull()
723 && theGlCtx->DefaultFrameBuffer().operator->() != this)
725 theGlCtx->DefaultFrameBuffer()->BindBuffer (theGlCtx);
729 theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, NO_FRAMEBUFFER);
730 theGlCtx->SetFrameBufferSRGB (false);
734 // =======================================================================
735 // function : getAligned
737 // =======================================================================
738 inline Standard_Size getAligned (const Standard_Size theNumber,
739 const Standard_Size theAlignment)
741 return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
745 inline void convertRowFromRgba (T* theRgbRow,
746 const Image_ColorRGBA* theRgbaRow,
747 const Standard_Size theWidth)
749 for (Standard_Size aCol = 0; aCol < theWidth; ++aCol)
751 const Image_ColorRGBA& anRgba = theRgbaRow[aCol];
752 T& anRgb = theRgbRow[aCol];
753 anRgb.r() = anRgba.r();
754 anRgb.g() = anRgba.g();
755 anRgb.b() = anRgba.b();
759 // =======================================================================
760 // function : BufferDump
762 // =======================================================================
763 Standard_Boolean OpenGl_FrameBuffer::BufferDump (const Handle(OpenGl_Context)& theGlCtx,
764 const Handle(OpenGl_FrameBuffer)& theFbo,
765 Image_PixMap& theImage,
766 Graphic3d_BufferType theBufferType)
768 if (theGlCtx.IsNull()
769 || theImage.IsEmpty())
771 return Standard_False;
776 bool toSwapRgbaBgra = false;
777 bool toConvRgba2Rgb = false;
778 switch (theImage.Format())
780 #if !defined(GL_ES_VERSION_2_0)
781 case Image_Format_Gray:
782 aFormat = GL_DEPTH_COMPONENT;
783 aType = GL_UNSIGNED_BYTE;
785 case Image_Format_GrayF:
786 aFormat = GL_DEPTH_COMPONENT;
789 case Image_Format_RGF:
793 case Image_Format_RGB:
795 aType = GL_UNSIGNED_BYTE;
797 case Image_Format_BGR:
799 aType = GL_UNSIGNED_BYTE;
801 case Image_Format_BGRA:
802 case Image_Format_BGR32:
804 aType = GL_UNSIGNED_BYTE;
806 case Image_Format_BGRF:
810 case Image_Format_BGRAF:
815 case Image_Format_Gray:
816 case Image_Format_GrayF:
817 case Image_Format_BGRF:
818 case Image_Format_BGRAF:
819 case Image_Format_RGF:
820 return Standard_False;
821 case Image_Format_BGRA:
822 case Image_Format_BGR32:
824 aType = GL_UNSIGNED_BYTE;
825 toSwapRgbaBgra = true;
827 case Image_Format_BGR:
828 case Image_Format_RGB:
830 aType = GL_UNSIGNED_BYTE;
831 toConvRgba2Rgb = true;
834 case Image_Format_RGBA:
835 case Image_Format_RGB32:
837 aType = GL_UNSIGNED_BYTE;
839 case Image_Format_RGBF:
843 case Image_Format_RGBAF:
847 case Image_Format_Alpha:
848 case Image_Format_AlphaF:
849 return Standard_False; // GL_ALPHA is no more supported in core context
850 case Image_Format_UNKNOWN:
851 return Standard_False;
856 return Standard_False;
859 #if !defined(GL_ES_VERSION_2_0)
860 GLint aReadBufferPrev = GL_BACK;
861 if (theBufferType == Graphic3d_BT_Depth
862 && aFormat != GL_DEPTH_COMPONENT)
864 return Standard_False;
867 (void )theBufferType;
871 if (!theFbo.IsNull() && theFbo->IsValid())
873 theFbo->BindBuffer (theGlCtx);
877 #if !defined(GL_ES_VERSION_2_0)
878 glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
879 GLint aDrawBufferPrev = GL_BACK;
880 glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
881 glReadBuffer (aDrawBufferPrev);
886 const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
887 glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
888 bool isBatchCopy = !theImage.IsTopDown();
890 const GLint anExtraBytes = GLint(theImage.RowExtraBytes());
891 GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
892 Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
893 if (anExtraBytes < anAligment)
897 else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
902 #if !defined(GL_ES_VERSION_2_0)
903 glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
905 if (aPixelsWidth != 0)
912 Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
913 const Standard_Size aRowSize = theImage.SizeX() * 4;
914 NCollection_Buffer aRowBuffer (anAlloc);
915 if (!aRowBuffer.Allocate (aRowSize))
917 return Standard_False;
920 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
922 // Image_PixMap rows indexation always starts from the upper corner
923 // while order in memory depends on the flag and processed by ChangeRow() method
924 glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, aRowBuffer.ChangeData());
925 const Image_ColorRGBA* aRowDataRgba = (const Image_ColorRGBA* )aRowBuffer.Data();
926 if (theImage.Format() == Image_Format_BGR)
928 convertRowFromRgba ((Image_ColorBGR* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
932 convertRowFromRgba ((Image_ColorRGB* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
936 else if (!isBatchCopy)
939 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
941 // Image_PixMap rows indexation always starts from the upper corner
942 // while order in memory depends on the flag and processed by ChangeRow() method
943 glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
948 glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
950 const bool hasErrors = theGlCtx->ResetErrors (true);
952 glPixelStorei (GL_PACK_ALIGNMENT, 1);
953 #if !defined(GL_ES_VERSION_2_0)
954 glPixelStorei (GL_PACK_ROW_LENGTH, 0);
957 if (!theFbo.IsNull() && theFbo->IsValid())
959 theFbo->UnbindBuffer (theGlCtx);
963 #if !defined(GL_ES_VERSION_2_0)
964 glReadBuffer (aReadBufferPrev);
970 Image_PixMap::SwapRgbaBgra (theImage);
976 // =======================================================================
977 // function : EstimatedDataSize
979 // =======================================================================
980 Standard_Size OpenGl_FrameBuffer::EstimatedDataSize() const
987 Standard_Size aSize = 0;
988 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
990 aSize += aTextureIt.Value()->EstimatedDataSize();
992 if (!myDepthStencilTexture.IsNull())
994 aSize += myDepthStencilTexture->EstimatedDataSize();
996 if (myGlColorRBufferId != NO_RENDERBUFFER
997 && !myColorFormats.IsEmpty())
999 aSize += OpenGl_Texture::PixelSizeOfPixelFormat (myColorFormats.First()) * myInitVPSizeX * myInitVPSizeY;
1001 if (myGlDepthRBufferId != NO_RENDERBUFFER)
1003 aSize += OpenGl_Texture::PixelSizeOfPixelFormat (myDepthFormat) * myInitVPSizeX * myInitVPSizeY;