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 | |
6cde53c4 |
18 | #include <NCollection_AlignedAllocator.hxx> |
fd4a6963 |
19 | #include <Standard_Assert.hxx> |
a2e4f780 |
20 | #include <TCollection_ExtendedString.hxx> |
fd4a6963 |
21 | |
92efcf78 |
22 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameBuffer,OpenGl_Resource) |
23 | |
3c4b62a4 |
24 | namespace |
25 | { |
da2a6aee |
26 | //! Checks whether two format arrays are equal or not. |
27 | static bool operator== (const OpenGl_ColorFormats& theFmt1, |
28 | const OpenGl_ColorFormats& theFmt2) |
29 | { |
30 | if (theFmt1.Length() != theFmt2.Length()) |
31 | return false; |
32 | OpenGl_ColorFormats::Iterator anIt1 (theFmt1); |
33 | OpenGl_ColorFormats::Iterator anIt2 (theFmt1); |
34 | for (; anIt1.More(); anIt1.Next(), anIt2.Next()) |
35 | { |
36 | if (anIt1.Value() != anIt2.Value()) |
37 | return false; |
38 | } |
39 | return true; |
40 | } |
41 | } |
3c4b62a4 |
42 | |
fd4a6963 |
43 | // ======================================================================= |
44 | // function : OpenGl_FrameBuffer |
45 | // purpose : |
46 | // ======================================================================= |
3c4b62a4 |
47 | OpenGl_FrameBuffer::OpenGl_FrameBuffer() |
a0b49de4 |
48 | : myInitVPSizeX (0), |
49 | myInitVPSizeY (0), |
50 | myVPSizeX (0), |
7fd59977 |
51 | myVPSizeY (0), |
3c4b62a4 |
52 | myNbSamples (0), |
3c4b62a4 |
53 | myDepthFormat (GL_DEPTH24_STENCIL8), |
7fd59977 |
54 | myGlFBufferId (NO_FRAMEBUFFER), |
a2e4f780 |
55 | myGlColorRBufferId (NO_RENDERBUFFER), |
56 | myGlDepthRBufferId (NO_RENDERBUFFER), |
57 | myIsOwnBuffer (false), |
12d6e155 |
58 | myIsOwnDepth (false), |
18f4e8e2 |
59 | myDepthStencilTexture (new OpenGl_Texture()) |
7fd59977 |
60 | { |
a1073ae2 |
61 | myColorFormats.Append (GL_RGBA8); |
62 | myColorTextures.Append (new OpenGl_Texture()); |
7fd59977 |
63 | } |
64 | |
fd4a6963 |
65 | // ======================================================================= |
66 | // function : ~OpenGl_FrameBuffer |
67 | // purpose : |
68 | // ======================================================================= |
69 | OpenGl_FrameBuffer::~OpenGl_FrameBuffer() |
70 | { |
71 | Release (NULL); |
72 | } |
73 | |
74 | // ======================================================================= |
75 | // function : Init |
76 | // purpose : |
77 | // ======================================================================= |
2166f0fa |
78 | Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext, |
a1073ae2 |
79 | const GLsizei theSizeX, |
80 | const GLsizei theSizeY, |
81 | const GLint theColorFormat, |
82 | const GLint theDepthFormat, |
83 | const GLsizei theNbSamples) |
7fd59977 |
84 | { |
a1073ae2 |
85 | OpenGl_ColorFormats aColorFormats; |
86 | |
87 | aColorFormats.Append (theColorFormat); |
88 | |
89 | return Init (theGlContext, theSizeX, theSizeY, aColorFormats, theDepthFormat, theNbSamples); |
90 | } |
91 | |
92 | // ======================================================================= |
93 | // function : Init |
94 | // purpose : |
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) |
102 | { |
103 | myColorFormats = theColorFormats; |
104 | |
105 | OpenGl_TextureArray aTextures (myColorTextures); |
106 | if (!myColorTextures.IsEmpty()) |
107 | { |
108 | for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next()) |
109 | { |
110 | aTextureIt.Value()->Release (theGlContext.operator->()); |
111 | } |
112 | myColorTextures.Clear(); |
113 | } |
114 | for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength) |
115 | { |
116 | myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture()); |
117 | } |
118 | |
119 | myDepthFormat = theDepthStencilTexture->GetFormat(); |
120 | myNbSamples = theNbSamples; |
121 | if (theGlContext->arbFBO == NULL) |
122 | { |
123 | return Standard_False; |
124 | } |
125 | |
126 | // clean up previous state |
127 | Release (theGlContext.operator->()); |
128 | if (myColorFormats.IsEmpty() |
129 | && myDepthFormat == 0) |
130 | { |
131 | return Standard_False; |
132 | } |
133 | |
134 | myDepthStencilTexture = theDepthStencilTexture; |
135 | myIsOwnDepth = false; |
136 | myIsOwnBuffer = true; |
137 | |
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; |
143 | |
144 | // Create the textures (will be used as color buffer and depth-stencil buffer) |
145 | if (theNbSamples != 0) |
146 | { |
147 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
148 | { |
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)) |
154 | { |
ba00aab7 |
155 | Release (theGlContext.get()); |
a1073ae2 |
156 | return Standard_False; |
157 | } |
158 | } |
159 | } |
160 | else |
161 | { |
162 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
163 | { |
a1073ae2 |
164 | const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); |
165 | const GLint aColorFormat = myColorFormats (aColorBufferIdx); |
ba00aab7 |
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)) |
a1073ae2 |
169 | { |
ba00aab7 |
170 | Release (theGlContext.get()); |
a1073ae2 |
171 | return Standard_False; |
172 | } |
173 | } |
174 | } |
175 | |
176 | // Build FBO and setup it as texture |
177 | theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId); |
178 | theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); |
179 | |
180 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
181 | { |
182 | const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); |
183 | if (aColorTexture->IsValid()) |
184 | { |
185 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx, |
186 | aColorTexture->GetTarget(), aColorTexture->TextureId(), 0); |
187 | } |
188 | } |
189 | if (myDepthStencilTexture->IsValid()) |
190 | { |
191 | #ifdef GL_DEPTH_STENCIL_ATTACHMENT |
192 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, |
193 | myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); |
194 | #else |
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); |
199 | #endif |
200 | } |
201 | if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) |
202 | { |
203 | Release (theGlContext.operator->()); |
204 | return Standard_False; |
205 | } |
206 | |
207 | UnbindBuffer (theGlContext); |
208 | return Standard_True; |
209 | } |
210 | |
211 | // ======================================================================= |
212 | // function : Init |
213 | // purpose : |
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) |
221 | { |
222 | myColorFormats = theColorFormats; |
223 | |
224 | OpenGl_TextureArray aTextures (myColorTextures); |
225 | if (!myColorTextures.IsEmpty()) |
226 | { |
227 | for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next()) |
228 | { |
229 | aTextureIt.Value()->Release (theGlContext.operator->()); |
230 | } |
231 | myColorTextures.Clear(); |
232 | } |
233 | for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength) |
234 | { |
235 | myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture()); |
236 | } |
237 | |
3c4b62a4 |
238 | myDepthFormat = theDepthFormat; |
239 | myNbSamples = theNbSamples; |
a0b49de4 |
240 | myInitVPSizeX = theSizeX; |
241 | myInitVPSizeY = theSizeY; |
01ca42b2 |
242 | if (theGlContext->arbFBO == NULL) |
7fd59977 |
243 | { |
7fd59977 |
244 | return Standard_False; |
245 | } |
246 | |
247 | // clean up previous state |
fd4a6963 |
248 | Release (theGlContext.operator->()); |
a1073ae2 |
249 | if (myColorFormats.IsEmpty() |
3c4b62a4 |
250 | && myDepthFormat == 0) |
251 | { |
252 | return Standard_False; |
253 | } |
7fd59977 |
254 | |
a447178e |
255 | myIsOwnBuffer = true; |
a1073ae2 |
256 | myIsOwnDepth = true; |
a447178e |
257 | |
7fd59977 |
258 | // setup viewport sizes as is |
62e1beed |
259 | myVPSizeX = theSizeX; |
260 | myVPSizeY = theSizeY; |
261 | const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2; |
262 | const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2; |
e473b95f |
263 | bool hasStencilRB = false; |
7fd59977 |
264 | |
18f4e8e2 |
265 | // Create the textures (will be used as color buffer and depth-stencil buffer) |
3c4b62a4 |
266 | if (theNbSamples != 0) |
7fd59977 |
267 | { |
a1073ae2 |
268 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
3c4b62a4 |
269 | { |
a1073ae2 |
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)) |
274 | { |
275 | Release (theGlContext.operator->()); |
276 | return Standard_False; |
277 | } |
3c4b62a4 |
278 | } |
279 | if (myDepthFormat != 0 |
280 | && !myDepthStencilTexture->Init2DMultisample (theGlContext, theNbSamples, myDepthFormat, aSizeX, aSizeY)) |
281 | { |
282 | Release (theGlContext.operator->()); |
283 | return Standard_False; |
284 | } |
7fd59977 |
285 | } |
3c4b62a4 |
286 | else |
fe3a29bc |
287 | { |
a1073ae2 |
288 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
3c4b62a4 |
289 | { |
a1073ae2 |
290 | const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); |
291 | const GLint aColorFormat = myColorFormats (aColorBufferIdx); |
ba00aab7 |
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)) |
a1073ae2 |
295 | { |
296 | Release (theGlContext.operator->()); |
297 | return Standard_False; |
298 | } |
3c4b62a4 |
299 | } |
fe3a29bc |
300 | |
3c4b62a4 |
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 |
ba00aab7 |
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)) |
3c4b62a4 |
306 | { |
ba00aab7 |
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!"); |
309 | |
310 | hasStencilRB = aDepthFormat.PixelFormat() == GL_DEPTH_STENCIL |
e473b95f |
311 | && theGlContext->extPDS; |
312 | GLint aDepthStencilFormat = hasStencilRB |
313 | ? GL_DEPTH24_STENCIL8 |
314 | : GL_DEPTH_COMPONENT16; |
315 | |
3c4b62a4 |
316 | theGlContext->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId); |
317 | theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId); |
e473b95f |
318 | theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, aDepthStencilFormat, aSizeX, aSizeY); |
3c4b62a4 |
319 | theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER); |
320 | } |
fe3a29bc |
321 | } |
322 | |
7fd59977 |
323 | // Build FBO and setup it as texture |
01ca42b2 |
324 | theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId); |
325 | theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); |
a1073ae2 |
326 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
3c4b62a4 |
327 | { |
a1073ae2 |
328 | const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); |
329 | if (aColorTexture->IsValid()) |
330 | { |
331 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx, |
332 | aColorTexture->GetTarget(), aColorTexture->TextureId(), 0); |
333 | } |
3c4b62a4 |
334 | } |
fe3a29bc |
335 | if (myDepthStencilTexture->IsValid()) |
336 | { |
337 | #ifdef GL_DEPTH_STENCIL_ATTACHMENT |
338 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, |
3c4b62a4 |
339 | myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); |
fe3a29bc |
340 | #else |
341 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, |
3c4b62a4 |
342 | myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); |
fe3a29bc |
343 | theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, |
3c4b62a4 |
344 | myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); |
fe3a29bc |
345 | #endif |
346 | } |
347 | else if (myGlDepthRBufferId != NO_RENDERBUFFER) |
348 | { |
e473b95f |
349 | #ifdef GL_DEPTH_STENCIL_ATTACHMENT |
350 | theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, hasStencilRB ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, |
351 | GL_RENDERBUFFER, myGlDepthRBufferId); |
352 | #else |
fe3a29bc |
353 | theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, |
354 | GL_RENDERBUFFER, myGlDepthRBufferId); |
e473b95f |
355 | if (hasStencilRB) |
356 | { |
357 | theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, |
358 | GL_RENDERBUFFER, myGlDepthRBufferId); |
359 | } |
360 | #endif |
fe3a29bc |
361 | } |
01ca42b2 |
362 | if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) |
7fd59977 |
363 | { |
fd4a6963 |
364 | Release (theGlContext.operator->()); |
7fd59977 |
365 | return Standard_False; |
366 | } |
367 | |
18f4e8e2 |
368 | UnbindBuffer (theGlContext); |
7fd59977 |
369 | return Standard_True; |
370 | } |
371 | |
38a0206f |
372 | // ======================================================================= |
a1073ae2 |
373 | // function : InitLazy |
38a0206f |
374 | // purpose : |
375 | // ======================================================================= |
376 | Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext, |
377 | const GLsizei theViewportSizeX, |
3c4b62a4 |
378 | const GLsizei theViewportSizeY, |
379 | const GLint theColorFormat, |
380 | const GLint theDepthFormat, |
381 | const GLsizei theNbSamples) |
38a0206f |
382 | { |
a1073ae2 |
383 | OpenGl_ColorFormats aColorFormats; |
384 | |
385 | aColorFormats.Append (theColorFormat); |
386 | |
387 | return InitLazy (theGlContext, theViewportSizeX, theViewportSizeY, aColorFormats, theDepthFormat, theNbSamples); |
388 | } |
389 | |
390 | // ======================================================================= |
391 | // function : InitLazy |
392 | // purpose : |
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) |
400 | { |
401 | if (myVPSizeX == theViewportSizeX |
402 | && myVPSizeY == theViewportSizeY |
403 | && myColorFormats == theColorFormats |
404 | && myDepthFormat == theDepthFormat |
405 | && myNbSamples == theNbSamples) |
38a0206f |
406 | { |
407 | return IsValid(); |
408 | } |
409 | |
a1073ae2 |
410 | return Init (theGlContext, theViewportSizeX, theViewportSizeY, theColorFormats, theDepthFormat, theNbSamples); |
38a0206f |
411 | } |
412 | |
a2e4f780 |
413 | // ======================================================================= |
414 | // function : InitWithRB |
415 | // purpose : |
416 | // ======================================================================= |
417 | Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& theGlCtx, |
62e1beed |
418 | const GLsizei theSizeX, |
419 | const GLsizei theSizeY, |
3c4b62a4 |
420 | const GLint theColorFormat, |
421 | const GLint theDepthFormat, |
a2e4f780 |
422 | const GLuint theColorRBufferFromWindow) |
423 | { |
a1073ae2 |
424 | myColorFormats.Clear(); |
425 | myColorFormats.Append (theColorFormat); |
426 | if (!myColorTextures.IsEmpty()) |
427 | { |
428 | Handle(OpenGl_Texture) aTexutre = myColorTextures.First(); |
429 | for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next()) |
430 | { |
431 | aTextureIt.Value()->Release (theGlCtx.operator->()); |
432 | } |
433 | myColorTextures.Clear(); |
434 | myColorTextures.Append (aTexutre); |
435 | } |
436 | |
3c4b62a4 |
437 | myDepthFormat = theDepthFormat; |
438 | myNbSamples = 0; |
a0b49de4 |
439 | myInitVPSizeX = theSizeX; |
440 | myInitVPSizeY = theSizeY; |
a2e4f780 |
441 | if (theGlCtx->arbFBO == NULL) |
442 | { |
443 | return Standard_False; |
444 | } |
445 | |
446 | // clean up previous state |
447 | Release (theGlCtx.operator->()); |
448 | |
a447178e |
449 | myIsOwnBuffer = true; |
a1073ae2 |
450 | myIsOwnDepth = true; |
a447178e |
451 | |
a2e4f780 |
452 | // setup viewport sizes as is |
62e1beed |
453 | myVPSizeX = theSizeX; |
454 | myVPSizeY = theSizeY; |
455 | const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2; |
456 | const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2; |
a2e4f780 |
457 | |
458 | // Create the render-buffers |
459 | if (theColorRBufferFromWindow != NO_RENDERBUFFER) |
460 | { |
461 | myGlColorRBufferId = theColorRBufferFromWindow; |
462 | } |
a1073ae2 |
463 | else if (theColorFormat != 0) |
a2e4f780 |
464 | { |
465 | theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlColorRBufferId); |
466 | theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlColorRBufferId); |
a1073ae2 |
467 | theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, theColorFormat, aSizeX, aSizeY); |
a2e4f780 |
468 | } |
469 | |
e473b95f |
470 | bool hasStencilRB = false; |
3c4b62a4 |
471 | if (myDepthFormat != 0) |
472 | { |
ba00aab7 |
473 | const OpenGl_TextureFormat aDepthFormat = OpenGl_TextureFormat::FindSizedFormat (theGlCtx, myDepthFormat); |
474 | hasStencilRB = aDepthFormat.PixelFormat() == GL_DEPTH_STENCIL; |
e473b95f |
475 | |
3c4b62a4 |
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); |
480 | } |
a2e4f780 |
481 | |
482 | // create FBO |
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); |
3c4b62a4 |
487 | if (myGlDepthRBufferId != NO_RENDERBUFFER) |
488 | { |
489 | #ifdef GL_DEPTH_STENCIL_ATTACHMENT |
e473b95f |
490 | theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, hasStencilRB ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, |
3c4b62a4 |
491 | GL_RENDERBUFFER, myGlDepthRBufferId); |
492 | #else |
493 | theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, |
494 | GL_RENDERBUFFER, myGlDepthRBufferId); |
e473b95f |
495 | if (hasStencilRB) |
496 | { |
497 | theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, |
498 | GL_RENDERBUFFER, myGlDepthRBufferId); |
499 | } |
3c4b62a4 |
500 | #endif |
501 | } |
a2e4f780 |
502 | if (theGlCtx->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) |
503 | { |
504 | UnbindBuffer (theGlCtx); |
505 | Release (theGlCtx.operator->()); |
506 | return Standard_False; |
507 | } |
508 | |
509 | UnbindBuffer (theGlCtx); |
510 | return Standard_True; |
511 | } |
512 | |
513 | // ======================================================================= |
514 | // function : InitWrapper |
515 | // purpose : |
516 | // ======================================================================= |
517 | Standard_Boolean OpenGl_FrameBuffer::InitWrapper (const Handle(OpenGl_Context)& theGlCtx) |
518 | { |
3c4b62a4 |
519 | myNbSamples = 0; |
a2e4f780 |
520 | if (theGlCtx->arbFBO == NULL) |
521 | { |
522 | return Standard_False; |
523 | } |
524 | |
525 | // clean up previous state |
526 | Release (theGlCtx.operator->()); |
527 | |
528 | GLint anFbo = GLint(NO_FRAMEBUFFER); |
529 | ::glGetIntegerv (GL_FRAMEBUFFER_BINDING, &anFbo); |
530 | if (anFbo == GLint(NO_FRAMEBUFFER)) |
531 | { |
532 | return Standard_False; |
533 | } |
534 | |
535 | GLint aColorType = 0; |
536 | GLint aColorId = 0; |
537 | GLint aDepthType = 0; |
538 | GLint aDepthId = 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); |
541 | |
542 | myGlFBufferId = GLuint(anFbo); |
543 | myIsOwnBuffer = false; |
a1073ae2 |
544 | myIsOwnDepth = false; |
a2e4f780 |
545 | if (aColorType == GL_RENDERBUFFER) |
546 | { |
547 | theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aColorId); |
548 | myGlColorRBufferId = aColorId; |
549 | } |
550 | else if (aColorType != GL_NONE) |
551 | { |
552 | TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), color attachment of unsupported type has been skipped!"; |
3b523c4c |
553 | theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
554 | GL_DEBUG_TYPE_ERROR, |
a2e4f780 |
555 | 0, |
3b523c4c |
556 | GL_DEBUG_SEVERITY_HIGH, |
a2e4f780 |
557 | aMsg); |
558 | } |
559 | |
560 | if (aDepthType == GL_RENDERBUFFER) |
561 | { |
562 | theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aDepthId); |
563 | myGlDepthRBufferId = aDepthId; |
564 | } |
565 | else if (aDepthType != GL_NONE) |
566 | { |
567 | TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), depth attachment of unsupported type has been skipped!"; |
3b523c4c |
568 | theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
569 | GL_DEBUG_TYPE_ERROR, |
a2e4f780 |
570 | 0, |
3b523c4c |
571 | GL_DEBUG_SEVERITY_HIGH, |
a2e4f780 |
572 | aMsg); |
573 | } |
574 | |
575 | // retrieve dimensions |
576 | GLuint aRBuffer = myGlColorRBufferId != NO_RENDERBUFFER ? myGlColorRBufferId : myGlDepthRBufferId; |
577 | if (aRBuffer != NO_RENDERBUFFER) |
578 | { |
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); |
583 | } |
584 | |
585 | return aRBuffer != NO_RENDERBUFFER; |
586 | } |
587 | |
fd4a6963 |
588 | // ======================================================================= |
589 | // function : Release |
590 | // purpose : |
591 | // ======================================================================= |
10b9c7df |
592 | void OpenGl_FrameBuffer::Release (OpenGl_Context* theGlCtx) |
7fd59977 |
593 | { |
18f4e8e2 |
594 | if (isValidFrameBuffer()) |
7fd59977 |
595 | { |
fd4a6963 |
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...",); |
a2e4f780 |
599 | if (theGlCtx->IsValid() |
600 | && myIsOwnBuffer) |
2166f0fa |
601 | { |
01ca42b2 |
602 | theGlCtx->arbFBO->glDeleteFramebuffers (1, &myGlFBufferId); |
a2e4f780 |
603 | if (myGlColorRBufferId != NO_RENDERBUFFER) |
604 | { |
605 | theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlColorRBufferId); |
606 | } |
607 | if (myGlDepthRBufferId != NO_RENDERBUFFER) |
608 | { |
609 | theGlCtx->arbFBO->glDeleteRenderbuffers (1, &myGlDepthRBufferId); |
610 | } |
2166f0fa |
611 | } |
a2e4f780 |
612 | myGlFBufferId = NO_FRAMEBUFFER; |
613 | myGlColorRBufferId = NO_RENDERBUFFER; |
614 | myGlDepthRBufferId = NO_RENDERBUFFER; |
615 | myIsOwnBuffer = false; |
7fd59977 |
616 | } |
7fd59977 |
617 | |
a1073ae2 |
618 | for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx) |
619 | { |
620 | myColorTextures (aColorBufferIdx)->Release (theGlCtx); |
621 | } |
622 | |
623 | if (myIsOwnDepth) |
624 | { |
625 | myDepthStencilTexture->Release (theGlCtx); |
626 | myIsOwnDepth = false; |
627 | } |
bf02aa7d |
628 | |
629 | myVPSizeX = 0; |
630 | myVPSizeY = 0; |
7fd59977 |
631 | } |
632 | |
fd4a6963 |
633 | // ======================================================================= |
634 | // function : SetupViewport |
635 | // purpose : |
636 | // ======================================================================= |
3bffef55 |
637 | void OpenGl_FrameBuffer::SetupViewport (const Handle(OpenGl_Context)& theGlCtx) |
fd4a6963 |
638 | { |
3bffef55 |
639 | const Standard_Integer aViewport[4] = { 0, 0, myVPSizeX, myVPSizeY }; |
640 | theGlCtx->ResizeViewport (aViewport); |
fd4a6963 |
641 | } |
642 | |
643 | // ======================================================================= |
644 | // function : ChangeViewport |
645 | // purpose : |
646 | // ======================================================================= |
647 | void OpenGl_FrameBuffer::ChangeViewport (const GLsizei theVPSizeX, |
648 | const GLsizei theVPSizeY) |
649 | { |
650 | myVPSizeX = theVPSizeX; |
651 | myVPSizeY = theVPSizeY; |
652 | } |
653 | |
654 | // ======================================================================= |
655 | // function : BindBuffer |
656 | // purpose : |
657 | // ======================================================================= |
658 | void OpenGl_FrameBuffer::BindBuffer (const Handle(OpenGl_Context)& theGlCtx) |
659 | { |
01ca42b2 |
660 | theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); |
ba00aab7 |
661 | theGlCtx->SetFrameBufferSRGB (true); |
fd4a6963 |
662 | } |
663 | |
b86bb3df |
664 | // ======================================================================= |
665 | // function : BindDrawBuffer |
666 | // purpose : |
667 | // ======================================================================= |
668 | void OpenGl_FrameBuffer::BindDrawBuffer (const Handle(OpenGl_Context)& theGlCtx) |
669 | { |
670 | theGlCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myGlFBufferId); |
ba00aab7 |
671 | theGlCtx->SetFrameBufferSRGB (true); |
b86bb3df |
672 | } |
673 | |
674 | // ======================================================================= |
675 | // function : BindReadBuffer |
676 | // purpose : |
677 | // ======================================================================= |
678 | void OpenGl_FrameBuffer::BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx) |
679 | { |
680 | theGlCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, myGlFBufferId); |
681 | } |
682 | |
fd4a6963 |
683 | // ======================================================================= |
684 | // function : UnbindBuffer |
685 | // purpose : |
686 | // ======================================================================= |
687 | void OpenGl_FrameBuffer::UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx) |
688 | { |
a2e4f780 |
689 | if (!theGlCtx->DefaultFrameBuffer().IsNull() |
690 | && theGlCtx->DefaultFrameBuffer().operator->() != this) |
691 | { |
692 | theGlCtx->DefaultFrameBuffer()->BindBuffer (theGlCtx); |
693 | } |
694 | else |
695 | { |
696 | theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, NO_FRAMEBUFFER); |
ba00aab7 |
697 | theGlCtx->SetFrameBufferSRGB (false); |
a2e4f780 |
698 | } |
fd4a6963 |
699 | } |
6cde53c4 |
700 | |
701 | // ======================================================================= |
702 | // function : getAligned |
703 | // purpose : |
704 | // ======================================================================= |
705 | inline Standard_Size getAligned (const Standard_Size theNumber, |
706 | const Standard_Size theAlignment) |
707 | { |
708 | return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment; |
709 | } |
710 | |
711 | template<typename T> |
712 | inline void convertRowFromRgba (T* theRgbRow, |
713 | const Image_ColorRGBA* theRgbaRow, |
714 | const Standard_Size theWidth) |
715 | { |
716 | for (Standard_Size aCol = 0; aCol < theWidth; ++aCol) |
717 | { |
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(); |
723 | } |
724 | } |
725 | |
726 | // ======================================================================= |
727 | // function : BufferDump |
728 | // purpose : |
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) |
734 | { |
735 | if (theGlCtx.IsNull() |
736 | || theImage.IsEmpty()) |
737 | { |
738 | return Standard_False; |
739 | } |
740 | |
741 | GLenum aFormat = 0; |
742 | GLenum aType = 0; |
743 | bool toSwapRgbaBgra = false; |
744 | bool toConvRgba2Rgb = false; |
745 | switch (theImage.Format()) |
746 | { |
747 | #if !defined(GL_ES_VERSION_2_0) |
748 | case Image_Format_Gray: |
749 | aFormat = GL_DEPTH_COMPONENT; |
750 | aType = GL_UNSIGNED_BYTE; |
751 | break; |
752 | case Image_Format_GrayF: |
753 | aFormat = GL_DEPTH_COMPONENT; |
754 | aType = GL_FLOAT; |
755 | break; |
756 | case Image_Format_RGB: |
757 | aFormat = GL_RGB; |
758 | aType = GL_UNSIGNED_BYTE; |
759 | break; |
760 | case Image_Format_BGR: |
761 | aFormat = GL_BGR; |
762 | aType = GL_UNSIGNED_BYTE; |
763 | break; |
764 | case Image_Format_BGRA: |
765 | case Image_Format_BGR32: |
766 | aFormat = GL_BGRA; |
767 | aType = GL_UNSIGNED_BYTE; |
768 | break; |
769 | case Image_Format_BGRF: |
770 | aFormat = GL_BGR; |
771 | aType = GL_FLOAT; |
772 | break; |
773 | case Image_Format_BGRAF: |
774 | aFormat = GL_BGRA; |
775 | aType = GL_FLOAT; |
776 | break; |
777 | #else |
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: |
785 | aFormat = GL_RGBA; |
786 | aType = GL_UNSIGNED_BYTE; |
787 | toSwapRgbaBgra = true; |
788 | break; |
789 | case Image_Format_BGR: |
790 | case Image_Format_RGB: |
791 | aFormat = GL_RGBA; |
792 | aType = GL_UNSIGNED_BYTE; |
793 | toConvRgba2Rgb = true; |
794 | break; |
795 | #endif |
796 | case Image_Format_RGBA: |
797 | case Image_Format_RGB32: |
798 | aFormat = GL_RGBA; |
799 | aType = GL_UNSIGNED_BYTE; |
800 | break; |
801 | case Image_Format_RGBF: |
802 | aFormat = GL_RGB; |
803 | aType = GL_FLOAT; |
804 | break; |
805 | case Image_Format_RGBAF: |
806 | aFormat = GL_RGBA; |
807 | aType = GL_FLOAT; |
808 | break; |
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; |
814 | } |
815 | |
816 | if (aFormat == 0) |
817 | { |
818 | return Standard_False; |
819 | } |
820 | |
821 | #if !defined(GL_ES_VERSION_2_0) |
822 | GLint aReadBufferPrev = GL_BACK; |
823 | if (theBufferType == Graphic3d_BT_Depth |
824 | && aFormat != GL_DEPTH_COMPONENT) |
825 | { |
826 | return Standard_False; |
827 | } |
828 | #else |
829 | (void )theBufferType; |
830 | #endif |
831 | |
832 | // bind FBO if used |
833 | if (!theFbo.IsNull() && theFbo->IsValid()) |
834 | { |
835 | theFbo->BindBuffer (theGlCtx); |
836 | } |
837 | else |
838 | { |
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); |
844 | #endif |
845 | } |
846 | |
847 | // setup alignment |
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(); |
851 | |
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) |
856 | { |
857 | aPixelsWidth = 0; |
858 | } |
859 | else if (aSizeRowBytesEstim != theImage.SizeRowBytes()) |
860 | { |
861 | aPixelsWidth = 0; |
862 | isBatchCopy = false; |
863 | } |
864 | #if !defined(GL_ES_VERSION_2_0) |
865 | glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth); |
866 | #else |
867 | if (aPixelsWidth != 0) |
868 | { |
869 | isBatchCopy = false; |
870 | } |
871 | #endif |
872 | if (toConvRgba2Rgb) |
873 | { |
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)) |
878 | { |
879 | return Standard_False; |
880 | } |
881 | |
882 | for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow) |
883 | { |
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) |
889 | { |
890 | convertRowFromRgba ((Image_ColorBGR* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX()); |
891 | } |
892 | else |
893 | { |
894 | convertRowFromRgba ((Image_ColorRGB* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX()); |
895 | } |
896 | } |
897 | } |
898 | else if (!isBatchCopy) |
899 | { |
900 | // copy row by row |
901 | for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow) |
902 | { |
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)); |
906 | } |
907 | } |
908 | else |
909 | { |
910 | glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData()); |
911 | } |
912 | const bool hasErrors = theGlCtx->ResetErrors (true); |
913 | |
914 | glPixelStorei (GL_PACK_ALIGNMENT, 1); |
915 | #if !defined(GL_ES_VERSION_2_0) |
916 | glPixelStorei (GL_PACK_ROW_LENGTH, 0); |
917 | #endif |
918 | |
919 | if (!theFbo.IsNull() && theFbo->IsValid()) |
920 | { |
921 | theFbo->UnbindBuffer (theGlCtx); |
922 | } |
923 | else |
924 | { |
925 | #if !defined(GL_ES_VERSION_2_0) |
926 | glReadBuffer (aReadBufferPrev); |
927 | #endif |
928 | } |
929 | |
930 | if (toSwapRgbaBgra) |
931 | { |
932 | Image_PixMap::SwapRgbaBgra (theImage); |
933 | } |
934 | |
935 | return !hasErrors; |
936 | } |
15669413 |
937 | |
938 | // ======================================================================= |
939 | // function : EstimatedDataSize |
940 | // purpose : |
941 | // ======================================================================= |
942 | Standard_Size OpenGl_FrameBuffer::EstimatedDataSize() const |
943 | { |
944 | if (!IsValid()) |
945 | { |
946 | return 0; |
947 | } |
948 | |
949 | Standard_Size aSize = 0; |
950 | for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next()) |
951 | { |
952 | aSize += aTextureIt.Value()->EstimatedDataSize(); |
953 | } |
954 | if (!myDepthStencilTexture.IsNull()) |
955 | { |
956 | aSize += myDepthStencilTexture->EstimatedDataSize(); |
957 | } |
958 | if (myGlColorRBufferId != NO_RENDERBUFFER |
959 | && !myColorFormats.IsEmpty()) |
960 | { |
961 | aSize += OpenGl_Texture::PixelSizeOfPixelFormat (myColorFormats.First()) * myInitVPSizeX * myInitVPSizeY; |
962 | } |
963 | if (myGlDepthRBufferId != NO_RENDERBUFFER) |
964 | { |
965 | aSize += OpenGl_Texture::PixelSizeOfPixelFormat (myDepthFormat) * myInitVPSizeX * myInitVPSizeY; |
966 | } |
967 | return aSize; |
968 | } |