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 "GLDeviceFactory.h"
25
#include "GLDeviceObjects.h"
26
#include "IOpenGLFrameBufferObject.h"
27
#include "OpenGLEngine.h"
31
IMPLEMENT_OBJECT_TYPE(IOpenGLFrameBufferObject);
33
IOpenGLFrameBufferObject::IOpenGLFrameBufferObject(unsigned int Width, unsigned int Height, BitmapFormat PixelFormat)
36
, _PixelFormat(PixelFormat)
38
, _Depth_Attachment(0)
39
, _Stencil_Attachment(0)
40
, IOpenGLResource(RTFRAMEBUFFEROBJECT)
42
for (int i = 0; i < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment(); i++)
44
_Color_AttachmentArray.push_back(TRefGL<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(unsigned int Width, unsigned int Height, BitmapFormat PixelFormat)
62
for(int i=0; i< GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment(); i++)
64
_Color_AttachmentArray[i] = NULL;
66
_Depth_Attachment = NULL;
67
_Stencil_Attachment = NULL;
69
if((_Width == Width) && (_Height == Height) && (_PixelFormat == PixelFormat))
72
_Rbo.Set (GL_DEPTH_COMPONENT, Width, Height);
74
// Clear clipping region stack
77
EmptyClippingRegion();
78
_PixelFormat = PixelFormat;
82
int IOpenGLFrameBufferObject::SetRenderTarget(unsigned int ColorAttachmentIndex, TRefGL<IOpenGLSurface> pRenderTargetSurface)
84
nuxAssert(ColorAttachmentIndex < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment());
85
if(pRenderTargetSurface.IsNull())
87
_Color_AttachmentArray[ColorAttachmentIndex] = 0;
91
if(_Color_AttachmentArray[ColorAttachmentIndex] == pRenderTargetSurface)
96
BitmapFormat PixelFormat = pRenderTargetSurface->GetPixelFormat();
97
if(!(_Width == pRenderTargetSurface->GetWidth() && _Height == pRenderTargetSurface->GetHeight()))
99
nuxAssertMsg(0, TEXT("[IOpenGLFrameBufferObject::SetRenderTarget] Invalid surface size.") );
103
_Color_AttachmentArray[ColorAttachmentIndex] = pRenderTargetSurface;
111
int IOpenGLFrameBufferObject::SetDepthSurface(TRefGL<IOpenGLSurface> pDepthSurface)
113
//nuxAssert(pDepthSurface.IsValid());
115
if(pDepthSurface.IsNull())
117
_Depth_Attachment = 0;
118
_Stencil_Attachment = 0;
122
BitmapFormat PixelFormat = pDepthSurface->GetPixelFormat();
124
if(!(_Width == pDepthSurface->GetWidth() && _Height == pDepthSurface->GetHeight()))
126
nuxAssertMsg(0, TEXT("The depth surface size is not compatible with the frame buffer size.") );
130
if(_Depth_Attachment == pDepthSurface)
133
// We rely on the fact that the depth texture is actually a D24_S8 texture.
134
// That is, the surface for the depth and stencil attachment is the same. When we bound, the surface,
135
// we explicitly bind the depth attachment and the stencil attachment with the same surface.
136
_Depth_Attachment = pDepthSurface;
137
_Stencil_Attachment = pDepthSurface;
146
TRefGL<IOpenGLSurface> IOpenGLFrameBufferObject::GetRenderTarget(unsigned int ColorAttachmentIndex)
148
nuxAssert(ColorAttachmentIndex < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment());
149
return _Color_AttachmentArray[ColorAttachmentIndex];
152
TRefGL<IOpenGLSurface> IOpenGLFrameBufferObject::GetDepthRenderTarget()
154
return _Depth_Attachment;
157
int IOpenGLFrameBufferObject::Activate(bool WithClippingStack)
159
GLuint NumBuffers = 0;
162
if(GetThreadGLDeviceFactory())
163
GetThreadGLDeviceFactory()->SetCurrentFrameBufferObject(this);
165
for (int i = 0; i < GetThreadGLDeviceFactory()->GetOpenGLMaxFrameBufferAttachment(); i++)
167
if(_Color_AttachmentArray[i].IsValid())
169
GLenum target = _Color_AttachmentArray[i]->GetSurfaceTarget();
170
GLenum glID = _Color_AttachmentArray[i]->GetOpenGLID();
171
GLint level = _Color_AttachmentArray[i]->GetMipLevel();
172
CHECKGL( glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, target, glID, level) );
173
CHECKGL( glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + i) );
179
CHECKGL( glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, 0, 0) );
183
// if(_Depth_Attachment.IsValid())
185
// GLenum target = _Depth_Attachment->GetSurfaceTarget();
186
// GLenum glID = _Depth_Attachment->GetOpenGLID();
187
// GLint level = _Depth_Attachment->GetMipLevel();
188
// CHECKGL( glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, target, glID, level) );
192
// CHECKGL( glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0) );
193
// // On the PC you need to bing the same D24S8 surface to the depth and the stencil attachment.
196
//_Rbo.Set (GL_DEPTH_COMPONENT, _Width, _Height);
197
CHECKGL( glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
198
GL_DEPTH_ATTACHMENT_EXT,
202
nuxAssert( _Fbo.IsValid() == true );
203
if(GetThreadGraphicsContext())
204
GetThreadGraphicsContext()->SetViewport(0, 0, _Width, _Height);
206
if(WithClippingStack)
207
ApplyClippingRegion();
213
// Restore the original opengl back buffer as defined when creating the opengl context(color + depth + stencil).
214
int IOpenGLFrameBufferObject::Deactivate()
216
CHECKGL( glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ) );
217
CHECKGL( glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0) );
219
if(GetThreadGLDeviceFactory())
220
GetThreadGLDeviceFactory()->SetCurrentFrameBufferObject(0);
222
if(GetThreadGraphicsContext())
223
GetThreadGraphicsContext()->SetScissor(0, 0, _Width, _Height);
228
void IOpenGLFrameBufferObject::PushClippingRegion(Rect clip_rect)
230
clip_rect.OffsetPosition(0, 0);
232
Rect current_clip_rect;
233
unsigned int stacksize = (unsigned int)_ClippingRegionStack.size();
237
current_clip_rect = Rect(0, 0, _Width, _Height);
241
current_clip_rect = _ClippingRegionStack[stacksize-1];
245
if(GetThreadGraphicsContext())
246
rect = GetThreadGraphicsContext()->GetViewportRect();
247
clip_rect.OffsetPosition(rect.x, _Height - (rect.y + rect.GetHeight()));
249
Rect Intersection = current_clip_rect.Intersect(clip_rect);
250
if(!Intersection.IsNull())
252
_ClippingRegionStack.push_back(Intersection);
254
SetClippingRegion(Intersection.x + GetThreadGraphicsContext()->GetContextX(),
255
_Height - Intersection.y - Intersection.GetHeight() - GetThreadGraphicsContext()->GetContextY(),
256
Intersection.GetWidth(), Intersection.GetHeight());
260
_ClippingRegionStack.push_back(Rect(0, 0, 0, 0));
261
SetClippingRegion(0, 0, 0, 0);
265
void IOpenGLFrameBufferObject::PopClippingRegion()
267
_ClippingRegionStack.pop_back();
268
int stacksize = (int)_ClippingRegionStack.size();
271
SetClippingRegion(0, 0, _Width, _Height);
275
Rect current_clip_rect = _ClippingRegionStack[stacksize-1];
276
SetClippingRegion(current_clip_rect.x, _Height - current_clip_rect.y - current_clip_rect.GetHeight(), current_clip_rect.GetWidth(), current_clip_rect.GetHeight());
280
void IOpenGLFrameBufferObject::EmptyClippingRegion()
282
_ClippingRegionStack.clear();
284
SetClippingRegion(0, 0, _Width, _Height);
288
void IOpenGLFrameBufferObject::ApplyClippingRegion()
290
int stacksize = (int)_ClippingRegionStack.size();
293
SetClippingRegion(0, 0, _Width, _Height);
297
Rect current_clip_rect = _ClippingRegionStack[stacksize-1];
298
SetClippingRegion(current_clip_rect.x, _Height - current_clip_rect.y - current_clip_rect.GetHeight(), current_clip_rect.GetWidth(), current_clip_rect.GetHeight());
302
void IOpenGLFrameBufferObject::SetClippingRegion(int x, int y, unsigned int width, unsigned int height)
304
if(GetThreadGraphicsContext())
305
GetThreadGraphicsContext()->SetScissor(x, y, width, height);
308
Rect IOpenGLFrameBufferObject::GetClippingRegion()
310
unsigned int stacksize = (unsigned int)_ClippingRegionStack.size();
313
return Rect(0, 0, _Width, _Height);
317
Rect r = _ClippingRegionStack[stacksize-1];