Back to index

nux  3.0.0
GLTextureResourceManager.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 "GLResource.h"
00024 #include "GLResourceManager.h"
00025 #include "GpuDevice.h"
00026 #include "GraphicsEngine.h"
00027 #include "GLTextureResourceManager.h"
00028 
00029 namespace nux
00030 {
00031 
00032   NUX_IMPLEMENT_OBJECT_TYPE(BaseTexture);
00033   NUX_IMPLEMENT_OBJECT_TYPE(Texture2D);
00034   NUX_IMPLEMENT_OBJECT_TYPE(TextureRectangle);
00035   NUX_IMPLEMENT_OBJECT_TYPE(TextureCube);
00036   NUX_IMPLEMENT_OBJECT_TYPE(TextureVolume);
00037   NUX_IMPLEMENT_OBJECT_TYPE(TextureFrameAnimation);
00038 
00039   NUX_IMPLEMENT_OBJECT_TYPE(CachedBaseTexture);
00040   NUX_IMPLEMENT_OBJECT_TYPE(CachedTexture2D);
00041   NUX_IMPLEMENT_OBJECT_TYPE(CachedTextureRectangle);
00042   NUX_IMPLEMENT_OBJECT_TYPE(CachedTextureCube);
00043   NUX_IMPLEMENT_OBJECT_TYPE(CachedTextureVolume);
00044   NUX_IMPLEMENT_OBJECT_TYPE(CachedTextureFrameAnimation);
00045 
00052   template < class T, class U >
00053   static T* UpCastResource(U* Src)
00054   {
00055     if (!Src || !Src->Type().IsDerivedFromType(T::StaticObjectType))
00056       nuxError("[UpCastResource] Cast of %s to %s failed", U::StaticObjectType.name, T::StaticObjectType.name);
00057 
00058     return(T*) Src;
00059   }
00060 
00061   BaseTexture* CreateTexture2DFromPixbuf(GdkPixbuf* pixbuf, bool premultiply)
00062   {
00063     const unsigned int rowstride = gdk_pixbuf_get_rowstride(pixbuf);
00064     const unsigned int width = gdk_pixbuf_get_width(pixbuf);
00065     const unsigned int height = gdk_pixbuf_get_height(pixbuf);
00066 
00067     // Put the RGB or RGBA pixels in a RGBA texture data object taking care
00068     // of alpha premultiplication if requested.
00069     // FIXME(loicm) Implies a useless copy. NTextureData should be able to
00070     //     take ownership of pre-allocated memory.
00071     // FIXME(loicm) Add support for big-endian systems. For performance
00072     //     reasons, pixels are loaded by block of 4 bytes with the color
00073     //     components bit-shifted considering little-endian ordering. Nux
00074     //     doesn't seem to be big-endian aware anyway.
00075     // FIXME(loicm) Surface::Write32b does branching, splits the 32-bit value
00076     //     as four 8-bit values(using bit-shifts) that are then stored
00077     //     separately, that's slow considering it's meant to be used a lot in
00078     //     deep loops.
00079     NTextureData* data = new NTextureData(BITFMT_R8G8B8A8, width, height, 1);
00080     ImageSurface& surface = data->GetSurface(0);
00081     if (gdk_pixbuf_get_has_alpha(pixbuf) == TRUE)
00082     {
00083       unsigned char* pixels_u8 = gdk_pixbuf_get_pixels(pixbuf);
00084       unsigned int* pixels_u32 = reinterpret_cast<unsigned int*> (pixels_u8);
00085 
00086       if (premultiply == true)
00087       {
00088         // Copy from pixbuf(RGBA) to surface(premultiplied RGBA).
00089         for (unsigned int i = 0; i < height; i++)
00090         {
00091           for (unsigned int j = 0; j < width; j++)
00092           {
00093             const unsigned int pixel = pixels_u32[j];
00094             const unsigned int a = pixel >> 24;
00095             if (a == 0)
00096               surface.Write32b(j, i, 0);
00097             else
00098             {
00099               const unsigned int b = (((pixel >> 16) & 0xff) * a) / 255;
00100               const unsigned int g = (((pixel >> 8) & 0xff) * a) / 255;
00101               const unsigned int r = ((pixel & 0xff) * a) / 255;
00102               const unsigned int p = a << 24 | b << 16 | g << 8 | r;
00103               surface.Write32b(j, i, p);
00104             }
00105           }
00106           pixels_u8 += rowstride;
00107           pixels_u32 = reinterpret_cast<unsigned int*> (pixels_u8);
00108         }
00109       }
00110       else
00111       {
00112         // Copy from pixbuf(RGBA) to surface(RGBA).
00113         for (unsigned int i = 0; i < height; i++)
00114         {
00115           for (unsigned int j = 0; j < width; j++)
00116             surface.Write32b(j, i, pixels_u32[j]);
00117           pixels_u8 += rowstride;
00118           pixels_u32 = reinterpret_cast<unsigned int*> (pixels_u8);
00119         }
00120       }
00121     }
00122     else
00123     {
00124       // Copy from pixbuf(RGB) to surface(RGBA).
00125       unsigned char* pixels = gdk_pixbuf_get_pixels(pixbuf);
00126       for (unsigned int i = 0; i < height; i++)
00127       {
00128         for (unsigned int j = 0; j < width; j++)
00129         {
00130           const unsigned char r = pixels[j*3];
00131           const unsigned char g = pixels[j*3+1];
00132           const unsigned char b = pixels[j*3+2];
00133           surface.Write(j, i, r, g, b, 0xff);
00134         }
00135         pixels += rowstride;
00136       }
00137     }
00138 
00139     // Create a 2D texture and upload the pixels.
00140     BaseTexture* texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture();
00141     texture->Update(data);
00142     
00143     delete data; // data is deleted as texture->Update() copies it.
00144     return texture;
00145   }
00146 
00147   BaseTexture* CreateTexture2DFromFile(const char* filename, int max_size,
00148                                         bool premultiply)
00149   {
00150     GError* error = NULL;
00151     GdkPixbuf* pixbuf =
00152       gdk_pixbuf_new_from_file_at_size(filename, max_size, max_size, &error);
00153     if (error == NULL)
00154     {
00155       BaseTexture* texture = CreateTexture2DFromPixbuf(pixbuf, premultiply);
00156       g_object_unref(pixbuf);
00157       return texture;
00158     }
00159     else
00160     {
00161       nuxDebugMsg("%s", error->message);
00162       return NULL;
00163     }
00164   }
00165 
00166   BaseTexture* CreateTextureFromPixbuf(GdkPixbuf* pixbuf)
00167   {
00168     NBitmapData* BitmapData = LoadGdkPixbuf(pixbuf);
00169     NUX_RETURN_VALUE_IF_NULL(BitmapData, 0);
00170 
00171     if (BitmapData->IsTextureData())
00172     {
00173       BaseTexture* texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture();
00174       texture->Update(BitmapData);
00175       return texture;
00176     }
00177     delete BitmapData;
00178     return 0;
00179   }
00180 
00181   BaseTexture* CreateTextureFromFile(const char* TextureFilename)
00182   {
00183     BaseTexture* texture = NULL;
00184 
00185     NBitmapData* BitmapData = LoadImageFile(TextureFilename);
00186     NUX_RETURN_VALUE_IF_NULL(BitmapData, 0);
00187 
00188     if (BitmapData->IsTextureData())
00189     {
00190       texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture();
00191     }
00192     else if (BitmapData->IsCubemapTextureData())
00193     {
00194       texture = new TextureCube();
00195     }
00196     else if (BitmapData->IsVolumeTextureData())
00197     {
00198       texture = new TextureVolume();
00199     }
00200     else if (BitmapData->IsAnimatedTextureData())
00201     {
00202       texture = new TextureFrameAnimation();
00203     }
00204 
00205     if (texture)
00206     {
00207       texture->Update(BitmapData);
00208     }
00209     else
00210     {
00211       nuxDebugMsg("[CreateTextureFromFile] Invalid texture format type for file(%s)", TextureFilename);
00212     }
00213 
00214     delete BitmapData;
00215     return texture;
00216   }
00217 
00218   BaseTexture* CreateTextureFromBitmapData(const NBitmapData* BitmapData)
00219   {
00220     if (BitmapData == 0)
00221       return 0;
00222 
00223     if (BitmapData->IsTextureData())
00224     {
00225       BaseTexture* texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture();
00226       texture->Update(BitmapData);
00227       return texture;
00228     }
00229     else if (BitmapData->IsCubemapTextureData())
00230     {
00231       TextureCube* texture = new TextureCube();
00232       texture->Update(BitmapData);
00233       return texture;
00234     }
00235     else if (BitmapData->IsVolumeTextureData())
00236     {
00237       TextureVolume* texture = new TextureVolume();
00238       texture->Update(BitmapData);
00239       return texture;
00240     }
00241     else if (BitmapData->IsAnimatedTextureData())
00242     {
00243       TextureFrameAnimation* texture = new TextureFrameAnimation();
00244       texture->Update(BitmapData);
00245       return texture;
00246     }
00247     return 0;
00248   }
00249 
00250   BaseTexture* LoadTextureFromFile(const std::string& filename)
00251   {
00252     NBitmapData* bitmap = LoadImageFile(filename.c_str());
00253 
00254     if (bitmap == NULL)
00255       return NULL;
00256 
00257     BaseTexture* texture = CreateTextureFromBitmapData(bitmap);
00258     return texture;
00259   }
00260 
00261   BaseTexture::BaseTexture(NUX_FILE_LINE_DECL)
00262     : ResourceData(NUX_FILE_LINE_PARAM)
00263   {
00264 
00265   }
00266 
00267   BaseTexture::~BaseTexture()
00268   {
00269 
00270   }
00271 
00272   ObjectPtr < IOpenGLBaseTexture > BaseTexture::GetDeviceTexture()
00273   {
00274     ObjectPtr<CachedBaseTexture> CachedTexture = GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(this);
00275     return CachedTexture->m_Texture;
00276   }
00277 
00278   ObjectPtr<CachedBaseTexture> BaseTexture::GetCachedTexture()
00279   {
00280     return GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(this);
00281   }
00282 
00283   Texture2D::Texture2D(NUX_FILE_LINE_DECL)
00284     : BaseTexture(NUX_FILE_LINE_PARAM)
00285   {
00286   }
00287 
00288   Texture2D::Texture2D(const Texture2D& texture, NUX_FILE_LINE_DECL)
00289     : BaseTexture(NUX_FILE_LINE_PARAM)
00290   {
00291     _image = texture._image;
00292   }
00293 
00294   Texture2D::Texture2D(const NTextureData& texture_data, NUX_FILE_LINE_DECL)
00295     : BaseTexture(NUX_FILE_LINE_PARAM)
00296   {
00297     _image = texture_data;
00298   }
00299 
00300   Texture2D& Texture2D::operator = (const Texture2D& texture)
00301   {
00302     if (this == &texture)
00303       return *this;   // Handle self assignment
00304 
00305     _image = texture._image;
00306     return *this;
00307   }
00308 
00309   Texture2D::~Texture2D()
00310   {
00311   }
00312 
00313   bool Texture2D::Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource)
00314   {
00315     nuxAssertMsg(BitmapData, "[Texture2D::Update] Argument BitmapData is NULL.");
00316     NUX_RETURN_VALUE_IF_NULL(BitmapData, false);
00317 
00318     if (!BitmapData->IsTextureData())
00319     {
00320       nuxAssertMsg(0, "[Texture2D::Update] Argument BitmapData is not a 2D texture");
00321       return false;
00322     }
00323 
00324     _image = *static_cast<const NTextureData*> (BitmapData);
00325 
00326     if (UpdateAndCacheResource)
00327     {
00328       // call the texture manager and recreate the texture(CachedTexture2D) associated with this object if any.
00329       GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource(this);
00330     }
00331 
00332     return true;
00333   }
00334 
00335   bool Texture2D::Update(const char* filename, bool UpdateAndCacheResource)
00336   {
00337     NBitmapData* BitmapData = LoadImageFile(filename);
00338     nuxAssertMsg(BitmapData, "[Texture2D::Update] Bitmap for file(%s) is NULL.", filename);
00339     NUX_RETURN_VALUE_IF_NULL(BitmapData, false);
00340     bool ret = Update(BitmapData, UpdateAndCacheResource);
00341     NUX_SAFE_DELETE(BitmapData);
00342     return ret;
00343   }
00344 
00345   void Texture2D::GetData(void* Buffer, int MipIndex, int StrideY, int face)
00346   {
00347     BYTE              *Dest        = (BYTE*) Buffer;
00348     const BYTE        *Src         = _image.GetSurface(MipIndex).GetPtrRawData();
00349     int               RowByteSize = _image.GetSurface(MipIndex).GetPitch();
00350     int               NumRows     = _image.GetSurface(MipIndex).GetBlockHeight();
00351 
00352     for ( int Y = 0; Y < NumRows; Y++ )
00353     {
00354       // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
00355       // they contain the same amount of valid data since they have the same width, height and format.
00356       Memcpy(Dest + Y * StrideY, &Src[Y * RowByteSize], Min(RowByteSize, StrideY));
00357     }
00358   }
00359 
00360   BaseTexture* Texture2D::Clone() const
00361   {
00362     Texture2D* texture = new Texture2D(*this);
00363     return texture;
00364   }
00365 
00366   CachedBaseTexture::CachedBaseTexture(NResourceSet* ResourceManager)
00367     :   CachedResourceData(ResourceManager),
00368     SourceWidth(0),
00369     SourceHeight(0),
00370     SourceDepth(0),
00371     SourceFormat(BITFMT_UNKNOWN)
00372   {
00373 
00374   }
00375 
00376   CachedBaseTexture::~CachedBaseTexture()
00377   {
00378     m_Texture.Release();
00379   }
00380 
00381   bool CachedBaseTexture::UpdateResource(ResourceData* Resource)
00382   {
00383     UpdateTexture((BaseTexture*) Resource);
00384     return TRUE;
00385   }
00386 
00387   bool CachedBaseTexture::RecreateTexture(BaseTexture* Source)
00388   {
00389     int CurrentWidth   = m_Texture->GetWidth();
00390     int CurrentHeight  = m_Texture->GetHeight();
00391     int CurrentDepth   = m_Texture->GetDepth();
00392     int CurrentNumMipmap      = m_Texture->GetNumMipLevel();
00393     BitmapFormat CurrentFormat = m_Texture->GetPixelFormat();
00394 
00395     bool Recreate =
00396       (CurrentWidth       != Source->GetWidth()) ||
00397       (CurrentHeight      != Source->GetHeight()) ||
00398       (CurrentDepth       != Source->GetDepth()) ||
00399       (CurrentNumMipmap   != Source->GetNumMipLevel()) ||
00400       (CurrentFormat      != Source->GetFormat());
00401 
00402     return Recreate;
00403   }
00404 
00405   CachedTexture2D::CachedTexture2D(NResourceSet* ResourceManager, Texture2D* SourceTexture)
00406     : CachedBaseTexture(ResourceManager)
00407   {
00408     if (SourceTexture->IsNull())
00409     {
00410       m_Texture = ObjectPtr <IOpenGLBaseTexture> (0);
00411       return;
00412     }
00413 
00414     m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateTexture(SourceTexture->GetWidth(),
00415                 SourceTexture->GetHeight(),
00416                 SourceTexture->GetNumMipLevel(),
00417                 SourceTexture->GetFormat(), NUX_TRACKER_LOCATION);
00418 
00419     for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00420     {
00421       LoadMipLevel(SourceTexture, i);
00422     }
00423   }
00424 
00425   CachedTexture2D::~CachedTexture2D()
00426   {
00427 
00428   }
00429 
00430   void CachedTexture2D::UpdateTexture( BaseTexture* SourceTexture )
00431   {
00432     if ((SourceTexture == 0) || SourceTexture->IsNull())
00433     {
00434       m_Texture = ObjectPtr <IOpenGLBaseTexture> (0);
00435       return;
00436     }
00437 
00438     if (!SourceTexture->Type().IsObjectType(Texture2D::StaticObjectType))
00439     {
00440       nuxAssertMsg(0, "[Texture2D::UpdateTexture] Source texture is not of type Texture2D.");
00441       return;
00442     }
00443 
00444     if ( RecreateTexture(SourceTexture))
00445     {
00446       m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateTexture(SourceTexture->GetWidth(),
00447                   SourceTexture->GetHeight(),
00448                   SourceTexture->GetNumMipLevel(),
00449                   SourceTexture->GetFormat(), NUX_TRACKER_LOCATION);
00450 
00451       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00452       {
00453         LoadMipLevel(SourceTexture, i);
00454       }
00455     }
00456     else
00457     {
00458       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00459       {
00460         LoadMipLevel(SourceTexture, i);
00461       }
00462     }
00463   }
00464 
00465   void CachedTexture2D::LoadMipLevel(BaseTexture* SourceTexture, int MipLevel)
00466   {
00467     SURFACE_LOCKED_RECT LockedRect;
00468     ObjectPtr < IOpenGLTexture2D > Texture2D = m_Texture; //m_Texture.CastRef<IOpenGLTexture2D>();
00469 
00470     OGL_CALL(Texture2D->LockRect(MipLevel, &LockedRect, NULL));
00471     SourceTexture->GetData(LockedRect.pBits, MipLevel, LockedRect.Pitch);
00472     OGL_CALL(Texture2D->UnlockRect(MipLevel));
00473   }
00474 
00475   TextureRectangle::TextureRectangle(NUX_FILE_LINE_DECL)
00476     : BaseTexture(NUX_FILE_LINE_PARAM)
00477   {
00478   }
00479 
00480   TextureRectangle::TextureRectangle(const TextureRectangle& texture)
00481   {
00482     _image = texture._image;
00483   }
00484 
00485   TextureRectangle::TextureRectangle(const NTextureData& BaseTexture)
00486   {
00487     _image = BaseTexture;
00488   }
00489 
00490   TextureRectangle& TextureRectangle::operator = (const TextureRectangle& texture)
00491   {
00492     if (this == &texture)
00493       return *this;   // Handle self assignment
00494 
00495     _image = texture._image;
00496     return *this;
00497   }
00498 
00499   TextureRectangle::~TextureRectangle()
00500   {
00501 
00502   }
00503 
00504   bool TextureRectangle::Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource)
00505   {
00506     nuxAssertMsg(BitmapData, "[TextureRectangle::Update] Argument BitmapData is NULL.");
00507     NUX_RETURN_VALUE_IF_NULL(BitmapData, false);
00508 
00509     if (!BitmapData->IsTextureData())
00510     {
00511       nuxAssertMsg(0, "[TextureRectangle::Update] Argument BitmapData is not a 2D texture");
00512       return false;
00513     }
00514 
00515     _image = *static_cast<const NTextureData*> (BitmapData);
00516 
00517     if (UpdateAndCacheResource)
00518     {
00519       // call the texture manager and recreate the texture(CachedTexture2D) associated with this object if any.
00520       GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource(this);
00521     }
00522     return true;
00523   }
00524 
00525   bool TextureRectangle::Update(const char* filename, bool UpdateAndCacheResource)
00526   {
00527     bool b = false;
00528     NBitmapData* BitmapData = LoadImageFile(filename);
00529     nuxAssertMsg(BitmapData, "[TextureRectangle::Update] Bitmap for file(%s) is NULL.", filename);
00530     NUX_RETURN_VALUE_IF_NULL(BitmapData, false);
00531     b = Update(BitmapData);
00532     NUX_SAFE_DELETE(BitmapData);
00533     return b;
00534   }
00535 
00536   void TextureRectangle::GetData(void* Buffer, int MipIndex, int StrideY, int face)
00537   {
00538     BYTE              *Dest        = (BYTE *) Buffer;
00539     const BYTE         *Src         = _image.GetSurface(MipIndex).GetPtrRawData();
00540     int                 RowByteSize = _image.GetSurface(MipIndex).GetPitch();
00541     int                 NumRows     = _image.GetSurface(MipIndex).GetBlockHeight();
00542 
00543     for ( int Y = 0; Y < NumRows; Y++ )
00544     {
00545       // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
00546       // they contain the same amount of valid data since they have the same width, height and format.
00547       Memcpy(Dest + Y * StrideY, &Src[Y * RowByteSize], Min(RowByteSize, StrideY));
00548     }
00549   }
00550 
00551   BaseTexture* TextureRectangle::Clone() const
00552   {
00553     TextureRectangle* texture = new TextureRectangle(*this);
00554     return texture;
00555   }
00556 
00557   CachedTextureRectangle::CachedTextureRectangle(NResourceSet* ResourceManager, TextureRectangle* SourceTexture)
00558     : CachedBaseTexture(ResourceManager)
00559   {
00560     if (SourceTexture->IsNull())
00561     {
00562       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00563       return;
00564     }
00565 
00566     m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateRectangleTexture(SourceTexture->GetWidth(),
00567                 SourceTexture->GetHeight(),
00568                 SourceTexture->GetNumMipLevel(),
00569                 SourceTexture->GetFormat(), NUX_TRACKER_LOCATION);
00570 
00571     for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00572     {
00573       LoadMipLevel(SourceTexture, i);
00574     }
00575   }
00576 
00577   CachedTextureRectangle::~CachedTextureRectangle()
00578   {
00579 
00580   }
00581 
00582   void CachedTextureRectangle::UpdateTexture( BaseTexture* SourceTexture )
00583   {
00584     if ((SourceTexture == 0) || SourceTexture->IsNull())
00585     {
00586       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00587       return;
00588     }
00589 
00590     if (!SourceTexture->Type().IsObjectType(TextureRectangle::StaticObjectType))
00591     {
00592       nuxAssertMsg(0, "[CachedTextureRectangle::UpdateTexture] Source texture is not of type TextureRectangle.");
00593       return;
00594     }
00595 
00596     if ( RecreateTexture(SourceTexture))
00597     {
00598       m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateRectangleTexture(SourceTexture->GetWidth(),
00599                   SourceTexture->GetHeight(),
00600                   SourceTexture->GetNumMipLevel(),
00601                   SourceTexture->GetFormat(), NUX_TRACKER_LOCATION);
00602 
00603       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00604       {
00605         LoadMipLevel(SourceTexture, i);
00606       }
00607     }
00608     else
00609     {
00610       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00611       {
00612         LoadMipLevel(SourceTexture, i);
00613       }
00614     }
00615   }
00616 
00617   void CachedTextureRectangle::LoadMipLevel(BaseTexture* SourceTexture, int MipLevel)
00618   {
00619     SURFACE_LOCKED_RECT            LockedRect;
00620     ObjectPtr <IOpenGLRectangleTexture>  TextureRectangle = m_Texture; //m_Texture.CastRef<IOpenGLRectangleTexture>();
00621 
00622     OGL_CALL(TextureRectangle->LockRect( MipLevel, &LockedRect, NULL));
00623     SourceTexture->GetData( LockedRect.pBits, MipLevel, LockedRect.Pitch );
00624     OGL_CALL(TextureRectangle->UnlockRect( MipLevel ));
00625   }
00626 
00627   TextureCube::TextureCube(NUX_FILE_LINE_DECL)
00628     : BaseTexture(NUX_FILE_LINE_PARAM)
00629   {
00630   }
00631 
00632   TextureCube::TextureCube(const TextureCube& texture)
00633   {
00634     _image = texture._image;
00635   }
00636 
00637   TextureCube& TextureCube::operator = (const TextureCube& texture)
00638   {
00639     if (this == &texture)
00640       return *this;   // Handle self assignment
00641 
00642     _image = texture._image;
00643     return *this;
00644   }
00645 
00646   TextureCube::~TextureCube()
00647   {
00648 
00649   }
00650 
00651   bool TextureCube::Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource)
00652   {
00653     nuxAssertMsg(BitmapData, "[TextureCube::Update] Argument BitmapData is NULL.");
00654     NUX_RETURN_VALUE_IF_NULL(BitmapData, false);
00655 
00656     if (!BitmapData->IsCubemapTextureData())
00657     {
00658       nuxAssertMsg(0, "[TextureCube::Update] Argument BitmapData is not a Cube texture");
00659       return false;
00660     }
00661 
00662     _image = *static_cast<const NCubemapData*> (BitmapData);
00663 
00664     if (UpdateAndCacheResource)
00665     {
00666       // call the texture manager and recreate the texture(CachedTexture2D) associated with this object if any.
00667       GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource(this);
00668     }
00669 
00670     return true;
00671   }
00672 
00673   bool TextureCube::Update(const char* filename, bool UpdateAndCacheResource)
00674   {
00675     NBitmapData* BitmapData = LoadImageFile(filename);
00676     nuxAssertMsg(BitmapData, "[TextureCube::Update] Bitmap for file(%s) is NULL.", filename);
00677     NUX_RETURN_VALUE_IF_NULL(BitmapData, false);
00678     bool ret = Update(BitmapData);
00679     NUX_SAFE_DELETE(BitmapData);
00680     return ret;
00681   }
00682 
00683   void TextureCube::GetData(void* Buffer, int MipIndex, int StrideY, int face)
00684   {
00685     BYTE              *Dest        = (BYTE *) Buffer;
00686     const BYTE         *Src         = _image.GetSurface(face, MipIndex).GetPtrRawData();
00687     int                 RowByteSize = _image.GetSurface(face, MipIndex).GetPitch();
00688     int                 NumRows     = _image.GetSurface(face, MipIndex).GetBlockHeight();
00689 
00690     for ( int Y = 0; Y < NumRows; Y++ )
00691     {
00692       // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
00693       // they contain the same amount of valid data since they have the same width, height and format.
00694       Memcpy(Dest + Y * StrideY, &Src[Y * RowByteSize], Min(RowByteSize, StrideY));
00695     }
00696   }
00697 
00698   BaseTexture* TextureCube::Clone() const
00699   {
00700     TextureCube* texture = new TextureCube(*this);
00701     return texture;
00702   }
00703 
00704   CachedTextureCube::CachedTextureCube(NResourceSet* ResourceManager, TextureCube* SourceTexture)
00705     : CachedBaseTexture(ResourceManager)
00706   {
00707     if (SourceTexture->IsNull())
00708     {
00709       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00710       return;
00711     }
00712 
00713     m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateCubeTexture(SourceTexture->GetWidth(),
00714                 SourceTexture->GetNumMipLevel(),
00715                 SourceTexture->GetFormat());
00716 
00717     for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00718     {
00719       LoadMipLevel(SourceTexture, i);
00720     }
00721   }
00722 
00723   CachedTextureCube::~CachedTextureCube()
00724   {
00725 
00726   }
00727 
00728   void CachedTextureCube::UpdateTexture( BaseTexture* SourceTexture )
00729   {
00730     if ((SourceTexture == 0) || SourceTexture->IsNull())
00731     {
00732       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00733       return;
00734     }
00735 
00736     if (!SourceTexture->Type().IsObjectType(TextureCube::StaticObjectType))
00737     {
00738       nuxAssertMsg(0, "[CachedTextureCube::UpdateTexture] Source texture is not of type TextureCube.");
00739       return;
00740     }
00741 
00742     if ( RecreateTexture(SourceTexture))
00743     {
00744       m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateCubeTexture(SourceTexture->GetWidth(),
00745                   SourceTexture->GetNumMipLevel(),
00746                   SourceTexture->GetFormat());
00747 
00748       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00749       {
00750         LoadMipLevel(SourceTexture, i);
00751       }
00752     }
00753     else
00754     {
00755       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00756       {
00757         LoadMipLevel(SourceTexture, i);
00758       }
00759     }
00760   }
00761 
00762   void CachedTextureCube::LoadMipLevel(BaseTexture* SourceTexture, int MipLevel)
00763   {
00764     SURFACE_LOCKED_RECT    LockedRect;
00765     ObjectPtr <IOpenGLCubeTexture> CubemapTexture = m_Texture; //m_Texture.CastRef<IOpenGLCubeTexture>();
00766 
00767     for (int face = CUBEMAP_FACE_POSITIVE_X; face < GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + 1; face++)
00768     {
00769       OGL_CALL( CubemapTexture->LockRect(eCUBEMAP_FACES(face), MipLevel, &LockedRect, NULL));
00770       SourceTexture->GetData(LockedRect.pBits, MipLevel, LockedRect.Pitch, face - CUBEMAP_FACE_POSITIVE_X);
00771       OGL_CALL( CubemapTexture->UnlockRect(eCUBEMAP_FACES(face), MipLevel ));
00772     }
00773   }
00774 
00775   TextureVolume::TextureVolume(NUX_FILE_LINE_DECL)
00776     : BaseTexture(NUX_FILE_LINE_PARAM)
00777   {
00778   }
00779 
00780   TextureVolume::TextureVolume(const TextureVolume& texture)
00781   {
00782     _image = texture._image;
00783   }
00784 
00785   TextureVolume& TextureVolume::operator = (const TextureVolume& texture)
00786   {
00787     if (this == &texture)
00788       return *this;   // Handle self assignment
00789 
00790     _image = texture._image;
00791     return *this;
00792   }
00793 
00794   TextureVolume::~TextureVolume()
00795   {
00796 
00797   }
00798 
00799   bool TextureVolume::Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource)
00800   {
00801     nuxAssertMsg(BitmapData, "[TextureVolume::Update] Argument BitmapData is NULL.");
00802     NUX_RETURN_VALUE_IF_NULL(BitmapData, false);
00803 
00804     if (!BitmapData->IsVolumeTextureData())
00805     {
00806       nuxAssertMsg(0, "[TextureVolume::Update] Argument BitmapData is not a Volume texture");
00807       return false;
00808     }
00809 
00810     _image = *static_cast<const NVolumeData*> (BitmapData);
00811 
00812     if (UpdateAndCacheResource)
00813     {
00814       // call the texture manager and recreate the texture(CachedTexture2D) associated with this object if any.
00815       GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource(this);
00816     }
00817 
00818     return true;
00819   }
00820 
00821   bool TextureVolume::Update(const char* filename, bool UpdateAndCacheResource)
00822   {
00823     NBitmapData* BitmapData = LoadImageFile(filename);
00824     nuxAssertMsg(BitmapData, "[TextureVolume::Update] Bitmap for file(%s) is NULL.", filename);
00825     NUX_RETURN_VALUE_IF_NULL(BitmapData, false);
00826     bool ret = Update(filename);
00827     NUX_SAFE_DELETE(BitmapData);
00828     return ret;
00829   }
00830 
00831   void TextureVolume::GetData(void* Buffer, int MipIndex, int StrideY, int face)
00832   {
00833     BYTE               *Dest        = (BYTE *) Buffer;
00834 //     const BYTE*         Src         = _image.GetSurface(MipIndex, slice).GetPtrRawData();
00835 //     int                 RowByteSize = _image.GetSurface(MipIndex, slice).GetPitch();
00836 //     int                 NumRows     = _image.GetSurface(MipIndex, slice).GetBlockHeight();
00837 
00838     for (int slice = 0; slice < ImageSurface::GetLevelDim(_image.GetFormat(), _image.GetDepth(), MipIndex); slice++)
00839     {
00840       const BYTE         *Src         = _image.GetSurface(MipIndex, slice).GetPtrRawData();
00841       int                 RowByteSize = _image.GetSurface(MipIndex, slice).GetPitch();
00842       int                 NumRows     = _image.GetSurface(MipIndex, slice).GetBlockHeight();
00843 
00844       for ( int Y = 0; Y < NumRows; Y++ )
00845       {
00846         // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
00847         // they contain the same amount of valid data since they have the same width, height and format.
00848         Memcpy(Dest + Y * StrideY, &Src[Y * RowByteSize], Min(RowByteSize, StrideY));
00849       }
00850 
00851       Dest += NumRows * StrideY;
00852     }
00853 
00854 //     BYTE*              Dest        = (BYTE*)Buffer;
00855 //     const BYTE*         Src         = _image.GetSurface(MipIndex, slice).GetPtrRawData();
00856 //     int                 RowByteSize = _image.GetSurface(MipIndex, slice).GetPitch();
00857 //     int                 NumRows     = _image.GetSurface(MipIndex, slice).GetBlockHeight();
00858 //
00859 //     for ( int Y = 0; Y < NumRows; Y++ )
00860 //     {
00861 //         // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
00862 //         // they contain the same amount of valid data since they have the same width, height and format.
00863 //         Memcpy(Dest + Y * StrideY,&Src[Y * RowByteSize], Min(RowByteSize, StrideY));
00864 //     }
00865   }
00866 
00867   BaseTexture* TextureVolume::Clone() const
00868   {
00869     TextureVolume* texture = new TextureVolume(*this);
00870     return texture;
00871   }
00872 
00873   CachedTextureVolume::CachedTextureVolume(NResourceSet* ResourceManager, TextureVolume* SourceTexture)
00874     :   CachedBaseTexture(ResourceManager)
00875   {
00876     if (SourceTexture->IsNull())
00877     {
00878       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00879       return;
00880     }
00881 
00882     m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateVolumeTexture(SourceTexture->GetWidth(),
00883                 SourceTexture->GetHeight(),
00884                 SourceTexture->GetDepth(),
00885                 SourceTexture->GetNumMipLevel(),
00886                 SourceTexture->GetFormat());
00887 
00888     for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00889     {
00890       LoadMipLevel(SourceTexture, i);
00891     }
00892   }
00893 
00894   CachedTextureVolume::~CachedTextureVolume()
00895   {
00896 
00897   }
00898 
00899   void CachedTextureVolume::UpdateTexture( BaseTexture* SourceTexture )
00900   {
00901     if ((SourceTexture == 0) || SourceTexture->IsNull())
00902     {
00903       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00904       return;
00905     }
00906 
00907     if (!SourceTexture->Type().IsObjectType(TextureVolume::StaticObjectType))
00908     {
00909       nuxAssertMsg(0, "[CachedTextureVolume::UpdateTexture] Source texture is not of type TextureVolume.");
00910       return;
00911     }
00912 
00913     if ( RecreateTexture(SourceTexture))
00914     {
00915       m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateVolumeTexture(SourceTexture->GetWidth(),
00916                   SourceTexture->GetHeight(),
00917                   SourceTexture->GetDepth(),
00918                   SourceTexture->GetNumMipLevel(),
00919                   SourceTexture->GetFormat());
00920 
00921       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00922       {
00923         LoadMipLevel(SourceTexture, i);
00924       }
00925     }
00926     else
00927     {
00928       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00929       {
00930         LoadMipLevel(SourceTexture, i);
00931       }
00932     }
00933   }
00934 
00935   void CachedTextureVolume::LoadMipLevel(BaseTexture* SourceTexture, int MipLevel)
00936   {
00937     VOLUME_LOCKED_BOX       LockedBox;
00938     ObjectPtr <IOpenGLVolumeTexture> VolumeTexture = m_Texture; //m_Texture.CastRef<IOpenGLVolumeTexture>();
00939     //TextureVolume*     Source          = UpCastResource<TextureVolume, BaseTexture>(SourceTexture);
00940 
00941     //for(int slice = 0; slice < ImageSurface::GetLevelDim(Source->GetFormat(), Source->GetDepth(), MipLevel); slice++)
00942     {
00943       OGL_CALL( VolumeTexture->LockBox(MipLevel, &LockedBox, NULL));
00944       SourceTexture->GetData(LockedBox.pBits, MipLevel, LockedBox.RowPitch, 0);
00945       OGL_CALL( VolumeTexture->UnlockBox(MipLevel));
00946     }
00947 
00948 //     for (int slice = 0; slice < depth; slice++)
00949 //     {
00950 //         OGL_CALL( VolumeTexture->LockRect(slice, MipLevel, &LockedRect, NULL));
00951 //         SourceTexture->GetData(LockedRect.pBits, MipLevel, LockedRect.Pitch, slice);
00952 //         OGL_CALL( VolumeTexture->UnlockRect(slice, MipLevel ));
00953 //     }
00954   }
00955 
00956   TextureFrameAnimation::TextureFrameAnimation(NUX_FILE_LINE_DECL)
00957     : BaseTexture(NUX_FILE_LINE_PARAM)
00958   {
00959   }
00960 
00961   TextureFrameAnimation::TextureFrameAnimation(const TextureFrameAnimation& texture)
00962   {
00963     _image = texture._image;
00964   }
00965 
00966   TextureFrameAnimation& TextureFrameAnimation::operator = (const TextureFrameAnimation& texture)
00967   {
00968     if (this == &texture)
00969       return *this;   // Handle self assignment
00970 
00971     _image = texture._image;
00972     return *this;
00973   }
00974 
00975   TextureFrameAnimation::~TextureFrameAnimation()
00976   {
00977 
00978   }
00979 
00980   bool TextureFrameAnimation::Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource)
00981   {
00982     nuxAssertMsg(BitmapData, "[TextureFrameAnimation::Update] Argument BitmapData is NULL.");
00983     NUX_RETURN_VALUE_IF_NULL(BitmapData, false);
00984 
00985     if (!BitmapData->IsAnimatedTextureData())
00986     {
00987       nuxAssertMsg(0, "[TextureFrameAnimation::Update] Argument BitmapData is not a Animated texture");
00988       return false;
00989     }
00990 
00991     _image = *static_cast<const NAnimatedTextureData *> (BitmapData);
00992 
00993     if (UpdateAndCacheResource)
00994     {
00995       // call the texture manager and recreate the texture(CachedTexture2D) associated with this object if any.
00996       GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource(this);
00997     }
00998 
00999     return true;
01000   }
01001 
01002   bool TextureFrameAnimation::Update(const char* filename, bool UpdateAndCacheResource)
01003   {
01004     NBitmapData* BitmapData = LoadImageFile(filename);
01005     nuxAssertMsg(BitmapData, "[TextureFrameAnimation::Update] Bitmap for file(%s) is NULL.", filename);
01006     NUX_RETURN_VALUE_IF_NULL(BitmapData, false);
01007     bool ret = Update(BitmapData);
01008     NUX_SAFE_DELETE(BitmapData);
01009     return ret;
01010   }
01011 
01012   void TextureFrameAnimation::GetData(void* Buffer, int MipIndex, int StrideY, int slice)
01013   {
01014     BYTE               *Dest        = (BYTE *) Buffer;
01015     //for(int slice = 0; slice < ImageSurface::GetLevelDim(_image.GetFormat(), _image.GetDepth(), MipIndex); slice++)
01016     {
01017       const BYTE         *Src         = _image.GetSurface(slice).GetPtrRawData();
01018       int                 RowByteSize = _image.GetSurface(slice).GetPitch();
01019       int                 NumRows     = _image.GetSurface(slice).GetBlockHeight();
01020 
01021       for (int Y = 0; Y < NumRows; Y++)
01022       {
01023         // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
01024         // they contain the same amount of valid data since they have the same width, height and format.
01025         Memcpy(Dest + Y * StrideY, &Src[Y * RowByteSize], Min(RowByteSize, StrideY));
01026       }
01027 
01028       //Dest += NumRows * StrideY;
01029     }
01030   }
01031 
01032   int TextureFrameAnimation::GetFrameTime(int Frame)
01033   {
01034     return _image.GetFrameTime(Frame);
01035   }
01036 
01037   BaseTexture* TextureFrameAnimation::Clone() const
01038   {
01039     TextureFrameAnimation* texture = new TextureFrameAnimation(*this);
01040     return texture;
01041   }
01042 
01043   CachedTextureFrameAnimation::CachedTextureFrameAnimation(NResourceSet* ResourceManager, TextureFrameAnimation* SourceTexture)
01044     :   CachedBaseTexture(ResourceManager)
01045   {
01046     if (SourceTexture->IsNull())
01047     {
01048       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
01049       return;
01050     }
01051 
01052     m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateAnimatedTexture(SourceTexture->GetWidth(),
01053                 SourceTexture->GetHeight(),
01054                 SourceTexture->GetDepth(),
01055                 SourceTexture->GetFormat());
01056 
01057     for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
01058     {
01059       LoadMipLevel(SourceTexture, i);
01060     }
01061   }
01062 
01063   CachedTextureFrameAnimation::~CachedTextureFrameAnimation()
01064   {
01065 
01066   }
01067 
01068   void CachedTextureFrameAnimation::UpdateTexture( BaseTexture* SourceTexture )
01069   {
01070     if ((SourceTexture == 0) || SourceTexture->IsNull())
01071     {
01072       m_Texture = ObjectPtr <IOpenGLBaseTexture> (0);
01073       return;
01074     }
01075 
01076     if (!SourceTexture->Type().IsObjectType(TextureFrameAnimation::StaticObjectType))
01077     {
01078       nuxAssertMsg(0, "[CachedTextureFrameAnimation::UpdateTexture] Source texture is not of type TextureFrameAnimation.");
01079       return;
01080     }
01081 
01082     if (RecreateTexture(SourceTexture))
01083     {
01084       m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateAnimatedTexture(SourceTexture->GetWidth(),
01085                   SourceTexture->GetHeight(),
01086                   SourceTexture->GetDepth(),
01087                   SourceTexture->GetFormat());
01088 
01089       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
01090       {
01091         LoadMipLevel(SourceTexture, i);
01092       }
01093     }
01094     else
01095     {
01096       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
01097       {
01098         LoadMipLevel(SourceTexture, i);
01099       }
01100     }
01101   }
01102 
01103   void CachedTextureFrameAnimation::LoadMipLevel(BaseTexture* SourceTexture, int MipLevel)
01104   {
01105     SURFACE_LOCKED_RECT       LockedRect;
01106     ObjectPtr <IOpenGLAnimatedTexture> AnimatedTexture = m_Texture; //m_Texture.CastRef<IOpenGLAnimatedTexture>();
01107     TextureFrameAnimation*    Source          = UpCastResource<TextureFrameAnimation, BaseTexture> (SourceTexture);
01108 
01109     for (int frame = 0; frame < Source->GetDepth(); frame++)
01110     {
01111       OGL_CALL( AnimatedTexture->LockRect(frame, &LockedRect, NULL));
01112       SourceTexture->GetData(LockedRect.pBits, 0, LockedRect.Pitch, frame);
01113       OGL_CALL( AnimatedTexture->UnlockRect(frame));
01114 
01115       AnimatedTexture->SetFrameTime(frame, Source->GetFrameTime(frame));
01116     }
01117   }
01118 
01119 }