0024271: Provide Boolean operations for NCollection_Map
[occt.git] / src / OpenGl / OpenGl_FrameBuffer.cxx
CommitLineData
b311480e 1// Created by: Kirill GAVRILOV
2// Copyright (c) 2011-2012 OPEN CASCADE SAS
3//
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.
8//
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.
11//
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.
18
2166f0fa 19
7fd59977 20#include <OpenGl_FrameBuffer.hxx>
21
22#ifdef DEB
23 #include <iostream>
24#endif
25
7fd59977 26static inline bool isOddNumber (const GLsizei theNumber)
27{
28 return theNumber & 0x01;
29}
30
31static inline GLsizei getEvenNumber (const GLsizei theNumber)
32{
33 return isOddNumber (theNumber) ? (theNumber + 1) : theNumber;
34}
35
36//! Notice - 0 is not power of two here
37static inline bool isPowerOfTwo (const GLsizei theNumber)
38{
39 return !(theNumber & (theNumber - 1));
40}
41
7fd59977 42OpenGl_FrameBuffer::OpenGl_FrameBuffer (GLint theTextureFormat)
43: mySizeX (0),
44 mySizeY (0),
45 myVPSizeX (0),
46 myVPSizeY (0),
47 myTextFormat (theTextureFormat),
48 myGlTextureId (NO_TEXTURE),
49 myGlFBufferId (NO_FRAMEBUFFER),
b859a34d 50 myGlDepthRBId (NO_RENDERBUFFER),
51 myGlStencilRBId (NO_RENDERBUFFER)
7fd59977 52{
53 //
54}
55
2166f0fa
SK
56Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
57 GLsizei theViewportSizeX,
7fd59977 58 GLsizei theViewportSizeY,
59 GLboolean toForcePowerOfTwo)
60{
2166f0fa 61 if (theGlContext->extFBO == NULL)
7fd59977 62 {
63 #ifdef DEB
64 std::cerr << "OpenGl_FrameBuffer, FBO extension not supported!\n";
65 #endif
66 return Standard_False;
67 }
68
69 // clean up previous state
2166f0fa 70 Release (theGlContext);
7fd59977 71
72 // upscale width/height if numbers are odd
73 if (toForcePowerOfTwo)
74 {
a174a3c5 75 mySizeX = OpenGl_Context::GetPowerOfTwo (theViewportSizeX, theGlContext->MaxTextureSize());
76 mySizeY = OpenGl_Context::GetPowerOfTwo (theViewportSizeY, theGlContext->MaxTextureSize());
7fd59977 77 }
78 else
79 {
80 mySizeX = getEvenNumber (theViewportSizeX);
81 mySizeY = getEvenNumber (theViewportSizeY);
82 }
83
84 // setup viewport sizes as is
85 myVPSizeX = theViewportSizeX;
86 myVPSizeY = theViewportSizeY;
87
88 // Create the texture (will be used as color buffer)
2166f0fa 89 if (!InitTrashTexture (theGlContext))
7fd59977 90 {
91 if (!isPowerOfTwo (mySizeX) || !isPowerOfTwo (mySizeY))
92 {
2166f0fa 93 return Init (theGlContext, theViewportSizeX, theViewportSizeY, GL_TRUE);
7fd59977 94 }
2166f0fa 95 Release (theGlContext);
7fd59977 96 return Standard_False;
97 }
98
b859a34d 99 if (!theGlContext->extPDS)
100 {
101 // Create RenderBuffer to be used as depth buffer
102 theGlContext->extFBO->glGenRenderbuffersEXT (1, &myGlDepthRBId);
103 theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, myGlDepthRBId);
104 theGlContext->extFBO->glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, mySizeX, mySizeY);
105
106 // Create RenderBuffer to be used as stencil buffer
107 theGlContext->extFBO->glGenRenderbuffersEXT (1, &myGlStencilRBId);
108 theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, myGlStencilRBId);
109 theGlContext->extFBO->glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, mySizeX, mySizeY);
110 }
111 else
112 {
113 // Create combined depth stencil buffer
114 theGlContext->extFBO->glGenRenderbuffersEXT (1, &myGlDepthRBId);
115 theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, myGlDepthRBId);
116 theGlContext->extFBO->glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, mySizeX, mySizeY);
117 myGlStencilRBId = myGlDepthRBId;
118 }
7fd59977 119
120 // Build FBO and setup it as texture
2166f0fa
SK
121 theGlContext->extFBO->glGenFramebuffersEXT (1, &myGlFBufferId);
122 theGlContext->extFBO->glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, myGlFBufferId);
7fd59977 123 glEnable (GL_TEXTURE_2D);
124 glBindTexture (GL_TEXTURE_2D, myGlTextureId);
2166f0fa 125 theGlContext->extFBO->glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, myGlTextureId, 0);
9be3a894 126 theGlContext->extFBO->glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, myGlDepthRBId);
b859a34d 127 theGlContext->extFBO->glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, myGlStencilRBId);
2166f0fa 128 if (theGlContext->extFBO->glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
7fd59977 129 {
130 if (!isPowerOfTwo (mySizeX) || !isPowerOfTwo (mySizeY))
131 {
2166f0fa 132 return Init (theGlContext, theViewportSizeX, theViewportSizeY, GL_TRUE);
7fd59977 133 }
2166f0fa 134 Release (theGlContext);
7fd59977 135 return Standard_False;
136 }
137
2166f0fa 138 UnbindBuffer (theGlContext);
7fd59977 139 UnbindTexture();
2166f0fa 140 theGlContext->extFBO->glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, NO_RENDERBUFFER);
7fd59977 141
142 #ifdef DEB
143 std::cerr << "OpenGl_FrameBuffer, created FBO " << mySizeX << "x" << mySizeY
144 << " for viewport " << theViewportSizeX << "x" << theViewportSizeY << "\n";
145 #endif
146 return Standard_True;
147}
148
2166f0fa 149void OpenGl_FrameBuffer::Release (const Handle(OpenGl_Context)& theGlContext)
7fd59977 150{
151 if (IsValidDepthBuffer())
152 {
2166f0fa
SK
153 if (!theGlContext.IsNull() && theGlContext->extFBO != NULL)
154 {
155 theGlContext->extFBO->glDeleteRenderbuffersEXT (1, &myGlDepthRBId);
156 myGlDepthRBId = NO_RENDERBUFFER;
157 }
158 else
159 {
160 std::cerr << "OpenGl_FrameBuffer::Release() called with invalid OpenGl_Context!\n";
161 }
7fd59977 162 }
b859a34d 163 if (IsValidStencilBuffer())
164 {
165 if (!theGlContext.IsNull() && theGlContext->extFBO != NULL)
166 {
167 theGlContext->extFBO->glDeleteRenderbuffersEXT (1, &myGlStencilRBId);
168 myGlStencilRBId = NO_RENDERBUFFER;
169 }
170 else
171 {
172 std::cerr << "OpenGl_FrameBuffer::Release() called with invalid OpenGl_Context!\n";
173 }
174 }
7fd59977 175 if (IsValidTexture())
176 {
177 glDeleteTextures (1, &myGlTextureId);
178 myGlTextureId = NO_TEXTURE;
179 }
180 mySizeX = mySizeY = myVPSizeX = myVPSizeY = 0;
181 if (IsValidFrameBuffer())
182 {
2166f0fa
SK
183 if (!theGlContext.IsNull() && theGlContext->extFBO != NULL)
184 {
185 theGlContext->extFBO->glDeleteFramebuffersEXT (1, &myGlFBufferId);
186 myGlFBufferId = NO_FRAMEBUFFER;
187 }
188 else
189 {
190 std::cerr << "OpenGl_FrameBuffer::Release() called with invalid OpenGl_Context!\n";
191 }
7fd59977 192 }
193}
194
195Standard_Boolean OpenGl_FrameBuffer::IsProxySuccess() const
196{
197 // use proxy to check texture could be created or not
198 glTexImage2D (GL_PROXY_TEXTURE_2D,
199 0, // LOD number: 0 - base image level; n is the nth mipmap reduction image
200 myTextFormat, // internalformat
201 mySizeX, mySizeY, 0,
202 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
203 GLint aTestParamX (0), aTestParamY (0);
204 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestParamX);
205 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestParamY);
206 return aTestParamX != 0 && aTestParamY != 0;
207}
208
2166f0fa 209Standard_Boolean OpenGl_FrameBuffer::InitTrashTexture (const Handle(OpenGl_Context)& theGlContext)
7fd59977 210{
211 // Check texture size is fit dimension maximum
212 GLint aMaxTexDim = 2048;
213 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aMaxTexDim);
214 if (mySizeX > aMaxTexDim || mySizeY > aMaxTexDim)
215 {
216 return Standard_False;
217 }
218
219 // generate new id
220 glEnable (GL_TEXTURE_2D);
221 if (!IsValidTexture())
222 {
223 glGenTextures (1, &myGlTextureId); // Create The Texture
224 }
225 glBindTexture (GL_TEXTURE_2D, myGlTextureId);
226
227 // texture interpolation parameters - could be overridden later
228 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
229 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
230
231 if (!IsProxySuccess())
232 {
2166f0fa 233 Release (theGlContext);
7fd59977 234 return Standard_False;
235 }
236
237 glTexImage2D (GL_TEXTURE_2D,
238 0, // LOD number: 0 - base image level; n is the nth mipmap reduction image
239 myTextFormat, // internalformat
240 mySizeX, mySizeY, 0,
241 GL_RGBA, GL_UNSIGNED_BYTE, NULL); // NULL pointer supported from OpenGL 1.1
242 return Standard_True;
243}