nux-1.14.0
IOpenGLBaseTexture.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 "NuxCore/NuxCore.h"
00024 #include "GLResource.h"
00025 #include "IOpenGLResource.h"
00026 #include "GLShaderParameter.h"
00027 #include "GLTextureStates.h"
00028 #include "IOpenGLBaseTexture.h"
00029 #include "IOpenGLSurface.h"
00030 
00031 namespace nux
00032 {
00033 
00034   NUX_IMPLEMENT_OBJECT_TYPE (IOpenGLBaseTexture);
00035 
00036   IOpenGLBaseTexture::IOpenGLBaseTexture (OpenGLResourceType ResourceType,
00037                                           t_u32 Width,
00038                                           t_u32 Height,
00039                                           t_u32 Depth,
00040                                           t_u32 NumMipLevel,
00041                                           BitmapFormat PixelFormat, NUX_FILE_LINE_DECL)
00042     : IOpenGLResource (ResourceType, NUX_FILE_LINE_PARAM)
00043     , _IsPOT (false)
00044     , _NumMipLevel (NumMipLevel)
00045     , _PixelFormat (PixelFormat)
00046     , _Width (Width)
00047     , _Height (Height)
00048     , _Depth (Depth)
00049     , _RowMemoryAlignment (1)
00050   {
00051     //     if( (GPixelFormats[PixelFormat].BlockBytes == 1) ||
00052     //         (GPixelFormats[PixelFormat].BlockBytes == 2) ||
00053     //         (GPixelFormats[PixelFormat].BlockBytes == 3))
00054     //         _RowMemoryAlignment = 1;
00055     //     else
00056     //         _RowMemoryAlignment = 4;
00057 
00058 
00059     if (_ResourceType == RTTEXTURE)
00060       _TextureStates.SetType (GL_TEXTURE_2D);
00061 
00062     if (_ResourceType == RTTEXTURERECTANGLE)
00063       _TextureStates.SetType (GL_TEXTURE_RECTANGLE_ARB);
00064 
00065     if (_ResourceType == RTCUBETEXTURE)
00066       _TextureStates.SetType (GL_TEXTURE_CUBE_MAP_ARB);
00067 
00068     if (_ResourceType == RTVOLUMETEXTURE)
00069       _TextureStates.SetType (GL_TEXTURE_3D);
00070 
00071     if (_ResourceType == RTANIMATEDTEXTURE)
00072       _TextureStates.SetType (GL_TEXTURE_RECTANGLE_ARB);
00073 
00074     _RowMemoryAlignment = ImageSurface::GetMemAlignment (PixelFormat);
00075 
00076     if (IsPowerOf2 (Width) && IsPowerOf2 (Height) )
00077     {
00078       _IsPOT = true;
00079     }
00080   }
00081 
00082   IOpenGLBaseTexture::~IOpenGLBaseTexture()
00083   {
00084 
00085   }
00086 
00087   void IOpenGLBaseTexture::SetRenderStates()
00088   {
00089     if (_ResourceType == RTTEXTURE)
00090     {
00091       CHECKGL ( glBindTexture (GL_TEXTURE_2D, _OpenGLID) );
00092     }
00093     else if (_ResourceType == RTTEXTURERECTANGLE)
00094     {
00095       CHECKGL ( glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _OpenGLID) );
00096     }
00097     else if (_ResourceType == RTCUBETEXTURE)
00098     {
00099       CHECKGL ( glBindTexture (GL_TEXTURE_CUBE_MAP, _OpenGLID) );
00100     }
00101     else if (_ResourceType == RTVOLUMETEXTURE)
00102     {
00103       CHECKGL ( glBindTexture (GL_TEXTURE_3D, _OpenGLID) );
00104     }
00105     else if (_ResourceType == RTANIMATEDTEXTURE)
00106     {
00107       CHECKGL ( glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _OpenGLID) );
00108     }
00109     else
00110     {
00111       nuxError (TEXT ("[IOpenGLBaseTexture::SetRenderStates] Incorrect texture resource type.") );
00112     }
00113 
00114     _TextureStates.SetRenderStates();
00115   }
00116 
00117   void IOpenGLBaseTexture::SetFiltering (t_u32 MinFilter, t_u32 MagFilter/*, t_u32 MIP = GL_NEAREST*/)
00118   {
00119     _TextureStates.SetFiltering (MinFilter, MagFilter);
00120   }
00121 
00122   void IOpenGLBaseTexture::SetWrap (t_u32 U, t_u32 V, t_u32 W)
00123   {
00124     _TextureStates.SetWrap (U, V, W);
00125   }
00126 
00127   void IOpenGLBaseTexture::SetLOD (float MinLod, float MaxLod)
00128   {
00129     _TextureStates.SetLOD (MinLod, MaxLod);
00130   }
00131 
00132   void IOpenGLBaseTexture::SetMipLevel (t_u32 MinMip, t_u32 MaxMip)
00133   {
00134     _TextureStates.SetMipLevel (MinMip, MaxMip);
00135   }
00136 
00137   void IOpenGLBaseTexture::SetBorderColor (float R, float G, float B, float A)
00138   {
00139     _TextureStates.SetBorderColor (R, G, B, A);
00140   }
00141 
00142   int IOpenGLBaseTexture::BindTexture()
00143   {
00144     if (_OpenGLID == 0)
00145     {
00146       CHECKGL ( glBindTexture (GL_TEXTURE_2D, 0) );
00147     }
00148     else if (_ResourceType == RTTEXTURE)
00149     {
00150       CHECKGL ( glBindTexture (GL_TEXTURE_2D, _OpenGLID) );
00151     }
00152     else if (_ResourceType == RTTEXTURERECTANGLE)
00153     {
00154       CHECKGL ( glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _OpenGLID) );
00155     }
00156     else if (_ResourceType == RTCUBETEXTURE)
00157     {
00158       CHECKGL ( glBindTexture (GL_TEXTURE_CUBE_MAP, _OpenGLID) );
00159     }
00160     else if (_ResourceType == RTVOLUMETEXTURE)
00161     {
00162       CHECKGL ( glBindTexture (GL_TEXTURE_3D, _OpenGLID) );
00163     }
00164     else if (_ResourceType == RTANIMATEDTEXTURE)
00165     {
00166       CHECKGL (glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _OpenGLID) );
00167     }
00168     else
00169     {
00170       nuxError (TEXT ("[GpuDevice::BindTexture] Unknown texture type.") );
00171       return OGL_INVALID_TEXTURE;
00172     }
00173 
00174     _TextureStates.SetRenderStates();
00175     return OGL_OK;
00176   }
00177 
00178   int IOpenGLBaseTexture::BindTextureToUnit (int TextureUnitIndex)
00179   {
00180     CHECKGL ( glActiveTextureARB (TextureUnitIndex) );
00181     CHECKGL ( glBindTexture (GL_TEXTURE_2D, 0) );
00182     CHECKGL ( glBindTexture (GL_TEXTURE_3D, 0) );
00183     CHECKGL ( glBindTexture (GL_TEXTURE_CUBE_MAP, 0) );
00184     CHECKGL ( glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0) );
00185     CHECKGL ( glDisable (GL_TEXTURE_2D) );
00186     CHECKGL ( glDisable (GL_TEXTURE_3D) );
00187     CHECKGL ( glDisable (GL_TEXTURE_RECTANGLE_ARB) );
00188     CHECKGL ( glDisable (GL_TEXTURE_CUBE_MAP) );
00189 
00190     if (_ResourceType == RTTEXTURE)
00191     {
00192       CHECKGL (glBindTexture (GL_TEXTURE_2D, _OpenGLID) );
00193       CHECKGL (glEnable (GL_TEXTURE_2D) );
00194     }
00195     else if (_ResourceType == RTTEXTURERECTANGLE)
00196     {
00197       CHECKGL (glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _OpenGLID) );
00198       CHECKGL (glEnable (GL_TEXTURE_RECTANGLE_ARB) );
00199     }
00200     else if (_ResourceType == RTCUBETEXTURE)
00201     {
00202       CHECKGL (glBindTexture (GL_TEXTURE_CUBE_MAP, _OpenGLID) );
00203       CHECKGL (glEnable (GL_TEXTURE_CUBE_MAP) );
00204     }
00205     else if (_ResourceType == RTVOLUMETEXTURE)
00206     {
00207       CHECKGL (glBindTexture (GL_TEXTURE_3D, _OpenGLID) );
00208       CHECKGL (glEnable (GL_TEXTURE_3D) );
00209     }
00210     else if (_ResourceType == RTANIMATEDTEXTURE)
00211     {
00212       CHECKGL (glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _OpenGLID) );
00213       CHECKGL (glEnable (GL_TEXTURE_RECTANGLE_ARB) );
00214     }
00215     else
00216     {
00217       nuxError (TEXT ("[IOpenGLBaseTexture::BindTexture] unknown texture type.") );
00218       return OGL_ERROR;
00219     }
00220 
00221     _TextureStates.SetRenderStates();
00222     return OGL_OK;
00223   }
00224 
00225   void IOpenGLBaseTexture::GetSurfaceLevel (int Level, ObjectPtr<IOpenGLSurface>& surface)
00226   {
00227 
00228   }
00229 
00230   ObjectPtr<IOpenGLSurface> IOpenGLBaseTexture::GetSurfaceLevel (int Level)
00231   {
00232     return ObjectPtr<IOpenGLSurface> (0);
00233   }
00234 
00235   int IOpenGLBaseTexture::LockRect (int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect)
00236   {
00237     return 0;
00238   }
00239 
00240   int IOpenGLBaseTexture::UnlockRect (int Level)
00241   {
00242     return 0;
00243   }
00244 
00245   void* IOpenGLBaseTexture::GetSurfaceData (int level, int &width, int &height, int &format)
00246   {
00247     width = 0;
00248     height = 0;
00249     format = BITFMT_UNKNOWN;
00250     return 0;
00251   }
00252 
00253 
00254   t_s32 GetTextureSize (IOpenGLBaseTexture *pTexture)
00255   {
00256     GLint unpack_alignment = GPixelFormats[pTexture->_PixelFormat].RowMemoryAlignment;
00257     t_u32 halfUnpack = Log2 (unpack_alignment);
00258 
00259     t_u32 TextureSize = 0;
00260 
00261     if (
00262       pTexture->_PixelFormat == BITFMT_DXT1 ||
00263       pTexture->_PixelFormat == BITFMT_DXT2 ||
00264       pTexture->_PixelFormat == BITFMT_DXT3 ||
00265       pTexture->_PixelFormat == BITFMT_DXT4 ||
00266       pTexture->_PixelFormat == BITFMT_DXT5)
00267     {
00268       for (int Level = 0; Level < pTexture->GetNumMipLevel(); Level++)
00269       {
00270         t_u32 Width            = Max<t_u32> (1, pTexture->_Width >> Level);
00271         t_u32 Height           = Max<t_u32> (1, pTexture->_Height >> Level);
00272         t_u32 WidthInBlocks    = Max<t_u32> ( (Width + 3) / 4, 1); // round the width to the upper multiple of 4. DXT blocks are 4x4 texels.
00273         t_u32 HeightInBlocks   = Max<t_u32> ( (Height + 3) / 4, 1); // round the height to the upper multiple of 4. DXT blocks are 4x4 texels.
00274 
00275         if (pTexture->_PixelFormat == BITFMT_DXT1)
00276         {
00277           TextureSize += WidthInBlocks * HeightInBlocks * 8;;
00278         }
00279         else
00280         {
00281           TextureSize += WidthInBlocks * HeightInBlocks * 16;
00282         }
00283       }
00284     }
00285     else
00286     {
00287       for (int Level = 0; Level < pTexture->GetNumMipLevel(); Level++)
00288       {
00289         t_u32 Width             = Max<t_u32> (1, pTexture->_Width >> Level);
00290         t_u32 Height            = Max<t_u32> (1, pTexture->_Height >> Level);
00291         t_u32 BytePerPixel      = GPixelFormats[pTexture->_PixelFormat].BlockBytes;
00292         t_u32 SlicePitch        = ( ( (Width * BytePerPixel + (unpack_alignment - 1) ) >> (halfUnpack) ) << (halfUnpack) ) * Height;
00293 
00294         TextureSize += SlicePitch;
00295       }
00296     }
00297 
00298     if (pTexture->GetResourceType() == RTANIMATEDTEXTURE)
00299     {
00300       return TextureSize * pTexture->GetDepth();
00301     }
00302 
00303     return TextureSize;
00304   }
00305 
00306   void GetTextureDesc (IOpenGLBaseTexture *pTexture,
00307                        t_u32 Level,
00308                        TEXTURE_DESC *pDesc)
00309   {
00310     GLint unpack_alignment = GPixelFormats[pTexture->_PixelFormat].RowMemoryAlignment;
00311     t_u32 halfUnpack = Log2 (unpack_alignment);
00312 
00313     t_u32 BytePerPixel = 0;
00314 
00315     pDesc->PixelFormat = pTexture->_PixelFormat;
00316 
00317     if ( /*pTexture->_Format  == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||*/
00318       pTexture->_PixelFormat == BITFMT_DXT1 ||
00319       pTexture->_PixelFormat == BITFMT_DXT2 ||
00320       pTexture->_PixelFormat == BITFMT_DXT3 ||
00321       pTexture->_PixelFormat == BITFMT_DXT4 ||
00322       pTexture->_PixelFormat == BITFMT_DXT5)
00323     {
00324       pDesc->Width            = Max<t_u32> (1, pTexture->_Width >> Level);
00325       pDesc->Height           = Max<t_u32> (1, pTexture->_Height >> Level);
00326       pDesc->WidthInBlocks    = Max<t_u32> ( (pDesc->Width + 3) / 4, 1); // round the width to the upper multiple of 4. DXT blocks are 4x4 texels.
00327       pDesc->HeightInBlocks   = Max<t_u32> ( (pDesc->Height + 3) / 4, 1); // round the height to the upper multiple of 4. DXT blocks are 4x4 texels.
00328 
00329       if ( /*pTexture->_Format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||*/
00330         pTexture->_PixelFormat == BITFMT_DXT1)
00331       {
00332         // We can conceive a 4x4 DXT1 block as if each texel uses 4 bits.
00333         // Actually, for DXT, we have 2 16-bits colors(5:6:5), and each texel uses 2 bits to interpolate
00334         // between the 2 colors.
00335         //    ---------------------
00336         //    |      COLOR0       | 16 bits
00337         //    ---------------------
00338         //    |      COLOR1       | 16 bits
00339         //    ---------------------
00340         //    | xx | xx | xx | xx | xx = 2 bits
00341         //    ---------------------
00342         //    | xx | xx | xx | xx |
00343         //    ---------------------
00344         //    | xx | xx | xx | xx |
00345         //    ---------------------
00346         //    | xx | xx | xx | xx |
00347         //    ---------------------
00348 
00349         // A line of n texel DXT1 data uses n/2 bytes (4 bits/texel). So the number of bytes used for a
00350         // texwidth texel, is texwidth/2 bytes.
00351         // Note that texwidth is divisible by 4(to to the upper rounding to 4), therefore, it is also divisible
00352         // by 2.
00353 
00354         // glCompressedTexImage2DARB, glCompressedTexImage3DARB,
00355         // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei.
00356 
00357         pDesc->RowPitch = pDesc->WidthInBlocks * 8;
00358         pDesc->SlicePitch = pDesc->WidthInBlocks * pDesc->HeightInBlocks * 8;
00359         pDesc->BitsPerPixel     = 0; // compressed
00360         pDesc->BytesPerBlock    = 8;
00361       }
00362       else
00363       {
00364         // A line of n texel DXT3/5 data uses n bytes (1 byte/texel). So the number of bytes used for a
00365         // texwidth texels, is texwidth bytes.
00366 
00367         // glCompressedTexImage2DARB, glCompressedTexImage3DARB,
00368         // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei.
00369         pDesc->RowPitch = pDesc->WidthInBlocks * 16;
00370         pDesc->SlicePitch = pDesc->WidthInBlocks * pDesc->HeightInBlocks * 16;
00371         pDesc->BitsPerPixel     = 0; // compressed
00372         pDesc->BytesPerBlock    = 16;
00373       }
00374     }
00375     else
00376     {
00377       pDesc->Width            = Max<t_u32> (1, pTexture->_Width >> Level);
00378       pDesc->Height           = Max<t_u32> (1, pTexture->_Height >> Level);
00379       pDesc->WidthInBlocks    = pDesc->Width;
00380       pDesc->HeightInBlocks   = pDesc->Height;
00381       BytePerPixel            = GPixelFormats[pTexture->_PixelFormat].BlockBytes;
00382       pDesc->BitsPerPixel     = BytePerPixel * 8;
00383       pDesc->BytesPerBlock    = BytePerPixel; // a block is a 1x1 pixel ie. 1 pixel.
00384       pDesc->RowPitch = ( ( (pDesc->Width * BytePerPixel + (unpack_alignment - 1) ) >> (halfUnpack) ) << (halfUnpack) );
00385       pDesc->SlicePitch = ( ( (pDesc->Width * BytePerPixel + (unpack_alignment - 1) ) >> (halfUnpack) ) << (halfUnpack) ) * pDesc->Height;
00386     }
00387   }
00388 
00389 
00390 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends