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