1 /****************************************************************************
2 * Render Radiance Scaling                                                   *
3 * Meshlab's plugin                                                          *
4 *                                                                           *
5 * Copyright(C) 2010                                                         *
6 * Vergne Romain, Dumas Olivier                                              *
7 * INRIA - Institut Nationnal de Recherche en Informatique et Automatique    *
8 *                                                                           *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 #include "framebufferObject.h"
24 #include <iostream>
25 #include <assert.h>
26 
27 using namespace std;
28 
29 std::vector<GLenum> _buffers;
30 
FramebufferObject()31 FramebufferObject::FramebufferObject()
32   : fbo_id(0) {
33   glGenFramebuffersEXT(1,&fbo_id);
34 }
35 
~FramebufferObject()36 FramebufferObject::~FramebufferObject() {
37   glDeleteFramebuffersEXT(1,&fbo_id);
38 }
39 
attachTexture(GLenum tex_target,GLuint tex_id,GLenum attachment,int mip_level,int z_slice)40 void FramebufferObject::attachTexture(GLenum tex_target,GLuint tex_id,
41                                       GLenum attachment,int mip_level,int z_slice) {
42   unbindCurrentBindThis();
43 
44   glBindTexture(tex_target,tex_id);
45 
46   if(tex_target==GL_TEXTURE_1D)
47     glFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT,attachment,
48                               GL_TEXTURE_1D,tex_id,mip_level);
49   else if(tex_target == GL_TEXTURE_3D)
50     glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT,attachment,
51                               GL_TEXTURE_3D,tex_id,mip_level,z_slice);
52   else
53     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,attachment,
54                               tex_target,tex_id,mip_level);
55 
56   unbindThisBindCurrent();
57 }
58 
attachRenderBuffer(GLuint buff_id,GLenum attachment)59 void FramebufferObject::attachRenderBuffer(GLuint buff_id,GLenum attachment) {
60   unbindCurrentBindThis();
61 
62   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,attachment,
63                                GL_RENDERBUFFER_EXT,buff_id);
64 
65   unbindThisBindCurrent();
66 }
67 
unattach(GLenum attachment)68 void FramebufferObject::unattach(GLenum attachment) {
69   unbindCurrentBindThis();
70 
71   GLenum type = getAttachedType(attachment);
72   switch(type){
73   case GL_RENDERBUFFER_EXT:
74     attachRenderBuffer(0, attachment);
75     break;
76   case GL_TEXTURE:
77     attachTexture(GL_TEXTURE_2D, 0, attachment);
78     break;
79   default:
80     break;
81   }
82 
83   unbindThisBindCurrent();
84 }
85 
unattachAll()86 void FramebufferObject::unattachAll() {
87   int nb_attachments = getMaxColorAttachments();
88   for(int i=0;i<nb_attachments;i++)
89     unattach(GL_COLOR_ATTACHMENT0_EXT+i);
90 }
91 
getMaxColorAttachments()92 GLint FramebufferObject::getMaxColorAttachments() {
93   GLint max_attach = 0;
94   glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_attach);
95   return max_attach;
96 }
97 
unbindCurrentBindThis()98 void FramebufferObject::unbindCurrentBindThis() {
99   glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT,&current_fbo_id);
100   if(fbo_id != (GLuint)current_fbo_id)
101     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fbo_id);
102 }
103 
unbindThisBindCurrent()104 void FramebufferObject::unbindThisBindCurrent() {
105   if(fbo_id != (GLuint)current_fbo_id)
106     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,(GLuint)current_fbo_id);
107 }
108 
isValid()109 bool FramebufferObject::isValid() {
110   unbindCurrentBindThis();
111 
112   bool res = false;
113 
114   GLenum status;
115   status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
116   switch(status){
117   case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK
118     res = true;
119     break;
120   case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
121     cerr << "glift::CheckFramebufferStatus() ERROR:\n\t"
122          << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n";
123     res = false;
124     break;
125   case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
126     cerr << "glift::CheckFramebufferStatus() ERROR:\n\t"
127          << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n";
128     res = false;
129     break;
130   case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
131     cerr << "glift::CheckFramebufferStatus() ERROR:\n\t"
132          << "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n";
133     res = false;
134     break;
135   case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
136     cerr << "glift::CheckFramebufferStatus() ERROR:\n\t"
137          << "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n";
138     res = false;
139     break;
140   case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
141     cerr << "glift::CheckFramebufferStatus() ERROR:\n\t"
142          << "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n";
143     res = false;
144     break;
145   case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
146     cerr << "glift::CheckFramebufferStatus() ERROR:\n\t"
147          << "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n";
148     res = false;
149     break;
150   case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
151     cerr << "glift::CheckFramebufferStatus() ERROR:\n\t"
152          << "GL_FRAMEBUFFER_UNSUPPORTED_EXT\n";
153     res = false;
154     break;
155   default:
156     cerr << "glift::CheckFramebufferStatus() ERROR:\n\t"
157          << "Unknown ERROR\n";
158     res = false;
159   }
160 
161   unbindThisBindCurrent();
162   return res;
163 }
164 
getAttachedType(GLenum attachment)165 GLenum FramebufferObject::getAttachedType(GLenum attachment) {
166   // GL_RENDERBUFFER_EXT or GL_TEXTURE
167   unbindCurrentBindThis();
168 
169   GLint type = 0;
170   glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
171                                            GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT,
172                                            &type);
173   unbindThisBindCurrent();
174 
175   return GLenum(type);
176 }
177 
getAttachedId(GLenum attachment)178 GLuint FramebufferObject::getAttachedId(GLenum attachment) {
179   unbindCurrentBindThis();
180 
181   GLint id = 0;
182   glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
183                                            GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
184                                            &id);
185   unbindThisBindCurrent();
186 
187   return GLuint(id);
188 }
189 
getAttachedMipLevel(GLenum attachment)190 GLint FramebufferObject::getAttachedMipLevel(GLenum attachment) {
191   unbindCurrentBindThis();
192 
193   GLint level = 0;
194   glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
195                                            GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT,
196                                            &level);
197   unbindThisBindCurrent();
198 
199   return level;
200 }
201 
getAttachedCubeFace(GLenum attachment)202 GLint FramebufferObject::getAttachedCubeFace(GLenum attachment) {
203   unbindCurrentBindThis();
204 
205   GLint level = 0;
206   glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
207                                            GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT,
208                                            &level);
209   unbindThisBindCurrent();
210 
211   return level;
212 }
213 
getAttachedZSlice(GLenum attachment)214 GLint FramebufferObject::getAttachedZSlice(GLenum attachment) {
215   unbindCurrentBindThis();
216 
217   GLint slice = 0;
218   glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
219                                            GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT,
220                                            &slice);
221   unbindThisBindCurrent();
222 
223   return slice;
224 }
225 
buffers(unsigned int i)226 GLenum *FramebufferObject::buffers(unsigned int i) {
227   if(_buffers.empty()) {
228     for(int j=0;j<getMaxColorAttachments();++j) {
229       _buffers.push_back(GL_COLOR_ATTACHMENT0_EXT+j);
230     }
231   }
232 
233   assert((int)i<getMaxColorAttachments());
234 
235   return &(_buffers[i]);
236 }
237 
238