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 : OpenGl_FrameBuffer
46 // =======================================================================
47 OpenGl_FrameBuffer::OpenGl_FrameBuffer()
53 myDepthFormat (GL_DEPTH24_STENCIL8),
54 myGlFBufferId (NO_FRAMEBUFFER),
55 myGlColorRBufferId (NO_RENDERBUFFER),
56 myGlDepthRBufferId (NO_RENDERBUFFER),
57 myIsOwnBuffer (false),
59 myDepthStencilTexture (new OpenGl_Texture())
61 myColorFormats.Append (GL_RGBA8);
62 myColorTextures.Append (new OpenGl_Texture());
65 // =======================================================================
66 // function : ~OpenGl_FrameBuffer
68 // =======================================================================
69 OpenGl_FrameBuffer::~OpenGl_FrameBuffer()
74 // =======================================================================
77 // =======================================================================
78 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
79 const GLsizei theSizeX,
80 const GLsizei theSizeY,
81 const GLint theColorFormat,
82 const GLint theDepthFormat,
83 const GLsizei theNbSamples)
85 OpenGl_ColorFormats aColorFormats;
87 aColorFormats.Append (theColorFormat);
89 return Init (theGlContext, theSizeX, theSizeY, aColorFormats, theDepthFormat, theNbSamples);
92 // =======================================================================
95 // =======================================================================
96 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
97 const GLsizei theSizeX,
98 const GLsizei theSizeY,
99 const OpenGl_ColorFormats& theColorFormats,
100 const Handle(OpenGl_Texture)& theDepthStencilTexture,
101 const GLsizei theNbSamples)
103 myColorFormats = theColorFormats;
105 OpenGl_TextureArray aTextures (myColorTextures);
106 if (!myColorTextures.IsEmpty())
108 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
110 aTextureIt.Value()->Release (theGlContext.operator->());
112 myColorTextures.Clear();
114 for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength)
116 myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture());
119 myDepthFormat = theDepthStencilTexture->GetFormat();
120 myNbSamples = theNbSamples;
121 if (theGlContext->arbFBO == NULL)
123 return Standard_False;
126 // clean up previous state
127 Release (theGlContext.operator->());
128 if (myColorFormats.IsEmpty()
129 && myDepthFormat == 0)
131 return Standard_False;
134 myDepthStencilTexture = theDepthStencilTexture;
135 myIsOwnDepth = false;
136 myIsOwnBuffer = true;
138 // setup viewport sizes as is
139 myVPSizeX = theSizeX;
140 myVPSizeY = theSizeY;
141 const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
142 const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
144 // Create the textures (will be used as color buffer and depth-stencil buffer)
145 if (theNbSamples != 0)
147 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
149 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
150 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
151 if (aColorFormat != 0
152 && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples,
153 aColorFormat, aSizeX, aSizeY))
155 Release (theGlContext.get());
156 return Standard_False;
162 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
164 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
165 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
166 const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindSizedFormat (theGlContext, aColorFormat);
167 if (aFormat.IsValid()
168 && !aColorTexture->Init (theGlContext, aFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TOT_2D))
170 Release (theGlContext.get());
171 return Standard_False;
176 // Build FBO and setup it as texture
177 theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
178 theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
180 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
182 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
183 if (aColorTexture->IsValid())
185 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx,
186 aColorTexture->GetTarget(), aColorTexture->TextureId(), 0);
189 if (myDepthStencilTexture->IsValid())
191 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
192 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
193 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
195 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
196 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
197 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
198 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
201 if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
203 Release (theGlContext.operator->());
204 return Standard_False;
207 UnbindBuffer (theGlContext);
208 return Standard_True;
211 // =======================================================================
214 // =======================================================================
215 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
216 const GLsizei theSizeX,
217 const GLsizei theSizeY,
218 const OpenGl_ColorFormats& theColorFormats,
219 const GLint theDepthFormat,
220 const GLsizei theNbSamples)
222 myColorFormats = theColorFormats;
224 OpenGl_TextureArray aTextures (myColorTextures);
225 if (!myColorTextures.IsEmpty())
227 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
229 aTextureIt.Value()->Release (theGlContext.operator->());
231 myColorTextures.Clear();
233 for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength)
235 myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture());
238 myDepthFormat = theDepthFormat;
239 myNbSamples = theNbSamples;
240 myInitVPSizeX = theSizeX;
241 myInitVPSizeY = theSizeY;
242 if (theGlContext->arbFBO == NULL)
244 return Standard_False;
247 // clean up previous state
248 Release (theGlContext.operator->());
249 if (myColorFormats.IsEmpty()
250 && myDepthFormat == 0)
252 return Standard_False;
255 myIsOwnBuffer = true;
258 // setup viewport sizes as is
259 myVPSizeX = theSizeX;
260 myVPSizeY = theSizeY;
261 const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
262 const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
263 bool hasStencilRB = false;
265 // Create the textures (will be used as color buffer and depth-stencil buffer)
266 if (theNbSamples != 0)
268 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
270 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
271 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
272 if (aColorFormat != 0
273 && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples, aColorFormat, aSizeX, aSizeY))
275 Release (theGlContext.operator->());
276 return Standard_False;
279 if (myDepthFormat != 0
280 && !myDepthStencilTexture->Init2DMultisample (theGlContext, theNbSamples, myDepthFormat, aSizeX, aSizeY))
282 Release (theGlContext.operator->());
283 return Standard_False;
288 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
290 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
291 const GLint aColorFormat = myColorFormats (aColorBufferIdx);
292 const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindSizedFormat (theGlContext, aColorFormat);
293 if (aFormat.IsValid()
294 && !aColorTexture->Init (theGlContext, aFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TOT_2D))
296 Release (theGlContext.operator->());
297 return Standard_False;
301 // extensions (GL_OES_packed_depth_stencil, GL_OES_depth_texture) + GL version might be used to determine supported formats
302 // instead of just trying to create such texture
303 const OpenGl_TextureFormat aDepthFormat = OpenGl_TextureFormat::FindSizedFormat (theGlContext, myDepthFormat);
304 if (aDepthFormat.IsValid()
305 && !myDepthStencilTexture->Init (theGlContext, aDepthFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TOT_2D))
307 theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
308 "Warning! Depth textures are not supported by hardware!");
310 hasStencilRB = aDepthFormat.PixelFormat() == GL_DEPTH_STENCIL
311 && theGlContext->extPDS;
312 GLint aDepthStencilFormat = hasStencilRB
313 ? GL_DEPTH24_STENCIL8
314 : GL_DEPTH_COMPONENT16;
316 theGlContext->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId);
317 theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId);
318 theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, aDepthStencilFormat, aSizeX, aSizeY);
319 theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
323 // Build FBO and setup it as texture
324 theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
325 theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
326 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
328 const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
329 if (aColorTexture->IsValid())
331 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx,
332 aColorTexture->GetTarget(), aColorTexture->TextureId(), 0);
335 if (myDepthStencilTexture->IsValid())
337 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
338 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
339 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
341 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
342 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
343 theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
344 myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
347 else if (myGlDepthRBufferId != NO_RENDERBUFFER)
349 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
350 theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, hasStencilRB ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT,
351 GL_RENDERBUFFER, myGlDepthRBufferId);
353 theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
354 GL_RENDERBUFFER, myGlDepthRBufferId);
357 theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
358 GL_RENDERBUFFER, myGlDepthRBufferId);
362 if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
364 Release (theGlContext.operator->());
365 return Standard_False;
368 UnbindBuffer (theGlContext);
369 return Standard_True;
372 // =======================================================================
373 // function : InitLazy
375 // =======================================================================
376 Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext,
377 const GLsizei theViewportSizeX,
378 const GLsizei theViewportSizeY,
379 const GLint theColorFormat,
380 const GLint theDepthFormat,
381 const GLsizei theNbSamples)
383 OpenGl_ColorFormats aColorFormats;
385 aColorFormats.Append (theColorFormat);
387 return InitLazy (theGlContext, theViewportSizeX, theViewportSizeY, aColorFormats, theDepthFormat, theNbSamples);
390 // =======================================================================
391 // function : InitLazy
393 // =======================================================================
394 Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext,
395 const GLsizei theViewportSizeX,
396 const GLsizei theViewportSizeY,
397 const OpenGl_ColorFormats& theColorFormats,
398 const GLint theDepthFormat,
399 const GLsizei theNbSamples)
401 if (myVPSizeX == theViewportSizeX
402 && myVPSizeY == theViewportSizeY
403 && myColorFormats == theColorFormats
404 && myDepthFormat == theDepthFormat
405 && myNbSamples == theNbSamples)
410 return Init (theGlContext, theViewportSizeX, theViewportSizeY, theColorFormats, theDepthFormat, theNbSamples);
413 // =======================================================================
414 // function : InitWithRB
416 // =======================================================================
417 Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& theGlCtx,
418 const GLsizei theSizeX,
419 const GLsizei theSizeY,
420 const GLint theColorFormat,
421 const GLint theDepthFormat,
422 const GLuint theColorRBufferFromWindow)
424 myColorFormats.Clear();
425 myColorFormats.Append (theColorFormat);
426 if (!myColorTextures.IsEmpty())
428 Handle(OpenGl_Texture) aTexutre = myColorTextures.First();
429 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
431 aTextureIt.Value()->Release (theGlCtx.operator->());
433 myColorTextures.Clear();
434 myColorTextures.Append (aTexutre);
437 myDepthFormat = theDepthFormat;
439 myInitVPSizeX = theSizeX;
440 myInitVPSizeY = theSizeY;
441 if (theGlCtx->arbFBO == NULL)
443 return Standard_False;
446 // clean up previous state
447 Release (theGlCtx.operator->());
449 myIsOwnBuffer = true;
452 // setup viewport sizes as is
453 myVPSizeX = theSizeX;
454 myVPSizeY = theSizeY;
455 const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
456 const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
458 // Create the render-buffers
459 if (theColorRBufferFromWindow != NO_RENDERBUFFER)
461 myGlColorRBufferId = theColorRBufferFromWindow;
463 else if (theColorFormat != 0)
465 theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlColorRBufferId);
466 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlColorRBufferId);
467 theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, theColorFormat, aSizeX, aSizeY);
470 bool hasStencilRB = false;
471 if (myDepthFormat != 0)
473 const OpenGl_TextureFormat aDepthFormat = OpenGl_TextureFormat::FindSizedFormat (theGlCtx, myDepthFormat);
474 hasStencilRB = aDepthFormat.PixelFormat() == GL_DEPTH_STENCIL;
476 theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId);
477 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId);
478 theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, myDepthFormat, aSizeX, aSizeY);
479 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
483 theGlCtx->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
484 theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
485 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
486 GL_RENDERBUFFER, myGlColorRBufferId);
487 if (myGlDepthRBufferId != NO_RENDERBUFFER)
489 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
490 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, hasStencilRB ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT,
491 GL_RENDERBUFFER, myGlDepthRBufferId);
493 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
494 GL_RENDERBUFFER, myGlDepthRBufferId);
497 theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
498 GL_RENDERBUFFER, myGlDepthRBufferId);
502 if (theGlCtx->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
504 UnbindBuffer (theGlCtx);
505 Release (theGlCtx.operator->());
506 return Standard_False;
509 UnbindBuffer (theGlCtx);
510 return Standard_True;
513 // =======================================================================
514 // function : InitWrapper
516 // =======================================================================
517 Standard_Boolean OpenGl_FrameBuffer::InitWrapper (const Handle(OpenGl_Context)& theGlCtx)
520 if (theGlCtx->arbFBO == NULL)
522 return Standard_False;
525 // clean up previous state
526 Release (theGlCtx.operator->());
528 GLint anFbo = GLint(NO_FRAMEBUFFER);
529 ::glGetIntegerv (GL_FRAMEBUFFER_BINDING, &anFbo);
530 if (anFbo == GLint(NO_FRAMEBUFFER))
532 return Standard_False;
535 GLint aColorType = 0;
537 GLint aDepthType = 0;
539 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aColorType);
540 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aDepthType);
542 myGlFBufferId = GLuint(anFbo);
543 myIsOwnBuffer = false;
544 myIsOwnDepth = false;
545 if (aColorType == GL_RENDERBUFFER)
547 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aColorId);
548 myGlColorRBufferId = aColorId;
550 else if (aColorType != GL_NONE)
552 TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), color attachment of unsupported type has been skipped!";
553 theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
556 GL_DEBUG_SEVERITY_HIGH,
560 if (aDepthType == GL_RENDERBUFFER)
562 theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aDepthId);
563 myGlDepthRBufferId = aDepthId;
565 else if (aDepthType != GL_NONE)
567 TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), depth attachment of unsupported type has been skipped!";
568 theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
571 GL_DEBUG_SEVERITY_HIGH,
575 // retrieve dimensions
576 GLuint aRBuffer = myGlColorRBufferId != NO_RENDERBUFFER ? myGlColorRBufferId : myGlDepthRBufferId;
577 if (aRBuffer != NO_RENDERBUFFER)
579 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, aRBuffer);
580 theGlCtx->arbFBO->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &myVPSizeX);
581 theGlCtx->arbFBO->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &myVPSizeY);
582 theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
585 return aRBuffer != NO_RENDERBUFFER;
588 // =======================================================================
589 // function : Release
591 // =======================================================================
592 void OpenGl_FrameBuffer::Release (OpenGl_Context* theGlCtx)
594 if (isValidFrameBuffer())
596 // application can not handle this case by exception - this is bug in code
597 Standard_ASSERT_RETURN (theGlCtx != NULL,
598 "OpenGl_FrameBuffer destroyed without GL context! Possible GPU memory leakage...",);
599 if (theGlCtx->IsValid()
602 theGlCtx->arbFBO->glDeleteFramebuffers (1, &myGlFBufferId);
603 if (myGlColorRBufferId != NO_RENDERBUFFER)
605 theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlColorRBufferId);
607 if (myGlDepthRBufferId != NO_RENDERBUFFER)
609 theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlDepthRBufferId);
612 myGlFBufferId = NO_FRAMEBUFFER;
613 myGlColorRBufferId = NO_RENDERBUFFER;
614 myGlDepthRBufferId = NO_RENDERBUFFER;
615 myIsOwnBuffer = false;
618 for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
620 myColorTextures (aColorBufferIdx)->Release (theGlCtx);
625 myDepthStencilTexture->Release (theGlCtx);
626 myIsOwnDepth = false;
633 // =======================================================================
634 // function : SetupViewport
636 // =======================================================================
637 void OpenGl_FrameBuffer::SetupViewport (const Handle(OpenGl_Context)& theGlCtx)
639 const Standard_Integer aViewport[4] = { 0, 0, myVPSizeX, myVPSizeY };
640 theGlCtx->ResizeViewport (aViewport);
643 // =======================================================================
644 // function : ChangeViewport
646 // =======================================================================
647 void OpenGl_FrameBuffer::ChangeViewport (const GLsizei theVPSizeX,
648 const GLsizei theVPSizeY)
650 myVPSizeX = theVPSizeX;
651 myVPSizeY = theVPSizeY;
654 // =======================================================================
655 // function : BindBuffer
657 // =======================================================================
658 void OpenGl_FrameBuffer::BindBuffer (const Handle(OpenGl_Context)& theGlCtx)
660 theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
661 theGlCtx->SetFrameBufferSRGB (true);
664 // =======================================================================
665 // function : BindDrawBuffer
667 // =======================================================================
668 void OpenGl_FrameBuffer::BindDrawBuffer (const Handle(OpenGl_Context)& theGlCtx)
670 theGlCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myGlFBufferId);
671 theGlCtx->SetFrameBufferSRGB (true);
674 // =======================================================================
675 // function : BindReadBuffer
677 // =======================================================================
678 void OpenGl_FrameBuffer::BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx)
680 theGlCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, myGlFBufferId);
683 // =======================================================================
684 // function : UnbindBuffer
686 // =======================================================================
687 void OpenGl_FrameBuffer::UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx)
689 if (!theGlCtx->DefaultFrameBuffer().IsNull()
690 && theGlCtx->DefaultFrameBuffer().operator->() != this)
692 theGlCtx->DefaultFrameBuffer()->BindBuffer (theGlCtx);
696 theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, NO_FRAMEBUFFER);
697 theGlCtx->SetFrameBufferSRGB (false);
701 // =======================================================================
702 // function : getAligned
704 // =======================================================================
705 inline Standard_Size getAligned (const Standard_Size theNumber,
706 const Standard_Size theAlignment)
708 return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
712 inline void convertRowFromRgba (T* theRgbRow,
713 const Image_ColorRGBA* theRgbaRow,
714 const Standard_Size theWidth)
716 for (Standard_Size aCol = 0; aCol < theWidth; ++aCol)
718 const Image_ColorRGBA& anRgba = theRgbaRow[aCol];
719 T& anRgb = theRgbRow[aCol];
720 anRgb.r() = anRgba.r();
721 anRgb.g() = anRgba.g();
722 anRgb.b() = anRgba.b();
726 // =======================================================================
727 // function : BufferDump
729 // =======================================================================
730 Standard_Boolean OpenGl_FrameBuffer::BufferDump (const Handle(OpenGl_Context)& theGlCtx,
731 const Handle(OpenGl_FrameBuffer)& theFbo,
732 Image_PixMap& theImage,
733 Graphic3d_BufferType theBufferType)
735 if (theGlCtx.IsNull()
736 || theImage.IsEmpty())
738 return Standard_False;
743 bool toSwapRgbaBgra = false;
744 bool toConvRgba2Rgb = false;
745 switch (theImage.Format())
747 #if !defined(GL_ES_VERSION_2_0)
748 case Image_Format_Gray:
749 aFormat = GL_DEPTH_COMPONENT;
750 aType = GL_UNSIGNED_BYTE;
752 case Image_Format_GrayF:
753 aFormat = GL_DEPTH_COMPONENT;
756 case Image_Format_RGB:
758 aType = GL_UNSIGNED_BYTE;
760 case Image_Format_BGR:
762 aType = GL_UNSIGNED_BYTE;
764 case Image_Format_BGRA:
765 case Image_Format_BGR32:
767 aType = GL_UNSIGNED_BYTE;
769 case Image_Format_BGRF:
773 case Image_Format_BGRAF:
778 case Image_Format_Gray:
779 case Image_Format_GrayF:
780 case Image_Format_BGRF:
781 case Image_Format_BGRAF:
782 return Standard_False;
783 case Image_Format_BGRA:
784 case Image_Format_BGR32:
786 aType = GL_UNSIGNED_BYTE;
787 toSwapRgbaBgra = true;
789 case Image_Format_BGR:
790 case Image_Format_RGB:
792 aType = GL_UNSIGNED_BYTE;
793 toConvRgba2Rgb = true;
796 case Image_Format_RGBA:
797 case Image_Format_RGB32:
799 aType = GL_UNSIGNED_BYTE;
801 case Image_Format_RGBF:
805 case Image_Format_RGBAF:
809 case Image_Format_Alpha:
810 case Image_Format_AlphaF:
811 return Standard_False; // GL_ALPHA is no more supported in core context
812 case Image_Format_UNKNOWN:
813 return Standard_False;
818 return Standard_False;
821 #if !defined(GL_ES_VERSION_2_0)
822 GLint aReadBufferPrev = GL_BACK;
823 if (theBufferType == Graphic3d_BT_Depth
824 && aFormat != GL_DEPTH_COMPONENT)
826 return Standard_False;
829 (void )theBufferType;
833 if (!theFbo.IsNull() && theFbo->IsValid())
835 theFbo->BindBuffer (theGlCtx);
839 #if !defined(GL_ES_VERSION_2_0)
840 glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
841 GLint aDrawBufferPrev = GL_BACK;
842 glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
843 glReadBuffer (aDrawBufferPrev);
848 const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
849 glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
850 bool isBatchCopy = !theImage.IsTopDown();
852 const GLint anExtraBytes = GLint(theImage.RowExtraBytes());
853 GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
854 Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
855 if (anExtraBytes < anAligment)
859 else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
864 #if !defined(GL_ES_VERSION_2_0)
865 glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
867 if (aPixelsWidth != 0)
874 Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
875 const Standard_Size aRowSize = theImage.SizeX() * 4;
876 NCollection_Buffer aRowBuffer (anAlloc);
877 if (!aRowBuffer.Allocate (aRowSize))
879 return Standard_False;
882 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
884 // Image_PixMap rows indexation always starts from the upper corner
885 // while order in memory depends on the flag and processed by ChangeRow() method
886 glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, aRowBuffer.ChangeData());
887 const Image_ColorRGBA* aRowDataRgba = (const Image_ColorRGBA* )aRowBuffer.Data();
888 if (theImage.Format() == Image_Format_BGR)
890 convertRowFromRgba ((Image_ColorBGR* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
894 convertRowFromRgba ((Image_ColorRGB* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
898 else if (!isBatchCopy)
901 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
903 // Image_PixMap rows indexation always starts from the upper corner
904 // while order in memory depends on the flag and processed by ChangeRow() method
905 glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
910 glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
912 const bool hasErrors = theGlCtx->ResetErrors (true);
914 glPixelStorei (GL_PACK_ALIGNMENT, 1);
915 #if !defined(GL_ES_VERSION_2_0)
916 glPixelStorei (GL_PACK_ROW_LENGTH, 0);
919 if (!theFbo.IsNull() && theFbo->IsValid())
921 theFbo->UnbindBuffer (theGlCtx);
925 #if !defined(GL_ES_VERSION_2_0)
926 glReadBuffer (aReadBufferPrev);
932 Image_PixMap::SwapRgbaBgra (theImage);
938 // =======================================================================
939 // function : EstimatedDataSize
941 // =======================================================================
942 Standard_Size OpenGl_FrameBuffer::EstimatedDataSize() const
949 Standard_Size aSize = 0;
950 for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
952 aSize += aTextureIt.Value()->EstimatedDataSize();
954 if (!myDepthStencilTexture.IsNull())
956 aSize += myDepthStencilTexture->EstimatedDataSize();
958 if (myGlColorRBufferId != NO_RENDERBUFFER
959 && !myColorFormats.IsEmpty())
961 aSize += OpenGl_Texture::PixelSizeOfPixelFormat (myColorFormats.First()) * myInitVPSizeX * myInitVPSizeY;
963 if (myGlDepthRBufferId != NO_RENDERBUFFER)
965 aSize += OpenGl_Texture::PixelSizeOfPixelFormat (myDepthFormat) * myInitVPSizeX * myInitVPSizeY;