nux-1.16.0
|
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 }