1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2011-2012 OPEN CASCADE SAS
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
20 #include <OpenGl_FrameBuffer.hxx>
26 static inline bool isOddNumber (const GLsizei theNumber)
28 return theNumber & 0x01;
31 static inline GLsizei getEvenNumber (const GLsizei theNumber)
33 return isOddNumber (theNumber) ? (theNumber + 1) : theNumber;
36 //! Notice - 0 is not power of two here
37 static inline bool isPowerOfTwo (const GLsizei theNumber)
39 return !(theNumber & (theNumber - 1));
42 static inline GLsizei getPowerOfTwo (const GLsizei theNumber,
43 const GLsizei theThreshold)
45 for (GLsizei p2 = 2; p2 <= theThreshold; p2 <<= 1)
55 OpenGl_FrameBuffer::OpenGl_FrameBuffer (GLint theTextureFormat)
60 myTextFormat (theTextureFormat),
61 myGlTextureId (NO_TEXTURE),
62 myGlFBufferId (NO_FRAMEBUFFER),
63 myGlDepthRBId (NO_RENDERBUFFER)
68 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
69 GLsizei theViewportSizeX,
70 GLsizei theViewportSizeY,
71 GLboolean toForcePowerOfTwo)
73 if (theGlContext->extFBO == NULL)
76 std::cerr << "OpenGl_FrameBuffer, FBO extension not supported!\n";
78 return Standard_False;
81 // clean up previous state
82 Release (theGlContext);
84 // upscale width/height if numbers are odd
85 if (toForcePowerOfTwo)
87 GLint aMaxTexDim = 2048;
88 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aMaxTexDim);
89 mySizeX = getPowerOfTwo (theViewportSizeX, aMaxTexDim);
90 mySizeY = getPowerOfTwo (theViewportSizeY, aMaxTexDim);
94 mySizeX = getEvenNumber (theViewportSizeX);
95 mySizeY = getEvenNumber (theViewportSizeY);
98 // setup viewport sizes as is
99 myVPSizeX = theViewportSizeX;
100 myVPSizeY = theViewportSizeY;
102 // Create the texture (will be used as color buffer)
103 if (!InitTrashTexture (theGlContext))
105 if (!isPowerOfTwo (mySizeX) || !isPowerOfTwo (mySizeY))
107 return Init (theGlContext, theViewportSizeX, theViewportSizeY, GL_TRUE);
109 Release (theGlContext);
110 return Standard_False;
113 // Create RenderBuffer (will be used as depth buffer)
114 theGlContext->extFBO->glGenRenderbuffersEXT (1, &myGlDepthRBId);
115 theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, myGlDepthRBId);
116 theGlContext->extFBO->glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, mySizeX, mySizeY);
118 // Build FBO and setup it as texture
119 theGlContext->extFBO->glGenFramebuffersEXT (1, &myGlFBufferId);
120 theGlContext->extFBO->glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, myGlFBufferId);
121 glEnable (GL_TEXTURE_2D);
122 glBindTexture (GL_TEXTURE_2D, myGlTextureId);
123 theGlContext->extFBO->glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, myGlTextureId, 0);
124 theGlContext->extFBO->glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, myGlFBufferId);
125 if (theGlContext->extFBO->glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
127 if (!isPowerOfTwo (mySizeX) || !isPowerOfTwo (mySizeY))
129 return Init (theGlContext, theViewportSizeX, theViewportSizeY, GL_TRUE);
131 Release (theGlContext);
132 return Standard_False;
135 UnbindBuffer (theGlContext);
137 theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, NO_RENDERBUFFER);
140 std::cerr << "OpenGl_FrameBuffer, created FBO " << mySizeX << "x" << mySizeY
141 << " for viewport " << theViewportSizeX << "x" << theViewportSizeY << "\n";
143 return Standard_True;
146 void OpenGl_FrameBuffer::Release (const Handle(OpenGl_Context)& theGlContext)
148 if (IsValidDepthBuffer())
150 if (!theGlContext.IsNull() && theGlContext->extFBO != NULL)
152 theGlContext->extFBO->glDeleteRenderbuffersEXT (1, &myGlDepthRBId);
153 myGlDepthRBId = NO_RENDERBUFFER;
157 std::cerr << "OpenGl_FrameBuffer::Release() called with invalid OpenGl_Context!\n";
160 if (IsValidTexture())
162 glDeleteTextures (1, &myGlTextureId);
163 myGlTextureId = NO_TEXTURE;
165 mySizeX = mySizeY = myVPSizeX = myVPSizeY = 0;
166 if (IsValidFrameBuffer())
168 if (!theGlContext.IsNull() && theGlContext->extFBO != NULL)
170 theGlContext->extFBO->glDeleteFramebuffersEXT (1, &myGlFBufferId);
171 myGlFBufferId = NO_FRAMEBUFFER;
175 std::cerr << "OpenGl_FrameBuffer::Release() called with invalid OpenGl_Context!\n";
180 Standard_Boolean OpenGl_FrameBuffer::IsProxySuccess() const
182 // use proxy to check texture could be created or not
183 glTexImage2D (GL_PROXY_TEXTURE_2D,
184 0, // LOD number: 0 - base image level; n is the nth mipmap reduction image
185 myTextFormat, // internalformat
187 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
188 GLint aTestParamX (0), aTestParamY (0);
189 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestParamX);
190 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestParamY);
191 return aTestParamX != 0 && aTestParamY != 0;
194 Standard_Boolean OpenGl_FrameBuffer::InitTrashTexture (const Handle(OpenGl_Context)& theGlContext)
196 // Check texture size is fit dimension maximum
197 GLint aMaxTexDim = 2048;
198 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aMaxTexDim);
199 if (mySizeX > aMaxTexDim || mySizeY > aMaxTexDim)
201 return Standard_False;
205 glEnable (GL_TEXTURE_2D);
206 if (!IsValidTexture())
208 glGenTextures (1, &myGlTextureId); // Create The Texture
210 glBindTexture (GL_TEXTURE_2D, myGlTextureId);
212 // texture interpolation parameters - could be overridden later
213 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
214 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
216 if (!IsProxySuccess())
218 Release (theGlContext);
219 return Standard_False;
222 glTexImage2D (GL_TEXTURE_2D,
223 0, // LOD number: 0 - base image level; n is the nth mipmap reduction image
224 myTextFormat, // internalformat
226 GL_RGBA, GL_UNSIGNED_BYTE, NULL); // NULL pointer supported from OpenGL 1.1
227 return Standard_True;