Back to index

nux  3.0.0
GraphicsEngine.cpp
Go to the documentation of this file.
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 "NuxCore/NuxCore.h"
00024 
00025 #include "ImageSurface.h"
00026 
00027 #include "GpuDevice.h"
00028 #include "GLDeviceObjects.h"
00029 #include "GLResourceManager.h"
00030 
00031 #include "GLTextureResourceManager.h"
00032 #include "GLVertexResourceManager.h"
00033 
00034 #include "FontTexture.h"
00035 #include "FontRenderer.h"
00036 #include "GraphicsEngine.h"
00037 
00038 namespace nux
00039 {
00040 
00041   BlendOperator::BlendOperator()
00042   {
00043     _enable = true;
00044     _src_blend = GL_ONE;
00045     _dst_blend = GL_ONE_MINUS_SRC_ALPHA;
00046   }
00047 
00048   BlendOperator::~BlendOperator()
00049   {
00050     _enable = true;
00051     _src_blend = GL_ONE;
00052     _dst_blend = GL_ONE_MINUS_SRC_ALPHA;
00053   }
00054 
00055   void BlendOperator::EnableBlending(bool enable)
00056   {
00057     _enable = enable;
00058   }
00059 
00060   void BlendOperator::SetPorterDuffOperator(PorterDuffOperator op)
00061   {
00062     switch(op)
00063     {
00064     case CLEAR:
00065       _src_blend = GL_ZERO;
00066       _dst_blend = GL_ZERO;
00067       break;
00068     case SRC:
00069       _src_blend = GL_ONE;
00070       _dst_blend = GL_ZERO;
00071       break;
00072     case DST:
00073       _src_blend = GL_ZERO;
00074       _dst_blend = GL_ONE;
00075       break;
00076     case SRC_OVER:
00077       _src_blend = GL_ONE;
00078       _dst_blend = GL_ONE_MINUS_SRC_ALPHA;
00079       break;
00080     case DST_OVER:
00081       _src_blend = GL_ONE_MINUS_DST_ALPHA;
00082       _dst_blend = GL_ONE;
00083       break;
00084     case SRC_IN:
00085       _src_blend = GL_DST_ALPHA;
00086       _dst_blend = GL_ZERO;
00087       break;
00088     case DST_IN:
00089       _src_blend = GL_ZERO;
00090       _dst_blend = GL_SRC_ALPHA;
00091       break;
00092     case SRC_OUT:
00093       _src_blend = GL_ONE_MINUS_DST_ALPHA;
00094       _dst_blend = GL_ZERO;
00095       break;
00096     case DST_OUT:
00097       _src_blend = GL_ZERO;
00098       _dst_blend = GL_ONE_MINUS_SRC_ALPHA;
00099       break;
00100     case SRC_ATOP:
00101       _src_blend = GL_DST_ALPHA;
00102       _dst_blend = GL_ONE_MINUS_SRC_ALPHA;
00103       break;
00104     case DST_ATOP:
00105       _src_blend = GL_ONE_MINUS_DST_ALPHA;
00106       _dst_blend = GL_SRC_ALPHA;
00107       break;
00108     case XOR:
00109       _src_blend = GL_ONE_MINUS_DST_ALPHA;
00110       _dst_blend = GL_ONE_MINUS_SRC_ALPHA;
00111       break;
00112     case PLUS:
00113       _src_blend = GL_ONE;
00114       _dst_blend = GL_ONE;
00115       break;
00116     default:
00117       // Use SRC_OVER
00118       _src_blend = GL_ONE;
00119       _dst_blend = GL_ONE_MINUS_SRC_ALPHA;
00120       break;
00121     }
00122   }
00123 
00124   void BlendOperator::SetCustomBlendOperator(unsigned int src_blend, unsigned int dst_blend)
00125   {
00126 
00127   }
00128 
00129 
00130   ROPConfig ROPConfig::Default;
00131   ROPConfig::ROPConfig()
00132   {
00133     Blend = false;
00134     SrcBlend = GL_SRC_ALPHA;
00135     DstBlend = GL_ONE_MINUS_SRC_ALPHA;
00136   }
00137   ROPConfig::~ROPConfig()
00138   {
00139   }
00140 
00141 
00142   FxStructure::FxStructure()
00143   {
00144     src_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture(1, 1, 1, nux::BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION);
00145     dst_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture(1, 1, 1, nux::BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION);
00146     temp_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture(1, 1, 1, nux::BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION);
00147   }
00148 
00149   FxStructure::~FxStructure()
00150   {
00151   }
00152 
00153   GraphicsEngine::GraphicsEngine(GraphicsDisplay& GlWindow, bool create_rendering_data)
00154   : _graphics_display(GlWindow)
00155   {
00156     _scissor.x = 0;
00157     _scissor.y = 0;
00158     _clip_offset_x = 0;
00159     _clip_offset_y = 0;
00160 
00161     _font_renderer = 0;
00162 
00163     _use_glsl_shaders = false;
00164     _global_clipping_enabled = false;
00165 
00166     // Evaluate the features provided by the GPU.
00167     EvaluateGpuCaps();
00168 
00169     if (UsingGLSLCodePath())
00170     {
00171       nuxDebugMsg("The GraphicsEngine is using the GLSL shader code path.");
00172     }
00173     else
00174     {
00175       nuxDebugMsg("The GraphicsEngine is using the assenbly shader code path."); 
00176     }
00177 
00178 
00179     GlWindow.m_GraphicsContext = this;
00180     ResetStats();
00181 
00182     _projection_matrix.Identity();
00183     _model_view_matrix.Identity();
00184 
00185     ResourceCache.InitializeResourceFactories();
00186 
00187     m_CurrrentContext.x = 0;
00188     m_CurrrentContext.y = 0;
00189     m_CurrrentContext.width = _graphics_display.GetWindowWidth();
00190     m_CurrrentContext.height = _graphics_display.GetWindowHeight();
00191 
00192     SetViewport(0, 0, _graphics_display.GetWindowWidth(), _graphics_display.GetWindowHeight());
00193     SetScissor(0, 0, _graphics_display.GetWindowWidth(), _graphics_display.GetWindowHeight());
00194     EnableScissoring(true);
00195 
00196 
00197     bool opengl_14_support = true;
00198 
00199     if ((_graphics_display.GetGpuDevice()->GetOpenGLMajorVersion() == 1) &&
00200       (_graphics_display.GetGpuDevice()->GetOpenGLMinorVersion() < 4))
00201     {
00202       // OpenGL version is less than OpenGL 1.4
00203       opengl_14_support = false;
00204     }
00205 
00206     if (create_rendering_data)
00207     {
00208 #ifndef NUX_OPENGLES_20
00209       if (_graphics_display.GetGpuDevice()->GetGpuInfo().Support_ARB_Fragment_Shader() &&
00210         _graphics_display.GetGpuDevice()->GetGpuInfo().Support_ARB_Vertex_Program() &&
00211         opengl_14_support)
00212       {
00213         InitAsmColorShader();
00214         InitAsmTextureShader();
00215         InitAsmPixelateShader();
00216         InitAsmColorModTexMaskAlpha();
00217         InitAsm2TextureAdd();
00218         InitAsm2TextureMod();
00219         InitAsm4TextureAdd();
00220         InitAsmBlendModes();
00221 
00222         InitAsmPower();
00223         InitAsmAlphaReplicate();
00224         InitAsmSeparableGaussFilter();
00225         InitAsmColorMatrixFilter();
00226 
00227         //InitAsm2TextureDepRead(); // NUXTODO: fix the shader
00228       }
00229 #endif
00230 
00231       GpuInfo& gpu_info = _graphics_display.GetGpuDevice()->GetGpuInfo();
00232 
00233       if ((gpu_info.Support_ARB_Vertex_Program() && gpu_info.Support_ARB_Fragment_Program())
00234           || (gpu_info.Support_ARB_Vertex_Shader() && gpu_info.Support_ARB_Fragment_Shader()))
00235       {
00236         _font_renderer = new FontRenderer(*this);
00237       }
00238 
00239       if (gpu_info.Support_EXT_Framebuffer_Object())
00240         _offscreen_fbo = _graphics_display.GetGpuDevice()->CreateFrameBufferObject();
00241 
00242       _offscreen_color_rt0  = _graphics_display.GetGpuDevice()->CreateTexture(2, 2, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION);
00243       _offscreen_color_rt1  = _graphics_display.GetGpuDevice()->CreateTexture(2, 2, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION);
00244       _offscreen_color_rt2  = _graphics_display.GetGpuDevice()->CreateTexture(2, 2, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION);
00245       _offscreen_color_rt3  = _graphics_display.GetGpuDevice()->CreateTexture(2, 2, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION);
00246     }
00247   }
00248 
00249   GraphicsEngine::~GraphicsEngine()
00250   {
00251     _offscreen_color_rt0.Release();
00252     _offscreen_color_rt1.Release();
00253     _offscreen_depth_rt0.Release();
00254     _offscreen_depth_rt1.Release();
00255     _offscreen_fbo.Release();
00256 
00257     ResourceCache.Flush();
00258     NUX_SAFE_DELETE(_font_renderer);
00259   }
00260 
00261   void GraphicsEngine::EvaluateGpuCaps()
00262   {
00263 #ifdef NUX_OS_WINDOWS
00264     if (_graphics_display.GetGpuDevice()->GetGpuInfo().Support_ARB_Vertex_Shader() &&
00265       _graphics_display.GetGpuDevice()->GetGpuInfo().Support_ARB_Fragment_Shader())
00266 #else
00267     if (_graphics_display.GetGpuDevice()->GetGpuInfo().Support_ARB_Vertex_Shader() &&
00268       _graphics_display.GetGpuDevice()->GetGpuInfo().Support_ARB_Fragment_Shader() &&
00269       (_graphics_display.GetGpuDevice()->GetOpenGLMajorVersion() >= 2))
00270 #endif
00271     {
00272       NString renderer_string = ANSI_TO_TCHAR(NUX_REINTERPRET_CAST(const char* , glGetString(GL_RENDERER)));
00273       CHECKGL_MSG(glGetString(GL_RENDERER));
00274 
00275       // Exclude Geforce FX from using GLSL
00276       if (renderer_string.FindFirstOccurence("GeForce FX") != tstring::npos)
00277       {
00278         _use_glsl_shaders = false;
00279         return;
00280       }
00281 
00282       // Exclude Geforce FX Go from using GLSL: this case is not needed since it is detected by the one above.
00283       if (renderer_string.FindFirstOccurence("GeForce FX Go") != tstring::npos)
00284       {
00285         _use_glsl_shaders = false;
00286         return;
00287       }
00288 
00289       _use_glsl_shaders = true;
00290     }
00291     else
00292     {
00293       _use_glsl_shaders = false;
00294     }
00295   }
00296 
00297   bool GraphicsEngine::UsingGLSLCodePath()
00298   {
00299     return _use_glsl_shaders;
00300   }
00301 
00302   bool GraphicsEngine::UsingARBProgramCodePath()
00303   {
00304     return !_use_glsl_shaders;
00305   }
00306 
00307   ObjectPtr<FontTexture> GraphicsEngine::GetFont()
00308   {
00309 #if defined(NUX_OS_WINDOWS)
00310       if (_normal_font.IsNull())
00311       {
00312         FontTexture* fnt = new FontTexture(GNuxGraphicsResources.FindResourceLocation("Fonts/Tahoma_size_8.txt", true).GetTCharPtr(), NUX_TRACKER_LOCATION);
00313         _normal_font = ObjectPtr<FontTexture> (fnt);
00314         fnt->UnReference();
00315       }
00316 #else
00317       if (_normal_font.IsNull())
00318       {
00319         FontTexture* fnt = new FontTexture(GNuxGraphicsResources.FindResourceLocation("Fonts/nuxfont_size_8.txt", true).GetTCharPtr(), NUX_TRACKER_LOCATION);
00320         _normal_font = ObjectPtr<FontTexture> (fnt);
00321         fnt->UnReference();
00322       }
00323 #endif
00324     return _normal_font;
00325   }
00326 
00327   ObjectPtr<FontTexture> GraphicsEngine::GetBoldFont()
00328   {
00329     #if defined(NUX_OS_WINDOWS)
00330       if (_bold_font.IsNull())
00331       {
00332         FontTexture* fnt = new FontTexture(GNuxGraphicsResources.FindResourceLocation("Fonts/Tahoma_size_8_bold.txt", true).GetTCharPtr(), NUX_TRACKER_LOCATION);
00333         _bold_font = ObjectPtr<FontTexture> (fnt);
00334         fnt->UnReference();
00335       }
00336 #else
00337       if (_bold_font.IsNull())
00338       {
00339         FontTexture* fnt = new FontTexture(GNuxGraphicsResources.FindResourceLocation("Fonts/nuxfont_size_8_bold.txt", true).GetTCharPtr(), NUX_TRACKER_LOCATION);
00340         _bold_font = ObjectPtr<FontTexture> (fnt);
00341         fnt->UnReference();
00342       }
00343 #endif
00344     return _bold_font;
00345   }
00346 
00347   void GraphicsEngine::SetContext(int x, int y, int width, int height)
00348   {
00349     m_CurrrentContext.x = x;
00350     m_CurrrentContext.y = y;
00351 
00352     if (width <= 0 || height <= 0)
00353     {
00354       //nuxAssertMsg(0, "[GraphicsEngine::SetContext] Incorrect context size.");
00355       if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid())
00356       {
00357         m_CurrrentContext.width = _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->GetWidth();
00358         m_CurrrentContext.height = _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->GetHeight();
00359       }
00360       else
00361       {
00362         m_CurrrentContext.width = GetWindowWidth();
00363         m_CurrrentContext.height = GetWindowHeight();
00364       }
00365     }
00366     else
00367     {
00368       m_CurrrentContext.width = width;
00369       m_CurrrentContext.height = height;
00370     }
00371   }
00372 
00373   void GraphicsEngine::GetContextSize(int& w, int& h) const
00374   {
00375     w = m_CurrrentContext.width;
00376     h = m_CurrrentContext.height;
00377   }
00378 
00379   int GraphicsEngine::GetContextWidth() const
00380   {
00381     return m_CurrrentContext.width;
00382   }
00383 
00384   int GraphicsEngine::GetContextHeight() const
00385   {
00386     return m_CurrrentContext.height;
00387   }
00388 
00389   int GraphicsEngine::GetContextX() const
00390   {
00391     return m_CurrrentContext.x;
00392   }
00393 
00394   int GraphicsEngine::GetContextY() const
00395   {
00396     return m_CurrrentContext.y;
00397   }
00398 
00399   void GraphicsEngine::GetWindowSize(int& w, int& h) const
00400   {
00401     _graphics_display.GetWindowSize(w, h);
00402   }
00403 
00404   int GraphicsEngine::GetWindowWidth() const
00405   {
00406     return _graphics_display.GetWindowWidth();
00407   }
00408 
00409   int GraphicsEngine::GetWindowHeight() const
00410   {
00411     return _graphics_display.GetWindowHeight();
00412   }
00413 
00414   int GraphicsEngine::RenderColorText(ObjectPtr<FontTexture> Font, int x, int y, const NString& Str,
00415                                         const Color& TextColor,
00416                                         bool WriteAlphaChannel,
00417                                         int NumCharacter)
00418   {
00419     if (_font_renderer)
00420       return _font_renderer->RenderColorText(Font, x, y, Str, TextColor, WriteAlphaChannel, NumCharacter);
00421 
00422     return 0;
00423   }
00424 
00425   int GraphicsEngine::RenderColorTextLineStatic(ObjectPtr<FontTexture> Font, const PageBBox& pageSize, const NString& Str,
00426       const Color& TextColor,
00427       bool WriteAlphaChannel,
00428       TextAlignment alignment)
00429   {
00430     if (_font_renderer)
00431       return _font_renderer->RenderColorTextLineStatic(Font, pageSize, Str, TextColor, WriteAlphaChannel, alignment);
00432 
00433     return 0;
00434   }
00435 
00436   int GraphicsEngine::RenderColorTextLineEdit(ObjectPtr<FontTexture> Font, const PageBBox& pageSize, const NString& Str,
00437       const Color& TextColor,
00438       bool WriteAlphaChannel,
00439       const Color& SelectedTextColor,
00440       const Color& SelectedTextBackgroundColor,
00441       const Color& TextBlinkColor,
00442       const Color& CursorColor,
00443       bool ShowCursor, unsigned int CursorPosition, int offset, int selection_start, int selection_end)
00444   {
00445     if (_font_renderer)
00446       return _font_renderer->RenderColorTextLineEdit(Font, pageSize, Str,
00447              TextColor,
00448              WriteAlphaChannel,
00449              SelectedTextColor,
00450              SelectedTextBackgroundColor,
00451              TextBlinkColor,
00452              CursorColor,
00453              ShowCursor, CursorPosition, offset, selection_start, selection_end);
00454 
00455     return 0;
00456   }
00457 
00458   void GraphicsEngine::SetTexture(int TextureUnit, BaseTexture* Texture)
00459   {
00460     nuxAssertMsg(Texture != 0, "[GraphicsEngine::SetTexture] Texture is NULL.");
00461 
00462     if ((TextureUnit < GL_TEXTURE0) || (TextureUnit > GL_TEXTURE31))
00463       return;
00464 
00465     ObjectPtr <CachedBaseTexture> CachedTexture = ResourceCache.GetCachedResource(Texture);
00466     SetTexture(TextureUnit, CachedTexture->m_Texture);
00467   }
00468 
00469   void GraphicsEngine::SetTexture(int TextureUnit, ObjectPtr< IOpenGLBaseTexture > DeviceTexture)
00470   {
00471     NUX_RETURN_IF_FALSE(DeviceTexture.IsValid());
00472 
00473     CHECKGL(glActiveTextureARB(TextureUnit));
00474     DeviceTexture->BindTextureToUnit(TextureUnit);
00475   }
00476 
00477   void GraphicsEngine::EnableTextureMode(int TextureUnit, int TextureMode)
00478   {
00479     if ((TextureUnit < GL_TEXTURE0) || (TextureUnit > GL_TEXTURE31))
00480       return;
00481 
00482     CHECKGL(glActiveTextureARB(TextureUnit));
00483     CHECKGL(glEnable(TextureMode));
00484   }
00485 
00486   void GraphicsEngine::DisableTextureMode(int TextureUnit, int TextureMode)
00487   {
00488     if ((TextureUnit < GL_TEXTURE0) || (TextureUnit > GL_TEXTURE31))
00489       return;
00490 
00491     CHECKGL(glActiveTextureARB(TextureUnit));
00492     CHECKGL(glDisable(TextureMode));
00493     CHECKGL(glBindTexture(TextureMode, 0));
00494   }
00495 
00496   void GraphicsEngine::DisableAllTextureMode(int TextureUnit)
00497   {
00498     if ((TextureUnit < GL_TEXTURE0) || (TextureUnit > GL_TEXTURE31))
00499       return;
00500 
00501     _graphics_display.GetGpuDevice()->InvalidateTextureUnit(TextureUnit);
00502   }
00503 
00505 // DRAW CLIPPING    //
00507   void GraphicsEngine::PushClippingRectangle(Rect rect)
00508   {
00509     if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid())
00510     {
00511       // There is an active framebuffer set. Push the clipping rectangles to that fbo clipping stack.
00512       _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->PushClippingRegion(rect);
00513       return;
00514     }
00515 
00516     Rect r0 = ModelViewXFormRect(rect);
00517 
00518     Rect r1;
00519     unsigned int stacksize = (unsigned int) ClippingRect.size();
00520     int x0, y0, x1, y1;
00521 
00522     int window_width, window_height;
00523     window_width = _viewport.width;
00524     window_height = _viewport.height;
00525 
00526     if (stacksize == 0)
00527     {
00528       r1 = Rect(0, 0, window_width, window_height);
00529     }
00530     else
00531     {
00532       r1 = ClippingRect[stacksize-1];
00533     }
00534 
00535 //    http://www.codecomments.com/archive263-2004-12-350347.html
00536 //    If your rectangles are given in 2D as Top,Left,Bottom,Right coordinates, as typical for GUI programming, then it's simply:
00537 //        intersect.Left = max(a.Left, b.Left);
00538 //        intersect.Top = max(a.Top, b.Top);
00539 //        intersect.Right = min(a.Right, b.Right );
00540 //        intersect.Bottom = min(a.Bottom, b.Bottom);
00541 //    And the intersection is empty unless intersect.Right > intersect.Left && intersect.Bottom > intersect.Top
00542 
00543     x0 = Max(r0.x, r1.x);
00544     y0 = Max(r0.y, r1.y);
00545     x1 = Min(r0.x + r0.width, r1.x + r1.width);
00546     y1 = Min(r0.y + r0.height, r1.y + r1.height);
00547 
00548     Rect r = r0.Intersect(r1);
00549 
00550     if ((x1 > x0) && (y1 > y0))
00551     {
00552       _clipping_rect = Rect(x0, y0, x1 - x0, y1 - y0);
00553       ClippingRect.push_back(Rect(x0, y0, x1 - x0, y1 - y0));
00554 
00555       EnableScissoring(true);
00556       SetOpenGLClippingRectangle(x0, window_height - y0 - (y1 - y0), x1 - x0, y1 - y0);
00557     }
00558     else
00559     {
00560       _clipping_rect = Rect(0, 0, 0, 0);
00561       ClippingRect.push_back(_clipping_rect);
00562       EnableScissoring(true);
00563       SetOpenGLClippingRectangle(0, 0, 0, 0);
00564     }
00565   }
00566 
00567   void GraphicsEngine::PopClippingRectangle()
00568   {
00569     if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid())
00570     {
00571       _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->PopClippingRegion();
00572       return;
00573     }
00574 
00575     ClippingRect.pop_back();
00576     unsigned int stacksize = (unsigned int) ClippingRect.size();
00577 
00578     if (stacksize == 0)
00579     {
00580       _clipping_rect = Rect(0, 0, _viewport.width, _viewport.height);
00581       EnableScissoring(true);
00582       SetOpenGLClippingRectangle(0, 0, _viewport.width, _viewport.height);
00583     }
00584     else
00585     {
00586       _clipping_rect = ClippingRect [stacksize-1];
00587       Rect B = _clipping_rect;
00588       EnableScissoring(true);
00589       SetOpenGLClippingRectangle(B.x, _viewport.height - B.y - B.GetHeight(), B.GetWidth(), B.GetHeight());
00590     }
00591   }
00592 
00593   void GraphicsEngine::ApplyClippingRectangle()
00594   {
00595     if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid())
00596     {
00597       _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->ApplyClippingRegion();
00598       return;
00599     }
00600 
00601     unsigned int stacksize = (unsigned int) ClippingRect.size();
00602 
00603     if (stacksize == 0)
00604     {
00605       _clipping_rect = Rect(0, 0, _viewport.width, _viewport.height);
00606       EnableScissoring(true);
00607       SetOpenGLClippingRectangle(0, 0, _viewport.width, _viewport.height);
00608     }
00609     else
00610     {
00611       _clipping_rect = ClippingRect[stacksize-1];
00612       Rect B = _clipping_rect;
00613       EnableScissoring(true);
00614       SetOpenGLClippingRectangle(B.x, _viewport.height - B.y - B.GetHeight(), B.GetWidth(), B.GetHeight());
00615     }
00616   }
00617 
00618   void GraphicsEngine::EmptyClippingRegion()
00619   {
00620     if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid())
00621     {
00622       _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->EmptyClippingRegion();
00623       return;
00624     }
00625 
00626     ClippingRect.clear();
00627     {
00628       _clipping_rect = Rect(0, 0, _viewport.width, _viewport.height);
00629       EnableScissoring(true);
00630       SetOpenGLClippingRectangle(0, 0, _viewport.width, _viewport.height);
00631     }
00632   }
00633   
00634   void GraphicsEngine::SetGlobalClippingRectangle(Rect rect)
00635   {
00636     _global_clipping_enabled = true;
00637     _global_clipping_rect = Rect(rect.x, _viewport.height - rect.y - rect.height, rect.width, rect.height);
00638     ApplyClippingRectangle();
00639   }
00640   
00641   void GraphicsEngine::DisableGlobalClippingRectangle()
00642   {
00643     _global_clipping_enabled = false;
00644     _global_clipping_rect = Rect(0, 0, _viewport.width, _viewport.height);
00645     ApplyClippingRectangle();
00646   }
00647 
00648   Rect GraphicsEngine::GetClippingRegion() const
00649   {
00650     if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid())
00651     {
00652       Rect r = _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->GetClippingRegion();
00653       return r;      
00654     }
00655 
00656     return _clipping_rect;
00657 
00658 //     unsigned int stacksize = (unsigned int) ClippingRect.size();
00659 // 
00660 //     if (stacksize == 0)
00661 //     {
00662 //       return Rect(0, 0, _viewport.width, _viewport.height);
00663 //     }
00664 //     else
00665 //     {
00666 //       Rect r = ClippingRect[stacksize-1];
00667 //       return r;
00668 //     }
00669   }
00670 
00671   void GraphicsEngine::SetClippingRectangle(const Rect& rect)
00672   {
00673     _clipping_rect = rect;
00674     SetOpenGLClippingRectangle(rect.x, _viewport.height - rect.y - rect.height, rect.width, rect.height);
00675   }
00676 
00677   void GraphicsEngine::SetOpenGLClippingRectangle(int x, int y, unsigned int width, unsigned int height)
00678   {
00679     if (!_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid())
00680     {
00681       if (_global_clipping_enabled)
00682       {
00683         Rect intersection = Rect(x, y, width, height).Intersect(_global_clipping_rect);
00684         SetScissor(intersection.x, intersection.y, intersection.width, intersection.height);
00685       }
00686       else
00687       {
00688         SetScissor(x, y, width, height);
00689       }
00690     }
00691     else
00692     {
00693       SetScissor(x, y, width, height);
00694     }
00695   }
00696 
00697   int GraphicsEngine::GetNumberOfClippingRegions() const
00698   {
00699     if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid())
00700     {
00701       int n = _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->GetNumberOfClippingRegions();
00702       return n;
00703     }
00704 
00705     return(int) ClippingRect.size();
00706   }
00707 
00708   void GraphicsEngine::AddClipOffset(int x, int y)
00709   {
00710     PushClipOffset(x, y);
00711   }
00712 
00713   void GraphicsEngine::PushClipOffset(int x, int y)
00714   {
00715     _clip_offset_stack.push_back(Point(x, y));
00716 
00717     _clip_offset_x = 0;
00718     _clip_offset_y = 0;
00719 
00720     std::list<Point>::iterator it;
00721     for (it = _clip_offset_stack.begin(); it != _clip_offset_stack.end(); it++)
00722     {
00723       _clip_offset_x += (*it).x;
00724       _clip_offset_y += (*it).y;
00725     }
00726   }
00727 
00728   void GraphicsEngine::PopClipOffset()
00729   {
00730     if (_clip_offset_stack.size() == 0)
00731     {
00732       _clip_offset_x = 0;
00733       _clip_offset_y = 0;
00734     }
00735 
00736     _clip_offset_stack.pop_back();
00737 
00738     _clip_offset_x = 0;
00739     _clip_offset_y = 0;
00740 
00741     std::list<Point>::iterator it;
00742     for (it = _clip_offset_stack.begin(); it != _clip_offset_stack.end(); it++)
00743     {
00744       _clip_offset_x += (*it).x;
00745       _clip_offset_y += (*it).y;
00746     }
00747   }
00748 
00750 // DRAW TEXTURE  //
00752 
00754 // Rendering calls
00755 
00756 //
00757 //    From "OpenGL Programming Guide.pdf"
00758 //
00759 //    If exact two-dimensional rasterization is desired, you must carefully specify both the orthographic
00760 //    projection and the vertices of primitives that are to be rasterized. The orthographic projection
00761 //    should be specified with integer coordinates, as shown in the following example:
00762 //    gluOrtho2D(0, width, 0, height);
00763 //    where width and height are the dimensions of the viewport. Given this projection matrix, polygon
00764 //    vertices and pixel image positions should be placed at integer coordinates to rasterize predictably.
00765 //    For example, glRecti(0, 0, 1, 1) reliably fills the lower left pixel of the viewport, and glRasterPos2i(0,
00766 //    0) reliably positions an unzoomed image at the lower left of the viewport. Point vertices, line
00767 //    vertices, and bitmap positions should be placed at half-integer locations, however. For example, a
00768 //    line drawn from(x1, 0.5) to(x2, 0.5) will be reliably rendered along the bottom row of pixels int the
00769 //    viewport, and a point drawn at(0.5, 0.5) will reliably fill the same pixel as glRecti(0, 0, 1, 1).
00770 //    An optimum compromise that allows all primitives to be specified at integer positions, while still
00771 //    ensuring predictable rasterization, is to translate x and y by 0.375, as shown in the following code
00772 //    fragment. Such a translation keeps polygon and pixel image edges safely away from the centers of
00773 //    pixels, while moving line vertices close enough to the pixel centers.
00774 //    glViewport(0, 0, width, height);
00775 //    glMatrixMode(GL_PROJECTION);
00776 //    glLoadIdentity();
00777 //    gluOrtho2D(0, width, 0, height);
00778 //    glMatrixMode(GL_MODELVIEW);
00779 //    glLoadIdentity();
00780 //    glTranslatef(0.375, 0.375, 0.0);
00781   /* render all primitives at integer positions */
00782 
00783   const float RASTERIZATION_OFFSET = 0.0f;
00784   void GraphicsEngine::Push2DWindow(int w, int h)
00785   {
00786 #ifndef NUX_OPENGLES_20
00787     {
00788       _model_view_matrix.Translate(m_CurrrentContext.x + RASTERIZATION_OFFSET, m_CurrrentContext.y + RASTERIZATION_OFFSET, 0);
00789       Matrix4 temp;
00790       std::list<Matrix4>::iterator it;
00791 
00792       for (it = m_2DModelViewMatricesStack.begin(); it != m_2DModelViewMatricesStack.end(); it++)
00793       {
00794         temp = _model_view_matrix;
00795         _model_view_matrix = temp * (*it);
00796       }
00797 
00798     }
00799 
00800     {
00801       _projection_matrix.Orthographic(0, w, h, 0, -1.0f, 1.0f);
00802     }
00803 #else
00804     // ModelView
00805     {
00806       _model_view_matrix.Translate(m_CurrrentContext.x + RASTERIZATION_OFFSET, m_CurrrentContext.y + RASTERIZATION_OFFSET, 0);
00807       Matrix4 temp;
00808       std::list<Matrix4>::iterator it;
00809 
00810       for (it = m_2DModelViewMatricesStack.begin(); it != m_2DModelViewMatricesStack.end(); it++)
00811       {
00812         temp = _model_view_matrix;
00813         _model_view_matrix = temp * (*it);
00814       }
00815 
00816     }
00817 
00818     // Projection
00819     {
00820       _projection_matrix.Orthographic(0, w, h, 0, -1.0f, 1.0f);
00821     }
00822 #endif
00823   }
00824 
00825   void GraphicsEngine::Pop2DWindow()
00826   {
00827 #ifndef NUX_OPENGLES_20
00828     CHECKGL(glMatrixMode(GL_PROJECTION));
00829     CHECKGL(glLoadIdentity());
00830     CHECKGL(glMatrixMode(GL_MODELVIEW));
00831     CHECKGL(glLoadIdentity());
00832     CHECKGL(glFrustum(
00833                 -1.0,     // left
00834                 1.0,      // right
00835                 -1.0,     // bottom
00836                 1.0,      // top
00837                 0.1,    // near,
00838                 2000.0  // far
00839               ));
00840 #endif
00841   }
00842 
00843   void GraphicsEngine::Push2DModelViewMatrix(Matrix4 mat)
00844   {
00845     m_2DModelViewMatricesStack.push_back(mat);
00846     {
00847       _model_view_matrix.Translate(m_CurrrentContext.x + RASTERIZATION_OFFSET, m_CurrrentContext.y + RASTERIZATION_OFFSET, 0);
00848       Matrix4 temp;
00849       std::list<Matrix4>::iterator it;
00850 
00851       for (it = m_2DModelViewMatricesStack.begin(); it != m_2DModelViewMatricesStack.end(); it++)
00852       {
00853         temp = _model_view_matrix;
00854         _model_view_matrix = (*it) * temp;
00855       }
00856 
00857     }
00858   }
00859 
00860   Matrix4 GraphicsEngine::Pop2DModelViewMatrix()
00861   {
00862     Matrix4 Mat;
00863     Mat.Zero();
00864 
00865     if (m_2DModelViewMatricesStack.size() <= 0)
00866       return Mat;
00867 
00868     std::list<Matrix4>::iterator it;
00869     it = m_2DModelViewMatricesStack.end();
00870     --it;
00871     Mat = (*it);
00872     m_2DModelViewMatricesStack.pop_back();
00873 
00874     {
00875       _model_view_matrix.Translate(m_CurrrentContext.x + RASTERIZATION_OFFSET, m_CurrrentContext.y + RASTERIZATION_OFFSET, 0);
00876       Matrix4 temp;
00877       std::list<Matrix4>::iterator it;
00878 
00879       for (it = m_2DModelViewMatricesStack.begin(); it != m_2DModelViewMatricesStack.end(); it++)
00880       {
00881         temp = _model_view_matrix;
00882         _model_view_matrix = temp * (*it);
00883       }
00884     }
00885     return Mat;
00886   }
00887 
00888   void GraphicsEngine::Clear2DModelViewMatrix()
00889   {
00890     m_2DModelViewMatricesStack.clear();
00891 
00892     {
00893       _model_view_matrix.Translate(m_CurrrentContext.x + RASTERIZATION_OFFSET, m_CurrrentContext.y + RASTERIZATION_OFFSET, 0);
00894       Matrix4 temp;
00895       std::list<Matrix4>::iterator it;
00896 
00897       for (it = m_2DModelViewMatricesStack.begin(); it != m_2DModelViewMatricesStack.end(); it++)
00898       {
00899         temp = _model_view_matrix;
00900         _model_view_matrix = temp * (*it);
00901       }
00902     }
00903   }
00904 
00905   void GraphicsEngine::PushIdentityModelViewMatrix()
00906   {
00907     PushModelViewMatrix(Matrix4::IDENTITY());
00908   }
00909 
00910   void GraphicsEngine::PushModelViewMatrix(const Matrix4& matrix)
00911   {
00912     if (_model_view_stack.empty())
00913       _model_view_matrix = matrix;
00914     else
00915       _model_view_matrix = matrix * _model_view_stack.back();
00916 
00917     _model_view_stack.push_back(_model_view_matrix);
00918   }
00919 
00920   void GraphicsEngine::Push2DTranslationModelViewMatrix(float tx, float ty, float tz)
00921   {
00922     Matrix4 temp;
00923     temp.Translate(tx, ty, tz);
00924 
00925     PushModelViewMatrix(temp);
00926   }
00927 
00928   bool GraphicsEngine::PopModelViewMatrix()
00929   {
00930     if (!_model_view_stack.empty())
00931       _model_view_stack.pop_back();
00932 
00933     if (_model_view_stack.empty())
00934     {
00935       _model_view_matrix = Matrix4::IDENTITY();
00936       return false;
00937     }
00938 
00939     _model_view_matrix = _model_view_stack.back();
00940 
00941     return true;
00942   }
00943 
00944   void GraphicsEngine::ResetModelViewMatrixStack()
00945   {
00946     _model_view_stack.clear();
00947     _model_view_matrix = Matrix4::IDENTITY();
00948   }
00949 
00950   void GraphicsEngine::SetModelViewMatrix(const Matrix4& matrix)
00951   {
00952     _model_view_matrix = matrix;
00953   }
00954 
00955   void GraphicsEngine::ApplyModelViewMatrix()
00956   {
00957     if (_model_view_stack.empty())
00958       _model_view_matrix = Matrix4::IDENTITY();
00959     else
00960       _model_view_matrix = _model_view_stack.back();
00961   }
00962 
00963   Rect GraphicsEngine::ModelViewXFormRect(const Rect& rect)
00964   {
00965     Vector4 v0(rect.x, rect.y, 0.0f, 1.0f);
00966     Vector4 v1 = _model_view_matrix * v0;
00967     Rect r(v1.x, v1.y, rect.width, rect.height);
00968     return r;
00969   }
00970 
00971   int GraphicsEngine::ModelViewStackDepth()
00972   {
00973     return(int)_model_view_stack.size();
00974   }
00975 
00976   void GraphicsEngine::PushPorterDuffBlend(const PorterDuffOperator& porter_duff_op)
00977   {
00978     BlendOperator blend_op;
00979     blend_op.SetPorterDuffOperator(porter_duff_op);
00980 
00981     _blend_stack.push_front(blend_op);
00982 
00983     GetRenderStates().SetBlend(blend_op._enable, blend_op._src_blend, blend_op._dst_blend);
00984   }
00985 
00986   void GraphicsEngine::PushDisableBlend()
00987   {
00988     BlendOperator blend_op;
00989     blend_op.EnableBlending(false);
00990 
00991     _blend_stack.push_front(blend_op);
00992 
00993     GetRenderStates().SetBlend(blend_op._enable);
00994   }
00995 
00996   bool GraphicsEngine::PopBlend()
00997   {
00998     if (_blend_stack.size() == 0)
00999     {
01000       GetRenderStates().SetBlend(false, GL_ONE, GL_ZERO);
01001       return false;
01002     }
01003 
01004     _blend_stack.pop_front();
01005     
01006     BlendOperator blend_op = (*_blend_stack.begin());
01007     GetRenderStates().SetBlend(blend_op._enable, blend_op._src_blend, blend_op._dst_blend);
01008 
01009     return true;
01010   }
01011 
01012   int GraphicsEngine::BlendStackDepth()
01013   {
01014     return(int) _blend_stack.size();
01015   }
01016 
01017   Matrix4 GraphicsEngine::GetProjectionMatrix()
01018   {
01019     return _projection_matrix;
01020   }
01021 
01022   Matrix4 GraphicsEngine::GetOpenGLProjectionMatrix()
01023   {
01024     Matrix4 mat = GetProjectionMatrix();
01025     mat.Transpose();
01026     return mat;
01027   }
01028 
01029   void GraphicsEngine::SetProjectionMatrix(const Matrix4& matrix)
01030   {
01031     _projection_matrix = matrix;
01032   }
01033 
01034   void GraphicsEngine::SetOrthographicProjectionMatrix(int viewport_width, int viewport_height)
01035   {
01036     _projection_matrix.Orthographic(0, viewport_width, viewport_height, 0, -1.0f, 1.0f);
01037   }
01038 
01039   void GraphicsEngine::ResetProjectionMatrix()
01040   {
01041     _projection_matrix = Matrix4::IDENTITY();
01042   }
01043 
01044   Matrix4 GraphicsEngine::GetModelViewMatrix()
01045   {
01046     return _model_view_matrix;
01047   }
01048 
01049   Matrix4 GraphicsEngine::GetOpenGLModelViewMatrix()
01050   {
01051     Matrix4 mat = _model_view_matrix;
01052     mat.Transpose();
01053     return mat;
01054   }
01055 
01056   Matrix4 GraphicsEngine::GetModelViewProjectionMatrix()
01057   {
01058     return _projection_matrix * _model_view_matrix;
01059   }
01060 
01061   Matrix4 GraphicsEngine::GetOpenGLModelViewProjectionMatrix()
01062   {
01063     // This matrix is the transposed version of GetModelViewProjectionMatrix.
01064     Matrix4 mat = _projection_matrix * _model_view_matrix;
01065     mat.Transpose();
01066     return mat;
01067   }
01068 
01069   void GraphicsEngine::SetViewport(int origin_x, int origin_y, int w, int h)
01070   {
01071     nuxAssert(w >= 0);
01072     nuxAssert(h >= 0);
01073 
01074     _viewport.x = origin_x;
01075     _viewport.y = origin_y;
01076     _viewport.width = w;
01077     _viewport.height = h;
01078 
01079     if (_viewport.width < 0)
01080     {
01081       nuxAssertMsg(0, "[GraphicsEngine::SetViewport] Incorrect context size.");
01082       _viewport.width = 1;
01083     }
01084 
01085     if (_viewport.height < 0)
01086     {
01087       nuxAssertMsg(0, "[GraphicsEngine::SetViewport] Incorrect context size.");
01088       _viewport.height = 1;
01089     }
01090 
01091     CHECKGL(glViewport(origin_x, origin_y, _viewport.width, _viewport.height));
01092   }
01093 
01094 //   Rect GraphicsEngine::GetViewportRect()
01095 //   {
01096 //     return Rect(_viewport.x, _viewport.y, _viewport.width, _viewport.height);
01097 //   }
01098   
01099   Rect GraphicsEngine::GetViewportRect() const
01100   {
01101     return _viewport;
01102   }
01103 
01104   int  GraphicsEngine::GetViewportWidth() const
01105   {
01106     return _viewport.width;
01107   }
01108 
01109   int  GraphicsEngine::GetViewportHeight() const
01110   {
01111     return _viewport.height;
01112   }
01113 
01114   int GraphicsEngine::GetViewportX() const
01115   {
01116     return _viewport.x;
01117   }
01118 
01119   int GraphicsEngine::GetViewportY() const
01120   {
01121     return _viewport.y;
01122   }
01123 
01124   void  GraphicsEngine::GetViewportSize(int& viewport_width, int& viewport_height) const
01125   {
01126     viewport_width = _viewport.width;
01127     viewport_height = _viewport.height;
01128   }
01129 
01130   void GraphicsEngine::SetScissorOffset(int x, int y)
01131   {
01132     nuxAssertMsg(0, "[GraphicsEngine::SetScissorOffset] SetScissorOffset is deprecated.");
01133 //     m_ScissorXOffset = x;
01134 //     m_ScissorYOffset = y;
01135   }
01136 
01137   void GraphicsEngine::SetScissor(int x, int y, int w, int h)
01138   {
01139     nuxAssert(w >= 0);
01140     nuxAssert(h >= 0);
01141 
01142     NUX_RETURN_IF_FALSE(w >= 0);
01143     NUX_RETURN_IF_FALSE(h >= 0);
01144 
01145     _scissor.x = x;
01146     _scissor.y = y;
01147     _scissor.width = w;
01148     _scissor.height = h;
01149 
01150     if (_scissor.x < 0)
01151     {
01152       _scissor.width += _scissor.x;
01153       _scissor.x = 0;
01154     }
01155     
01156     if (_scissor.y < 0)
01157     {
01158       _scissor.height += _scissor.y;
01159       _scissor.y = 0;
01160     }
01161 
01162     if (_scissor.width <= 0)
01163     {
01164       // jaytaoko: This is a hack for what looks like a bug(#726033) in the radeon opensource driver
01165       // on R300/400/500. Rather than passing a null region to glScissor, we give the clip area a 1 pixel width.
01166       //_scissor.width = 1;
01167       CHECKGL(glScissor(0, 0, 1, 1));
01168       return;
01169     }
01170 
01171     if (_scissor.height <= 0)
01172     {
01173       // jaytaoko: This is a hack for what looks like a bug(#726033) in the radeon opensource driver
01174       // on R300/400/500. Rather than passing a null region to glScissor, we give the clip area a 1 pixel height.
01175       //_scissor.height = 1;
01176       CHECKGL(glScissor(0, 0, 1, 1));
01177       return;
01178     }
01179 
01180     CHECKGL(glScissor(_scissor.x, _scissor.y, _scissor.width, _scissor.height));
01181   }
01182 
01183   Rect GraphicsEngine::GetScissorRect()
01184   {
01185     return Rect(_scissor.x, _scissor.y, _scissor.width, _scissor.height);
01186   }
01187 
01188   void GraphicsEngine::EnableScissoring(bool b)
01189   {
01190     GetRenderStates().EnableScissor(b);
01191   }
01192 
01194   // 2D Area Clear Color Depth Stencil   //
01196 
01197   void GraphicsEngine::ClearAreaColorDepthStencil(int x, int y, int width, int height, Color clear_color, float cleardepth, int clearstencil)
01198   {
01199     // enable stencil buffer
01200     CHECKGL(glEnable(GL_STENCIL_TEST));
01201     // write a one to the stencil buffer everywhere we are about to draw
01202     CHECKGL(glStencilFunc(GL_ALWAYS, clearstencil, 0xFFFFFFFF));
01203     // this is to always pass a one to the stencil buffer where we draw
01204     CHECKGL(glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
01205 
01206     //CHECKGL(glEnable(GL_DEPTH_TEST));
01207     //CHECKGL(glDepthFunc(GL_ALWAYS));
01208 
01209     QRP_Color(x, y, width, height, clear_color);
01210 
01211     //CHECKGL(glDepthFunc(GL_LESS));
01212     //CHECKGL(glDisable(GL_DEPTH_TEST));
01213     CHECKGL(glDisable(GL_STENCIL_TEST));
01214   }
01215 
01216   void GraphicsEngine::ClearAreaColor(int x, int y, int width, int height, Color clear_color)
01217   {
01218     QRP_Color(x, y, width, height, clear_color);
01219   }
01220 
01221   void GraphicsEngine::ClearAreaDepthStencil(int x, int y, int width, int height, float cleardepth, int clearstencil)
01222   {
01223     // enable stencil buffer
01224     CHECKGL(glEnable(GL_STENCIL_TEST));
01225     // write a one to the stencil buffer everywhere we are about to draw
01226     CHECKGL(glStencilFunc(GL_ALWAYS, clearstencil, 0xFFFFFFFF));
01227     // this is to always pass a one to the stencil buffer where we draw
01228     CHECKGL(glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
01229 
01230     CHECKGL(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
01231     //CHECKGL(glEnable(GL_DEPTH_TEST));
01232     //CHECKGL(glDepthFunc(GL_ALWAYS));
01233 
01234     QRP_Color(x, y, width, height, color::Black);
01235 
01236     //CHECKGL(glDepthFunc(GL_LESS));
01237     //CHECKGL(glDisable(GL_DEPTH_TEST));
01238     CHECKGL(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
01239     CHECKGL(glDisable(GL_STENCIL_TEST));
01240 
01241   }
01242 
01243 //Statistics
01244   void GraphicsEngine::ResetStats()
01245   {
01246     m_quad_stats            = 0;
01247     m_quad_tex_stats        = 0;
01248     m_triangle_stats        = 0;
01249     m_triangle_tex_stats    = 0;
01250     m_line_stats            = 0;
01251   }
01252 
01253   ObjectPtr< CachedResourceData > GraphicsEngine::CacheResource(ResourceData* Resource)
01254   {
01255     return ResourceCache.GetCachedResource(Resource);
01256   }
01257 
01258   bool GraphicsEngine::FlushCachedResourceData(ResourceData* Resource)
01259   {
01260     if (!IsResourceCached(Resource))
01261       return false;
01262 
01263     ResourceCache.FlushResourceId(Resource->GetResourceIndex());
01264     return true;
01265   }
01266 
01267   void GraphicsEngine::UpdateResource(ResourceData* Resource)
01268   {
01269     ObjectPtr<CachedResourceData> GLResource = ResourceCache.FindCachedResourceById(Resource->GetResourceIndex()); //(CachedResourceData*)(*(ResourceCache.ResourceMap.find(Resource->ResourceIndex))).second;
01270 
01271     if (GLResource.IsValid())
01272     {
01273       // Iterate through all resource updater types(list is sorted by subclass depth).
01274       for (unsigned int i = 0; i < ResourceCache.GetResourceUpdaters().size(); ++i)
01275       {
01276         NResourceUpdater* ResourceUpdater = ResourceCache.GetResourceUpdaters() [i];
01277         nuxAssert(ResourceUpdater);
01278 
01279         // Check if the updater is valid for updating the resource.
01280         if (ResourceUpdater->UpdatesThisResource(Resource))
01281         {
01282           ResourceUpdater->UpdateResource(GLResource, Resource);
01283           break;
01284         }
01285       }
01286     }
01287   }
01288 
01289   bool GraphicsEngine::IsResourceCached(ResourceData* Resource)
01290   {
01291     return ResourceCache.IsCachedResource(Resource);
01292   }
01293 
01294   void GraphicsEngine::SetFrameBufferHelper(
01295     ObjectPtr<IOpenGLFrameBufferObject>& fbo,
01296     ObjectPtr<IOpenGLBaseTexture>& colorbuffer,
01297     ObjectPtr<IOpenGLBaseTexture>& depthbuffer,
01298     int width, int height)
01299   {
01300     if ((colorbuffer.IsValid() == false) || (colorbuffer->GetWidth() != width) || (colorbuffer->GetHeight() != height))
01301     {
01302       colorbuffer = _graphics_display.GetGpuDevice()->CreateTexture(width, height, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION);
01303     }
01304 
01305     if ((depthbuffer.IsValid()) && ((depthbuffer->GetWidth() != width) || (depthbuffer->GetHeight() != height)))
01306     {
01307       // Generate a new depth texture only if a valid one was passed to this function.
01308       depthbuffer = _graphics_display.GetGpuDevice()->CreateTexture(width, height, 1, BITFMT_D24S8, NUX_TRACKER_LOCATION);
01309     }
01310 
01311     fbo->FormatFrameBufferObject(width, height, BITFMT_R8G8B8A8);
01312     fbo->SetRenderTarget(0, colorbuffer->GetSurfaceLevel(0));
01313     
01314     if (depthbuffer.IsValid())
01315       fbo->SetDepthSurface(depthbuffer->GetSurfaceLevel(0));
01316     else
01317       fbo->SetDepthSurface(ObjectPtr<IOpenGLSurface>(NULL));
01318 
01319     fbo->Activate();
01320     fbo->EmptyClippingRegion();
01321     SetContext(0, 0, width, height);
01322     SetViewport(0, 0, width, height);
01323     Push2DWindow(width, height);
01324   }
01325 
01326   void GraphicsEngine::GaussianWeights(float **weights, float sigma, unsigned int num_tap)
01327   {
01328     *weights = new float[num_tap];
01329     float sum = 0.0f;
01330     unsigned int i = 0;
01331 
01332     unsigned int half = (num_tap-1)/2;
01333 
01334     (*weights)[half] = (1.0f/(sqrt(2.0f*3.14159265358f)*sigma)) * exp(-0.0f/(2.0f*sigma*sigma));
01335     sum += (*weights)[half];
01336     for (i = 0; i < half; i++)
01337     {
01338       float X = (i + 1)*(i + 1);
01339       (*weights)[half - i - 1] = (*weights)[half + i + 1] = (1.0f/(sqrt(2.0f*3.14159265358f)*sigma)) * exp(-X/(2.0f*sigma*sigma));
01340       sum += 2.0f * ((*weights)[half - i - 1]);
01341     }
01342 
01343     /* normalization */
01344     for (i = 0; i < num_tap; i++)
01345     {
01346       (*weights)[i] = (*weights)[i] / sum;
01347     }
01348   }
01349 
01350   ObjectPtr <IOpenGLBaseTexture> GraphicsEngine::CreateTextureFromBackBuffer(int x, int y, int width, int height)
01351   {
01352     ObjectPtr<IOpenGLFrameBufferObject> fbo = _graphics_display.GetGpuDevice()->GetCurrentFrameBufferObject();
01353 
01354     int X, Y, W, H;
01355     if (fbo.IsValid())
01356     {
01357       int fbo_width = fbo->GetWidth();
01358       int fbo_height = fbo->GetHeight();
01359 
01360       X = Clamp<int> (x, 0, fbo_width);
01361       Y = Clamp<int> (y, 0, fbo_height);
01362       W = Min<int> (fbo_width - x, width);
01363       H = Min<int> (fbo_height - y, height);
01364 
01365 
01366       if ((W <= 0) || (H <= 0))
01367       {
01368         nuxAssertMsg(0, "[GraphicsEngine::CreateTextureFromBackBuffer] Invalid request.");
01369         return ObjectPtr<IOpenGLBaseTexture> (0);
01370       }
01371       
01372       // Inverse Y because of OpenGL upside-down nature
01373       Y = fbo_height - Y - H;
01374     }
01375     else
01376     {
01377       // There is no fbo. Reading directly from the back-buffer.
01378       int bb_width = _graphics_display.GetWindowWidth();
01379       int bb_height = _graphics_display.GetWindowHeight();
01380 
01381       X = Clamp<int> (x, 0, bb_width);
01382       Y = Clamp<int> (y, 0, bb_height);
01383       W = Min<int> (bb_width - x, width);
01384       H = Min<int> (bb_height - y, height);
01385 
01386       if ((W <= 0) || (H <= 0))
01387       {
01388         nuxAssertMsg(0, "[GraphicsEngine::CreateTextureFromBackBuffer] Invalid request.");
01389         return ObjectPtr<IOpenGLBaseTexture> (0);
01390       }
01391 
01392       // Inverse Y because of OpenGL upside-down nature
01393       Y = bb_height - Y - H;
01394     }
01395 
01396     ObjectPtr <IOpenGLBaseTexture> device_texture = _graphics_display.GetGpuDevice()->CreateSystemCapableDeviceTexture(W, H, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION);
01397     ObjectPtr <IOpenGLSurface> sfc = device_texture->GetSurfaceLevel(0);
01398 
01399     sfc->CopyRenderTarget(X, Y, W, H);
01400 
01401     return device_texture;
01402   }
01403 
01404 }