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())
43 // =======================================================================
44 // function : getDepthDataFormat
46 // =======================================================================
47 bool OpenGl_FrameBuffer::getDepthDataFormat (GLint theTextFormat,
48 GLenum& thePixelFormat,
51 switch (theTextFormat)
53 case GL_DEPTH24_STENCIL8:
55 thePixelFormat = GL_DEPTH_STENCIL;
56 theDataType = GL_UNSIGNED_INT_24_8;
59 case GL_DEPTH32F_STENCIL8:
61 thePixelFormat = GL_DEPTH_STENCIL;
62 theDataType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
65 case GL_DEPTH_COMPONENT16:
67 thePixelFormat = GL_DEPTH_COMPONENT;
68 theDataType = GL_UNSIGNED_SHORT;
71 case GL_DEPTH_COMPONENT24:
73 thePixelFormat = GL_DEPTH_COMPONENT;
74 theDataType = GL_UNSIGNED_INT;
77 case GL_DEPTH_COMPONENT32F:
79 thePixelFormat = GL_DEPTH_COMPONENT;
80 theDataType = GL_FLOAT;
87 // =======================================================================
88 // function : getColorDataFormat
90 // =======================================================================
91 bool OpenGl_FrameBuffer::getColorDataFormat (const Handle(OpenGl_Context)& theGlContext,
93 GLenum& thePixelFormat,
96 switch (theTextFormat)
100 thePixelFormat = GL_RGBA;
101 theDataType = GL_FLOAT;
106 thePixelFormat = GL_RED;
107 theDataType = GL_FLOAT;
112 thePixelFormat = GL_RGBA;
113 theDataType = GL_HALF_FLOAT;
114 if (theGlContext->hasHalfFloatBuffer == OpenGl_FeatureInExtensions)
116 #if defined(GL_ES_VERSION_2_0)
117 theDataType = GL_HALF_FLOAT_OES;
119 theDataType = GL_FLOAT;
126 thePixelFormat = GL_RED;
127 theDataType = GL_HALF_FLOAT;
128 if (theGlContext->hasHalfFloatBuffer == OpenGl_FeatureInExtensions)
130 #if defined(GL_ES_VERSION_2_0)
131 theDataType = GL_HALF_FLOAT_OES;
133 theDataType = GL_FLOAT;
141 thePixelFormat = GL_RGBA;
142 theDataType = GL_UNSIGNED_BYTE;
148 thePixelFormat = GL_RGB;
149 theDataType = GL_UNSIGNED_BYTE;
156 // =======================================================================
157 // function : OpenGl_FrameBuffer
159 // =======================================================================
160 OpenGl_FrameBuffer::OpenGl_FrameBuffer()
166 myDepthFormat (GL_DEPTH24_STENCIL8),
167 myGlFBufferId (NO_FRAMEBUFFER),
168 myGlColorRBufferId (NO_RENDERBUFFER),
169 myGlDepthRBufferId (NO_RENDERBUFFER),
170 myIsOwnBuffer (false),
171 myIsOwnDepth (false),
172 myDepthStencilTexture (new OpenGl_Texture())
174 myColorFormats.Append (GL_RGBA8);
175 myColorTextures.Append (new OpenGl_Texture());
178 // =======================================================================
179 // function : ~OpenGl_FrameBuffer
181 // =======================================================================
182 OpenGl_FrameBuffer::~OpenGl_FrameBuffer()
187 // =======================================================================
190 // =======================================================================
191 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
192 const GLsizei theSizeX,
193 const GLsizei theSizeY,
194 const GLint theColorFormat,
195 const GLint theDepthFormat,
196 const GLsizei theNbSamples)
198 OpenGl_ColorFormats aColorFormats;
200 aColorFormats.Append (theColorFormat);
202 return Init (theGlContext, theSizeX, theSizeY, aColorFormats, theDepthFormat, theNbSamples);
205 // =======================================================================
208 // =======================================================================
209 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
210 const GLsizei theSizeX,
211 const GLsizei theSizeY,
212 const OpenGl_ColorFormats& theColorFormats,
213 const Handle(OpenGl_Texture)& theDepthStencilTexture,
214 const GLsizei theNbSamples)
216 myColorFormats = theColorFormats;
218 OpenGl_TextureArray aTextures (myColorTextures);
219 if (!myColorTextures.IsEmpty())
221 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
223 aTextureIt.Value()->Release (theGlContext.operator->());
225 myColorTextures.Clear();
227 for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength)
229 myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture());
232 myDepthFormat = theDepthStencilTexture->GetFormat();
233 myNbSamples = theNbSamples;
234 if (theGlContext->arbFBO == NULL)
236 return Standard_False;
239 // clean up previous state
240 Release (theGlContext.operator->());
241 if (myColorFormats.IsEmpty()
242 && myDepthFormat == 0)
244 return Standard_False;
247 myDepthStencilTexture = theDepthStencilTexture;
248 myIsOwnDepth = false;
249 myIsOwnBuffer = true;
251 // setup viewport sizes as is
252 myVPSizeX = theSizeX;
253 myVPSizeY = theSizeY;
254 const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
255 const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
257 // Create the textures (will be used as color buffer and depth-stencil buffer)
258 if (theNbSamples != 0)
260 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
262 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
263 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
264 if (aColorFormat != 0
265 && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples,
266 aColorFormat, aSizeX, aSizeY))
268 Release (theGlContext.operator->());
269 return Standard_False;
275 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
277 GLenum aPixelFormat = 0;
278 GLenum aDataType = 0;
279 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
280 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
281 if (aColorFormat != 0
282 && getColorDataFormat (theGlContext, aColorFormat, aPixelFormat, aDataType)
283 && !aColorTexture->Init (theGlContext, aColorFormat,
284 aPixelFormat, aDataType,
285 aSizeX, aSizeY, Graphic3d_TOT_2D))
287 Release (theGlContext.operator->());
288 return Standard_False;
293 // Build FBO and setup it as texture
294 theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
295 theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
297 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
299 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
300 if (aColorTexture->IsValid())
302 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx,
303 aColorTexture->GetTarget(), aColorTexture->TextureId(), 0);
306 if (myDepthStencilTexture->IsValid())
308 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
309 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
310 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
312 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
313 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
314 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
315 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
318 if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
320 Release (theGlContext.operator->());
321 return Standard_False;
324 UnbindBuffer (theGlContext);
325 return Standard_True;
328 // =======================================================================
331 // =======================================================================
332 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
333 const GLsizei theSizeX,
334 const GLsizei theSizeY,
335 const OpenGl_ColorFormats& theColorFormats,
336 const GLint theDepthFormat,
337 const GLsizei theNbSamples)
339 myColorFormats = theColorFormats;
341 OpenGl_TextureArray aTextures (myColorTextures);
342 if (!myColorTextures.IsEmpty())
344 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
346 aTextureIt.Value()->Release (theGlContext.operator->());
348 myColorTextures.Clear();
350 for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength)
352 myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture());
355 myDepthFormat = theDepthFormat;
356 myNbSamples = theNbSamples;
357 myInitVPSizeX = theSizeX;
358 myInitVPSizeY = theSizeY;
359 if (theGlContext->arbFBO == NULL)
361 return Standard_False;
364 // clean up previous state
365 Release (theGlContext.operator->());
366 if (myColorFormats.IsEmpty()
367 && myDepthFormat == 0)
369 return Standard_False;
372 myIsOwnBuffer = true;
375 // setup viewport sizes as is
376 myVPSizeX = theSizeX;
377 myVPSizeY = theSizeY;
378 const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
379 const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
380 bool hasStencilRB = false;
382 // Create the textures (will be used as color buffer and depth-stencil buffer)
383 if (theNbSamples != 0)
385 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
387 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
388 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
389 if (aColorFormat != 0
390 && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples, aColorFormat, aSizeX, aSizeY))
392 Release (theGlContext.operator->());
393 return Standard_False;
396 if (myDepthFormat != 0
397 && !myDepthStencilTexture->Init2DMultisample (theGlContext, theNbSamples, myDepthFormat, aSizeX, aSizeY))
399 Release (theGlContext.operator->());
400 return Standard_False;
405 GLenum aPixelFormat = 0;
406 GLenum aDataType = 0;
408 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
410 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
411 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
412 if (aColorFormat != 0
413 && getColorDataFormat (theGlContext, aColorFormat, aPixelFormat, aDataType)
414 && !aColorTexture->Init (theGlContext, aColorFormat,
415 aPixelFormat, aDataType,
416 aSizeX, aSizeY, Graphic3d_TOT_2D))
418 Release (theGlContext.operator->());
419 return Standard_False;
423 // extensions (GL_OES_packed_depth_stencil, GL_OES_depth_texture) + GL version might be used to determine supported formats
424 // instead of just trying to create such texture
425 if (myDepthFormat != 0
426 && getDepthDataFormat (myDepthFormat, aPixelFormat, aDataType)
427 && !myDepthStencilTexture->Init (theGlContext, myDepthFormat,
428 aPixelFormat, aDataType,
429 aSizeX, aSizeY, Graphic3d_TOT_2D))
431 TCollection_ExtendedString aMsg = TCollection_ExtendedString()
432 + "Warning! Depth textures are not supported by hardware!";
433 theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
434 GL_DEBUG_TYPE_PORTABILITY,
436 GL_DEBUG_SEVERITY_HIGH,
439 hasStencilRB = aPixelFormat == GL_DEPTH_STENCIL
440 && theGlContext->extPDS;
441 GLint aDepthStencilFormat = hasStencilRB
442 ? GL_DEPTH24_STENCIL8
443 : GL_DEPTH_COMPONENT16;
445 theGlContext->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId);
446 theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId);
447 theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, aDepthStencilFormat, aSizeX, aSizeY);
448 theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
452 // Build FBO and setup it as texture
453 theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
454 theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
455 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
457 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
458 if (aColorTexture->IsValid())
460 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx,
461 aColorTexture->GetTarget(), aColorTexture->TextureId(), 0);
464 if (myDepthStencilTexture->IsValid())
466 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
467 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
468 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
470 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
471 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
472 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
473 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
476 else if (myGlDepthRBufferId != NO_RENDERBUFFER)
478 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
479 theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, hasStencilRB ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT,
480 GL_RENDERBUFFER, myGlDepthRBufferId);
482 theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
483 GL_RENDERBUFFER, myGlDepthRBufferId);
486 theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
487 GL_RENDERBUFFER, myGlDepthRBufferId);
491 if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
493 Release (theGlContext.operator->());
494 return Standard_False;
497 UnbindBuffer (theGlContext);
498 return Standard_True;
501 // =======================================================================
502 // function : InitLazy
504 // =======================================================================
505 Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext,
506 const GLsizei theViewportSizeX,
507 const GLsizei theViewportSizeY,
508 const GLint theColorFormat,
509 const GLint theDepthFormat,
510 const GLsizei theNbSamples)
512 OpenGl_ColorFormats aColorFormats;
514 aColorFormats.Append (theColorFormat);
516 return InitLazy (theGlContext, theViewportSizeX, theViewportSizeY, aColorFormats, theDepthFormat, theNbSamples);
519 // =======================================================================
520 // function : InitLazy
522 // =======================================================================
523 Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext,
524 const GLsizei theViewportSizeX,
525 const GLsizei theViewportSizeY,
526 const OpenGl_ColorFormats& theColorFormats,
527 const GLint theDepthFormat,
528 const GLsizei theNbSamples)
530 if (myVPSizeX == theViewportSizeX
531 && myVPSizeY == theViewportSizeY
532 && myColorFormats == theColorFormats
533 && myDepthFormat == theDepthFormat
534 && myNbSamples == theNbSamples)
539 return Init (theGlContext, theViewportSizeX, theViewportSizeY, theColorFormats, theDepthFormat, theNbSamples);
542 // =======================================================================
543 // function : InitWithRB
545 // =======================================================================
546 Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& theGlCtx,
547 const GLsizei theSizeX,
548 const GLsizei theSizeY,
549 const GLint theColorFormat,
550 const GLint theDepthFormat,
551 const GLuint theColorRBufferFromWindow)
553 myColorFormats.Clear();
554 myColorFormats.Append (theColorFormat);
555 if (!myColorTextures.IsEmpty())
557 Handle(OpenGl_Texture) aTexutre = myColorTextures.First();
558 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
560 aTextureIt.Value()->Release (theGlCtx.operator->());
562 myColorTextures.Clear();
563 myColorTextures.Append (aTexutre);
566 myDepthFormat = theDepthFormat;
568 myInitVPSizeX = theSizeX;
569 myInitVPSizeY = theSizeY;
570 if (theGlCtx->arbFBO == NULL)
572 return Standard_False;
575 // clean up previous state
576 Release (theGlCtx.operator->());
578 myIsOwnBuffer = true;
581 // setup viewport sizes as is
582 myVPSizeX = theSizeX;
583 myVPSizeY = theSizeY;
584 const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
585 const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
587 // Create the render-buffers
588 if (theColorRBufferFromWindow != NO_RENDERBUFFER)
590 myGlColorRBufferId = theColorRBufferFromWindow;
592 else if (theColorFormat != 0)
594 theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlColorRBufferId);
595 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlColorRBufferId);
596 theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, theColorFormat, aSizeX, aSizeY);
599 bool hasStencilRB = false;
600 if (myDepthFormat != 0)
602 GLenum aPixelFormat = 0;
603 GLenum aDataType = 0;
604 getDepthDataFormat (myDepthFormat, aPixelFormat, aDataType);
605 hasStencilRB = aPixelFormat == GL_DEPTH_STENCIL;
607 theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId);
608 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId);
609 theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, myDepthFormat, aSizeX, aSizeY);
610 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
614 theGlCtx->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
615 theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
616 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
617 GL_RENDERBUFFER, myGlColorRBufferId);
618 if (myGlDepthRBufferId != NO_RENDERBUFFER)
620 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
621 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, hasStencilRB ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT,
622 GL_RENDERBUFFER, myGlDepthRBufferId);
624 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
625 GL_RENDERBUFFER, myGlDepthRBufferId);
628 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
629 GL_RENDERBUFFER, myGlDepthRBufferId);
633 if (theGlCtx->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
635 UnbindBuffer (theGlCtx);
636 Release (theGlCtx.operator->());
637 return Standard_False;
640 UnbindBuffer (theGlCtx);
641 return Standard_True;
644 // =======================================================================
645 // function : InitWrapper
647 // =======================================================================
648 Standard_Boolean OpenGl_FrameBuffer::InitWrapper (const Handle(OpenGl_Context)& theGlCtx)
651 if (theGlCtx->arbFBO == NULL)
653 return Standard_False;
656 // clean up previous state
657 Release (theGlCtx.operator->());
659 GLint anFbo = GLint(NO_FRAMEBUFFER);
660 ::glGetIntegerv (GL_FRAMEBUFFER_BINDING, &anFbo);
661 if (anFbo == GLint(NO_FRAMEBUFFER))
663 return Standard_False;
666 GLint aColorType = 0;
668 GLint aDepthType = 0;
670 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aColorType);
671 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aDepthType);
673 myGlFBufferId = GLuint(anFbo);
674 myIsOwnBuffer = false;
675 myIsOwnDepth = false;
676 if (aColorType == GL_RENDERBUFFER)
678 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aColorId);
679 myGlColorRBufferId = aColorId;
681 else if (aColorType != GL_NONE)
683 TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), color attachment of unsupported type has been skipped!";
684 theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
687 GL_DEBUG_SEVERITY_HIGH,
691 if (aDepthType == GL_RENDERBUFFER)
693 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aDepthId);
694 myGlDepthRBufferId = aDepthId;
696 else if (aDepthType != GL_NONE)
698 TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), depth attachment of unsupported type has been skipped!";
699 theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
702 GL_DEBUG_SEVERITY_HIGH,
706 // retrieve dimensions
707 GLuint aRBuffer = myGlColorRBufferId != NO_RENDERBUFFER ? myGlColorRBufferId : myGlDepthRBufferId;
708 if (aRBuffer != NO_RENDERBUFFER)
710 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, aRBuffer);
711 theGlCtx->arbFBO->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &myVPSizeX);
712 theGlCtx->arbFBO->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &myVPSizeY);
713 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
716 return aRBuffer != NO_RENDERBUFFER;
719 // =======================================================================
720 // function : Release
722 // =======================================================================
723 void OpenGl_FrameBuffer::Release (OpenGl_Context* theGlCtx)
725 if (isValidFrameBuffer())
727 // application can not handle this case by exception - this is bug in code
728 Standard_ASSERT_RETURN (theGlCtx != NULL,
729 "OpenGl_FrameBuffer destroyed without GL context! Possible GPU memory leakage...",);
730 if (theGlCtx->IsValid()
733 theGlCtx->arbFBO->glDeleteFramebuffers (1, &myGlFBufferId);
734 if (myGlColorRBufferId != NO_RENDERBUFFER)
736 theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlColorRBufferId);
738 if (myGlDepthRBufferId != NO_RENDERBUFFER)
740 theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlDepthRBufferId);
743 myGlFBufferId = NO_FRAMEBUFFER;
744 myGlColorRBufferId = NO_RENDERBUFFER;
745 myGlDepthRBufferId = NO_RENDERBUFFER;
746 myIsOwnBuffer = false;
749 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
751 myColorTextures (aColorBufferIdx)->Release (theGlCtx);
756 myDepthStencilTexture->Release (theGlCtx);
757 myIsOwnDepth = false;
764 // =======================================================================
765 // function : SetupViewport
767 // =======================================================================
768 void OpenGl_FrameBuffer::SetupViewport (const Handle(OpenGl_Context)& theGlCtx)
770 const Standard_Integer aViewport[4] = { 0, 0, myVPSizeX, myVPSizeY };
771 theGlCtx->ResizeViewport (aViewport);
774 // =======================================================================
775 // function : ChangeViewport
777 // =======================================================================
778 void OpenGl_FrameBuffer::ChangeViewport (const GLsizei theVPSizeX,
779 const GLsizei theVPSizeY)
781 myVPSizeX = theVPSizeX;
782 myVPSizeY = theVPSizeY;
785 // =======================================================================
786 // function : BindBuffer
788 // =======================================================================
789 void OpenGl_FrameBuffer::BindBuffer (const Handle(OpenGl_Context)& theGlCtx)
791 theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
794 // =======================================================================
795 // function : BindDrawBuffer
797 // =======================================================================
798 void OpenGl_FrameBuffer::BindDrawBuffer (const Handle(OpenGl_Context)& theGlCtx)
800 theGlCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myGlFBufferId);
803 // =======================================================================
804 // function : BindReadBuffer
806 // =======================================================================
807 void OpenGl_FrameBuffer::BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx)
809 theGlCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, myGlFBufferId);
812 // =======================================================================
813 // function : UnbindBuffer
815 // =======================================================================
816 void OpenGl_FrameBuffer::UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx)
818 if (!theGlCtx->DefaultFrameBuffer().IsNull()
819 && theGlCtx->DefaultFrameBuffer().operator->() != this)
821 theGlCtx->DefaultFrameBuffer()->BindBuffer (theGlCtx);
825 theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, NO_FRAMEBUFFER);
829 // =======================================================================
830 // function : getAligned
832 // =======================================================================
833 inline Standard_Size getAligned (const Standard_Size theNumber,
834 const Standard_Size theAlignment)
836 return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
840 inline void convertRowFromRgba (T* theRgbRow,
841 const Image_ColorRGBA* theRgbaRow,
842 const Standard_Size theWidth)
844 for (Standard_Size aCol = 0; aCol < theWidth; ++aCol)
846 const Image_ColorRGBA& anRgba = theRgbaRow[aCol];
847 T& anRgb = theRgbRow[aCol];
848 anRgb.r() = anRgba.r();
849 anRgb.g() = anRgba.g();
850 anRgb.b() = anRgba.b();
854 // =======================================================================
855 // function : BufferDump
857 // =======================================================================
858 Standard_Boolean OpenGl_FrameBuffer::BufferDump (const Handle(OpenGl_Context)& theGlCtx,
859 const Handle(OpenGl_FrameBuffer)& theFbo,
860 Image_PixMap& theImage,
861 Graphic3d_BufferType theBufferType)
863 if (theGlCtx.IsNull()
864 || theImage.IsEmpty())
866 return Standard_False;
871 bool toSwapRgbaBgra = false;
872 bool toConvRgba2Rgb = false;
873 switch (theImage.Format())
875 #if !defined(GL_ES_VERSION_2_0)
876 case Image_Format_Gray:
877 aFormat = GL_DEPTH_COMPONENT;
878 aType = GL_UNSIGNED_BYTE;
880 case Image_Format_GrayF:
881 aFormat = GL_DEPTH_COMPONENT;
884 case Image_Format_RGB:
886 aType = GL_UNSIGNED_BYTE;
888 case Image_Format_BGR:
890 aType = GL_UNSIGNED_BYTE;
892 case Image_Format_BGRA:
893 case Image_Format_BGR32:
895 aType = GL_UNSIGNED_BYTE;
897 case Image_Format_BGRF:
901 case Image_Format_BGRAF:
906 case Image_Format_Gray:
907 case Image_Format_GrayF:
908 case Image_Format_BGRF:
909 case Image_Format_BGRAF:
910 return Standard_False;
911 case Image_Format_BGRA:
912 case Image_Format_BGR32:
914 aType = GL_UNSIGNED_BYTE;
915 toSwapRgbaBgra = true;
917 case Image_Format_BGR:
918 case Image_Format_RGB:
920 aType = GL_UNSIGNED_BYTE;
921 toConvRgba2Rgb = true;
924 case Image_Format_RGBA:
925 case Image_Format_RGB32:
927 aType = GL_UNSIGNED_BYTE;
929 case Image_Format_RGBF:
933 case Image_Format_RGBAF:
937 case Image_Format_Alpha:
938 case Image_Format_AlphaF:
939 return Standard_False; // GL_ALPHA is no more supported in core context
940 case Image_Format_UNKNOWN:
941 return Standard_False;
946 return Standard_False;
949 #if !defined(GL_ES_VERSION_2_0)
950 GLint aReadBufferPrev = GL_BACK;
951 if (theBufferType == Graphic3d_BT_Depth
952 && aFormat != GL_DEPTH_COMPONENT)
954 return Standard_False;
957 (void )theBufferType;
961 if (!theFbo.IsNull() && theFbo->IsValid())
963 theFbo->BindBuffer (theGlCtx);
967 #if !defined(GL_ES_VERSION_2_0)
968 glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
969 GLint aDrawBufferPrev = GL_BACK;
970 glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
971 glReadBuffer (aDrawBufferPrev);
976 const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
977 glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
978 bool isBatchCopy = !theImage.IsTopDown();
980 const GLint anExtraBytes = GLint(theImage.RowExtraBytes());
981 GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
982 Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
983 if (anExtraBytes < anAligment)
987 else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
992 #if !defined(GL_ES_VERSION_2_0)
993 glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
995 if (aPixelsWidth != 0)
1002 Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
1003 const Standard_Size aRowSize = theImage.SizeX() * 4;
1004 NCollection_Buffer aRowBuffer (anAlloc);
1005 if (!aRowBuffer.Allocate (aRowSize))
1007 return Standard_False;
1010 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
1012 // Image_PixMap rows indexation always starts from the upper corner
1013 // while order in memory depends on the flag and processed by ChangeRow() method
1014 glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, aRowBuffer.ChangeData());
1015 const Image_ColorRGBA* aRowDataRgba = (const Image_ColorRGBA* )aRowBuffer.Data();
1016 if (theImage.Format() == Image_Format_BGR)
1018 convertRowFromRgba ((Image_ColorBGR* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
1022 convertRowFromRgba ((Image_ColorRGB* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
1026 else if (!isBatchCopy)
1029 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
1031 // Image_PixMap rows indexation always starts from the upper corner
1032 // while order in memory depends on the flag and processed by ChangeRow() method
1033 glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
1038 glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
1040 const bool hasErrors = theGlCtx->ResetErrors (true);
1042 glPixelStorei (GL_PACK_ALIGNMENT, 1);
1043 #if !defined(GL_ES_VERSION_2_0)
1044 glPixelStorei (GL_PACK_ROW_LENGTH, 0);
1047 if (!theFbo.IsNull() && theFbo->IsValid())
1049 theFbo->UnbindBuffer (theGlCtx);
1053 #if !defined(GL_ES_VERSION_2_0)
1054 glReadBuffer (aReadBufferPrev);
1060 Image_PixMap::SwapRgbaBgra (theImage);
1066 // =======================================================================
1067 // function : EstimatedDataSize
1069 // =======================================================================
1070 Standard_Size OpenGl_FrameBuffer::EstimatedDataSize() const
1077 Standard_Size aSize = 0;
1078 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
1080 aSize += aTextureIt.Value()->EstimatedDataSize();
1082 if (!myDepthStencilTexture.IsNull())
1084 aSize += myDepthStencilTexture->EstimatedDataSize();
1086 if (myGlColorRBufferId != NO_RENDERBUFFER
1087 && !myColorFormats.IsEmpty())
1089 aSize += OpenGl_Texture::PixelSizeOfPixelFormat (myColorFormats.First()) * myInitVPSizeX * myInitVPSizeY;
1091 if (myGlDepthRBufferId != NO_RENDERBUFFER)
1093 aSize += OpenGl_Texture::PixelSizeOfPixelFormat (myDepthFormat) * myInitVPSizeX * myInitVPSizeY;