Back to index

nux  3.0.0
IOpenGLBaseTexture.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "NuxCore/NuxCore.h"
00024 #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                                           unsigned int Width,
00038                                           unsigned int Height,
00039                                           unsigned int Depth,
00040                                           unsigned int 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 #ifndef NUX_OPENGLES_20
00063     if (_ResourceType == RTTEXTURERECTANGLE)
00064       _TextureStates.SetType(GL_TEXTURE_RECTANGLE_ARB);
00065 
00066     if (_ResourceType == RTCUBETEXTURE)
00067       _TextureStates.SetType(GL_TEXTURE_CUBE_MAP_ARB);
00068 
00069     if (_ResourceType == RTVOLUMETEXTURE)
00070       _TextureStates.SetType(GL_TEXTURE_3D);
00071 
00072     if (_ResourceType == RTANIMATEDTEXTURE)
00073       _TextureStates.SetType(GL_TEXTURE_RECTANGLE_ARB);
00074 #endif
00075 
00076     _RowMemoryAlignment = ImageSurface::GetMemAlignment(PixelFormat);
00077 
00078     if (IsPowerOf2(Width) && IsPowerOf2(Height))
00079     {
00080       _IsPOT = true;
00081     }
00082   }
00083 
00084   IOpenGLBaseTexture::~IOpenGLBaseTexture()
00085   {
00086 
00087   }
00088 
00089   void IOpenGLBaseTexture::SetRenderStates()
00090   {
00091     if (_ResourceType == RTTEXTURE)
00092     {
00093       CHECKGL(glBindTexture(GL_TEXTURE_2D, _OpenGLID));
00094     }
00095 #ifndef NUX_OPENGLES_20
00096     else if (_ResourceType == RTTEXTURERECTANGLE)
00097     {
00098       CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID));
00099     }
00100     else if (_ResourceType == RTCUBETEXTURE)
00101     {
00102       CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, _OpenGLID));
00103     }
00104     else if (_ResourceType == RTVOLUMETEXTURE)
00105     {
00106       CHECKGL(glBindTexture(GL_TEXTURE_3D, _OpenGLID));
00107     }
00108     else if (_ResourceType == RTANIMATEDTEXTURE)
00109     {
00110       CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID));
00111     }
00112 #endif
00113     else
00114     {
00115       nuxError("[IOpenGLBaseTexture::SetRenderStates] Incorrect texture resource type.");
00116     }
00117 
00118     _TextureStates.SetRenderStates();
00119   }
00120 
00121   void IOpenGLBaseTexture::SetFiltering(unsigned int MinFilter, unsigned int MagFilter/*, unsigned int MIP = GL_NEAREST*/)
00122   {
00123     _TextureStates.SetFiltering(MinFilter, MagFilter);
00124   }
00125 
00126   void IOpenGLBaseTexture::SetWrap(unsigned int U, unsigned int V, unsigned int W)
00127   {
00128     _TextureStates.SetWrap(U, V, W);
00129   }
00130 
00131   void IOpenGLBaseTexture::SetLOD(float MinLod, float MaxLod)
00132   {
00133     _TextureStates.SetLOD(MinLod, MaxLod);
00134   }
00135 
00136   void IOpenGLBaseTexture::SetMipLevel(unsigned int MinMip, unsigned int MaxMip)
00137   {
00138     _TextureStates.SetMipLevel(MinMip, MaxMip);
00139   }
00140 
00141   void IOpenGLBaseTexture::SetBorderColor(float R, float G, float B, float A)
00142   {
00143     _TextureStates.SetBorderColor(R, G, B, A);
00144   }
00145 
00146   int IOpenGLBaseTexture::BindTexture()
00147   {
00148     if (_OpenGLID == 0)
00149     {
00150       CHECKGL(glBindTexture(GL_TEXTURE_2D, 0));
00151     }
00152     else if (_ResourceType == RTTEXTURE)
00153     {
00154       CHECKGL(glBindTexture(GL_TEXTURE_2D, _OpenGLID));
00155     }
00156 #ifndef NUX_OPENGLES_20
00157     else if (_ResourceType == RTTEXTURERECTANGLE)
00158     {
00159       CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID));
00160     }
00161     else if (_ResourceType == RTCUBETEXTURE)
00162     {
00163       CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, _OpenGLID));
00164     }
00165     else if (_ResourceType == RTVOLUMETEXTURE)
00166     {
00167       CHECKGL(glBindTexture(GL_TEXTURE_3D, _OpenGLID));
00168     }
00169     else if (_ResourceType == RTANIMATEDTEXTURE)
00170     {
00171       CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID));
00172     }
00173 #endif
00174     else
00175     {
00176       nuxError("[GpuDevice::BindTexture] Unknown texture type.");
00177       return OGL_INVALID_TEXTURE;
00178     }
00179 
00180     _TextureStates.SetRenderStates();
00181     return OGL_OK;
00182   }
00183 
00184   int IOpenGLBaseTexture::BindTextureToUnit(int TextureUnitIndex)
00185   {
00186     CHECKGL(glActiveTextureARB(TextureUnitIndex));
00187     CHECKGL(glBindTexture(GL_TEXTURE_2D, 0));
00188 #ifndef NUX_OPENGLES_20
00189     CHECKGL(glBindTexture(GL_TEXTURE_3D, 0));
00190     CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, 0));
00191     CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0));
00192     CHECKGL(glDisable(GL_TEXTURE_2D));
00193     CHECKGL(glDisable(GL_TEXTURE_3D));
00194     CHECKGL(glDisable(GL_TEXTURE_RECTANGLE_ARB));
00195     CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP));
00196 #endif
00197 
00198     if (_ResourceType == RTTEXTURE)
00199     {
00200       CHECKGL(glBindTexture(GL_TEXTURE_2D, _OpenGLID));
00201 #ifndef NUX_OPENGLES_20
00202       CHECKGL(glEnable(GL_TEXTURE_2D));
00203 #endif
00204     }
00205 #ifndef NUX_OPENGLES_20
00206     else if (_ResourceType == RTTEXTURERECTANGLE)
00207     {
00208       CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID));
00209       CHECKGL(glEnable(GL_TEXTURE_RECTANGLE_ARB));
00210     }
00211     else if (_ResourceType == RTCUBETEXTURE)
00212     {
00213       CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, _OpenGLID));
00214       CHECKGL(glEnable(GL_TEXTURE_CUBE_MAP));
00215     }
00216     else if (_ResourceType == RTVOLUMETEXTURE)
00217     {
00218       CHECKGL(glBindTexture(GL_TEXTURE_3D, _OpenGLID));
00219       CHECKGL(glEnable(GL_TEXTURE_3D));
00220     }
00221     else if (_ResourceType == RTANIMATEDTEXTURE)
00222     {
00223       CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID));
00224       CHECKGL(glEnable(GL_TEXTURE_RECTANGLE_ARB));
00225     }
00226 #endif
00227     else
00228     {
00229       nuxError("[IOpenGLBaseTexture::BindTexture] unknown texture type.");
00230       return OGL_ERROR;
00231     }
00232 
00233     _TextureStates.SetRenderStates();
00234     return OGL_OK;
00235   }
00236 
00237   void IOpenGLBaseTexture::GetSurfaceLevel(int Level, ObjectPtr<IOpenGLSurface>& surface)
00238   {
00239 
00240   }
00241 
00242   ObjectPtr<IOpenGLSurface> IOpenGLBaseTexture::GetSurfaceLevel(int Level)
00243   {
00244     return ObjectPtr<IOpenGLSurface> (0);
00245   }
00246 
00247   int IOpenGLBaseTexture::LockRect(int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect)
00248   {
00249     return 0;
00250   }
00251 
00252   int IOpenGLBaseTexture::UnlockRect(int Level)
00253   {
00254     return 0;
00255   }
00256 
00257   unsigned char* IOpenGLBaseTexture::GetSurfaceData(int level, int &width, int &height, int &stride)
00258   {
00259     // Make this call a pure virtual once it has been implemented for IOpenGLCubeTexture,
00260     // IOpenGLVolumeTexture and IOpenGLAnimatedTexture.
00261     width = 0;
00262     height = 0;
00263     stride = 0;
00264     return 0;
00265   }
00266 
00267 
00268   int GetTextureSize(IOpenGLBaseTexture *pTexture)
00269   {
00270     GLint unpack_alignment = GPixelFormats[pTexture->_PixelFormat].RowMemoryAlignment;
00271     unsigned int halfUnpack = Log2(unpack_alignment);
00272 
00273     unsigned int TextureSize = 0;
00274 
00275     if (
00276       pTexture->_PixelFormat == BITFMT_DXT1 ||
00277       pTexture->_PixelFormat == BITFMT_DXT2 ||
00278       pTexture->_PixelFormat == BITFMT_DXT3 ||
00279       pTexture->_PixelFormat == BITFMT_DXT4 ||
00280       pTexture->_PixelFormat == BITFMT_DXT5)
00281     {
00282       for (int Level = 0; Level < pTexture->GetNumMipLevel(); Level++)
00283       {
00284         unsigned int Width            = Max<unsigned int> (1, pTexture->_Width >> Level);
00285         unsigned int Height           = Max<unsigned int> (1, pTexture->_Height >> Level);
00286         unsigned int WidthInBlocks    = Max<unsigned int> ((Width + 3) / 4, 1); // round the width to the upper multiple of 4. DXT blocks are 4x4 texels.
00287         unsigned int HeightInBlocks   = Max<unsigned int> ((Height + 3) / 4, 1); // round the height to the upper multiple of 4. DXT blocks are 4x4 texels.
00288 
00289         if (pTexture->_PixelFormat == BITFMT_DXT1)
00290         {
00291           TextureSize += WidthInBlocks * HeightInBlocks * 8;;
00292         }
00293         else
00294         {
00295           TextureSize += WidthInBlocks * HeightInBlocks * 16;
00296         }
00297       }
00298     }
00299     else
00300     {
00301       for (int Level = 0; Level < pTexture->GetNumMipLevel(); Level++)
00302       {
00303         unsigned int Width             = Max<unsigned int> (1, pTexture->_Width >> Level);
00304         unsigned int Height            = Max<unsigned int> (1, pTexture->_Height >> Level);
00305         unsigned int BytePerPixel      = GPixelFormats[pTexture->_PixelFormat].BlockBytes;
00306         unsigned int SlicePitch        = (((Width * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack)) * Height;
00307 
00308         TextureSize += SlicePitch;
00309       }
00310     }
00311 
00312     if (pTexture->GetResourceType() == RTANIMATEDTEXTURE)
00313     {
00314       return TextureSize * pTexture->GetDepth();
00315     }
00316 
00317     return TextureSize;
00318   }
00319 
00320   void GetTextureDesc(IOpenGLBaseTexture *pTexture,
00321                        unsigned int Level,
00322                        TEXTURE_DESC *pDesc)
00323   {
00324     GLint unpack_alignment = GPixelFormats[pTexture->_PixelFormat].RowMemoryAlignment;
00325     unsigned int halfUnpack = Log2(unpack_alignment);
00326 
00327     unsigned int BytePerPixel = 0;
00328 
00329     pDesc->PixelFormat = pTexture->_PixelFormat;
00330 
00331     if ( /*pTexture->_Format  == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||*/
00332       pTexture->_PixelFormat == BITFMT_DXT1 ||
00333       pTexture->_PixelFormat == BITFMT_DXT2 ||
00334       pTexture->_PixelFormat == BITFMT_DXT3 ||
00335       pTexture->_PixelFormat == BITFMT_DXT4 ||
00336       pTexture->_PixelFormat == BITFMT_DXT5)
00337     {
00338       pDesc->Width            = Max<unsigned int> (1, pTexture->_Width >> Level);
00339       pDesc->Height           = Max<unsigned int> (1, pTexture->_Height >> Level);
00340       pDesc->WidthInBlocks    = Max<unsigned int> ((pDesc->Width + 3) / 4, 1); // round the width to the upper multiple of 4. DXT blocks are 4x4 texels.
00341       pDesc->HeightInBlocks   = Max<unsigned int> ((pDesc->Height + 3) / 4, 1); // round the height to the upper multiple of 4. DXT blocks are 4x4 texels.
00342 
00343       if ( /*pTexture->_Format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||*/
00344         pTexture->_PixelFormat == BITFMT_DXT1)
00345       {
00346         // We can conceive a 4x4 DXT1 block as if each texel uses 4 bits.
00347         // Actually, for DXT, we have 2 16-bits colors(5:6:5), and each texel uses 2 bits to interpolate
00348         // between the 2 colors.
00349         //    ---------------------
00350         //    |      COLOR0       | 16 bits
00351         //    ---------------------
00352         //    |      COLOR1       | 16 bits
00353         //    ---------------------
00354         //    | xx | xx | xx | xx | xx = 2 bits
00355         //    ---------------------
00356         //    | xx | xx | xx | xx |
00357         //    ---------------------
00358         //    | xx | xx | xx | xx |
00359         //    ---------------------
00360         //    | xx | xx | xx | xx |
00361         //    ---------------------
00362 
00363         // A line of n texel DXT1 data uses n/2 bytes(4 bits/texel). So the number of bytes used for a
00364         // texwidth texel, is texwidth/2 bytes.
00365         // Note that texwidth is divisible by 4(to to the upper rounding to 4), therefore, it is also divisible
00366         // by 2.
00367 
00368         // glCompressedTexImage2DARB, glCompressedTexImage3DARB,
00369         // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei.
00370 
00371         pDesc->RowPitch = pDesc->WidthInBlocks * 8;
00372         pDesc->SlicePitch = pDesc->WidthInBlocks * pDesc->HeightInBlocks * 8;
00373         pDesc->BitsPerPixel     = 0; // compressed
00374         pDesc->BytesPerBlock    = 8;
00375       }
00376       else
00377       {
00378         // A line of n texel DXT3/5 data uses n bytes(1 byte/texel). So the number of bytes used for a
00379         // texwidth texels, is texwidth bytes.
00380 
00381         // glCompressedTexImage2DARB, glCompressedTexImage3DARB,
00382         // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei.
00383         pDesc->RowPitch = pDesc->WidthInBlocks * 16;
00384         pDesc->SlicePitch = pDesc->WidthInBlocks * pDesc->HeightInBlocks * 16;
00385         pDesc->BitsPerPixel     = 0; // compressed
00386         pDesc->BytesPerBlock    = 16;
00387       }
00388     }
00389     else
00390     {
00391       pDesc->Width            = Max<unsigned int> (1, pTexture->_Width >> Level);
00392       pDesc->Height           = Max<unsigned int> (1, pTexture->_Height >> Level);
00393       pDesc->WidthInBlocks    = pDesc->Width;
00394       pDesc->HeightInBlocks   = pDesc->Height;
00395       BytePerPixel            = GPixelFormats[pTexture->_PixelFormat].BlockBytes;
00396       pDesc->BitsPerPixel     = BytePerPixel * 8;
00397       pDesc->BytesPerBlock    = BytePerPixel; // a block is a 1x1 pixel ie. 1 pixel.
00398       pDesc->RowPitch = (((pDesc->Width * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack));
00399       pDesc->SlicePitch = (((pDesc->Width * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack)) * pDesc->Height;
00400     }
00401   }
00402 
00403 
00404 }