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 OpenGl_FrameBuffer::OpenGl_FrameBuffer (GLint theTextureFormat)
47 myTextFormat (theTextureFormat),
48 myGlTextureId (NO_TEXTURE),
49 myGlFBufferId (NO_FRAMEBUFFER),
50 myGlDepthRBId (NO_RENDERBUFFER)
55 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
56 GLsizei theViewportSizeX,
57 GLsizei theViewportSizeY,
58 GLboolean toForcePowerOfTwo)
60 if (theGlContext->extFBO == NULL)
63 std::cerr << "OpenGl_FrameBuffer, FBO extension not supported!\n";
65 return Standard_False;
68 // clean up previous state
69 Release (theGlContext);
71 // upscale width/height if numbers are odd
72 if (toForcePowerOfTwo)
74 mySizeX = OpenGl_Context::GetPowerOfTwo (theViewportSizeX, theGlContext->MaxTextureSize());
75 mySizeY = OpenGl_Context::GetPowerOfTwo (theViewportSizeY, theGlContext->MaxTextureSize());
79 mySizeX = getEvenNumber (theViewportSizeX);
80 mySizeY = getEvenNumber (theViewportSizeY);
83 // setup viewport sizes as is
84 myVPSizeX = theViewportSizeX;
85 myVPSizeY = theViewportSizeY;
87 // Create the texture (will be used as color buffer)
88 if (!InitTrashTexture (theGlContext))
90 if (!isPowerOfTwo (mySizeX) || !isPowerOfTwo (mySizeY))
92 return Init (theGlContext, theViewportSizeX, theViewportSizeY, GL_TRUE);
94 Release (theGlContext);
95 return Standard_False;
98 // Create RenderBuffer (will be used as depth buffer)
99 theGlContext->extFBO->glGenRenderbuffersEXT (1, &myGlDepthRBId);
100 theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, myGlDepthRBId);
101 theGlContext->extFBO->glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, mySizeX, mySizeY);
103 // Build FBO and setup it as texture
104 theGlContext->extFBO->glGenFramebuffersEXT (1, &myGlFBufferId);
105 theGlContext->extFBO->glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, myGlFBufferId);
106 glEnable (GL_TEXTURE_2D);
107 glBindTexture (GL_TEXTURE_2D, myGlTextureId);
108 theGlContext->extFBO->glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, myGlTextureId, 0);
109 theGlContext->extFBO->glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, myGlDepthRBId);
110 if (theGlContext->extFBO->glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
112 if (!isPowerOfTwo (mySizeX) || !isPowerOfTwo (mySizeY))
114 return Init (theGlContext, theViewportSizeX, theViewportSizeY, GL_TRUE);
116 Release (theGlContext);
117 return Standard_False;
120 UnbindBuffer (theGlContext);
122 theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, NO_RENDERBUFFER);
125 std::cerr << "OpenGl_FrameBuffer, created FBO " << mySizeX << "x" << mySizeY
126 << " for viewport " << theViewportSizeX << "x" << theViewportSizeY << "\n";
128 return Standard_True;
131 void OpenGl_FrameBuffer::Release (const Handle(OpenGl_Context)& theGlContext)
133 if (IsValidDepthBuffer())
135 if (!theGlContext.IsNull() && theGlContext->extFBO != NULL)
137 theGlContext->extFBO->glDeleteRenderbuffersEXT (1, &myGlDepthRBId);
138 myGlDepthRBId = NO_RENDERBUFFER;
142 std::cerr << "OpenGl_FrameBuffer::Release() called with invalid OpenGl_Context!\n";
145 if (IsValidTexture())
147 glDeleteTextures (1, &myGlTextureId);
148 myGlTextureId = NO_TEXTURE;
150 mySizeX = mySizeY = myVPSizeX = myVPSizeY = 0;
151 if (IsValidFrameBuffer())
153 if (!theGlContext.IsNull() && theGlContext->extFBO != NULL)
155 theGlContext->extFBO->glDeleteFramebuffersEXT (1, &myGlFBufferId);
156 myGlFBufferId = NO_FRAMEBUFFER;
160 std::cerr << "OpenGl_FrameBuffer::Release() called with invalid OpenGl_Context!\n";
165 Standard_Boolean OpenGl_FrameBuffer::IsProxySuccess() const
167 // use proxy to check texture could be created or not
168 glTexImage2D (GL_PROXY_TEXTURE_2D,
169 0, // LOD number: 0 - base image level; n is the nth mipmap reduction image
170 myTextFormat, // internalformat
172 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
173 GLint aTestParamX (0), aTestParamY (0);
174 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestParamX);
175 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestParamY);
176 return aTestParamX != 0 && aTestParamY != 0;
179 Standard_Boolean OpenGl_FrameBuffer::InitTrashTexture (const Handle(OpenGl_Context)& theGlContext)
181 // Check texture size is fit dimension maximum
182 GLint aMaxTexDim = 2048;
183 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aMaxTexDim);
184 if (mySizeX > aMaxTexDim || mySizeY > aMaxTexDim)
186 return Standard_False;
190 glEnable (GL_TEXTURE_2D);
191 if (!IsValidTexture())
193 glGenTextures (1, &myGlTextureId); // Create The Texture
195 glBindTexture (GL_TEXTURE_2D, myGlTextureId);
197 // texture interpolation parameters - could be overridden later
198 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
199 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
201 if (!IsProxySuccess())
203 Release (theGlContext);
204 return Standard_False;
207 glTexImage2D (GL_TEXTURE_2D,
208 0, // LOD number: 0 - base image level; n is the nth mipmap reduction image
209 myTextFormat, // internalformat
211 GL_RGBA, GL_UNSIGNED_BYTE, NULL); // NULL pointer supported from OpenGL 1.1
212 return Standard_True;