~thumper/nux/next-changes

« back to all changes in this revision

Viewing changes to NuxGraphics/GLDeviceFrameBufferObject.cpp

  • Committer: Neil Jagdish Patel
  • Date: 2010-09-01 21:15:42 UTC
  • Revision ID: neil.patel@canonical.com-20100901211542-cw2ce3ak28unouwb
Add NuxGraphics with licensing

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2010 Inalogic Inc.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it 
 
5
 * under the terms of the GNU Lesser General Public License version 3, as
 
6
 * published by the  Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but 
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranties of 
 
10
 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 
 
11
 * PURPOSE.  See the applicable version of the GNU Lesser General Public 
 
12
 * License for more details.
 
13
 * 
 
14
 * You should have received a copy of both the GNU Lesser General Public 
 
15
 * License version 3 along with this program.  If not, see 
 
16
 * <http://www.gnu.org/licenses/>
 
17
 *
 
18
 * Authored by: Jay Taoko <jay.taoko_AT_gmail_DOT_com>
 
19
 *
 
20
 */
 
21
 
 
22
 
 
23
#include "GLResource.h"
 
24
#include "GLDeviceFactory.h"
 
25
#include "GLDeviceObjects.h"
 
26
#include "GLResourceManager.h"
 
27
 
 
28
#include "GLTextureResourceManager.h"
 
29
#include "GLVertexResourceManager.h"
 
30
#include "GLDeviceFrameBufferObject.h"
 
31
#include "GLTemplatePrimitiveBuffer.h"
 
32
#include "OpenGLEngine.h"
 
33
 
 
34
NAMESPACE_BEGIN_OGL
 
35
 
 
36
GLenum AttachmentBuffer[] = 
 
37
{   
 
38
    GL_COLOR_ATTACHMENT0_EXT
 
39
    ,GL_COLOR_ATTACHMENT1_EXT
 
40
    ,GL_COLOR_ATTACHMENT2_EXT
 
41
    ,GL_COLOR_ATTACHMENT3_EXT
 
42
};
 
43
 
 
44
//////////////////////////////////////////////////////////////////////////
 
45
// GLFramebufferObject
 
46
//////////////////////////////////////////////////////////////////////////
 
47
 
 
48
GLFramebufferObject::GLFramebufferObject()
 
49
: m_fboId(_GenerateFboId()),
 
50
m_savedFboId(0)
 
51
{
 
52
    // Bind this FBO so that it actually gets created now
 
53
    _GuardedBind();
 
54
    _GuardedUnbind();
 
55
}
 
56
 
 
57
GLFramebufferObject::~GLFramebufferObject() 
 
58
{
 
59
    CHECKGL( glDeleteFramebuffersEXT(1, &m_fboId) );
 
60
}
 
61
 
 
62
void GLFramebufferObject::Bind() 
 
63
{
 
64
    CHECKGL( glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId) );
 
65
}
 
66
 
 
67
void GLFramebufferObject::Disable() 
 
68
{
 
69
    CHECKGL( glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0) );
 
70
}
 
71
 
 
72
void
 
73
GLFramebufferObject::AttachTexture( GLenum attachment, GLenum texType,
 
74
                                 GLuint texId, int mipLevel, int zSlice)
 
75
{
 
76
    _GuardedBind();
 
77
    if( GetAttachedId(attachment) != texId )
 
78
    {
 
79
        _FramebufferTextureND( attachment, texType,
 
80
            texId, mipLevel, zSlice );
 
81
    }
 
82
    else
 
83
    {
 
84
//        nuxError(TEXT("GLFramebufferObject::AttachTexture PERFORMANCE WARNING:\n    \
 
85
//            \tRedundant bind of texture (id = %d).\n"), texId);        
 
86
    }
 
87
    _GuardedUnbind();
 
88
}
 
89
void
 
90
GLFramebufferObject::AttachTextures( int numTextures, GLenum texTarget[], GLuint texId[],
 
91
                                  GLenum attachment[], int mipLevel[], int zSlice[] )
 
92
{
 
93
    for(int i = 0; i < numTextures; ++i) {
 
94
        AttachTexture( texTarget[i], texId[i], 
 
95
            attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i), 
 
96
            mipLevel ? mipLevel[i] : 0, 
 
97
            zSlice ? zSlice[i] : 0 );
 
98
    }
 
99
}
 
100
 
 
101
 
 
102
void
 
103
GLFramebufferObject::AttachRenderBuffer( GLenum attachment, GLuint buffId )
 
104
{
 
105
    _GuardedBind();
 
106
    if( GetAttachedId(attachment) != buffId )
 
107
    {
 
108
        CHECKGL( glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, 
 
109
            GL_RENDERBUFFER_EXT, buffId) );
 
110
    }
 
111
    else
 
112
    {
 
113
//        nuxError(TEXT("GLFramebufferObject::AttachRenderBuffer PERFORMANCE WARNING:\n    \
 
114
//            \tRedundant bind of GLRenderbuffer (id = %d).\n"), buffId);    
 
115
    }
 
116
    _GuardedUnbind();
 
117
}
 
118
 
 
119
void
 
120
GLFramebufferObject::Unattach( GLenum attachment )
 
121
{
 
122
    _GuardedBind();
 
123
    GLenum type = GetAttachedType(attachment);
 
124
 
 
125
    switch(type)
 
126
    {
 
127
    case GL_NONE:
 
128
        break;
 
129
    case GL_RENDERBUFFER_EXT:
 
130
        AttachRenderBuffer( attachment, 0 );
 
131
        break;
 
132
    case GL_TEXTURE:
 
133
        AttachTexture( attachment, GL_TEXTURE_2D, 0 );
 
134
        break;
 
135
    default:
 
136
        std::cout << "GLFramebufferObject::unbind_attachment ERROR: Unknown attached resource type\n";        
 
137
    }
 
138
    _GuardedUnbind();
 
139
}
 
140
 
 
141
GLint GLFramebufferObject::GetMaxColorAttachments()
 
142
{
 
143
    GLint maxAttach = 0;
 
144
    CHECKGL( glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS_EXT, &maxAttach ) );
 
145
    return maxAttach;
 
146
}
 
147
 
 
148
GLuint GLFramebufferObject::_GenerateFboId()
 
149
{
 
150
    GLuint id = 0;
 
151
    CHECKGL( glGenFramebuffersEXT(1, &id) );
 
152
    return id;
 
153
}
 
154
 
 
155
void GLFramebufferObject::_GuardedBind() 
 
156
{
 
157
    // Only binds if m_fboId is different than the currently bound FBO
 
158
    CHECKGL( glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId ) );
 
159
    if (m_fboId != m_savedFboId)
 
160
    {
 
161
        CHECKGL( glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId) );
 
162
    }
 
163
}
 
164
 
 
165
void GLFramebufferObject::_GuardedUnbind() 
 
166
{
 
167
    // Returns FBO binding to the previously enabled FBO
 
168
    if (m_savedFboId != m_fboId) 
 
169
    {
 
170
        CHECKGL( glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)m_savedFboId) );
 
171
    }
 
172
}
 
173
 
 
174
void
 
175
GLFramebufferObject::_FramebufferTextureND( GLenum attachment, GLenum texType,
 
176
                                         GLuint texId, int mipLevel,
 
177
                                         int zSlice )
 
178
{
 
179
    if(texType == GL_TEXTURE_2D)
 
180
    {
 
181
        // Default is GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, or cube faces
 
182
        CHECKGL( glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment,
 
183
            texType, texId, mipLevel ) );
 
184
    }
 
185
    else if (texType == GL_TEXTURE_1D)
 
186
    {
 
187
        CHECKGL( glFramebufferTexture1DEXT( GL_FRAMEBUFFER_EXT, attachment,
 
188
            GL_TEXTURE_1D, texId, mipLevel ) );
 
189
    }
 
190
    else if (texType == GL_TEXTURE_3D) 
 
191
    {
 
192
        CHECKGL( glFramebufferTexture3DEXT( GL_FRAMEBUFFER_EXT, attachment,
 
193
            GL_TEXTURE_3D, texId, mipLevel, zSlice ) );
 
194
    }
 
195
}
 
196
 
 
197
bool GLFramebufferObject::IsValid()
 
198
{
 
199
    _GuardedBind();
 
200
 
 
201
    bool isOK = false;
 
202
 
 
203
    GLenum status;               
 
204
    status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
 
205
    CHECKGL_MSG(glCheckFramebufferStatusEXT);
 
206
 
 
207
    switch(status) 
 
208
    {                                          
 
209
  case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK
 
210
      isOK = true;
 
211
      break;
 
212
  case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
 
213
      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT"));
 
214
      isOK = false;
 
215
      break;
 
216
  case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
 
217
      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT"));
 
218
      isOK = false;
 
219
      break;
 
220
// See issue (87) of http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
 
221
//  case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
 
222
//      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT"));
 
223
//      isOK = false;
 
224
//      break;
 
225
  case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
 
226
      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT"));
 
227
      isOK = false;
 
228
      break;
 
229
  case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
 
230
      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT"));
 
231
      isOK = false;
 
232
      break;
 
233
  case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
 
234
      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT"));
 
235
      isOK = false;
 
236
      break;
 
237
  case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
 
238
      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT"));
 
239
      isOK = false;
 
240
      break;
 
241
//  case GL_FRAMEBUFFER_STATUS_ERROR_EXT:
 
242
//      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_STATUS_ERROR_EXT"));
 
243
//      isOK = false;
 
244
//      break;
 
245
  case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
 
246
      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_UNSUPPORTED_EXT"));
 
247
      isOK = false;
 
248
      break;
 
249
  default:
 
250
      nuxError(TEXT("[GLFramebufferObject::IsValid] Unknown ERROR"));
 
251
      isOK = false;
 
252
    }
 
253
 
 
254
    _GuardedUnbind();
 
255
    return isOK;
 
256
}
 
257
 
 
258
/// Accessors
 
259
GLenum GLFramebufferObject::GetAttachedType( GLenum attachment )
 
260
{
 
261
    // Returns GL_RENDERBUFFER_EXT or GL_TEXTURE
 
262
    _GuardedBind();
 
263
    GLint type = 0;
 
264
    CHECKGL( glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
 
265
        GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT, 
 
266
        &type) );
 
267
    _GuardedUnbind();
 
268
    return GLenum(type);
 
269
}
 
270
 
 
271
GLuint GLFramebufferObject::GetAttachedId( GLenum attachment )
 
272
{
 
273
    _GuardedBind();
 
274
    GLint id = 0;
 
275
    CHECKGL( glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
 
276
        GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
 
277
        &id) );
 
278
    _GuardedUnbind();
 
279
    return GLuint(id);
 
280
}
 
281
 
 
282
GLint GLFramebufferObject::GetAttachedMipLevel( GLenum attachment )
 
283
{
 
284
    _GuardedBind();
 
285
    GLint level = 0;
 
286
    CHECKGL( glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
 
287
        GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT, 
 
288
        &level) );
 
289
    _GuardedUnbind();
 
290
    return level;
 
291
}
 
292
 
 
293
GLint GLFramebufferObject::GetAttachedCubeFace( GLenum attachment )
 
294
{
 
295
    _GuardedBind();
 
296
    GLint level = 0;
 
297
    CHECKGL( glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
 
298
        GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT,
 
299
        &level) );
 
300
    _GuardedUnbind();
 
301
    return level;
 
302
}
 
303
 
 
304
GLint GLFramebufferObject::GetAttachedZSlice( GLenum attachment )
 
305
{
 
306
    _GuardedBind();
 
307
    GLint slice = 0;
 
308
    CHECKGL( glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
 
309
        GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT,
 
310
        &slice) );
 
311
    _GuardedUnbind();
 
312
    return slice;
 
313
}
 
314
 
 
315
//////////////////////////////////////////////////////////////////////////
 
316
// GLRenderbuffer
 
317
//////////////////////////////////////////////////////////////////////////
 
318
 
 
319
 
 
320
GLRenderbuffer::GLRenderbuffer()
 
321
: m_bufId(_CreateBufferId())
 
322
{}
 
323
 
 
324
GLRenderbuffer::GLRenderbuffer(GLenum internalFormat, int width, int height)
 
325
: m_bufId(_CreateBufferId())
 
326
{
 
327
    Set(internalFormat, width, height);
 
328
}
 
329
 
 
330
GLRenderbuffer::~GLRenderbuffer()
 
331
{
 
332
    CHECKGL( glDeleteRenderbuffersEXT(1, &m_bufId) );
 
333
}
 
334
 
 
335
void GLRenderbuffer::Bind() 
 
336
{
 
337
    CHECKGL( glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_bufId) );
 
338
}
 
339
 
 
340
void GLRenderbuffer::Unbind() 
 
341
{
 
342
    CHECKGL( glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0) );
 
343
}
 
344
 
 
345
void GLRenderbuffer::Set(GLenum internalFormat, int width, int height)
 
346
{
 
347
    int maxSize = GLRenderbuffer::GetMaxSize();
 
348
    if (width > maxSize || height > maxSize )
 
349
    {
 
350
        std::cout << "GLRenderbuffer::GLRenderbuffer() ERROR: Size too big width=" << width << "height=" << height << "\n";
 
351
        return;
 
352
    }
 
353
 
 
354
    // Guarded bind
 
355
    GLint savedId = 0;
 
356
    CHECKGL( glGetIntegerv( GL_RENDERBUFFER_BINDING_EXT, &savedId ) );
 
357
    if (savedId != m_bufId)
 
358
    {
 
359
        Bind();
 
360
    }
 
361
 
 
362
    // Allocate memory for renderBuffer
 
363
    CHECKGL( glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalFormat, width, height ) );
 
364
 
 
365
    // Guarded unbind
 
366
    if (savedId != m_bufId)
 
367
    {
 
368
        Unbind();
 
369
    }
 
370
}
 
371
 
 
372
GLuint GLRenderbuffer::GetId() const 
 
373
{
 
374
    return m_bufId;
 
375
}
 
376
 
 
377
GLint GLRenderbuffer::GetMaxSize()
 
378
{
 
379
    GLint maxAttach = 0;
 
380
    CHECKGL( glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE_EXT, &maxAttach ) );
 
381
    return maxAttach;
 
382
}
 
383
 
 
384
GLuint GLRenderbuffer::_CreateBufferId() 
 
385
{
 
386
    GLuint id = 0;
 
387
    CHECKGL( glGenRenderbuffersEXT(1, &id) );
 
388
    return id;
 
389
}
 
390
 
 
391
NAMESPACE_END_OGL