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