nux-1.16.0
|
00001 /* 00002 * Copyright 2010 Inalogic® Inc. 00003 * 00004 * This program is free software: you can redistribute it and/or modify it 00005 * under the terms of the GNU Lesser General Public License, as 00006 * published by the Free Software Foundation; either version 2.1 or 3.0 00007 * of the License. 00008 * 00009 * This program is distributed in the hope that it will be useful, but 00010 * WITHOUT ANY WARRANTY; without even the implied warranties of 00011 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 00012 * PURPOSE. See the applicable version of the GNU Lesser General Public 00013 * License for more details. 00014 * 00015 * You should have received a copy of both the GNU Lesser General Public 00016 * License along with this program. If not, see <http://www.gnu.org/licenses/> 00017 * 00018 * Authored by: Jay Taoko <jaytaoko@inalogic.com> 00019 * 00020 */ 00021 00022 00023 #include "GLResource.h" 00024 #include "GraphicsDisplay.h" 00025 #include "GpuDevice.h" 00026 #include "GLDeviceObjects.h" 00027 #include "IOpenGLFrameBufferObject.h" 00028 #include "GraphicsEngine.h" 00029 00030 namespace nux 00031 { 00032 00033 NUX_IMPLEMENT_OBJECT_TYPE (IOpenGLFrameBufferObject); 00034 00035 IOpenGLFrameBufferObject::IOpenGLFrameBufferObject (NUX_FILE_LINE_DECL) 00036 : IOpenGLResource (RTFRAMEBUFFEROBJECT, NUX_FILE_LINE_PARAM) 00037 { 00038 _Width = 1; 00039 _Height = 1; 00040 _PixelFormat = BITFMT_R8G8B8A8; 00041 _IsActive = false; 00042 00043 for (int i = 0; i < 1 /*GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxFboAttachment()*/; i++) 00044 { 00045 _Color_AttachmentArray.push_back (ObjectPtr<IOpenGLSurface> (0) ); 00046 } 00047 00048 FormatFrameBufferObject (_Width, _Height, _PixelFormat); 00049 GRunTimeStats.Register (this); 00050 } 00051 00052 IOpenGLFrameBufferObject::~IOpenGLFrameBufferObject() 00053 { 00054 // IOpenGLFrameBufferObject is an abstraction. Is does not have an opengl id. 00055 // _Fbo has an opengl id that is destroyed when the destructor is called. 00056 _OpenGLID = 0; 00057 GRunTimeStats.UnRegister (this); 00058 } 00059 00060 int IOpenGLFrameBufferObject::FormatFrameBufferObject (int Width, int Height, BitmapFormat PixelFormat) 00061 { 00062 Deactivate(); 00063 00064 for (int i = 0; i < 1 /*GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxFboAttachment()*/; i++) 00065 { 00066 _Color_AttachmentArray[i] = ObjectPtr<IOpenGLSurface> (0); 00067 } 00068 00069 _Depth_Attachment = ObjectPtr<IOpenGLSurface> (0); 00070 _Stencil_Attachment = ObjectPtr<IOpenGLSurface> (0); 00071 00072 if ( (_Width == Width) && (_Height == Height) && (_PixelFormat == PixelFormat) ) 00073 return 1; 00074 00075 // #ifndef NUX_OPENGLES_20 00076 // _Rbo.Set (GL_DEPTH_COMPONENT, Width, Height); 00077 // #endif 00078 00079 // Clear clipping region stack 00080 _Width = Width; 00081 _Height = Height; 00082 _PixelFormat = PixelFormat; 00083 EmptyClippingRegion(); 00084 00085 return 1; 00086 } 00087 00088 int IOpenGLFrameBufferObject::SetRenderTarget (int ColorAttachmentIndex, ObjectPtr<IOpenGLSurface> pRenderTargetSurface) 00089 { 00090 nuxAssert (ColorAttachmentIndex < 1 /*GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxFboAttachment()*/); 00091 00092 if (pRenderTargetSurface.IsNull() ) 00093 { 00094 _Color_AttachmentArray[ColorAttachmentIndex] = ObjectPtr<IOpenGLSurface> (0); 00095 return 1; 00096 } 00097 00098 if (_Color_AttachmentArray[ColorAttachmentIndex] == pRenderTargetSurface) 00099 { 00100 return 1; 00101 } 00102 00103 if (! (_Width == pRenderTargetSurface->GetWidth() && _Height == pRenderTargetSurface->GetHeight() ) ) 00104 { 00105 nuxAssertMsg (0, TEXT ("[IOpenGLFrameBufferObject::SetRenderTarget] Invalid surface size.") ); 00106 return 0; 00107 } 00108 00109 _Color_AttachmentArray[ColorAttachmentIndex] = pRenderTargetSurface; 00110 00111 if (_IsActive) 00112 { 00113 Activate(); 00114 } 00115 00116 return 1; 00117 } 00118 00119 int IOpenGLFrameBufferObject::SetDepthSurface (ObjectPtr<IOpenGLSurface> pDepthSurface) 00120 { 00121 //nuxAssert(pDepthSurface.IsValid()); 00122 00123 if (pDepthSurface.IsNull() ) 00124 { 00125 _Depth_Attachment = ObjectPtr<IOpenGLSurface> (0); 00126 _Stencil_Attachment = ObjectPtr<IOpenGLSurface> (0); 00127 return 1; 00128 } 00129 00130 if (! (_Width == pDepthSurface->GetWidth() && _Height == pDepthSurface->GetHeight() ) ) 00131 { 00132 nuxAssertMsg (0, TEXT ("The depth surface size is not compatible with the frame buffer size.") ); 00133 return 0; 00134 } 00135 00136 if (_Depth_Attachment == pDepthSurface) 00137 return 1; 00138 00139 // We rely on the fact that the depth texture is actually a D24_S8 texture. 00140 // That is, the surface for the depth and stencil attachment is the same. When we bound, the surface, 00141 // we explicitly bind the depth attachment and the stencil attachment with the same surface. 00142 _Depth_Attachment = pDepthSurface; 00143 _Stencil_Attachment = pDepthSurface; 00144 00145 if (_IsActive) 00146 { 00147 Activate(); 00148 } 00149 00150 return 1; 00151 } 00152 00153 ObjectPtr<IOpenGLSurface> IOpenGLFrameBufferObject::GetRenderTarget (int ColorAttachmentIndex) 00154 { 00155 nuxAssert (ColorAttachmentIndex < 1 /*GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxFboAttachment()*/); 00156 return _Color_AttachmentArray[ColorAttachmentIndex]; 00157 } 00158 00159 ObjectPtr<IOpenGLSurface> IOpenGLFrameBufferObject::GetDepthRenderTarget() 00160 { 00161 return _Depth_Attachment; 00162 } 00163 00164 int IOpenGLFrameBufferObject::Activate (bool WithClippingStack) 00165 { 00166 GLuint NumBuffers = 0; 00167 _Fbo.Bind(); 00168 00169 if (GetGraphicsDisplay()->GetGpuDevice() ) 00170 GetGraphicsDisplay()->GetGpuDevice()->SetCurrentFrameBufferObject (ObjectPtr<IOpenGLFrameBufferObject> (this)); 00171 00172 for (int i = 0; i < 1 /*GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxFboAttachment()*/; i++) 00173 { 00174 if (_Color_AttachmentArray[i].IsValid() ) 00175 { 00176 GLenum target = _Color_AttachmentArray[i]->GetSurfaceTarget(); 00177 GLenum glID = _Color_AttachmentArray[i]->GetOpenGLID(); 00178 GLint level = _Color_AttachmentArray[i]->GetMipLevel(); 00179 CHECKGL ( glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, target, glID, level) ); 00180 00181 #ifndef NUX_OPENGLES_20 00182 CHECKGL ( glDrawBuffer (GL_COLOR_ATTACHMENT0 + i) ); 00183 #endif 00184 NumBuffers++; 00185 } 00186 else 00187 { 00188 CHECKGL ( glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, 0, 0) ); 00189 } 00190 } 00191 00192 if(_Depth_Attachment.IsValid()) 00193 { 00194 GLenum target = _Depth_Attachment->GetSurfaceTarget(); 00195 GLenum glID = _Depth_Attachment->GetOpenGLID(); 00196 GLint level = _Depth_Attachment->GetMipLevel(); 00197 CHECKGL( glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, target, glID, level) ); 00198 } 00199 else 00200 { 00201 CHECKGL( glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0) ); 00202 // On the PC you need to bing the same D24S8 surface to the depth and the stencil attachment. 00203 } 00204 00205 // #ifndef NUX_OPENGLES_20 00206 // _Rbo.Set (GL_DEPTH_COMPONENT, _Width, _Height); 00207 // CHECKGL ( glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, 00208 // GL_DEPTH_ATTACHMENT_EXT, 00209 // GL_RENDERBUFFER_EXT, 00210 // _Rbo.GetId() ) ); 00211 // #endif 00212 00213 nuxAssert ( _Fbo.IsValid() == true ); 00214 00215 if (GetGraphicsDisplay()->GetGraphicsEngine()) 00216 GetGraphicsDisplay()->GetGraphicsEngine()->SetViewport (0, 0, _Width, _Height); 00217 00218 if (WithClippingStack) 00219 ApplyClippingRegion(); 00220 00221 _IsActive = true; 00222 return 1; 00223 } 00224 00225 // Restore the original opengl back buffer as defined when creating the opengl context(color + depth + stencil). 00226 int IOpenGLFrameBufferObject::Deactivate() 00227 { 00228 CHECKGL ( glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, 0 ) ); 00229 00230 #ifndef NUX_OPENGLES_20 00231 CHECKGL ( glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, 0) ); 00232 #endif 00233 00234 if(GetGraphicsDisplay()->GetGpuDevice()) 00235 GetGraphicsDisplay()->GetGpuDevice()->SetCurrentFrameBufferObject (ObjectPtr<IOpenGLFrameBufferObject> (0)); 00236 00237 if(GetGraphicsDisplay()->GetGraphicsEngine()) 00238 GetGraphicsDisplay()->GetGraphicsEngine()->SetScissor (0, 0, _Width, _Height); 00239 00240 _IsActive = false; 00241 return 1; 00242 } 00243 00244 void IOpenGLFrameBufferObject::PushClippingRegion(Rect rect) 00245 { 00246 Rect r0; 00247 if(GetGraphicsDisplay()->GetGraphicsEngine()) 00248 { 00249 r0 = GetGraphicsDisplay()->GetGraphicsEngine()->ModelViewXFormRect(rect); 00250 } 00251 00252 Rect current_clip_rect; 00253 unsigned int stacksize = (unsigned int) _ClippingRegionStack.size(); 00254 00255 if (stacksize == 0) 00256 { 00257 current_clip_rect = Rect (0, 0, _Width, _Height); 00258 } 00259 else 00260 { 00261 current_clip_rect = _ClippingRegionStack[stacksize-1]; 00262 } 00263 00264 Rect r1; 00265 00266 if (GetGraphicsDisplay()->GetGraphicsEngine()) 00267 r1 = GetGraphicsDisplay()->GetGraphicsEngine()->GetViewportRect (); 00268 00269 r0.OffsetPosition (r1.x, _Height - (r1.y + r1.GetHeight ())); 00270 00271 Rect Intersection = current_clip_rect.Intersect(r0); 00272 00273 if (!Intersection.IsNull ()) 00274 { 00275 _clipping_rect = Intersection; 00276 _ClippingRegionStack.push_back (Intersection); 00277 00278 SetOpenGLClippingRectangle (Intersection.x + GetGraphicsDisplay()->GetGraphicsEngine()->GetViewportX (), 00279 _Height - Intersection.y - Intersection.GetHeight () - GetGraphicsDisplay()->GetGraphicsEngine()->GetViewportY (), 00280 Intersection.GetWidth (), Intersection.GetHeight ()); 00281 } 00282 else 00283 { 00284 _clipping_rect = Rect (0, 0, 0, 0); 00285 _ClippingRegionStack.push_back (Rect (0, 0, 0, 0)); 00286 SetOpenGLClippingRectangle (0, 0, 0, 0); 00287 } 00288 } 00289 00290 void IOpenGLFrameBufferObject::PopClippingRegion () 00291 { 00292 _ClippingRegionStack.pop_back (); 00293 int stacksize = (int) _ClippingRegionStack.size (); 00294 00295 if (stacksize == 0) 00296 { 00297 _clipping_rect = Rect (0, 0, _Width, _Height); 00298 SetOpenGLClippingRectangle (0, 0, _Width, _Height); 00299 } 00300 else 00301 { 00302 _clipping_rect = _ClippingRegionStack [stacksize-1]; 00303 Rect current_clip_rect = _ClippingRegionStack [stacksize-1]; 00304 SetOpenGLClippingRectangle (current_clip_rect.x, _Height - current_clip_rect.y - current_clip_rect.GetHeight(), current_clip_rect.GetWidth(), current_clip_rect.GetHeight() ); 00305 } 00306 } 00307 00308 void IOpenGLFrameBufferObject::EmptyClippingRegion() 00309 { 00310 _ClippingRegionStack.clear(); 00311 { 00312 _clipping_rect = Rect (0, 0, _Width, _Height); 00313 SetOpenGLClippingRectangle (0, 0, _Width, _Height); 00314 } 00315 } 00316 00317 void IOpenGLFrameBufferObject::ApplyClippingRegion() 00318 { 00319 int stacksize = (int) _ClippingRegionStack.size(); 00320 00321 if (stacksize == 0) 00322 { 00323 _clipping_rect = Rect (0, 0, _Width, _Height); 00324 SetOpenGLClippingRectangle (0, 0, _Width, _Height); 00325 } 00326 else 00327 { 00328 _clipping_rect = _ClippingRegionStack [stacksize-1]; 00329 Rect current_clip_rect = _ClippingRegionStack [stacksize-1]; 00330 SetOpenGLClippingRectangle (current_clip_rect.x, _Height - current_clip_rect.y - current_clip_rect.GetHeight(), current_clip_rect.GetWidth(), current_clip_rect.GetHeight() ); 00331 } 00332 } 00333 00334 void IOpenGLFrameBufferObject::SetClippingRectangle (const Rect &rect) 00335 { 00336 if (GetGraphicsDisplay()->GetGraphicsEngine()) 00337 { 00338 _clipping_rect = rect; 00339 GetGraphicsDisplay()->GetGraphicsEngine()->SetScissor (rect.x, _Height - rect.y - rect.height, rect.width, rect.height); 00340 } 00341 } 00342 00343 void IOpenGLFrameBufferObject::SetOpenGLClippingRectangle (int x, int y, int width, int height) 00344 { 00345 if (GetGraphicsDisplay()->GetGraphicsEngine()) 00346 { 00347 _clipping_rect = Rect (x, y, width, height); 00348 GetGraphicsDisplay()->GetGraphicsEngine()->SetScissor (x, y, width, height); 00349 } 00350 } 00351 00352 Rect IOpenGLFrameBufferObject::GetClippingRegion() 00353 { 00354 return _clipping_rect; 00355 00356 // unsigned int stacksize = (unsigned int) _ClippingRegionStack.size(); 00357 // 00358 // if (stacksize == 0) 00359 // { 00360 // return Rect (0, 0, _Width, _Height); 00361 // } 00362 // else 00363 // { 00364 // Rect r = _ClippingRegionStack [stacksize-1]; 00365 // return r; 00366 // } 00367 } 00368 00369 int IOpenGLFrameBufferObject::GetNumberOfClippingRegions () const 00370 { 00371 return _ClippingRegionStack.size (); 00372 } 00373 }