~om26er/ubuntu/oneiric/nux/sru-819721

« back to all changes in this revision

Viewing changes to NuxGraphics/IOpenGLFrameBufferObject.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-11-18 19:17:32 UTC
  • Revision ID: james.westby@ubuntu.com-20101118191732-rn35790vekj6o4my
Tags: upstream-0.9.4
ImportĀ upstreamĀ versionĀ 0.9.4

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 "GpuDevice.h"
 
25
#include "GLDeviceObjects.h"
 
26
#include "IOpenGLFrameBufferObject.h"
 
27
#include "GraphicsEngine.h"
 
28
 
 
29
namespace nux
 
30
{
 
31
 
 
32
  NUX_IMPLEMENT_OBJECT_TYPE (IOpenGLFrameBufferObject);
 
33
 
 
34
  IOpenGLFrameBufferObject::IOpenGLFrameBufferObject (NUX_FILE_LINE_DECL)
 
35
    :   IOpenGLResource (RTFRAMEBUFFEROBJECT, NUX_FILE_LINE_PARAM)
 
36
  {
 
37
    _Width = 1;
 
38
    _Height = 1;
 
39
    _PixelFormat = BITFMT_R8G8B8A8;
 
40
    _IsActive = false;
 
41
 
 
42
    for (int i = 0; i < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment(); i++)
 
43
    {
 
44
      _Color_AttachmentArray.push_back (IntrusiveSP<IOpenGLSurface> (0) );
 
45
    }
 
46
 
 
47
    FormatFrameBufferObject (_Width, _Height, _PixelFormat);
 
48
    GRunTimeStats.Register (this);
 
49
  }
 
50
 
 
51
  IOpenGLFrameBufferObject::~IOpenGLFrameBufferObject()
 
52
  {
 
53
    // IOpenGLFrameBufferObject is an abstraction. Is does not have an opengl id.
 
54
    // _Fbo has an opengl id that is destroyed when the destructor is called.
 
55
    _OpenGLID = 0;
 
56
    GRunTimeStats.UnRegister (this);
 
57
  }
 
58
 
 
59
  int IOpenGLFrameBufferObject::FormatFrameBufferObject (int Width, int Height, BitmapFormat PixelFormat)
 
60
  {
 
61
    Deactivate();
 
62
 
 
63
    for (int i = 0; i < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment(); i++)
 
64
    {
 
65
      _Color_AttachmentArray[i] = IntrusiveSP<IOpenGLSurface> (0);
 
66
    }
 
67
 
 
68
    _Depth_Attachment = IntrusiveSP<IOpenGLSurface> (0);
 
69
    _Stencil_Attachment = IntrusiveSP<IOpenGLSurface> (0);
 
70
 
 
71
    if ( (_Width == Width) && (_Height == Height) && (_PixelFormat == PixelFormat) )
 
72
      return 1;
 
73
 
 
74
    _Rbo.Set (GL_DEPTH_COMPONENT, Width, Height);
 
75
 
 
76
    // Clear clipping region stack
 
77
    _Width  = Width;
 
78
    _Height = Height;
 
79
    _PixelFormat = PixelFormat;
 
80
    EmptyClippingRegion();
 
81
    
 
82
    return 1;
 
83
  }
 
84
 
 
85
  int IOpenGLFrameBufferObject::SetRenderTarget (int ColorAttachmentIndex, IntrusiveSP<IOpenGLSurface> pRenderTargetSurface)
 
86
  {
 
87
    nuxAssert (ColorAttachmentIndex < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment() );
 
88
 
 
89
    if (pRenderTargetSurface.IsNull() )
 
90
    {
 
91
      _Color_AttachmentArray[ColorAttachmentIndex] = IntrusiveSP<IOpenGLSurface> (0);
 
92
      return 1;
 
93
    }
 
94
 
 
95
    if (_Color_AttachmentArray[ColorAttachmentIndex] == pRenderTargetSurface)
 
96
    {
 
97
      return 1;
 
98
    }
 
99
 
 
100
    if (! (_Width == pRenderTargetSurface->GetWidth() && _Height == pRenderTargetSurface->GetHeight() ) )
 
101
    {
 
102
      nuxAssertMsg (0, TEXT ("[IOpenGLFrameBufferObject::SetRenderTarget] Invalid surface size.") );
 
103
      return 0;
 
104
    }
 
105
 
 
106
    _Color_AttachmentArray[ColorAttachmentIndex] = pRenderTargetSurface;
 
107
 
 
108
    if (_IsActive)
 
109
    {
 
110
      Activate();
 
111
    }
 
112
 
 
113
    return 1;
 
114
  }
 
115
 
 
116
  int IOpenGLFrameBufferObject::SetDepthSurface (IntrusiveSP<IOpenGLSurface> pDepthSurface)
 
117
  {
 
118
    //nuxAssert(pDepthSurface.IsValid());
 
119
 
 
120
    if (pDepthSurface.IsNull() )
 
121
    {
 
122
      _Depth_Attachment = IntrusiveSP<IOpenGLSurface> (0);
 
123
      _Stencil_Attachment = IntrusiveSP<IOpenGLSurface> (0);
 
124
      return 1;
 
125
    }
 
126
 
 
127
    if (! (_Width == pDepthSurface->GetWidth() && _Height == pDepthSurface->GetHeight() ) )
 
128
    {
 
129
      nuxAssertMsg (0, TEXT ("The depth surface size is not compatible with the frame buffer size.") );
 
130
      return 0;
 
131
    }
 
132
 
 
133
    if (_Depth_Attachment == pDepthSurface)
 
134
      return 1;
 
135
 
 
136
    // We rely on the fact that the depth texture is actually a D24_S8 texture.
 
137
    // That is, the surface for the depth and stencil attachment is the same. When we bound, the surface,
 
138
    // we explicitly bind the depth attachment and the stencil attachment with the same surface.
 
139
    _Depth_Attachment = pDepthSurface;
 
140
    _Stencil_Attachment = pDepthSurface;
 
141
 
 
142
    if (_IsActive)
 
143
    {
 
144
      Activate();
 
145
    }
 
146
 
 
147
    return 1;
 
148
  }
 
149
 
 
150
  IntrusiveSP<IOpenGLSurface> IOpenGLFrameBufferObject::GetRenderTarget (int ColorAttachmentIndex)
 
151
  {
 
152
    nuxAssert (ColorAttachmentIndex < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment() );
 
153
    return _Color_AttachmentArray[ColorAttachmentIndex];
 
154
  }
 
155
 
 
156
  IntrusiveSP<IOpenGLSurface> IOpenGLFrameBufferObject::GetDepthRenderTarget()
 
157
  {
 
158
    return _Depth_Attachment;
 
159
  }
 
160
 
 
161
  int IOpenGLFrameBufferObject::Activate (bool WithClippingStack)
 
162
  {
 
163
    GLuint NumBuffers = 0;
 
164
    _Fbo.Bind();
 
165
 
 
166
    if (GetThreadGLDeviceFactory() )
 
167
      GetThreadGLDeviceFactory()->SetCurrentFrameBufferObject (IntrusiveSP<IOpenGLFrameBufferObject> (this));
 
168
 
 
169
    for (int i = 0; i < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment(); i++)
 
170
    {
 
171
      if (_Color_AttachmentArray[i].IsValid() )
 
172
      {
 
173
        GLenum target   = _Color_AttachmentArray[i]->GetSurfaceTarget();
 
174
        GLenum glID     = _Color_AttachmentArray[i]->GetOpenGLID();
 
175
        GLint level     = _Color_AttachmentArray[i]->GetMipLevel();
 
176
        CHECKGL ( glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, target, glID, level) );
 
177
        CHECKGL ( glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT + i) );
 
178
 
 
179
        NumBuffers++;
 
180
      }
 
181
      else
 
182
      {
 
183
        CHECKGL ( glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, 0, 0) );
 
184
      }
 
185
    }
 
186
 
 
187
//     if(_Depth_Attachment.IsValid())
 
188
//     {
 
189
//         GLenum target   = _Depth_Attachment->GetSurfaceTarget();
 
190
//         GLenum glID     = _Depth_Attachment->GetOpenGLID();
 
191
//         GLint level     = _Depth_Attachment->GetMipLevel();
 
192
//         CHECKGL( glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, target, glID, level) );
 
193
//     }
 
194
//     else
 
195
//     {
 
196
//         CHECKGL( glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0) );
 
197
//         // On the PC you need to bing the same D24S8 surface to the depth and the stencil attachment.
 
198
//     }
 
199
 
 
200
    //_Rbo.Set (GL_DEPTH_COMPONENT, _Width, _Height);
 
201
    CHECKGL ( glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
 
202
                                            GL_DEPTH_ATTACHMENT_EXT,
 
203
                                            GL_RENDERBUFFER_EXT,
 
204
                                            _Rbo.GetId() ) );
 
205
 
 
206
    nuxAssert ( _Fbo.IsValid() == true );
 
207
 
 
208
    if (GetThreadGraphicsContext() )
 
209
      GetThreadGraphicsContext()->SetViewport (0, 0, _Width, _Height);
 
210
 
 
211
    if (WithClippingStack)
 
212
      ApplyClippingRegion();
 
213
 
 
214
    _IsActive = true;
 
215
    return 1;
 
216
  }
 
217
 
 
218
// Restore the original opengl back buffer as defined when creating the opengl context(color + depth + stencil).
 
219
  int IOpenGLFrameBufferObject::Deactivate()
 
220
  {
 
221
    CHECKGL ( glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, 0 ) );
 
222
    CHECKGL ( glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, 0) );
 
223
 
 
224
    if (GetThreadGLDeviceFactory() )
 
225
      GetThreadGLDeviceFactory()->SetCurrentFrameBufferObject (IntrusiveSP<IOpenGLFrameBufferObject> (0));
 
226
 
 
227
    if (GetThreadGraphicsContext() )
 
228
      GetThreadGraphicsContext()->SetScissor (0, 0, _Width, _Height);
 
229
 
 
230
    _IsActive = false;
 
231
    return 1;
 
232
  }
 
233
 
 
234
  void IOpenGLFrameBufferObject::PushClippingRegion (Rect clip_rect)
 
235
  {
 
236
    clip_rect.OffsetPosition (0, 0);
 
237
 
 
238
    Rect current_clip_rect;
 
239
    unsigned int stacksize = (unsigned int) _ClippingRegionStack.size();
 
240
 
 
241
    if (stacksize == 0)
 
242
    {
 
243
      current_clip_rect = Rect (0, 0, _Width, _Height);
 
244
    }
 
245
    else
 
246
    {
 
247
      current_clip_rect = _ClippingRegionStack[stacksize-1];
 
248
    }
 
249
 
 
250
    Rect rect;
 
251
 
 
252
    if (GetThreadGraphicsContext() )
 
253
      rect = GetThreadGraphicsContext()->GetViewportRect();
 
254
 
 
255
    clip_rect.OffsetPosition (rect.x, _Height - (rect.y + rect.GetHeight() ) );
 
256
 
 
257
    Rect Intersection = current_clip_rect.Intersect (clip_rect);
 
258
 
 
259
    if (!Intersection.IsNull() )
 
260
    {
 
261
      _ClippingRegionStack.push_back (Intersection);
 
262
 
 
263
      SetClippingRegion (Intersection.x + GetThreadGraphicsContext()->GetContextX(),
 
264
                         _Height - Intersection.y - Intersection.GetHeight() - GetThreadGraphicsContext()->GetContextY(),
 
265
                         Intersection.GetWidth(), Intersection.GetHeight() );
 
266
    }
 
267
    else
 
268
    {
 
269
      _ClippingRegionStack.push_back (Rect (0, 0, 0, 0) );
 
270
      SetClippingRegion (0, 0, 0, 0);
 
271
    }
 
272
  }
 
273
 
 
274
  void IOpenGLFrameBufferObject::PopClippingRegion()
 
275
  {
 
276
    _ClippingRegionStack.pop_back();
 
277
    int stacksize = (int) _ClippingRegionStack.size();
 
278
 
 
279
    if (stacksize == 0)
 
280
    {
 
281
      SetClippingRegion (0, 0, _Width, _Height);
 
282
    }
 
283
    else
 
284
    {
 
285
      Rect current_clip_rect = _ClippingRegionStack[stacksize-1];
 
286
      SetClippingRegion (current_clip_rect.x, _Height - current_clip_rect.y - current_clip_rect.GetHeight(), current_clip_rect.GetWidth(), current_clip_rect.GetHeight() );
 
287
    }
 
288
  }
 
289
 
 
290
  void IOpenGLFrameBufferObject::EmptyClippingRegion()
 
291
  {
 
292
    _ClippingRegionStack.clear();
 
293
    {
 
294
      SetClippingRegion (0, 0, _Width, _Height);
 
295
    }
 
296
  }
 
297
 
 
298
  void IOpenGLFrameBufferObject::ApplyClippingRegion()
 
299
  {
 
300
    int stacksize = (int) _ClippingRegionStack.size();
 
301
 
 
302
    if (stacksize == 0)
 
303
    {
 
304
      SetClippingRegion (0, 0, _Width, _Height);
 
305
    }
 
306
    else
 
307
    {
 
308
      Rect current_clip_rect = _ClippingRegionStack[stacksize-1];
 
309
      SetClippingRegion (current_clip_rect.x, _Height - current_clip_rect.y - current_clip_rect.GetHeight(), current_clip_rect.GetWidth(), current_clip_rect.GetHeight() );
 
310
    }
 
311
  }
 
312
 
 
313
  void IOpenGLFrameBufferObject::SetClippingRegion (int x, int y, int width, int height)
 
314
  {
 
315
    if (GetThreadGraphicsContext() )
 
316
      GetThreadGraphicsContext()->SetScissor (x, y, width, height);
 
317
  }
 
318
 
 
319
  Rect IOpenGLFrameBufferObject::GetClippingRegion()
 
320
  {
 
321
    unsigned int stacksize = (unsigned int) _ClippingRegionStack.size();
 
322
 
 
323
    if (stacksize == 0)
 
324
    {
 
325
      return Rect (0, 0, _Width, _Height);
 
326
    }
 
327
    else
 
328
    {
 
329
      Rect r = _ClippingRegionStack[stacksize-1];
 
330
      return r;
 
331
    }
 
332
  }
 
333
}