2
* Copyright 2010 Inalogic Inc.
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.
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.
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/>
18
* Authored by: Jay Taoko <jay.taoko_AT_gmail_DOT_com>
23
#include "GLResource.h"
24
#include "GpuDevice.h"
25
#include "GLDeviceObjects.h"
26
#include "IOpenGLFrameBufferObject.h"
27
#include "GraphicsEngine.h"
32
NUX_IMPLEMENT_OBJECT_TYPE (IOpenGLFrameBufferObject);
34
IOpenGLFrameBufferObject::IOpenGLFrameBufferObject (NUX_FILE_LINE_DECL)
35
: IOpenGLResource (RTFRAMEBUFFEROBJECT, NUX_FILE_LINE_PARAM)
39
_PixelFormat = BITFMT_R8G8B8A8;
42
for (int i = 0; i < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment(); i++)
44
_Color_AttachmentArray.push_back (IntrusiveSP<IOpenGLSurface> (0) );
47
FormatFrameBufferObject (_Width, _Height, _PixelFormat);
48
GRunTimeStats.Register (this);
51
IOpenGLFrameBufferObject::~IOpenGLFrameBufferObject()
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.
56
GRunTimeStats.UnRegister (this);
59
int IOpenGLFrameBufferObject::FormatFrameBufferObject (int Width, int Height, BitmapFormat PixelFormat)
63
for (int i = 0; i < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment(); i++)
65
_Color_AttachmentArray[i] = IntrusiveSP<IOpenGLSurface> (0);
68
_Depth_Attachment = IntrusiveSP<IOpenGLSurface> (0);
69
_Stencil_Attachment = IntrusiveSP<IOpenGLSurface> (0);
71
if ( (_Width == Width) && (_Height == Height) && (_PixelFormat == PixelFormat) )
74
_Rbo.Set (GL_DEPTH_COMPONENT, Width, Height);
76
// Clear clipping region stack
79
_PixelFormat = PixelFormat;
80
EmptyClippingRegion();
85
int IOpenGLFrameBufferObject::SetRenderTarget (int ColorAttachmentIndex, IntrusiveSP<IOpenGLSurface> pRenderTargetSurface)
87
nuxAssert (ColorAttachmentIndex < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment() );
89
if (pRenderTargetSurface.IsNull() )
91
_Color_AttachmentArray[ColorAttachmentIndex] = IntrusiveSP<IOpenGLSurface> (0);
95
if (_Color_AttachmentArray[ColorAttachmentIndex] == pRenderTargetSurface)
100
if (! (_Width == pRenderTargetSurface->GetWidth() && _Height == pRenderTargetSurface->GetHeight() ) )
102
nuxAssertMsg (0, TEXT ("[IOpenGLFrameBufferObject::SetRenderTarget] Invalid surface size.") );
106
_Color_AttachmentArray[ColorAttachmentIndex] = pRenderTargetSurface;
116
int IOpenGLFrameBufferObject::SetDepthSurface (IntrusiveSP<IOpenGLSurface> pDepthSurface)
118
//nuxAssert(pDepthSurface.IsValid());
120
if (pDepthSurface.IsNull() )
122
_Depth_Attachment = IntrusiveSP<IOpenGLSurface> (0);
123
_Stencil_Attachment = IntrusiveSP<IOpenGLSurface> (0);
127
if (! (_Width == pDepthSurface->GetWidth() && _Height == pDepthSurface->GetHeight() ) )
129
nuxAssertMsg (0, TEXT ("The depth surface size is not compatible with the frame buffer size.") );
133
if (_Depth_Attachment == pDepthSurface)
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;
150
IntrusiveSP<IOpenGLSurface> IOpenGLFrameBufferObject::GetRenderTarget (int ColorAttachmentIndex)
152
nuxAssert (ColorAttachmentIndex < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment() );
153
return _Color_AttachmentArray[ColorAttachmentIndex];
156
IntrusiveSP<IOpenGLSurface> IOpenGLFrameBufferObject::GetDepthRenderTarget()
158
return _Depth_Attachment;
161
int IOpenGLFrameBufferObject::Activate (bool WithClippingStack)
163
GLuint NumBuffers = 0;
166
if (GetThreadGLDeviceFactory() )
167
GetThreadGLDeviceFactory()->SetCurrentFrameBufferObject (IntrusiveSP<IOpenGLFrameBufferObject> (this));
169
for (int i = 0; i < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment(); i++)
171
if (_Color_AttachmentArray[i].IsValid() )
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) );
183
CHECKGL ( glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, 0, 0) );
187
// if(_Depth_Attachment.IsValid())
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) );
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.
200
//_Rbo.Set (GL_DEPTH_COMPONENT, _Width, _Height);
201
CHECKGL ( glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
202
GL_DEPTH_ATTACHMENT_EXT,
206
nuxAssert ( _Fbo.IsValid() == true );
208
if (GetThreadGraphicsContext() )
209
GetThreadGraphicsContext()->SetViewport (0, 0, _Width, _Height);
211
if (WithClippingStack)
212
ApplyClippingRegion();
218
// Restore the original opengl back buffer as defined when creating the opengl context(color + depth + stencil).
219
int IOpenGLFrameBufferObject::Deactivate()
221
CHECKGL ( glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, 0 ) );
222
CHECKGL ( glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, 0) );
224
if (GetThreadGLDeviceFactory() )
225
GetThreadGLDeviceFactory()->SetCurrentFrameBufferObject (IntrusiveSP<IOpenGLFrameBufferObject> (0));
227
if (GetThreadGraphicsContext() )
228
GetThreadGraphicsContext()->SetScissor (0, 0, _Width, _Height);
234
void IOpenGLFrameBufferObject::PushClippingRegion (Rect clip_rect)
236
clip_rect.OffsetPosition (0, 0);
238
Rect current_clip_rect;
239
unsigned int stacksize = (unsigned int) _ClippingRegionStack.size();
243
current_clip_rect = Rect (0, 0, _Width, _Height);
247
current_clip_rect = _ClippingRegionStack[stacksize-1];
252
if (GetThreadGraphicsContext() )
253
rect = GetThreadGraphicsContext()->GetViewportRect();
255
clip_rect.OffsetPosition (rect.x, _Height - (rect.y + rect.GetHeight() ) );
257
Rect Intersection = current_clip_rect.Intersect (clip_rect);
259
if (!Intersection.IsNull() )
261
_ClippingRegionStack.push_back (Intersection);
263
SetClippingRegion (Intersection.x + GetThreadGraphicsContext()->GetContextX(),
264
_Height - Intersection.y - Intersection.GetHeight() - GetThreadGraphicsContext()->GetContextY(),
265
Intersection.GetWidth(), Intersection.GetHeight() );
269
_ClippingRegionStack.push_back (Rect (0, 0, 0, 0) );
270
SetClippingRegion (0, 0, 0, 0);
274
void IOpenGLFrameBufferObject::PopClippingRegion()
276
_ClippingRegionStack.pop_back();
277
int stacksize = (int) _ClippingRegionStack.size();
281
SetClippingRegion (0, 0, _Width, _Height);
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() );
290
void IOpenGLFrameBufferObject::EmptyClippingRegion()
292
_ClippingRegionStack.clear();
294
SetClippingRegion (0, 0, _Width, _Height);
298
void IOpenGLFrameBufferObject::ApplyClippingRegion()
300
int stacksize = (int) _ClippingRegionStack.size();
304
SetClippingRegion (0, 0, _Width, _Height);
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() );
313
void IOpenGLFrameBufferObject::SetClippingRegion (int x, int y, int width, int height)
315
if (GetThreadGraphicsContext() )
316
GetThreadGraphicsContext()->SetScissor (x, y, width, height);
319
Rect IOpenGLFrameBufferObject::GetClippingRegion()
321
unsigned int stacksize = (unsigned int) _ClippingRegionStack.size();
325
return Rect (0, 0, _Width, _Height);
329
Rect r = _ClippingRegionStack[stacksize-1];