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