nux-1.14.0
GLTextureResourceManager.cpp
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 (TEXT ("[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 TCHAR *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 TCHAR *TextureFilename)
00182   {
00183     BaseTexture* texture = nullptr;
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::BaseTexture(NUX_FILE_LINE_DECL)
00251     : ResourceData (NUX_FILE_LINE_PARAM)
00252   {
00253 
00254   }
00255 
00256   BaseTexture::~BaseTexture()
00257   {
00258 
00259   }
00260 
00261   ObjectPtr < IOpenGLBaseTexture > BaseTexture::GetDeviceTexture()
00262   {
00263     ObjectPtr<CachedBaseTexture> CachedTexture = GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource (this);
00264     return CachedTexture->m_Texture;
00265   }
00266 
00267   ObjectPtr<CachedBaseTexture> BaseTexture::GetCachedTexture()
00268   {
00269     return GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(this);
00270   }
00271 
00272   Texture2D::Texture2D(NUX_FILE_LINE_DECL)
00273     : BaseTexture(NUX_FILE_LINE_PARAM)
00274   {
00275   }
00276 
00277   Texture2D::Texture2D (const Texture2D &texture, NUX_FILE_LINE_DECL)
00278     : BaseTexture(NUX_FILE_LINE_PARAM)
00279   {
00280     _image = texture._image;
00281   }
00282 
00283   Texture2D::Texture2D (const NTextureData &texture_data, NUX_FILE_LINE_DECL)
00284     : BaseTexture(NUX_FILE_LINE_PARAM)
00285   {
00286     _image = texture_data;
00287   }
00288 
00289   Texture2D &Texture2D::operator = (const Texture2D &texture)
00290   {
00291     if (this == &texture)
00292       return *this;   // Handle self assignment
00293 
00294     _image = texture._image;
00295     return *this;
00296   }
00297 
00298   Texture2D::~Texture2D()
00299   {
00300   }
00301 
00302   bool Texture2D::Update (const NBitmapData *BitmapData, bool UpdateAndCacheResource)
00303   {
00304     nuxAssertMsg (BitmapData, TEXT ("[Texture2D::Update] Argument BitmapData is NULL."));
00305     NUX_RETURN_VALUE_IF_NULL (BitmapData, false);
00306 
00307     if (!BitmapData->IsTextureData())
00308     {
00309       nuxAssertMsg (0, TEXT ("[Texture2D::Update] Argument BitmapData is not a 2D texture"));
00310       return false;
00311     }
00312 
00313     _image = *static_cast<const NTextureData *> (BitmapData);
00314 
00315     if (UpdateAndCacheResource)
00316     {
00317       // call the texture manager and recreate the texture (CachedTexture2D) associated with this object if any.
00318       GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource (this);
00319     }
00320 
00321     return true;
00322   }
00323 
00324   bool Texture2D::Update (const TCHAR *filename, bool UpdateAndCacheResource)
00325   {
00326     NBitmapData *BitmapData = LoadImageFile (filename);
00327     nuxAssertMsg (BitmapData, TEXT ("[Texture2D::Update] Bitmap for file (%s) is NULL."), filename);
00328     NUX_RETURN_VALUE_IF_NULL (BitmapData, false);
00329     bool ret = Update (BitmapData, UpdateAndCacheResource);
00330     NUX_SAFE_DELETE (BitmapData);
00331     return ret;
00332   }
00333 
00334   void Texture2D::GetData (void *Buffer, int MipIndex, int StrideY, int face)
00335   {
00336     BYTE                    *Dest        = (BYTE *) Buffer;
00337     const BYTE         *Src         = _image.GetSurface (MipIndex).GetPtrRawData();
00338     int                 RowByteSize = _image.GetSurface (MipIndex).GetPitch();
00339     int                 NumRows     = _image.GetSurface (MipIndex).GetBlockHeight();
00340 
00341     for ( int Y = 0; Y < NumRows; Y++ )
00342     {
00343       // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
00344       // they contain the same amount of valid data since they have the same width, height and format.
00345       Memcpy (Dest + Y * StrideY, &Src[Y * RowByteSize], Min (RowByteSize, StrideY) );
00346     }
00347   }
00348 
00349   BaseTexture* Texture2D::Clone () const
00350   {
00351     Texture2D* texture = new Texture2D(*this);
00352     return texture;
00353   }
00354 
00355   CachedBaseTexture::CachedBaseTexture (NResourceSet *ResourceManager)
00356     :   CachedResourceData (ResourceManager),
00357     SourceWidth (0),
00358     SourceHeight (0),
00359     SourceDepth (0),
00360     SourceFormat (BITFMT_UNKNOWN)
00361   {
00362 
00363   }
00364 
00365   CachedBaseTexture::~CachedBaseTexture()
00366   {
00367     m_Texture.Release ();
00368   }
00369 
00370   bool CachedBaseTexture::UpdateResource (ResourceData *Resource)
00371   {
00372     UpdateTexture ( (BaseTexture *) Resource);
00373     return TRUE;
00374   }
00375 
00376   bool CachedBaseTexture::RecreateTexture (BaseTexture *Source)
00377   {
00378     int CurrentWidth   = m_Texture->GetWidth();
00379     int CurrentHeight  = m_Texture->GetHeight();
00380     int CurrentDepth   = m_Texture->GetDepth();
00381     int CurrentNumMipmap      = m_Texture->GetNumMipLevel();
00382     BitmapFormat CurrentFormat = m_Texture->GetPixelFormat();
00383 
00384     bool Recreate =
00385       (CurrentWidth       != Source->GetWidth() ) ||
00386       (CurrentHeight      != Source->GetHeight() ) ||
00387       (CurrentDepth       != Source->GetDepth() ) ||
00388       (CurrentNumMipmap   != Source->GetNumMipLevel() ) ||
00389       (CurrentFormat      != Source->GetFormat() );
00390 
00391     return Recreate;
00392   }
00393 
00394   CachedTexture2D::CachedTexture2D (NResourceSet *ResourceManager, Texture2D *SourceTexture)
00395     : CachedBaseTexture (ResourceManager)
00396   {
00397     if (SourceTexture->IsNull())
00398     {
00399       m_Texture = ObjectPtr <IOpenGLBaseTexture> (0);
00400       return;
00401     }
00402 
00403     m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateTexture (SourceTexture->GetWidth(),
00404                 SourceTexture->GetHeight(),
00405                 SourceTexture->GetNumMipLevel(),
00406                 SourceTexture->GetFormat());
00407 
00408     for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00409     {
00410       LoadMipLevel (SourceTexture, i);
00411     }
00412   }
00413 
00414   CachedTexture2D::~CachedTexture2D()
00415   {
00416 
00417   }
00418 
00419   void CachedTexture2D::UpdateTexture ( BaseTexture *SourceTexture )
00420   {
00421     if ( (SourceTexture == 0) || SourceTexture->IsNull() )
00422     {
00423       m_Texture = ObjectPtr <IOpenGLBaseTexture> (0);
00424       return;
00425     }
00426 
00427     if (!SourceTexture->Type().IsObjectType (Texture2D::StaticObjectType) )
00428     {
00429       nuxAssertMsg (0, TEXT ("[Texture2D::UpdateTexture] Source texture is not of type Texture2D.") );
00430       return;
00431     }
00432 
00433     if ( RecreateTexture (SourceTexture) )
00434     {
00435       m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateTexture (SourceTexture->GetWidth(),
00436                   SourceTexture->GetHeight(),
00437                   SourceTexture->GetNumMipLevel(),
00438                   SourceTexture->GetFormat() );
00439 
00440       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00441       {
00442         LoadMipLevel (SourceTexture, i);
00443       }
00444     }
00445     else
00446     {
00447       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00448       {
00449         LoadMipLevel (SourceTexture, i);
00450       }
00451     }
00452   }
00453 
00454   void CachedTexture2D::LoadMipLevel (BaseTexture *SourceTexture, int MipLevel)
00455   {
00456     SURFACE_LOCKED_RECT LockedRect;
00457     ObjectPtr < IOpenGLTexture2D > Texture2D = m_Texture; //m_Texture.CastRef<IOpenGLTexture2D>();
00458 
00459     OGL_CALL ( Texture2D->LockRect ( MipLevel, &LockedRect, NULL) );
00460     SourceTexture->GetData ( LockedRect.pBits, MipLevel, LockedRect.Pitch );
00461     OGL_CALL ( Texture2D->UnlockRect ( MipLevel ) );
00462   }
00463 
00464   TextureRectangle::TextureRectangle (NUX_FILE_LINE_DECL)
00465     : BaseTexture (NUX_FILE_LINE_PARAM)
00466   {
00467   }
00468 
00469   TextureRectangle::TextureRectangle (const TextureRectangle &texture)
00470   {
00471     _image = texture._image;
00472   }
00473 
00474   TextureRectangle::TextureRectangle (const NTextureData &BaseTexture)
00475   {
00476     _image = BaseTexture;
00477   }
00478 
00479   TextureRectangle &TextureRectangle::operator = (const TextureRectangle &texture)
00480   {
00481     if (this == &texture)
00482       return *this;   // Handle self assignment
00483 
00484     _image = texture._image;
00485     return *this;
00486   }
00487 
00488   TextureRectangle::~TextureRectangle()
00489   {
00490 
00491   }
00492 
00493   bool TextureRectangle::Update (const NBitmapData *BitmapData, bool UpdateAndCacheResource)
00494   {
00495     nuxAssertMsg (BitmapData, TEXT ("[TextureRectangle::Update] Argument BitmapData is NULL.") );
00496     NUX_RETURN_VALUE_IF_NULL (BitmapData, false);
00497 
00498     if (!BitmapData->IsTextureData() )
00499     {
00500       nuxAssertMsg (0, TEXT ("[TextureRectangle::Update] Argument BitmapData is not a 2D texture") );
00501       return false;
00502     }
00503 
00504     _image = *static_cast<const NTextureData *> (BitmapData);
00505 
00506     if (UpdateAndCacheResource)
00507     {
00508       // call the texture manager and recreate the texture (CachedTexture2D) associated with this object if any.
00509       GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource (this);
00510     }
00511     return true;
00512   }
00513 
00514   bool TextureRectangle::Update (const TCHAR *filename, bool UpdateAndCacheResource)
00515   {
00516     bool b = false;
00517     NBitmapData *BitmapData = LoadImageFile (filename);
00518     nuxAssertMsg (BitmapData, TEXT ("[TextureRectangle::Update] Bitmap for file (%s) is NULL."), filename);
00519     NUX_RETURN_VALUE_IF_NULL (BitmapData, false);
00520     b = Update (BitmapData);
00521     NUX_SAFE_DELETE (BitmapData);
00522     return b;
00523   }
00524 
00525   void TextureRectangle::GetData (void *Buffer, int MipIndex, int StrideY, int face)
00526   {
00527     BYTE                    *Dest        = (BYTE *) Buffer;
00528     const BYTE         *Src         = _image.GetSurface (MipIndex).GetPtrRawData();
00529     int                 RowByteSize = _image.GetSurface (MipIndex).GetPitch();
00530     int                 NumRows     = _image.GetSurface (MipIndex).GetBlockHeight();
00531 
00532     for ( int Y = 0; Y < NumRows; Y++ )
00533     {
00534       // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
00535       // they contain the same amount of valid data since they have the same width, height and format.
00536       Memcpy (Dest + Y * StrideY, &Src[Y * RowByteSize], Min (RowByteSize, StrideY) );
00537     }
00538   }
00539 
00540   BaseTexture* TextureRectangle::Clone () const
00541   {
00542     TextureRectangle* texture = new TextureRectangle(*this);
00543     return texture;
00544   }
00545 
00546   CachedTextureRectangle::CachedTextureRectangle (NResourceSet *ResourceManager, TextureRectangle *SourceTexture)
00547     : CachedBaseTexture (ResourceManager)
00548   {
00549     if (SourceTexture->IsNull() )
00550     {
00551       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00552       return;
00553     }
00554 
00555     m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateRectangleTexture (SourceTexture->GetWidth(),
00556                 SourceTexture->GetHeight(),
00557                 SourceTexture->GetNumMipLevel(),
00558                 SourceTexture->GetFormat() );
00559 
00560     for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00561     {
00562       LoadMipLevel (SourceTexture, i);
00563     }
00564   }
00565 
00566   CachedTextureRectangle::~CachedTextureRectangle()
00567   {
00568 
00569   }
00570 
00571   void CachedTextureRectangle::UpdateTexture ( BaseTexture *SourceTexture )
00572   {
00573     if ( (SourceTexture == 0) || SourceTexture->IsNull() )
00574     {
00575       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00576       return;
00577     }
00578 
00579     if (!SourceTexture->Type().IsObjectType (TextureRectangle::StaticObjectType) )
00580     {
00581       nuxAssertMsg (0, TEXT ("[CachedTextureRectangle::UpdateTexture] Source texture is not of type TextureRectangle.") );
00582       return;
00583     }
00584 
00585     if ( RecreateTexture (SourceTexture) )
00586     {
00587       m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateRectangleTexture (SourceTexture->GetWidth(),
00588                   SourceTexture->GetHeight(),
00589                   SourceTexture->GetNumMipLevel(),
00590                   SourceTexture->GetFormat() );
00591 
00592       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00593       {
00594         LoadMipLevel (SourceTexture, i);
00595       }
00596     }
00597     else
00598     {
00599       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00600       {
00601         LoadMipLevel (SourceTexture, i);
00602       }
00603     }
00604   }
00605 
00606   void CachedTextureRectangle::LoadMipLevel (BaseTexture *SourceTexture, int MipLevel)
00607   {
00608     SURFACE_LOCKED_RECT                 LockedRect;
00609     ObjectPtr <IOpenGLRectangleTexture> TextureRectangle = m_Texture; //m_Texture.CastRef<IOpenGLRectangleTexture>();
00610 
00611     OGL_CALL (TextureRectangle->LockRect ( MipLevel, &LockedRect, NULL) );
00612     SourceTexture->GetData ( LockedRect.pBits, MipLevel, LockedRect.Pitch );
00613     OGL_CALL (TextureRectangle->UnlockRect ( MipLevel ) );
00614   }
00615 
00616   TextureCube::TextureCube(NUX_FILE_LINE_DECL)
00617     : BaseTexture (NUX_FILE_LINE_PARAM)
00618   {
00619   }
00620 
00621   TextureCube::TextureCube (const TextureCube &texture)
00622   {
00623     _image = texture._image;
00624   }
00625 
00626   TextureCube &TextureCube::operator = (const TextureCube &texture)
00627   {
00628     if (this == &texture)
00629       return *this;   // Handle self assignment
00630 
00631     _image = texture._image;
00632     return *this;
00633   }
00634 
00635   TextureCube::~TextureCube()
00636   {
00637 
00638   }
00639 
00640   bool TextureCube::Update (const NBitmapData *BitmapData, bool UpdateAndCacheResource)
00641   {
00642     nuxAssertMsg (BitmapData, TEXT ("[TextureCube::Update] Argument BitmapData is NULL.") );
00643     NUX_RETURN_VALUE_IF_NULL (BitmapData, false);
00644 
00645     if (!BitmapData->IsCubemapTextureData() )
00646     {
00647       nuxAssertMsg (0, TEXT ("[TextureCube::Update] Argument BitmapData is not a Cube texture") );
00648       return false;
00649     }
00650 
00651     _image = *static_cast<const NCubemapData *> (BitmapData);
00652 
00653     if (UpdateAndCacheResource)
00654     {
00655       // call the texture manager and recreate the texture (CachedTexture2D) associated with this object if any.
00656       GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource (this);
00657     }
00658 
00659     return true;
00660   }
00661 
00662   bool TextureCube::Update (const TCHAR *filename, bool UpdateAndCacheResource)
00663   {
00664     NBitmapData *BitmapData = LoadImageFile (filename);
00665     nuxAssertMsg (BitmapData, TEXT ("[TextureCube::Update] Bitmap for file (%s) is NULL."), filename);
00666     NUX_RETURN_VALUE_IF_NULL (BitmapData, false);
00667     bool ret = Update (BitmapData);
00668     NUX_SAFE_DELETE (BitmapData);
00669     return ret;
00670   }
00671 
00672   void TextureCube::GetData (void *Buffer, int MipIndex, int StrideY, int face)
00673   {
00674     BYTE                    *Dest        = (BYTE *) Buffer;
00675     const BYTE         *Src         = _image.GetSurface (face, MipIndex).GetPtrRawData();
00676     int                 RowByteSize = _image.GetSurface (face, MipIndex).GetPitch();
00677     int                 NumRows     = _image.GetSurface (face, MipIndex).GetBlockHeight();
00678 
00679     for ( int Y = 0; Y < NumRows; Y++ )
00680     {
00681       // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
00682       // they contain the same amount of valid data since they have the same width, height and format.
00683       Memcpy (Dest + Y * StrideY, &Src[Y * RowByteSize], Min (RowByteSize, StrideY) );
00684     }
00685   }
00686 
00687   BaseTexture* TextureCube::Clone () const
00688   {
00689     TextureCube* texture = new TextureCube(*this);
00690     return texture;
00691   }
00692 
00693   CachedTextureCube::CachedTextureCube (NResourceSet *ResourceManager, TextureCube *SourceTexture)
00694     : CachedBaseTexture (ResourceManager)
00695   {
00696     if (SourceTexture->IsNull() )
00697     {
00698       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00699       return;
00700     }
00701 
00702     m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateCubeTexture (SourceTexture->GetWidth(),
00703                 SourceTexture->GetNumMipLevel(),
00704                 SourceTexture->GetFormat() );
00705 
00706     for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00707     {
00708       LoadMipLevel (SourceTexture, i);
00709     }
00710   }
00711 
00712   CachedTextureCube::~CachedTextureCube()
00713   {
00714 
00715   }
00716 
00717   void CachedTextureCube::UpdateTexture ( BaseTexture *SourceTexture )
00718   {
00719     if ( (SourceTexture == 0) || SourceTexture->IsNull() )
00720     {
00721       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00722       return;
00723     }
00724 
00725     if (!SourceTexture->Type().IsObjectType (TextureCube::StaticObjectType) )
00726     {
00727       nuxAssertMsg (0, TEXT ("[CachedTextureCube::UpdateTexture] Source texture is not of type TextureCube.") );
00728       return;
00729     }
00730 
00731     if ( RecreateTexture (SourceTexture) )
00732     {
00733       m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateCubeTexture (SourceTexture->GetWidth(),
00734                   SourceTexture->GetNumMipLevel(),
00735                   SourceTexture->GetFormat() );
00736 
00737       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00738       {
00739         LoadMipLevel (SourceTexture, i);
00740       }
00741     }
00742     else
00743     {
00744       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00745       {
00746         LoadMipLevel (SourceTexture, i);
00747       }
00748     }
00749   }
00750 
00751   void CachedTextureCube::LoadMipLevel (BaseTexture *SourceTexture, int MipLevel)
00752   {
00753     SURFACE_LOCKED_RECT         LockedRect;
00754     ObjectPtr <IOpenGLCubeTexture> CubemapTexture = m_Texture; //m_Texture.CastRef<IOpenGLCubeTexture>();
00755 
00756     for (int face = CUBEMAP_FACE_POSITIVE_X; face < GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + 1; face++)
00757     {
00758       OGL_CALL ( CubemapTexture->LockRect (eCUBEMAP_FACES (face), MipLevel, &LockedRect, NULL) );
00759       SourceTexture->GetData (LockedRect.pBits, MipLevel, LockedRect.Pitch, face - CUBEMAP_FACE_POSITIVE_X);
00760       OGL_CALL ( CubemapTexture->UnlockRect (eCUBEMAP_FACES (face), MipLevel ) );
00761     }
00762   }
00763 
00764   TextureVolume::TextureVolume(NUX_FILE_LINE_DECL)
00765     : BaseTexture (NUX_FILE_LINE_PARAM)
00766   {
00767   }
00768 
00769   TextureVolume::TextureVolume (const TextureVolume &texture)
00770   {
00771     _image = texture._image;
00772   }
00773 
00774   TextureVolume &TextureVolume::operator = (const TextureVolume &texture)
00775   {
00776     if (this == &texture)
00777       return *this;   // Handle self assignment
00778 
00779     _image = texture._image;
00780     return *this;
00781   }
00782 
00783   TextureVolume::~TextureVolume()
00784   {
00785 
00786   }
00787 
00788   bool TextureVolume::Update (const NBitmapData *BitmapData, bool UpdateAndCacheResource)
00789   {
00790     nuxAssertMsg (BitmapData, TEXT ("[TextureVolume::Update] Argument BitmapData is NULL.") );
00791     NUX_RETURN_VALUE_IF_NULL (BitmapData, false);
00792 
00793     if (!BitmapData->IsVolumeTextureData() )
00794     {
00795       nuxAssertMsg (0, TEXT ("[TextureVolume::Update] Argument BitmapData is not a Volume texture") );
00796       return false;
00797     }
00798 
00799     _image = *static_cast<const NVolumeData *> (BitmapData);
00800 
00801     if (UpdateAndCacheResource)
00802     {
00803       // call the texture manager and recreate the texture (CachedTexture2D) associated with this object if any.
00804       GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource (this);
00805     }
00806 
00807     return true;
00808   }
00809 
00810   bool TextureVolume::Update (const TCHAR *filename, bool UpdateAndCacheResource)
00811   {
00812     NBitmapData *BitmapData = LoadImageFile (filename);
00813     nuxAssertMsg (BitmapData, TEXT ("[TextureVolume::Update] Bitmap for file (%s) is NULL."), filename);
00814     NUX_RETURN_VALUE_IF_NULL (BitmapData, false);
00815     bool ret = Update (filename);
00816     NUX_SAFE_DELETE (BitmapData);
00817     return ret;
00818   }
00819 
00820   void TextureVolume::GetData (void *Buffer, int MipIndex, int StrideY, int slice)
00821   {
00822     BYTE               *Dest        = (BYTE *) Buffer;
00823 //     const BYTE*         Src         = _image.GetSurface(MipIndex, slice).GetPtrRawData();
00824 //     int                 RowByteSize = _image.GetSurface(MipIndex, slice).GetPitch();
00825 //     int                 NumRows     = _image.GetSurface(MipIndex, slice).GetBlockHeight();
00826 
00827     for (t_s32 slice = 0; slice < ImageSurface::GetLevelDim (_image.GetFormat(), _image.GetDepth(), MipIndex); slice++)
00828     {
00829       const BYTE         *Src         = _image.GetSurface (MipIndex, slice).GetPtrRawData();
00830       int                 RowByteSize = _image.GetSurface (MipIndex, slice).GetPitch();
00831       int                 NumRows     = _image.GetSurface (MipIndex, slice).GetBlockHeight();
00832 
00833       for ( int Y = 0; Y < NumRows; Y++ )
00834       {
00835         // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
00836         // they contain the same amount of valid data since they have the same width, height and format.
00837         Memcpy (Dest + Y * StrideY, &Src[Y * RowByteSize], Min (RowByteSize, StrideY) );
00838       }
00839 
00840       Dest += NumRows * StrideY;
00841     }
00842 
00843 //     BYTE*                Dest        = (BYTE*)Buffer;
00844 //     const BYTE*         Src         = _image.GetSurface(MipIndex, slice).GetPtrRawData();
00845 //     int                 RowByteSize = _image.GetSurface(MipIndex, slice).GetPitch();
00846 //     int                 NumRows     = _image.GetSurface(MipIndex, slice).GetBlockHeight();
00847 //
00848 //     for( int Y = 0; Y < NumRows; Y++ )
00849 //     {
00850 //         // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
00851 //         // they contain the same amount of valid data since they have the same width, height and format.
00852 //         Memcpy(Dest + Y * StrideY,&Src[Y * RowByteSize], Min(RowByteSize, StrideY));
00853 //     }
00854   }
00855 
00856   BaseTexture* TextureVolume::Clone () const
00857   {
00858     TextureVolume* texture = new TextureVolume(*this);
00859     return texture;
00860   }
00861 
00862   CachedTextureVolume::CachedTextureVolume (NResourceSet *ResourceManager, TextureVolume *SourceTexture)
00863     :   CachedBaseTexture (ResourceManager)
00864   {
00865     if (SourceTexture->IsNull() )
00866     {
00867       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00868       return;
00869     }
00870 
00871     m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateVolumeTexture (SourceTexture->GetWidth(),
00872                 SourceTexture->GetHeight(),
00873                 SourceTexture->GetDepth(),
00874                 SourceTexture->GetNumMipLevel(),
00875                 SourceTexture->GetFormat() );
00876 
00877     for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00878     {
00879       LoadMipLevel (SourceTexture, i);
00880     }
00881   }
00882 
00883   CachedTextureVolume::~CachedTextureVolume()
00884   {
00885 
00886   }
00887 
00888   void CachedTextureVolume::UpdateTexture ( BaseTexture *SourceTexture )
00889   {
00890     if ( (SourceTexture == 0) || SourceTexture->IsNull() )
00891     {
00892       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
00893       return;
00894     }
00895 
00896     if (!SourceTexture->Type().IsObjectType (TextureVolume::StaticObjectType) )
00897     {
00898       nuxAssertMsg (0, TEXT ("[CachedTextureVolume::UpdateTexture] Source texture is not of type TextureVolume.") );
00899       return;
00900     }
00901 
00902     if ( RecreateTexture (SourceTexture) )
00903     {
00904       m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateVolumeTexture (SourceTexture->GetWidth(),
00905                   SourceTexture->GetHeight(),
00906                   SourceTexture->GetDepth(),
00907                   SourceTexture->GetNumMipLevel(),
00908                   SourceTexture->GetFormat() );
00909 
00910       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00911       {
00912         LoadMipLevel (SourceTexture, i);
00913       }
00914     }
00915     else
00916     {
00917       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
00918       {
00919         LoadMipLevel (SourceTexture, i);
00920       }
00921     }
00922   }
00923 
00924   void CachedTextureVolume::LoadMipLevel (BaseTexture *SourceTexture, int MipLevel)
00925   {
00926     VOLUME_LOCKED_BOX       LockedBox;
00927     ObjectPtr <IOpenGLVolumeTexture> VolumeTexture = m_Texture; //m_Texture.CastRef<IOpenGLVolumeTexture>();
00928     //TextureVolume*     Source          = UpCastResource<TextureVolume, BaseTexture>(SourceTexture);
00929 
00930     //for(int slice = 0; slice < ImageSurface::GetLevelDim(Source->GetFormat(), Source->GetDepth(), MipLevel); slice++)
00931     {
00932       OGL_CALL ( VolumeTexture->LockBox (MipLevel, &LockedBox, NULL) );
00933       SourceTexture->GetData (LockedBox.pBits, MipLevel, LockedBox.RowPitch, 0);
00934       OGL_CALL ( VolumeTexture->UnlockBox (MipLevel) );
00935     }
00936 
00937 //     for(int slice = 0; slice < depth; slice++)
00938 //     {
00939 //         OGL_CALL( VolumeTexture->LockRect(slice, MipLevel, &LockedRect, NULL) );
00940 //         SourceTexture->GetData(LockedRect.pBits, MipLevel, LockedRect.Pitch, slice);
00941 //         OGL_CALL( VolumeTexture->UnlockRect(slice, MipLevel ) );
00942 //     }
00943   }
00944 
00945   TextureFrameAnimation::TextureFrameAnimation(NUX_FILE_LINE_DECL)
00946     : BaseTexture (NUX_FILE_LINE_PARAM)
00947   {
00948   }
00949 
00950   TextureFrameAnimation::TextureFrameAnimation (const TextureFrameAnimation &texture)
00951   {
00952     _image = texture._image;
00953   }
00954 
00955   TextureFrameAnimation &TextureFrameAnimation::operator = (const TextureFrameAnimation &texture)
00956   {
00957     if (this == &texture)
00958       return *this;   // Handle self assignment
00959 
00960     _image = texture._image;
00961     return *this;
00962   }
00963 
00964   TextureFrameAnimation::~TextureFrameAnimation()
00965   {
00966 
00967   }
00968 
00969   bool TextureFrameAnimation::Update (const NBitmapData *BitmapData, bool UpdateAndCacheResource)
00970   {
00971     nuxAssertMsg (BitmapData, TEXT ("[TextureFrameAnimation::Update] Argument BitmapData is NULL.") );
00972     NUX_RETURN_VALUE_IF_NULL (BitmapData, false);
00973 
00974     if (!BitmapData->IsAnimatedTextureData() )
00975     {
00976       nuxAssertMsg (0, TEXT ("[TextureFrameAnimation::Update] Argument BitmapData is not a Animated texture") );
00977       return false;
00978     }
00979 
00980     _image = *static_cast<const NAnimatedTextureData *> (BitmapData);
00981 
00982     if (UpdateAndCacheResource)
00983     {
00984       // call the texture manager and recreate the texture (CachedTexture2D) associated with this object if any.
00985       GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource (this);
00986     }
00987 
00988     return true;
00989   }
00990 
00991   bool TextureFrameAnimation::Update (const TCHAR *filename, bool UpdateAndCacheResource)
00992   {
00993     NBitmapData *BitmapData = LoadImageFile (filename);
00994     nuxAssertMsg (BitmapData, TEXT ("[TextureFrameAnimation::Update] Bitmap for file (%s) is NULL."), filename);
00995     NUX_RETURN_VALUE_IF_NULL (BitmapData, false);
00996     bool ret = Update (BitmapData);
00997     NUX_SAFE_DELETE (BitmapData);
00998     return ret;
00999   }
01000 
01001   void TextureFrameAnimation::GetData (void *Buffer, int MipIndex, int StrideY, int slice)
01002   {
01003     BYTE               *Dest        = (BYTE *) Buffer;
01004     //for(int slice = 0; slice < ImageSurface::GetLevelDim(_image.GetFormat(), _image.GetDepth(), MipIndex); slice++)
01005     {
01006       const BYTE         *Src         = _image.GetSurface (slice).GetPtrRawData();
01007       int                 RowByteSize = _image.GetSurface (slice).GetPitch();
01008       int                 NumRows     = _image.GetSurface (slice).GetBlockHeight();
01009 
01010       for (int Y = 0; Y < NumRows; Y++)
01011       {
01012         // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but
01013         // they contain the same amount of valid data since they have the same width, height and format.
01014         Memcpy (Dest + Y * StrideY, &Src[Y * RowByteSize], Min (RowByteSize, StrideY) );
01015       }
01016 
01017       //Dest += NumRows * StrideY;
01018     }
01019   }
01020 
01021   int TextureFrameAnimation::GetFrameTime (int Frame)
01022   {
01023     return _image.GetFrameTime (Frame);
01024   }
01025 
01026   BaseTexture* TextureFrameAnimation::Clone () const
01027   {
01028     TextureFrameAnimation* texture = new TextureFrameAnimation(*this);
01029     return texture;
01030   }
01031 
01032   CachedTextureFrameAnimation::CachedTextureFrameAnimation (NResourceSet *ResourceManager, TextureFrameAnimation *SourceTexture)
01033     :   CachedBaseTexture (ResourceManager)
01034   {
01035     if (SourceTexture->IsNull() )
01036     {
01037       m_Texture = ObjectPtr<IOpenGLBaseTexture> (0);
01038       return;
01039     }
01040 
01041     m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateAnimatedTexture (SourceTexture->GetWidth(),
01042                 SourceTexture->GetHeight(),
01043                 SourceTexture->GetDepth(),
01044                 SourceTexture->GetFormat() );
01045 
01046     for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
01047     {
01048       LoadMipLevel (SourceTexture, i);
01049     }
01050   }
01051 
01052   CachedTextureFrameAnimation::~CachedTextureFrameAnimation()
01053   {
01054 
01055   }
01056 
01057   void CachedTextureFrameAnimation::UpdateTexture ( BaseTexture *SourceTexture )
01058   {
01059     if ( (SourceTexture == 0) || SourceTexture->IsNull() )
01060     {
01061       m_Texture = ObjectPtr <IOpenGLBaseTexture> (0);
01062       return;
01063     }
01064 
01065     if (!SourceTexture->Type().IsObjectType (TextureFrameAnimation::StaticObjectType) )
01066     {
01067       nuxAssertMsg (0, TEXT ("[CachedTextureFrameAnimation::UpdateTexture] Source texture is not of type TextureFrameAnimation.") );
01068       return;
01069     }
01070 
01071     if (RecreateTexture (SourceTexture) )
01072     {
01073       m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateAnimatedTexture (SourceTexture->GetWidth(),
01074                   SourceTexture->GetHeight(),
01075                   SourceTexture->GetDepth(),
01076                   SourceTexture->GetFormat() );
01077 
01078       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
01079       {
01080         LoadMipLevel (SourceTexture, i);
01081       }
01082     }
01083     else
01084     {
01085       for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++)
01086       {
01087         LoadMipLevel (SourceTexture, i);
01088       }
01089     }
01090   }
01091 
01092   void CachedTextureFrameAnimation::LoadMipLevel (BaseTexture *SourceTexture, int MipLevel)
01093   {
01094     SURFACE_LOCKED_RECT       LockedRect;
01095     ObjectPtr <IOpenGLAnimatedTexture> AnimatedTexture = m_Texture; //m_Texture.CastRef<IOpenGLAnimatedTexture>();
01096     TextureFrameAnimation     *Source          = UpCastResource<TextureFrameAnimation, BaseTexture> (SourceTexture);
01097 
01098     for (int frame = 0; frame < Source->GetDepth(); frame++)
01099     {
01100       OGL_CALL ( AnimatedTexture->LockRect (frame, &LockedRect, NULL) );
01101       SourceTexture->GetData (LockedRect.pBits, 0, LockedRect.Pitch, frame);
01102       OGL_CALL ( AnimatedTexture->UnlockRect (frame) );
01103 
01104       AnimatedTexture->SetFrameTime (frame, Source->GetFrameTime (frame) );
01105     }
01106   }
01107 
01108 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends