NCBI C++ ToolKit
glframebuffer.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: glframebuffer.cpp 43452 2019-07-02 14:42:27Z katargir $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Bob Falk
27  *
28  * File Description:
29  */
30 
31 #include <ncbi_pch.hpp>
32 
34 #include <gui/opengl/gltexture.hpp>
35 #include <gui/opengl/glutils.hpp>
36 
37 
39 
45  eAbort
46 };
47 
49 : m_Fb(0)
50 , m_DepthRb(0)
51 , m_FbTex(0)
52 , m_FrameSize(dim)
53 , m_TexMin(GL_LINEAR)
54 , m_TexMag(GL_LINEAR)
55 , m_WrapS(GL_CLAMP)
56 , m_WrapT(GL_CLAMP)
57 , m_TextureReleased(false)
58 , m_ClearColorRed(1)
59 , m_ClearColorGreen(1)
60 , m_ClearColorBlue(1)
61 , m_ClearColorAlpha(1)
62 {
63 }
64 
66 {
67  Clear();
68 }
69 
71 {
72  GLenum status;
73  status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
74  if (status == GL_FRAMEBUFFER_COMPLETE_EXT)
75  return false;
76 
77  static EGlDiagMode mode = eUndefined;
78  if ( mode == eUndefined ) {
79  const char* value = getenv("NCBI_GBENCH_GLERROR");
80  if ( !value ) {
81  mode = eIgnore;
82  } else if (strcmp(value, "ABORT") == 0) {
83  mode = eAbort;
84  } else if (strcmp(value, "LOGPOST") == 0) {
85  mode = eLogPost;
86  } else if (strcmp(value, "THROW") == 0) {
87  mode = eThrow;
88  } else {
89  mode = eIgnore;
90  }
91  }
92 
94 
95  switch(status) {
96  case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
97  msg = "Framebuffer: Incomplete attachment";
98  break;
99  case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
100  msg = "Framebuffer: Incomplete missing attachment";
101  break;
102  case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
103  msg = "Framebuffer: Incomplete dimensions";
104  break;
105  case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
106  msg = "Framebuffer: Incomplete formats";
107  break;
108  case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
109  msg = "Framebuffer: Incomplete draw buffer";
110  break;
111  case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
112  msg = "Framebuffer: Incomplete read buffer";
113  break;
114  case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
115  msg = "Framebuffer: Unsupported framebuffer";
116  break;
117  default:
118  msg = "Framebuffer: Unknown error";
119  break;
120  }
121 
122  switch (mode) {
123  case eUndefined:
124  case eIgnore:
125  default:
126  break;
127 
128  case eLogPost:
129  LOG_POST(Error << msg);
130  break;
131 
132  case eAbort:
133  // abort
134  LOG_POST(Error << msg);
135  Abort();
136  break;
137 
138  //case eThrow:
139  // // throw
140  // NCBI_THROW(COpenGLException, eGlError, msg);
141  // break;
142  }
143 
144  return true;
145 }
146 
148 {
149  if (glewIsSupported("GL_EXT_framebuffer_object")) {
150  if (glIsTexture(m_FbTex) && !m_TextureReleased)
151  glDeleteTextures(1, &m_FbTex);
152  if (glIsRenderbufferEXT(m_DepthRb))
153  glDeleteRenderbuffersEXT(1, &m_DepthRb);
154  if (glIsFramebufferEXT(m_Fb))
155  glDeleteFramebuffersEXT(1, &m_Fb);
156  }
157 
158  m_Fb = 0;
159  m_FbTex = 0;
160  m_DepthRb = 0;
161 }
162 
163 void CGLFrameBuffer::SetTextureWrap(GLint wraps, GLint wrapt)
164 {
165  m_WrapS = wraps;
166  m_WrapT = wrapt;
167 }
168 
169 
170 void CGLFrameBuffer::SetTextureFiltering(GLint min_filter, GLint mag_filter)
171 {
172  m_TexMin = min_filter;
173  m_TexMag = mag_filter;
174 }
175 
176 
178 {
179  if (!glewIsSupported("GL_EXT_framebuffer_object"))
180  return;
181 
182  Clear();
183 
184  glGenFramebuffersEXT(1, &m_Fb);// frame buffer
185  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_Fb);
186 
187  // initialize texture
188  glEnable(GL_TEXTURE_2D);
189  glGenTextures(1, &m_FbTex); // texture
190 
191  glBindTexture(GL_TEXTURE_2D, m_FbTex);
192  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_TexMag );
193  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_TexMin );
194  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_WrapS);
195  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_WrapT);
196  // may need to generate mipmaps here to fix ati bug (shoudn't be required
197  // r.e. standard)
198  // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=249408
199  glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
200  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_FrameSize, (GLsizei)m_FrameSize, 0,
201  GL_RGBA, GL_FLOAT, NULL);
202  // attach texture to framebuffercolor buffer
203  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_FbTex, 0);
204 
205  // initialize depth/stencil renderbuffer
206  glGenRenderbuffersEXT(1, &m_DepthRb);
207  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_DepthRb);
208  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, (GLsizei)m_FrameSize, (GLsizei)m_FrameSize);
209  // attach renderbuffer to framebufferdepth buffer
210  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_DepthRb);
211  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_DepthRb);
212 
213  if (CheckFBOError()) {
214  Clear();
215  m_Fb = 0;
216  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
217  return;
218  }
219 
220  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
221 
222  // On mac at least, it seems you need to generate the mipmaps before you
223  // first use the framebuffer. (otherwise result is blank on first
224  // usage).
225  //m_TexMag can only be GL_NEAREST or GL_LINEAR (no mipmaps used in magnification)
226  if (m_TexMin == GL_NEAREST_MIPMAP_NEAREST ||
227  m_TexMin == GL_LINEAR_MIPMAP_NEAREST ||
228  m_TexMin == GL_NEAREST_MIPMAP_LINEAR ||
229  m_TexMin == GL_LINEAR_MIPMAP_LINEAR )
230  {
231  GenerateMipMaps();
232  }
233 
235 }
236 
237 void CGLFrameBuffer::SetClearColor(float red, float green, float blue, float alpha)
238 {
239  m_ClearColorRed = red;
240  m_ClearColorGreen = green;
241  m_ClearColorBlue = blue;
242  m_ClearColorAlpha = alpha;
243 }
244 
245 std::vector<int> CGLFrameBuffer::checkFramebufferAvailability(int start_size, int count)
246 {
247  int current_size = start_size;
248 
249  std::vector<int> sizes;
250 
251  if (!glewIsSupported("GL_EXT_framebuffer_object"))
252  return sizes;
253 
254  GLint max_tex_size;
255  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
256 
257  for (int i=0; i<count; ++i) {
258  if (current_size > max_tex_size)
259  break;
260 
261  sizes.push_back(current_size);
262  current_size *= 2;
263  }
264 
265  return sizes;
266 }
267 
268 
270 {
271  if (m_Fb > 0)
272  return true;
273 
274  return false;
275 }
276 
278 {
279  if (IsValid()) {
280 
281  if (b) {
282  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_Fb);
283 
284  glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
285  glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
286  }
287  else {
288  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
289 
290  glDrawBuffer(GL_BACK);
291  glReadBuffer(GL_BACK);
292  }
293  }
294 }
295 
296 void CGLFrameBuffer::Render(std::function<void()> renderer)
297 {
298  if (!IsValid())
299  return;
300 
301  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_Fb);
302 
303  glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
304  glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
305 
307  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
308 
309  renderer();
310 
311  glFinish();
312 
313  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
314 
315  glDrawBuffer(GL_BACK);
316  glReadBuffer(GL_BACK);
317 }
318 
319 
321 {
322  if (IsValid()) {
323  MakeCurrent(false);
324  glEnable(GL_TEXTURE_2D);
325  glBindTexture(GL_TEXTURE_2D, m_FbTex);
326 
327  // Had been using glGenerateMipmap(GL_TEXTURE_2D) but a bug
328  // with MESA made that crash (it didn't try to get the pointer
329  // to the function). This seems to work everywhere.
330  glGenerateMipmapEXT(GL_TEXTURE_2D);
331  }
332 }
333 
335 {
337 }
338 
GLint m_TexMag
magnification filter
virtual void SetClearColor(float red, float green, float blue, float alpha)
void SetTextureWrap(GLint wraps, GLint wrapt)
Set texture paramters, if needed. Call before calling CreateFrameBuffer.
static std::vector< int > checkFramebufferAvailability(int start_size, int count)
Return an arrray of valid image output sizes.
GLint m_WrapT
wrap t
GLint m_TexMin
Texture parameters.
virtual I3DTexture * Get3DTexture()
GLuint m_FbTex
Texture target id.
void Clear()
Deletes the current framebuffer, if any.
GLint m_WrapS
wrap s
virtual void Render(std::function< void()> renderer)
void MakeCurrent(bool b)
Makes this framebuffer the current rendering target if b==true, and if b==false, makes the rendering ...
CGLFrameBuffer(size_t dim)
virtual void GenerateMipMaps()
Generates mipmaps for the texture rendering target.
GLuint m_Fb
OpenGL IDs.
size_t m_FrameSize
Size of framebuffer (in both dimensions).
GLuint m_DepthRb
Depth renderbuffer id.
static bool CheckFBOError()
Returns true and writes error message if framebuffer is invalid.
bool m_TextureReleased
if true, the texture is not deleted with the framebuffer
virtual void SetTextureFiltering(GLint min_filter, GLint mag_filter)
Set texture filtering parameters (default: GL_LINEAR)
virtual bool IsValid()
Returns true if framebuffer was created successfully.
virtual void CreateFrameBuffer()
Create, set and validate framebuffer.
#define false
Definition: bool.h:36
EGlDiagMode
@ eIgnore
@ eLogPost
@ eThrow
@ eUndefined
@ eAbort
string
Definition: cgiapp.hpp:690
#define NULL
Definition: ncbistd.hpp:225
NCBI_XNCBI_EXPORT void Abort(void)
Smart abort function.
Definition: ncbidiag.cpp:8150
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
static bool CheckGlError()
Check if there are any OpenGL errors.
Definition: glutils.cpp:166
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
int i
mdb_mode_t mode
Definition: lmdb++.h:38
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
int strcmp(const char *str1, const char *str2)
Definition: odbc_utils.hpp:160
#define count
static SLJIT_INLINE sljit_ins msg(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
Modified on Fri Sep 20 14:57:55 2024 by modify_doxy.py rev. 669887